Home > functions > dynasim.m

dynasim

PURPOSE ^

DynaSim GUI

SYNOPSIS ^

function dynasim(spec)

DESCRIPTION ^

 DynaSim GUI
 Purpose: graphical interface for DynaSim model building and exploration.
 Usage:
   dynasim; % load default model
   dynasim(specification)
 
 Author: Jason Sherfey, PhD <jssherfey@gmail.com>
 Copyright (C) 2016 Jason Sherfey, Boston University, USA

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SUBFUNCTIONS ^

SOURCE CODE ^

0001 % DynaSim GUI
0002 % Purpose: graphical interface for DynaSim model building and exploration.
0003 % Usage:
0004 %   dynasim; % load default model
0005 %   dynasim(specification)
0006 %
0007 % Author: Jason Sherfey, PhD <jssherfey@gmail.com>
0008 % Copyright (C) 2016 Jason Sherfey, Boston University, USA
0009 
0010 function dynasim(spec)
0011 
0012 % abort if not running in MATLAB
0013 if ~strcmp(reportUI,'matlab')
0014   warning('DynaSim GUI is not supported in GNU Octave at this time.');
0015   return
0016 end
0017 
0018 global handles SPEC MODEL cfg LASTSPEC LASTCFG
0019 handles=[];
0020 
0021 if nargin==0 % default model
0022   %SPEC=dsCheckSpecification([]);
0023   ina={
0024     'INa(v,m,h) = -gNa.*m.^3.*h.*(v-50); gNa=120';  % sodium current
0025     'dm/dt = aM(v).*(1-m)-bM(v).*m; m(0)=.1';       % - activation
0026     'dh/dt = aH(v).*(1-h)-bH(v).*h; h(0)=.1';       % - inactivation
0027     'aM(v) = (2.5-.1*(v+65))./(exp(2.5-.1*(v+65))-1)';
0028     'bM(v) = 4*exp(-(v+65)/18)';
0029     'aH(v) = .07*exp(-(v+65)/20)';
0030     'bH(v) = 1./(exp(3-.1*(v+65))+1)';
0031     '@current+=INa';
0032   };
0033   ik={
0034     'IK(v,n) = -gK.*n.^4.*(v+77); gK=36';           % potassium current
0035     'dn/dt = aN(v).*(1-n)-bN(v).*n; n(0)=0';        % - activation
0036     'aN(v) = (.1-.01*(v+65))./(exp(1-.1*(v+65))-1)';
0037     'bN(v) = .125*exp(-(v+65)/80)';  
0038     '@current+=IK';
0039   };
0040   iampa={
0041     'gSYN=0.1; ESYN=0; tauD=2; tauR=0.4';
0042     'netcon=ones(N_pre,N_post)';
0043     'ISYN(X,s)=(gSYN.*(s*netcon).*(X-ESYN))';
0044     'ds/dt=-s./tauD+((1-s)/tauR).*(1+tanh(X_pre/10)); s(0)=.1';
0045     '@isyn += -ISYN(X_post,s)';    
0046   };
0047   igaba={
0048     'gSYN=0.25; ESYN=-80; tauD=10; tauR=0.4';
0049     'netcon=ones(N_pre,N_post)';
0050     'ISYN(X,s)=(gSYN.*(s*netcon).*(X-ESYN))';
0051     'ds/dt=-s./tauD+((1-s)/tauR).*(1+tanh(X_pre/10)); s(0)=.1';
0052     '@isyn += -ISYN(X_post,s)';
0053   };
0054   input='Iapp=0; noise=0; @input+=Iapp+noise*randn(1,N_pop)';
0055   master_equations='dv/dt=@input+@current+@isyn; v(0)=-65';
0056   mechanism_list={'ina','ik','input1'};
0057   %master_equations='dv/dt=Iapp+@current+noise*randn(1,N_pop);';
0058   %mechanism_list={'ina','ik'};
0059   s=[];
0060   s.populations(1).name='E';
0061   s.populations(1).size=8;
0062   s.populations(1).equations=master_equations;
0063   s.populations(1).mechanism_list=mechanism_list;
0064   s.populations(1).parameters={'Iapp',5,'noise',40,'gNa',125};
0065   s.populations(2).name='I';
0066   s.populations(2).size=2;
0067   s.populations(2).equations=master_equations;
0068   s.populations(2).mechanism_list=mechanism_list;
0069   s.populations(2).parameters={'Iapp',0,'noise',40};
0070   s.connections(1).direction='I->E';
0071   s.connections(1).mechanism_list={'igaba'};%{'iGABAa'};
0072   s.connections(1).parameters={'tauD',10,'gSYN',.1};
0073   s.connections(2).direction='E->I';
0074   s.connections(2).mechanism_list={'iampa'};%{'iAMPA'};
0075   s.connections(2).parameters={'tauD',2,'gSYN',.1};
0076   s.mechanisms(1).name='ina';
0077   s.mechanisms(1).equations=ina;
0078   s.mechanisms(2).name='ik';
0079   s.mechanisms(2).equations=ik;
0080   s.mechanisms(3).name='iampa';
0081   s.mechanisms(3).equations=iampa;
0082   s.mechanisms(4).name='igaba';
0083   s.mechanisms(4).equations=igaba;
0084   s.mechanisms(5).name='input1';
0085   s.mechanisms(5).equations=input;
0086   spec=s;
0087   
0088 end
0089 % check specification
0090 SPEC=dsCheckSpecification(spec);
0091 % remove global population params (already applied to pop(#).mechanisms(#).equation)
0092 [SPEC.populations.parameters]=deal([]);
0093 if ~isempty(SPEC.connections)
0094   [SPEC.connections.parameters]=deal([]);
0095 end
0096 % generate model
0097 MODEL=dsGenerateModel(SPEC);
0098 % extract model ODEFUN and IC
0099 try
0100   [ODEFUN,IC,elem_names]=dsDynasim2odefun(dsPropagateParameters(MODEL));
0101 catch
0102   ODEFUN='';
0103   IC=[];
0104   elem_names={};
0105 end
0106 % txt=dsExtractModelStrings(MODEL,'model',0);
0107 % ODEFUN=txt{1}; IC=txt{2}; elem_names=txt{3};
0108 
0109 % app configuration
0110 cfg.username='anonymous';
0111 cfg.model_text='model equations ...';
0112 cfg.V=linspace(-100,100,20e3); % default xdata for auxiliary function plot
0113 cfg.linecolors  = 'kbrgmy';
0114 cfg.linetype  = {'-',':','-.','--'};
0115 cfg.max_num_plots=3;
0116 cfg.num_xticks=5;
0117 cfg.num_steps_per_plot=400; % number sim time steps per sim view update
0118 cfg.sim_paused=-1;
0119 cfg.sim_stopped=0;
0120 cfg.ymin=-90*ones(1,cfg.max_num_plots);
0121 cfg.ymax=50*ones(1,cfg.max_num_plots);
0122 cfg.ModelFontName='Monospaced'; % 'Courier'
0123 cfg.autoscale_charcode=5864;
0124 
0125 cfg.BackgroundColor=[204 204 180]/255;
0126 cfg.ButtonColor=[0 102 153]/255/1.75; % 'c',[51 204 204]/255
0127 cfg.ButtonFontColor=[240 240 240]/255; % 'k'
0128 
0129 % cfg.BackgroundColor=[204 204 180]/255;
0130 % cfg.ButtonColor=[0 255 255]/255/1.25;
0131 % cfg.ButtonFontColor='k';
0132 
0133 % default data
0134 cfg.ODEFUN=ODEFUN;
0135 cfg.IC=IC;
0136 cfg.elem_names=elem_names;
0137 cfg.ntime=20e3+1;
0138 cfg.dt=.01;
0139 cfg.t0=0;
0140 cfg.tf=200;
0141 cfg.t=(0:cfg.ntime-1)'*cfg.dt;
0142 cfg.t_plot_indices=1:cfg.ntime;
0143 cfg.Y=zeros(cfg.ntime,max(1,length(cfg.IC)));
0144 cfg.xtick=linspace(cfg.t(1),cfg.t(end),cfg.num_xticks);
0145 cfg.xticklabel=linspace(cfg.t(1),cfg.t(end),cfg.num_xticks);
0146 
0147 if nargin==0
0148   LASTSPEC=SPEC;
0149   LASTCFG=cfg;
0150 end
0151 
0152 % open figure for model designer
0153 figure_position=[245 145 1460 770]; % compact
0154 handles.fig_main = figure('position',figure_position,'color',cfg.BackgroundColor,'tag','designer','name','DynaSim Model Builder','NumberTitle','off','WindowScrollWheelFcn',@ZoomFunction,'CloseRequestFcn','delete(gcf); clear global H');
0155 
0156 % #####################################
0157 % MENU NEEDS WORK!!!
0158 % #####################################
0159 % Set up Menu
0160 set(handles.fig_main,'MenuBar','none');
0161 file_m = uimenu(handles.fig_main,'Label','File');
0162 uimenu(file_m,'Label','New model','Callback','global handles; close(handles.fig_main); dynasim(dsCheckSpecification([]));');%{@OpenModel,1,'file'});
0163 uimenu(file_m,'Label','Open model','Callback',@OpenModel);%{@OpenModel,1,'file'});
0164 % uimenu(file_m,'Label','Append model(s)','Callback',{@OpenModel,0,'file'});
0165 uimenu(file_m,'Label','Save model','Callback',@SaveModel);
0166 % uimenu(file_m,'Label','Upload model','Callback',@UploadModel);
0167 % uimenu(file_m,'Label','Write solve file','Callback','global CURRSPEC; write_dnsim_script(CURRSPEC);');
0168 % ws_m = uimenu(file_m,'Label','Interact');
0169 % uimenu(ws_m,'Label','Pass model (''spec'') to command window','Callback','global CURRSPEC; assignin(''base'',''spec'',CURRSPEC);');
0170 % uimenu(ws_m,'Label','Update model (''spec'') from base workspace','Callback',{@refresh,1});
0171 % uimenu(ws_m,'Label','Pass ''sim_data'' (during interactive simulation) to command window','Callback','global cfg;cfg.publish=1;');
0172 % import_m = uimenu(file_m,'Label','Import');
0173 % uimenu(import_m,'Label','XPP (wip)','Callback','not implemented yet');
0174 % export_m = uimenu(file_m,'Label','Export');
0175 % uimenu(export_m,'Label','XPP (wip)','Callback','not implemented yet');
0176 % uimenu(export_m,'Label','NEURON (wip)','Callback','not implemented yet');
0177 % uimenu(export_m,'Label','CellML (wip)','Callback','not implemented yet');
0178 uimenu(file_m,'Label','Refresh GUI','Callback','global SPEC handles; close(handles.fig_main); dynasim(SPEC);');
0179 uimenu(file_m,'Label','Exit','Callback','global handles cfg; close(handles.fig_main); clear handles cfg; warning on');
0180 % plot_m = uimenu(handles.fig_main,'Label','Plot');
0181 % uimenu(plot_m,'Label','quick plot','Callback',['global CURRSPEC; if ismember(''sim_data'',evalin(''base'',''who'')), plotv(evalin(''base'',''sim_data''),CURRSPEC,''varlabel'',sprintf(''%s'',CURRSPEC.variables.global_oldlabel{1})); else disp(''load data to plot''); end']);
0182 % uimenu(plot_m,'Label','plotpow','Callback','global CURRSPEC; if ismember(''sim_data'',evalin(''base'',''who'')), plotpow(evalin(''base'',''sim_data''),CURRSPEC,''spectrogram_flag'',0); else disp(''load data to plot''); end');
0183 % uimenu(plot_m,'Label','plotspk','Callback','global CURRSPEC; if ismember(''sim_data'',evalin(''base'',''who'')), plotspk(evalin(''base'',''sim_data''),CURRSPEC,''window_size'',30/1000,''dW'',5/1000); else disp(''load data to plot''); end');
0184 % uimenu(plot_m,'Label','visualizer','Callback','global CURRSPEC; if ismember(''sim_data'',evalin(''base'',''who'')), visualizer(evalin(''base'',''sim_data'')); else disp(''load data to plot''); end');
0185 
0186 InitializeMainGUI;
0187 
0188 %% Set up GUI Model Builder
0189 function InitializeMainGUI % (todo: called by GUI Launcher)
0190 global handles SPEC cfg
0191 
0192 % extract specification content necessary for setting up app controls
0193 pop_names={SPEC.populations.name};
0194 active_model_component=SPEC.populations(1).name;
0195 active_mechanism_list=SPEC.populations(1).mechanism_list;
0196 if isfield(SPEC.populations(1).mechanisms,'equations')
0197   active_mechanism_text=SPEC.populations(1).mechanisms(1).equations;
0198 else
0199   active_mechanism_text='';
0200 end
0201 active_mechanism_userdata=[];
0202 
0203 bgcolor=cfg.BackgroundColor;
0204 % % open figure for model designer
0205 % figure_position=[50 80 1800 900]; % 50% aspect ratio
0206 % figure_position=[245 145 1460 770]; % compact
0207 % handles.fig_main = figure('position',figure_position,'color',bgcolor,'tag','designer','name','DynaSim Model Builder','NumberTitle','off','WindowScrollWheelFcn',@ZoomFunction,'CloseRequestFcn','delete(gcf); clear global H');
0208 
0209 % ####################################################################
0210 % Views: right panel
0211 handles.pview=uipanel('parent',handles.fig_main,'title','','visible','on','units','normalized','position',[.5 0 .5 1]);
0212 % Simulation View
0213 handles.bsimview=uicontrol('parent',handles.pview,'style','pushbutton','tag','viewtab','units','normalized','position',[0 .95 .5 .05],'string','Simulation View','fontsize',11,'FontWeight','bold','backgroundcolor',[.7 .7 .7],'callback','set(findobj(''tag'',''viewtoggle''),''visible'',''off''); set(findobj(''tag'',''viewtab''),''backgroundcolor'',[1 1 1]); set(findobj(''userdata'',''handles.psimview''),''visible'',''on''); set(gcbo,''backgroundcolor'',[.7 .7 .7]);');
0214 handles.psimview=uipanel('parent',handles.pview,'backgroundcolor','w','title','','visible','on','tag','viewtoggle','userdata','handles.psimview','units','normalized','position',[0 0 1 .95]);
0215 % Equation View
0216 handles.beqnview=uicontrol('parent',handles.pview,'style','pushbutton','tag','viewtab','units','normalized','position',[.5 .95 .5 .05],'string','Equation View','fontsize',11,'FontWeight','bold','backgroundcolor',[1 1 1],'callback','set(findobj(''tag'',''viewtoggle''),''visible'',''off''); set(findobj(''tag'',''viewtab''),''backgroundcolor'',[1 1 1]); set(findobj(''userdata'',''handles.peqnview''),''visible'',''on''); set(gcbo,''backgroundcolor'',[.7 .7 .7]);');
0217 handles.peqnview=uipanel('parent',handles.pview,'backgroundcolor',[.9 .9 .9],'title','','visible','off','tag','viewtoggle','userdata','handles.peqnview','units','normalized','position',[0 0 1 .95]);
0218 handles.txt_model = uicontrol('parent',handles.peqnview,'style','edit','units','normalized','tag','modeltext','position',[0 0 1 1],'string',cfg.model_text,'ForegroundColor','k','FontName',cfg.ModelFontName,'FontSize',9,'HorizontalAlignment','Left','Max',100,'BackgroundColor',[.95 .95 .95]);
0219 % % enable horizontal scrolling
0220 %   jEdit = findjobj(txt_model);
0221 %   try
0222 %     jEditbox = jEdit.getViewport().getComponent(0);
0223 %     jEditbox.setWrapping(false);                % turn off word-wrapping
0224 %     jEditbox.setEditable(false);                % non-editable
0225 %     set(jEdit,'HorizontalScrollBarPolicy',30);  % HORIZONTAL_SCROLLBAR_AS_NEEDED
0226 %     % maintain horizontal scrollbar policy which reverts back on component resize
0227 %     hjEdit = handle(jEdit,'CallbackProperties');
0228 %     set(hjEdit, 'ComponentResizedCallback','set(gcbo,''HorizontalScrollBarPolicy'',30)')
0229 %   end
0230 
0231 % ####################################################################
0232 % set up global controls (i.e., always present in main figure in all views)
0233 uicontrol('parent',handles.fig_main,'style','text','string','DynaSim Model Designer','fontsize',16,'units','normalized','position',[0 .95 .25 .04],'backgroundcolor',bgcolor,'FontWeight','bold','ForegroundColor',[0 0 0]);
0234 uicontrol('parent',handles.fig_main,'style','pushbutton','units','normalized','position',[.35 .95 .15 .05],'string','SAVE MODEL','backgroundcolor',cfg.ButtonColor,'ForegroundColor',cfg.ButtonFontColor,'ForegroundColor',cfg.ButtonFontColor,'FontWeight','bold','callback',@SaveModel,'FontSize',14);
0235 uicontrol('parent',handles.fig_main,'style','pushbutton','units','normalized','position',[.3 .97 .04 .03],'string','undo','backgroundcolor',cfg.ButtonColor,'ForegroundColor',cfg.ButtonFontColor,'FontWeight','bold','callback',@undo,'visible','on');
0236 bhistory=uicontrol('parent',handles.fig_main,'style','pushbutton','units','normalized','position',[0 .01 .1 .03],'string','View history','backgroundcolor',cfg.ButtonColor,'ForegroundColor',cfg.ButtonFontColor,'FontWeight','bold','callback',[],'Enable','off');
0237 bversion=uicontrol('parent',handles.fig_main,'style','pushbutton','units','normalized','position',[.12 .01 .08 .03],'string','+ Version','backgroundcolor',cfg.ButtonColor,'ForegroundColor',cfg.ButtonFontColor,'FontWeight','bold','callback',[],'Enable','off');
0238 bsimstudy=uicontrol('parent',handles.fig_main,'style','pushbutton','units','normalized','position',[.4 .01 .09 .03],'string','NEW SWEEP','backgroundcolor',cfg.ButtonColor,'ForegroundColor',cfg.ButtonFontColor,'FontWeight','bold','callback',[],'Enable','off');
0239 % ####################################################################
0240 
0241 % Model Designer:
0242 pcreate=uipanel('parent',handles.fig_main,'backgroundcolor',bgcolor,'title','','visible','on','units','normalized','position',[0 .05 .5 .9],'fontweight','normal');
0243 bnet=uicontrol('parent',pcreate,'style','pushbutton','tag','tab2','units','normalized','position',[.21 .65 .22 .04],'string','connections','backgroundcolor',[1 1 1],'FontWeight','bold','callback','set(findobj(''tag'',''ptoggle2''),''visible'',''off''); set(findobj(''tag'',''tab2''),''backgroundcolor'',[1 1 1]); set(findobj(''userdata'',''pnet''),''visible'',''on''); set(gcbo,''backgroundcolor'',[.7 .7 .7]);');
0244 bmech=uicontrol('parent',pcreate,'style','pushbutton','tag','tab2','units','normalized','position',[.43 .65 .22 .04],'string','mechanisms','backgroundcolor',[.7 .7 .7],'FontWeight','bold','callback','set(findobj(''tag'',''ptoggle2''),''visible'',''off''); set(findobj(''tag'',''tab2''),''backgroundcolor'',[1 1 1]); set(findobj(''userdata'',''pmech''),''visible'',''on''); set(gcbo,''backgroundcolor'',[.7 .7 .7]);');
0245 bcell=uicontrol('visible','off','parent',pcreate,'style','pushbutton','tag','tab2','units','normalized','position',[.65 .65 .22 .04],'string','parameters','backgroundcolor',[1 1 1],'FontWeight','bold','callback','set(findobj(''tag'',''ptoggle2''),''visible'',''off''); set(findobj(''tag'',''tab2''),''backgroundcolor'',[1 1 1]); set(findobj(''userdata'',''pcell''),''visible'',''on''); set(gcbo,''backgroundcolor'',[.7 .7 .7]);');
0246 pmech=uipanel('parent',pcreate,'backgroundcolor',bgcolor,'title','Mechanism Editor','visible','on','tag','ptoggle2','userdata','pmech','units','normalized','position',[0 0 1 .65],'fontweight','bold');
0247 pnet=uipanel('parent',pcreate,'backgroundcolor',bgcolor,'title','connection mechanism lists','visible','off','tag','ptoggle2','userdata','pnet','units','normalized','position',[0 0 1 .65]);
0248 pcell=uipanel('parent',pcreate,'backgroundcolor',bgcolor,'title','parameters','visible','off','tag','ptoggle2','userdata','pcell','units','normalized','position',[0 0 1 .65]);  
0249 % Model Designer: connections
0250 handles.p_pop_spec  = uipanel('parent',pcreate,'BackgroundColor',bgcolor,'Position',[0 .7 1 .29],'BorderWidth',.2,'BorderType','line'); % cell morphology
0251 handles.p_net_connect = uipanel('parent',pnet,'BackgroundColor',bgcolor,'Position',[0 .6 1 .4],'BorderWidth',.2,'BorderType','line','title','','fontweight','normal'); % cell specification
0252 p_net_kernel  = uipanel('parent',pnet,'BackgroundColor',bgcolor,'Position',[0 0 1 .6],'BorderWidth',.2,'BorderType','line','title','view and edit connectivity matrices'); % cell specification
0253 % Model Designer: population controls
0254 handles.list_pops = uicontrol('parent',handles.p_pop_spec,'units','normalized','style','listbox','position',[0 0 .2 .9],'value',1:length(pop_names),'string',pop_names,'BackgroundColor',[.9 .9 .9],'Max',5,'Min',0,'Callback',@UpdatePopSelection,'ButtonDownFcn',@RenamePopulation,'TooltipString','Right-click to edit node name','FontName',cfg.ModelFontName);
0255 % Model Designer: headers for cell info
0256 uicontrol('parent',handles.p_pop_spec,'tag','nodecontrols','BackgroundColor',bgcolor,'units','normalized','style','text','position',[0 .91 .25 .09],'string','populations','ListboxTop',0,'HorizontalAlignment','left','fontsize',10,'fontweight','bold');
0257 uicontrol('parent',handles.p_pop_spec,'tag','nodecontrols','BackgroundColor',bgcolor,'units','normalized','style','text','position',[.25 .91 .06 .09],'string','size','ListboxTop',0,'HorizontalAlignment','left','fontsize',10,'fontweight','normal');
0258 uicontrol('parent',handles.p_pop_spec,'tag','nodecontrols','BackgroundColor',bgcolor,'units','normalized','style','text','position',[.7 .91 .29 .09],'string','intrinsic mechanism lists','ListboxTop',0,'HorizontalAlignment','left','fontsize',10,'fontweight','normal');
0259 uicontrol('parent',handles.p_pop_spec,'tag','nodecontrols','BackgroundColor',bgcolor,'units','normalized','style','text','position',[.31 .91 .25 .09],'string','master equations','ListboxTop',0,'HorizontalAlignment','left','fontsize',10,'fontweight','normal');
0260 
0261 % Model Designer: Mechanism Editor
0262 % edit box with mech info
0263 handles.list_mechs = uicontrol('units','normalized','position',[0 .42 .2 .58],'parent',pmech,'BackgroundColor',[.9 .9 .9],'style','listbox','value',1,'string',active_mechanism_list,'Max',1,'Callback',@UpdateMechanismEditor,'ButtonDownFcn',@RenameMechanism,'TooltipString','Right-click to edit mechanism name','FontName',cfg.ModelFontName);
0264 handles.edit_mech_eqns = uicontrol('parent',pmech,'style','edit','units','normalized','BackgroundColor','w','callback',@UpdateMechanismEditor,'position',[.2 .42 .8 .58],'string',active_mechanism_text,'userdata',active_mechanism_userdata,'FontName',cfg.ModelFontName,'FontSize',12,'HorizontalAlignment','Left','Max',100);
0265 % mech plots associated w/ this compartment
0266 p_static_plots = uipanel('parent',pmech,'Position',[0 0 1 .4],'BackgroundColor','white','BorderWidth',.2,'BorderType','line','title','');
0267 handles.list_functions = uicontrol('units','normalized','position',[0 0 .2 .95],'parent',p_static_plots,'BackgroundColor',[.9 .9 .9],'style','listbox','value',1:5,'string',{},'Max',50,'Callback',@UpdateMechanismFunctions,'FontName',cfg.ModelFontName);
0268 handles.ax_static_plot = subplot('position',[.23 .1 .75 .78],'parent',p_static_plots,'linewidth',3,'color','w','fontsize',6); box on; 
0269 title('functions of one variable');
0270 edit_static_lims=uicontrol('Style','edit', 'Units','normalized','Position',[0.9 0.1 0.1 0.1],'backgroundcolor','w',...
0271           'String',sprintf('[%g,%g]',min(cfg.V),max(cfg.V)),'Callback',{@DrawAuxFunctions,1},'parent',p_static_plots);
0272 btn_static_autoscale=uicontrol('style','pushbutton','fontsize',10,'string','autoscale','parent',p_static_plots,'backgroundcolor',cfg.ButtonColor,'ForegroundColor',cfg.ButtonFontColor,...
0273           'Units','normalized','Position',[0.9 0 0.1 0.1],'callback',@AutoscaleMechPlot);    
0274 uicontrol('style','text','parent',p_static_plots,'Units','normalized','Position',[0.88 .12 0.02 0.075],'string','x','backgroundcolor','w');
0275 uicontrol('style','text','parent',p_static_plots,'Units','normalized','Position',[0.88 .02 0.02 0.075],'string','y','backgroundcolor','w');
0276 % set up function list for active mechanism
0277 set(handles.list_functions,'string',{});
0278 set(handles.list_functions,'value',[]);
0279 
0280 UpdatePopControls;
0281 UpdateConControls;
0282 UpdateMechanismEditor;
0283 InitializeSimView;
0284 UpdateSimView;
0285 UpdateEqnView;
0286 
0287 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
0288 function UpdatePopControls(src,evnt)
0289 % purpose: populate population controls
0290 global handles SPEC cfg
0291 c=1.5; dy=-.07*c; ht=.1;
0292 sel = get(handles.list_pops,'value');
0293 l={SPEC.populations(sel).name}; 
0294 N=[SPEC.populations(sel).size];
0295 mechs={SPEC.populations(sel).mechanism_list};
0296 for i=1:length(sel)
0297   m=mechs{i};
0298   if isempty(m)
0299     str='';
0300   else
0301     [~,str]=fileparts(m{1}); 
0302     for j=2:length(m)
0303       [~,name]=fileparts(m{j});
0304       str=[str ', ' name]; 
0305     end
0306   end
0307   if ~isempty(SPEC.populations(sel(i)).equations)
0308     if iscell(SPEC.populations(sel(i)).equations)
0309       pop_equations=[SPEC.populations(sel(i)).equations{:}];
0310     else
0311       pop_equations=SPEC.populations(sel(i)).equations;
0312     end
0313   else
0314     pop_equations='';
0315   end
0316   userdata.index=sel(i);
0317   size_callback='global SPEC LASTSPEC; LASTSPEC=SPEC; u=get(gcbo,''userdata''); SPEC.populations(u.index).size=str2num(get(gcbo,''string''));';
0318   eqn_callback='global SPEC LASTSPEC; LASTSPEC=SPEC; u=get(gcbo,''userdata''); SPEC.populations(u.index).equations=get(gcbo,''string'');';
0319   %mechlist_callback='global SPEC LASTSPEC; LASTSPEC=SPEC; u=get(gcbo,''userdata''); SPEC.populations(u.index).mechanism_list=strtrim(regexp(get(gcbo,''string''),'','',''split'',''once''));';
0320   mechlist_callback='global SPEC LASTSPEC; LASTSPEC=SPEC; u=get(gcbo,''userdata''); tmp=strtrim(regexp(get(gcbo,''string''),'','',''split'',''once'')); if isempty(tmp{1}), tmp=[]; end; SPEC.populations(u.index).mechanism_list=tmp;';  
0321   if ~isfield(handles,'btn_pop_delete') || length(handles.btn_pop_delete)<length(sel) || ~ishandle(handles.btn_pop_delete(i))
0322     handles.btn_pop_delete(i) = uicontrol('parent',handles.p_pop_spec,'units','normalized',...
0323       'style','pushbutton','fontsize',10,'string','-','callback',{@RemovePopulation,sel(i)},...
0324       'position',[.205 .8+dy*(i-1) .03 ht],'TooltipString',l{i});
0325     handles.edit_pop_size(i) = uicontrol('parent',handles.p_pop_spec,'units','normalized','userdata',userdata,...
0326       'style','edit','position',[.24 .8+dy*(i-1) .06 ht],'backgroundcolor','w','string',N(i),'FontName',cfg.ModelFontName,...
0327       'HorizontalAlignment','left','Callback',{@UpdateModel,size_callback},'TooltipString',l{i});
0328     handles.edit_pop_equations(i) = uicontrol('parent',handles.p_pop_spec,'units','normalized','userdata',userdata,...
0329       'style','edit','position',[.3 .8+dy*(i-1) .4 ht],'backgroundcolor','w','string',pop_equations,'FontName',cfg.ModelFontName,...
0330       'HorizontalAlignment','left','Callback',{@UpdateModel,eqn_callback},...
0331       'ButtonDownFcn',{@UpdateModel,eqn_callback},'fontsize',9,'TooltipString',l{i});    
0332     handles.edit_pop_mechlist(i) = uicontrol('parent',handles.p_pop_spec,'units','normalized','userdata',userdata,...
0333       'style','edit','position',[.7 .8+dy*(i-1) .26 ht],'backgroundcolor','w','string',str,'FontName',cfg.ModelFontName,...
0334       'HorizontalAlignment','left','Callback',{@UpdateModel,mechlist_callback},...
0335       'ButtonDownFcn',{@UpdateModel,mechlist_callback},'fontsize',9,'TooltipString',l{i});
0336     handles.btn_pop_copy(i) = uicontrol('parent',handles.p_pop_spec,'units','normalized',...
0337       'style','pushbutton','fontsize',10,'string','+','callback',{@AddPopulation,sel(i)},...
0338       'position',[.965 .8+dy*(i-1) .03 ht],'TooltipString',l{i});
0339   else
0340     % update properties
0341     set(handles.edit_pop_equations(i),'string',pop_equations,'visible','on','Callback',{@UpdateModel,eqn_callback},'TooltipString',l{i});
0342     set(handles.edit_pop_size(i),'string',N(i),'visible','on','Callback',{@UpdateModel,size_callback},'TooltipString',l{i});
0343     set(handles.edit_pop_mechlist(i),'string',str,'visible','on','Callback',{@UpdateModel,mechlist_callback},'TooltipString',l{i});
0344     set(handles.btn_pop_copy(i),'callback',{@AddPopulation,sel(i)},'visible','on','TooltipString',l{i});
0345     set(handles.btn_pop_delete(i),'callback',{@RemovePopulation,sel(i)},'visible','on','TooltipString',l{i});
0346   end
0347   if length(handles.btn_pop_delete)>i
0348     set(handles.edit_pop_equations(i+1:end),'visible','off');
0349     set(handles.edit_pop_size(i+1:end),'visible','off');
0350     set(handles.edit_pop_mechlist(i+1:end),'visible','off');
0351     set(handles.btn_pop_copy(i+1:end),'visible','off');
0352     set(handles.btn_pop_delete(i+1:end),'visible','off');
0353   end
0354 end
0355 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
0356 function UpdateMechanismEditor(src,evnt)
0357 % purpose: populate mechanism list and edit box controls
0358 global handles SPEC
0359 
0360 % create list of mechanisms for editor and associated userdata
0361 fields={'populations','connections'};
0362 userdata=[]; mech_names={}; cnt=1;
0363 for f=1:length(fields)
0364   object=fields{f};
0365   for i=1:length(SPEC.(object))
0366     for j=1:length(SPEC.(object)(i).mechanism_list)
0367       userdata(cnt).object_type=object;
0368       userdata(cnt).object_index=i;
0369       [~,mech_name]=fileparts(SPEC.(object)(i).mechanism_list{j});
0370       userdata(cnt).mechanism_name=mech_name;
0371       userdata(cnt).mechanism_index=j;
0372       if strcmp(object,'populations')
0373         userdata(cnt).object_name=SPEC.(object)(i).name;
0374       elseif strcmp(object,'connections')
0375         userdata(cnt).object_name=[SPEC.(object)(i).source '->' SPEC.(object)(i).target];
0376       end
0377       userdata(cnt).mechanism_list_name=sprintf('%s.%s',userdata(cnt).object_name,userdata(cnt).mechanism_name);
0378       mech_names{cnt}=userdata(cnt).mechanism_list_name;
0379       % add empty mechanism info if not found (i.e., if not defined yet, as when a new mechanism is created)
0380       if ~isfield(SPEC.(object),'mechanisms') || isempty(SPEC.(object)(i).mechanisms) || ~ismember(mech_name,{SPEC.(object)(i).mechanisms.name})
0381         SPEC.(object)(i).mechanisms(end+1).name=mech_name;
0382         SPEC.(object)(i).mechanisms(end).equations='';
0383       end
0384       cnt=cnt+1;
0385     end
0386     % sort *.mechanisms wrt *.mechanism_list:
0387     %[~,~,sort_ind]=intersect(SPEC.(object)(i).mechanism_list,{SPEC.(object)(i).mechanisms.name});
0388     %SPEC.(object)(i).mechanisms=SPEC.(object)(i).mechanisms(sort_ind);
0389   end
0390 end
0391 
0392 % callback for mechanism edit box
0393 edit_callback='global SPEC handles LASTSPEC; LASTSPEC=SPEC; u=get(handles.list_mechs,''userdata''); if ~isempty(u), u=u(get(handles.list_mechs,''value'')); eqns=get(gcbo,''string''); idx=cellfun(@isempty,regexp(eqns,'';$'')); eqns(idx)=cellfun(@(x)[x '';''],eqns(idx),''uni'',0); SPEC.(u.object_type)(u.object_index).mechanisms(u.mechanism_index).equations=[eqns{:}]; end';
0394 % callback for mechanism selection listbox
0395 % ... list_callback='';
0396 
0397 % update mech lists and selection index
0398 old_mech_index=get(handles.list_mechs,'value');
0399 old_mech_list=get(handles.list_mechs,'string');
0400 new_mech_index=old_mech_index;
0401 new_mech_list=mech_names;
0402 set(handles.list_mechs,'string',new_mech_list,'userdata',userdata);
0403 
0404 % extract mechanism details for the select mechanism
0405 if ~isempty(userdata)
0406   u=userdata(new_mech_index);
0407   if ~isempty(u)
0408     eqns=SPEC.(u.object_type)(u.object_index).mechanisms(u.mechanism_index).equations;
0409     % add line breaks
0410     eqns=strtrim(regexp(eqns,';','split'));
0411   else
0412     eqns='';
0413   end
0414   % update mechanism equations in edit box
0415   set(handles.edit_mech_eqns,'string',eqns,'Callback',{@UpdateModel,edit_callback});
0416   
0417   % update auxiliary plots of functions of one variable
0418   UpdateMechanismFunctions;
0419 else
0420   set(handles.edit_mech_eqns,'Callback',{@UpdateModel,edit_callback});
0421 end
0422 
0423 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
0424 function UpdateMechanismFunctions(src,evnt,limflag)
0425 % purpose: plot single-variable functions of select mechanism
0426 global handles cfg
0427 
0428 % get list of single-variable functions in this mechanism
0429 % all equations for the active mechanism
0430 eqns=get(handles.edit_mech_eqns,'string');
0431   % userdata=get(handles.edit_mech_eqns,'userdata');
0432   % u=userdata(get(handles.list_mechs,'value'));
0433   % eqns=SPEC.(u.object_type)(u.object_index).mechanisms(u.mechanism_index).equations;
0434 % split equations into cell array of strings listing separate equations
0435 idx=cellfun(@isempty,regexp(eqns,';$')); % lines that need semicolons
0436 eqns(idx)=cellfun(@(x)[x ';'],eqns(idx),'uni',0);
0437 eqns=[eqns{:}];
0438 eqns=regexp(eqns,';','split');
0439 eqns=eqns(cellfun(@ischar,eqns)&(~cellfun(@isempty,eqns)));
0440 
0441 % find single-variable functions
0442 idx=(~cellfun(@isempty,regexp(eqns,'^\w+\([a-zA-Z]\w*\)\s*=')));
0443 if ~any(idx)
0444   set(handles.list_functions,'string',{});
0445   set(handles.list_functions,'value',[]);  
0446   return;
0447 end
0448 functions=eqns(idx);
0449 LHS=regexp(functions,'^(\w+)\(','tokens','once');
0450 LHS=[LHS{:}];
0451 RHS=regexp(functions,'^\w+(\(.+)','tokens','once');
0452 RHS=strrep([RHS{:}],'=','');
0453 % update function list
0454 set(handles.list_functions,'string',functions);
0455 % clear axes
0456 if isfield(handles,'static_traces')
0457   axislimits=[get(handles.ax_static_plot,'xlim') get(handles.ax_static_plot,'ylim')];
0458   try delete(handles.static_traces); end
0459   handles=rmfield(handles,'static_traces'); 
0460   cla(handles.ax_static_plot);
0461 else
0462   axislimits='tight';
0463 end
0464 % evaluate function handles and plot curves
0465 X=cfg.V; cnt=1;
0466 for i=1:length(LHS)
0467   try % todo: support functions with parameters and embedded functions
0468     eval(sprintf('%s=@%s;',LHS{i},RHS{i}));
0469     eval(sprintf('Y=%s(X);',LHS{i}));
0470     warning('off','MATLAB:hg:EraseModeIgnored');
0471     handles.static_traces(cnt)=line('parent',handles.ax_static_plot,'color',cfg.linecolors(max(1,mod(i,length(cfg.linecolors)))),...
0472       'LineStyle',cfg.linetype{max(1,mod(i,length(cfg.linetype)))},'xdata',X,'ydata',Y,'zdata',[]);
0473 %     handles.static_traces(cnt)=line('parent',handles.ax_static_plot,'color',cfg.linecolors(max(1,mod(i,length(cfg.linecolors)))),...
0474 %       'LineStyle',cfg.linetype{max(1,mod(i,length(cfg.linetype)))},'erase','background','xdata',X,'ydata',Y,'zdata',[]);
0475     cnt=cnt+1;
0476   end
0477 end
0478 % add legend
0479 if isfield(handles,'static_traces') && ~isempty(handles.static_traces)
0480   h=legend(handles.ax_static_plot,LHS); set(h,'fontsize',6,'location','EastOutside');
0481   if strcmp(axislimits,'tight')
0482     axes(handles.ax_static_plot); axis(axislimits);
0483   else
0484     set(handles.ax_static_plot,'xlim',axislimits(1:2),'ylim',axislimits(3:4));
0485   end
0486 end
0487 
0488 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
0489 function UpdateConControls(src,evnt)
0490 % purpose: populate connection controls
0491 global SPEC handles cfg
0492 
0493 if isempty(SPEC.connections)
0494   sources={};
0495   targets={};
0496 else
0497   sources={SPEC.connections.source};
0498   targets={SPEC.connections.target};
0499 end
0500 
0501 dx=.15; x=.13; c=1.5; dy=-.1*c; ht=.14;
0502 sel_pop_inds = get(handles.list_pops,'value');
0503 num_sel_pops = length(sel_pop_inds);
0504 pop_names={SPEC.populations(sel_pop_inds).name};
0505 
0506 for i=1:num_sel_pops % targets
0507   for j=1:num_sel_pops % sources
0508     % prepare string listing mechanisms connecting source to target
0509     mech_names = '';
0510     con_index = find(ismember(sources,pop_names{j}) & ismember(targets,pop_names{i}));
0511     if ~isempty(con_index)
0512       for k=1:length(SPEC.connections(con_index).mechanism_list)
0513         [~,mech_name]=fileparts(SPEC.connections(con_index).mechanism_list{k});
0514         mech_names = [mech_names mech_name ', '];
0515       end
0516       mech_names=mech_names(1:end-2);
0517     end
0518     % prepare control location and metadata
0519     pos = [x+dx*(i-1) .8+dy*(j-1) .9*dx ht];
0520     userdata=[];
0521     userdata.source=pop_names{j}; 
0522     userdata.target=pop_names{i};
0523     userdata.index=con_index;
0524     con_name = [userdata.source '->' userdata.target];
0525     % create/update controls
0526     arrow_right_code=8658; % 8658, 8594, 9032
0527     mechlist_callback='global SPEC LASTSPEC; LASTSPEC=SPEC; u=get(gcbo,''userdata''); if isempty(u.index),u.index=length(SPEC.connections)+1; end; SPEC.connections(u.index).mechanism_list=strtrim(regexp(get(gcbo,''string''),'','',''split'',''once'')); SPEC.connections(u.index).source=u.source; SPEC.connections(u.index).target=u.target;';
0528     if ~isfield(handles,'txt_to') || i>length(handles.txt_from) || j>length(handles.txt_to) || ~ishandle(handles.edit_con_mechlist(i,j)) || handles.edit_con_mechlist(i,j)==0
0529       if i==1 % to
0530         this=zeros(max(sel_pop_inds),1);
0531         this(sel_pop_inds)=j;
0532         handles.txt_to(j) = uicontrol('parent',handles.p_net_connect,'units','normalized',...
0533           'style','text','position',[x+dx*(j-1) .88 .11 ht],'string',[char(arrow_right_code) ' ' pop_names{j}],...
0534           'callback',{@ShowClickMechList,this,'connections'},'backgroundcolor',cfg.BackgroundColor);
0535       end
0536       if j==1 % from
0537         this=ones(1,max(sel_pop_inds));
0538         this(sel_pop_inds)=i;
0539         handles.txt_from(i) = uicontrol('parent',handles.p_net_connect,'units','normalized',...
0540           'style','text','position',[.01 .8+dy*(i-1) .11 ht],'string',[pop_names{i} ' ' char(arrow_right_code)],...
0541           'callback',{@ShowClickMechList,this,'connections'},'backgroundcolor',cfg.BackgroundColor);
0542       end
0543       handles.edit_con_mechlist(i,j) = uicontrol('parent',handles.p_net_connect,'units','normalized',...
0544         'style','edit','position',pos,'backgroundcolor','w','userdata',userdata,...
0545         'string',mech_names,'HorizontalAlignment','left','userdata',userdata);
0546         set(handles.edit_con_mechlist(i,j),'Callback',{@UpdateModel,mechlist_callback},...
0547         'ButtonDownFcn',@RenameMechanism);
0548       handles.p_conn_mechs(i,j) = uipanel('parent',handles.p_net_connect,'units','normalized',...
0549       'position',pos,'visible','off');
0550     else
0551       set(handles.txt_to(i),'string',['--> ' pop_names{i}],'visible','on');
0552       set(handles.txt_from(i),'string',[pop_names{i} ' -->'],'visible','on');
0553       set(handles.p_conn_mechs(i,j),'visible','off');
0554       set(handles.edit_con_mechlist(i,j),'string',mech_names,'userdata',userdata,'Callback',{@UpdateModel,mechlist_callback},...
0555         'ButtonDownFcn',@RenameMechanism,'visible','on');
0556     end
0557   end
0558 end
0559     
0560 if isfield(handles,'txt_to') && length(handles.txt_to)>length(sel_pop_inds)
0561   set(handles.txt_to(i+1:end),'visible','off');
0562   set(handles.txt_from(i+1:end),'visible','off');
0563   set(handles.edit_con_mechlist(i+1:end,:),'visible','off');
0564   set(handles.edit_con_mechlist(:,i+1:end),'visible','off');
0565   set(handles.p_conn_mechs(i+1:end,:),'visible','off');
0566   set(handles.p_conn_mechs(:,i+1:end),'visible','off');
0567 end    
0568 
0569 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
0570 % Update Model
0571 function UpdateModel(src,evnt,aux_callback)
0572 % Purpose: update DynaSim model after modifing the DynaSim specification
0573 % evaluate caller-specific auxiliary commands
0574 if nargin>=3
0575   eval(aux_callback);
0576 end
0577 
0578 global SPEC MODEL cfg LASTCFG handles
0579 
0580 % check for special case where full model is inserted into mechanism editor
0581 if nargin>0 && isequal(src,handles.edit_mech_eqns)
0582   if isempty(SPEC.populations(1).equations) && isempty(SPEC.populations(1).mechanisms) && isempty(SPEC.populations(1).mechanism_list)
0583     % prepare equation string
0584     eqns=get(gcbo,'string'); 
0585     if ischar(eqns)
0586       eqns=cellstr(eqns);
0587     end
0588     idx=cellfun(@isempty,regexp(eqns,';$')); 
0589     eqns(idx)=cellfun(@(x)[x ';'],eqns(idx),'uni',0);    
0590     % add default name to mechanism
0591     SPEC.populations.mechanisms.name='l';
0592     SPEC.populations.mechanisms.equations=[eqns{:}];
0593     SPEC.populations(1).mechanism_list={'l'};
0594   end
0595 end
0596 
0597 % Execute common update operations
0598 % check specification
0599 SPEC=dsCheckSpecification(SPEC);
0600 [SPEC.populations.parameters]=deal([]);
0601 if ~isempty(SPEC.connections)
0602   [SPEC.connections.parameters]=deal([]);
0603 end
0604 % generate model
0605 MODEL=dsGenerateModel(SPEC);
0606 % extract model ODEFUN and IC
0607 try
0608   [ODEFUN,IC,elem_names]=dsDynasim2odefun(dsPropagateParameters(MODEL));
0609   % txt=dsExtractModelStrings(MODEL,'model',0);
0610   % ODEFUN=txt{1}; IC=txt{2}; elem_names=txt{3};
0611 
0612   % update model config for running simulation
0613   LASTCFG=cfg;
0614   if length(IC)~=length(cfg.IC)
0615     cfg.Y=zeros(cfg.ntime,length(IC));
0616   end
0617   cfg.ODEFUN=ODEFUN;
0618   cfg.IC=IC;
0619   cfg.elem_names=elem_names;
0620 end
0621 
0622 % update views
0623 UpdateViews('model');
0624 UpdateViews('selection');
0625 UpdateMechanismEditor;
0626 
0627 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
0628 % Update GUI based on listbox selections in Model Designer
0629 function UpdatePopSelection(src,evnt)
0630 % update designer controls:
0631 UpdatePopControls;
0632 UpdateConControls;
0633 UpdateMechanismEditor;
0634 
0635 % update sim view
0636 UpdateViews('selection');
0637 
0638 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
0639 % Update Views
0640 function UpdateViews(update_what)
0641 global handles
0642 % Purpose: update equation and simulation views
0643 switch (update_what)
0644   case 'model'
0645     %if strcmp('on',get(handles.peqnview,'visible'))
0646       UpdateEqnView;
0647     %end
0648   case 'selection'
0649     if strcmp('on',get(handles.psimview,'visible'))
0650       UpdateSimView;
0651     end    
0652 end
0653 
0654 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
0655 % EQUATION VIEW
0656 function UpdateEqnView(src,evnt)
0657 global MODEL cfg handles
0658 
0659 % get equation string to display:
0660 txt=dsExtractModelStrings(MODEL,'model',0);
0661 
0662 % construct display text
0663 txt{end+1}='';
0664 txt{end+1}='% ##############################################################';
0665 txt{end+1}='% Prepare ODEFUN for use with built-in Matlab solvers:';
0666 txt{end+1}='% ##############################################################';
0667 txt{end+1}=sprintf('ODEFUN = %s;',char(cfg.ODEFUN));
0668 txt{end+1}=sprintf('IC = [%s];',num2str(cfg.IC'));
0669 legs={}; 
0670 for i=1:length(cfg.elem_names), legs{end+1}=['''' cfg.elem_names{i} ''',']; end
0671 legs=[legs{:}];
0672 txt{end+1}=sprintf('elem_names = {%s};',legs(1:end-1));
0673 txt{end+1}='';
0674 txt{end+1}='% Solve system using built-in Matlab solver:';
0675 txt{end+1}='options=odeset(''RelTol'',1e-2,''AbsTol'',1e-4,''InitialStep'',.01);';
0676 txt{end+1}='[t,y]=ode23(ODEFUN,[0 100],IC,options);';
0677 txt{end+1}='figure; plot(t,y);';
0678 txt{end+1}=sprintf('legend(%s,''Location'',''EastOutside'');',strrep(legs(1:end-1),'_','\_'));
0679 cfg.model_text=txt;
0680 % update equation view
0681 set(handles.txt_model,'string',cfg.model_text);
0682 
0683 % todo: append other display mode options ('specification','xpp')
0684 
0685 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
0686 % SIMULATION VIEW
0687 function InitializeSimView(src,evnt)
0688 global handles cfg
0689 
0690 % initialize for max_num_plots rows (with 'visible','off'):
0691 % panel 'p_sim_plots'
0692 % - list_vars
0693 % - list_cells
0694 % - axes_data_trace
0695 % - axes_data_image
0696 % - axes_data_hist
0697 % - edit_ymax
0698 % - edit_ymin
0699 
0700 % initialize simulation controls:
0701 % - QuickSim (panel 'p_quicksim_settings'): button and edit boxes for t0,tf
0702 % - Running sims (panel 'p_runsim_settings'):
0703 %   - run control buttons (Start, Reset)
0704 %   - edit boxes for numerics (dt, ntime)
0705 %   - ylim maxmin buttons (by_pop, across_pops)
0706 
0707 % plot options
0708 dy=-1/cfg.max_num_plots;
0709 yp=1-1/cfg.max_num_plots+.04; % .7
0710 default_visible='on';
0711 
0712 % Create panels (parent: psimview):
0713 % p_sim_plots
0714 handles.p_sim_plots=uipanel('parent',handles.psimview,'units','normalized','position',[0 .15 1 .85],'backgroundcolor','w','title','','visible','on');
0715 % p_quicksim_settings
0716 handles.p_quicksim_settings=uipanel('parent',handles.psimview,'units','normalized','position',[0 0 .25 .15],'backgroundcolor','w','title','','visible','on');
0717 % p_runsim_settings
0718 handles.p_runsim_settings=uipanel('parent',handles.psimview,'units','normalized','position',[.25 0 .75 .15],'backgroundcolor','w','title','','visible','on');
0719 
0720 % Create controls for interactive plotting (parent: p_sim_plots)
0721 for i=1:cfg.max_num_plots
0722   % list_vars: listbox for pop-specific variables
0723   handles.list_vars(i)=uicontrol('units','normalized','position',[.01 yp+(i-1)*dy .14 -.8*dy],'parent',handles.p_sim_plots,'BackgroundColor',[.9 .9 .9],'style','listbox','value',1,'string',[],'Max',100,'Callback',@UpdateSimView,'TooltipString','Left-click to select variable to plot','visible',default_visible);
0724   % list_cells: listbox for pop-specific cell indices
0725   handles.list_cells(i)=uicontrol('units','normalized','position',[.15 yp+(i-1)*dy .05 -.8*dy],'parent',handles.p_sim_plots,'BackgroundColor',[.9 .9 .9],'style','listbox','value',[],'string',[],'Max',1000,'Callback',@UpdateSimView,'TooltipString','Left-click to select cells to plot','visible',default_visible);
0726   % axes_data_image: axis for plotting images
0727   handles.axes_data_image(i)=subplot('position',[.23 yp+(i-1)*dy .72 -.8*dy],'parent',handles.p_sim_plots,'visible','off','tag','simview_image');
0728   handles.img_data(i) = imagesc(cfg.t,1:length(cfg.IC),cfg.Y); axis xy; %colorbar
0729   set(handles.img_data(i),'visible','off','tag','simview_image');
0730   % axes_data_trace: axis for plotting traces
0731   handles.axes_data_trace(i)=subplot('position',[.23 yp+(i-1)*dy .72 -.8*dy],'xdata',cfg.t,'ydata',cfg.Y(:,1),'parent',handles.p_sim_plots,'linewidth',3,'color','w','visible',default_visible,'tag','simview_trace'); 
0732   % edit_ymax: max y-limits
0733   callback=sprintf('global handles; set(handles.axes_data_trace(%g),''ylim'',[str2double(get(handles.edit_ymin(%g),''string'')) str2double(get(gco,''string''))]); set(handles.axes_data_image(%g),''clim'',[str2double(get(handles.edit_ymin(%g),''string'')) str2double(get(gco,''string''))]); cfg.ymax(%g)=str2double(get(gco,''string''));',i,i,i,i,i);
0734   handles.edit_ymax(i)=uicontrol('style','edit','parent',handles.p_sim_plots,'tag','ymax','units','normalized','position',[.955 .95+dy*(i-1)-.01 .037 .03],'backgroundcolor','w','string',cfg.ymax(i),'HorizontalAlignment','left','Callback',callback,'fontsize',8);
0735   % edit_ymin: min y-limits
0736   callback=sprintf('global handles; set(handles.axes_data_trace(%g),''ylim'',[str2double(get(gco,''string'')) str2double(get(handles.edit_ymax(%g),''string''))]); set(handles.axes_data_image(%g),''clim'',[str2double(get(gco,''string'')) str2double(get(handles.edit_ymax(%g),''string''))]); cfg.ymin(%g)=str2double(get(gco,''string''));',i,i,i,i,i);
0737   handles.edit_ymin(i)=uicontrol('style','edit','parent',handles.p_sim_plots,'tag','ymin','units','normalized','position',[.955 .95+dy*(i-1)+.8*dy+.03-.01 .037 .03],'backgroundcolor','w','string',cfg.ymin(i),'HorizontalAlignment','left','Callback',callback,'fontsize',8);
0738   handles.btn_sim_autoscale(i)=uicontrol('style','pushbutton','parent',handles.p_sim_plots,'units','normalized','position',[.96 .95+dy*(i-1)+.8*dy/2 .027 .05],'fontsize',12,'fontweight','bold','fontname','Blue Highway','String',char(cfg.autoscale_charcode),'callback',{@AutoscaleSimPlot,i},'visible',default_visible);%,'backgroundcolor',cfg.ButtonColor,'ForegroundColor',cfg.ButtonFontColor);
0739   % ref: how to display pic on button: https://www.mathworks.com/matlabcentral/newsreader/view_thread/51230
0740     % for charcode=1:10000,fprintf('%g: %s\n',charcode,char(charcode)); end
0741     % up/down arrows: 5864, 8597, 8645, 8661
0742     % arrow right: 8594, 8658, 9032
0743     % arrow left: 8592, 8656, 9031
0744     % 8592-8703: ARROWS
0745     % 991: lightning bolt
0746     % 9398: encircled "A"
0747     % 9786: smiley face
0748     % 9733: 5-point star
0749 %   pic_arrow=imread('/home/jason/code/dynasim/functions/arrow_up_down.png');
0750 %   pic_arrow=1-ind2rgb(pic_arrow,gray);
0751 %   handles.btn_sim_autoscale(i)=uicontrol('style','pushbutton','parent',handles.p_sim_plots,'units','normalized','position',[.955 .95+dy*(i-1)+.8*dy/2 .037 .08],'fontsize',12,'fontweight','bold','Cdata',pic_arrow,'callback',@QuickSim);%,'backgroundcolor',cfg.ButtonColor,'ForegroundColor',cfg.ButtonFontColor);
0752 end
0753 handles.line_data=[];
0754 % Create controls with default settings for QuickSim (parent: p_quicksim_settings)
0755 % btn_quicksim
0756 handles.btn_quicksim=uicontrol('style','pushbutton','parent',handles.p_quicksim_settings,'units','normalized','position',[.15 .55 .7 .3],'fontsize',12,'fontweight','bold','string','QuickSim','callback',@QuickSim,'backgroundcolor',cfg.ButtonColor,'ForegroundColor',cfg.ButtonFontColor);
0757 % edit_t0
0758 handles.edit_t0 = uicontrol('style','edit','parent',handles.p_quicksim_settings,'units','normalized','position',[.15 .15 .3 .3],'fontsize',12,'string','0','HorizontalAlignment','left','backgroundcolor','w','callback','global cfg; cfg.t0=str2num(get(gcbo,''string''));');
0759 uicontrol('style','text','parent',handles.p_quicksim_settings,'units','normalized','position',[.05 .1 .1 .3],'fontsize',10,'string','t0','HorizontalAlignment','center','backgroundcolor','w','callback','global cfg; cfg.dt=str2num(get(gcbo,''string''));');
0760 % edit_tf
0761 handles.edit_tf = uicontrol('style','edit','parent',handles.p_quicksim_settings,'units','normalized','position',[.55 .15 .3 .3],'fontsize',12,'string','200','HorizontalAlignment','left','backgroundcolor','w','callback','global cfg; cfg.tf=str2num(get(gcbo,''string''));');
0762 uicontrol('style','text','parent',handles.p_quicksim_settings,'units','normalized','position',[.45 .1 .1 .3],'fontsize',10,'string','tf','HorizontalAlignment','center','backgroundcolor','w','callback','global cfg; cfg.dt=str2num(get(gcbo,''string''));');
0763 handles.check_compile = uicontrol('style','checkbox','parent',handles.p_quicksim_settings,'units','normalized','position',[.15 .05 .85 .1],'string','compile','value',0,'backgroundcolor','w');
0764 
0765 % Create controls with default settings for running sims (parent: p_runsim_settings)
0766 % btn_start (string: start/pause/resume)
0767 handles.btn_start=uicontrol('style','pushbutton','parent',handles.p_runsim_settings,'units','normalized','position',[.05 .55 .15 .3],'fontsize',12,'fontweight','bold','string','Start','callback',@RunSim,'backgroundcolor',cfg.ButtonColor,'ForegroundColor',cfg.ButtonFontColor);
0768 % btn_pause
0769 handles.btn_pause=uicontrol('style','pushbutton','parent',handles.p_runsim_settings,'units','normalized','position',[.05 .55 .15 .3],'fontsize',12,'fontweight','bold','string','Pause','callback','global cfg; cfg.sim_paused=-cfg.sim_paused;','visible','off','backgroundcolor',cfg.ButtonColor,'ForegroundColor',cfg.ButtonFontColor);
0770 % btn_stop
0771 handles.btn_stop=uicontrol('style','pushbutton','parent',handles.p_runsim_settings,'units','normalized','position',[.05 .15 .15 .3],'fontsize',12,'fontweight','bold','string','Stop','callback','global cfg; cfg.sim_stopped=1; cfg.sim_paused=-1;','visible','off','backgroundcolor',cfg.ButtonColor,'ForegroundColor',cfg.ButtonFontColor);
0772 % edit_dt
0773 handles.edit_dt = uicontrol('style','edit','parent',handles.p_runsim_settings,'units','normalized','position',[.23 .55 .07 .3],'fontsize',12,'string','.01','HorizontalAlignment','left','backgroundcolor','w','callback','global cfg; cfg.dt=str2num(get(gcbo,''string''));');
0774 uicontrol('style','text','parent',handles.p_runsim_settings,'units','normalized','position',[.23 .4 .07 .15],'fontsize',10,'string','dt','HorizontalAlignment','center','backgroundcolor','w','callback','global cfg; cfg.dt=str2num(get(gcbo,''string''));');
0775 % edit_ntime
0776 handles.edit_ntime = uicontrol('style','edit','parent',handles.p_runsim_settings,'units','normalized','position',[.32 .55 .15 .3],'fontsize',12,'string','20001','HorizontalAlignment','left','backgroundcolor','w','callback','global cfg; cfg.ntime=str2num(get(gcbo,''string''));');
0777 uicontrol('style','text','parent',handles.p_runsim_settings,'units','normalized','position',[.32 .4 .15 .15],'fontsize',10,'string','# times','HorizontalAlignment','center','backgroundcolor','w','callback','global cfg; cfg.dt=str2num(get(gcbo,''string''));');
0778 % btn_auto_ylim_by_pop
0779 handles.btn_auto_ylim_by_pop=uicontrol('style','pushbutton','parent',handles.p_runsim_settings,'units','normalized','position',[.75 .55 .23 .3],'fontsize',10,'fontweight','bold','string','auto_by_pop','callback',@UpdateSimView,'visible','off','backgroundcolor',cfg.ButtonColor,'ForegroundColor',cfg.ButtonFontColor);
0780 % btn_auto_ylim_across_pops
0781 handles.btn_auto_ylim_by_pop=uicontrol('style','pushbutton','parent',handles.p_runsim_settings,'units','normalized','position',[.75 .15 .23 .3],'fontsize',10,'fontweight','bold','string','auto_all_pops','callback',@UpdateSimView,'visible','off','backgroundcolor',cfg.ButtonColor,'ForegroundColor',cfg.ButtonFontColor);
0782 % edit_max_num_plots
0783 % ...
0784 
0785 % radio buttons to select kind of plot
0786 handles.radio_plot_type=uibuttongroup('visible','off','SelectionChangeFcn',@UpdateSimView,'units','normalized','Position',[.55 .07 .15 .85],'parent',handles.p_runsim_settings,'backgroundcolor','w','title','Display');
0787 handles.radio_plot_type_trace=uicontrol('style','radiobutton','string','trace','units','normalized','pos',[.1 .6 .9 .3],'userdata','simview_trace','parent',handles.radio_plot_type,'HandleVisibility','on','backgroundcolor','w');
0788 handles.radio_plot_type_image=uicontrol('style','radiobutton','string','image','units','normalized','pos',[.1 .2 .9 .3],'userdata','simview_image','parent',handles.radio_plot_type,'HandleVisibility','on','backgroundcolor','w');
0789 set(handles.radio_plot_type,'SelectedObject',handles.radio_plot_type_trace,'Visible','on');
0790 
0791 % special plot options
0792 % handles.check_compile  = uibuttongroup('visible','off','SelectionChangeFcn',@UpdateSimView,'units','normalized','Position',[.55 .07 .15 .85],'parent',handles.p_runsim_settings,'backgroundcolor','w','title','Display');
0793 handles.check_zscore = uicontrol('style','checkbox','parent',handles.p_runsim_settings,'callback',@UpdateSimView,'units','normalized','position',[.75 .5 .2 .15],'string','zscore','value',0,'backgroundcolor','w');
0794 
0795 % autoscale simview
0796 uicontrol('style','pushbutton','parent',handles.p_runsim_settings,'units','normalized','Position',[.94 .35 .04 .3],'fontsize',12,'fontweight','bold','fontname','Blue Highway','String',char(cfg.autoscale_charcode),'callback',{@AutoscaleSimPlot,0},'visible','on');
0797 
0798 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
0799 function UpdateSimView(src,evnt)
0800 % Purpose: update Sim View controls (except plotted data)
0801 global handles cfg MODEL
0802 % update plot type
0803 if nargin>0 && isequal(src,handles.radio_plot_type)
0804   % hide all sim view plot objects
0805   Children=get(handles.radio_plot_type,'Children');
0806   for i=1:length(Children)
0807     set(findobj('tag',get(Children(i),'userdata')),'visible','off');
0808   end
0809   % show plot objects for the select type
0810   SelectedObject=get(handles.radio_plot_type,'SelectedObject');
0811   set(findobj('tag',get(SelectedObject,'userdata')),'visible','on');
0812 end
0813 % get selection info
0814 pop_names=get(handles.list_pops,'string');
0815 sel_pop_inds=get(handles.list_pops,'value');
0816 sel_pop_names=pop_names(sel_pop_inds);
0817 num_plots=min(length(sel_pop_inds),cfg.max_num_plots);
0818 all_state_vars=MODEL.state_variables;
0819 if ~isempty(MODEL.monitors)
0820   all_state_vars=cat(2,all_state_vars,fieldnames(MODEL.monitors)');
0821 end
0822 %
0823 for plot_index=1:num_plots
0824   pop_name=sel_pop_names{plot_index};
0825   % get vars for this pop
0826   pat=['^' pop_name '_'];
0827   sel_state_vars=all_state_vars(~cellfun(@isempty,regexp(all_state_vars,pat,'once')));
0828   % get cell indices for this pop
0829   num_cells=MODEL.parameters.([pop_name '_Npop']);
0830   str_cell_inds=cellfun(@num2str,num2cell(1:num_cells),'uni',0);
0831   sel_cell_inds=1:length(str_cell_inds);
0832   % update controls
0833   set(handles.list_vars(plot_index),'string',sel_state_vars);
0834   set(handles.list_cells(plot_index),'string',str_cell_inds);
0835   val=get(handles.list_vars(plot_index),'value');
0836   if isempty(val) || max(val)>length(sel_state_vars)
0837     set(handles.list_vars(plot_index),'value',1);
0838   end
0839   val=get(handles.list_cells(plot_index),'value');
0840   if isempty(val) || max(val)>length(str_cell_inds)
0841     set(handles.list_cells(plot_index),'value',sel_cell_inds);
0842   end
0843 end
0844 % display all axes with select pops to plot
0845 for plot_index=1:num_plots
0846   switch get(get(handles.radio_plot_type,'SelectedObject'),'String')
0847     case 'trace'
0848       set(handles.axes_data_trace(plot_index),'visible','on');
0849       if size(handles.line_data,1)>=plot_index
0850         ind=handles.line_data(plot_index,:)~=0;
0851         set(handles.line_data(plot_index,ind),'visible','on');
0852       end
0853     case 'image'
0854       set(handles.axes_data_image(plot_index),'visible','on');    
0855       set(handles.img_data(plot_index),'visible','on');  
0856   end
0857   set(handles.edit_ymax(plot_index),'visible','on');
0858   set(handles.edit_ymin(plot_index),'visible','on');
0859   set(handles.list_vars(plot_index),'visible','on');
0860   set(handles.list_cells(plot_index),'visible','on');
0861   set(handles.btn_sim_autoscale(plot_index),'visible','on');
0862 end
0863 % hide all available axes without select pops to plot
0864 for plot_index=num_plots+1:cfg.max_num_plots
0865   set(handles.edit_ymax(plot_index),'visible','off');
0866   set(handles.edit_ymin(plot_index),'visible','off');
0867   set(handles.list_vars(plot_index),'visible','off');
0868   set(handles.list_cells(plot_index),'visible','off');
0869   set(handles.axes_data_trace(plot_index),'visible','off');
0870   if size(handles.line_data,1)>=plot_index
0871     ind=find(handles.line_data(plot_index,:)~=0);    
0872     set(handles.line_data(plot_index,ind),'visible','off');
0873   end
0874   set(handles.axes_data_image(plot_index),'visible','off');
0875   set(handles.img_data(plot_index),'visible','off');
0876   set(handles.btn_sim_autoscale(plot_index),'visible','off');
0877 end
0878 % update plotted data
0879 UpdateSimPlots;
0880 
0881 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
0882 function UpdateSimPlots(src,evnt)
0883 % Purpose: update plotted data (from cfg.Y given listbox selections)
0884 global handles cfg
0885 sel_pop_inds=get(handles.list_pops,'value');
0886 num_plots=min(length(sel_pop_inds),cfg.max_num_plots);
0887 % what kind of plot? (trace, image)
0888 plot_type=get(get(handles.radio_plot_type,'SelectedObject'),'String');
0889 % loop over populations to plot
0890 for plot_index=1:num_plots
0891   % select data to plot for this population
0892   plot_Y=SelectPlotData(plot_index);
0893   num_elems=size(plot_Y,2);
0894   % update plots for this population
0895   switch plot_type
0896     case 'trace'
0897       % loop over cells to update
0898       for line_index=1:num_elems
0899         % lines in handles.axes_data_trace(plot_index)
0900         if size(handles.line_data,1)>=plot_index && size(handles.line_data,2)>=line_index && ishandle(handles.line_data(plot_index,line_index)) && handles.line_data(plot_index,line_index)>0
0901           set(handles.line_data(plot_index,line_index),'ydata',plot_Y(:,line_index),'xdata',(0:cfg.ntime-1)*cfg.dt,'visible','on');
0902         else
0903           try
0904             warning('off','MATLAB:hg:EraseModeIgnored');
0905             handles.line_data(plot_index,line_index)=line('parent',handles.axes_data_trace(plot_index),'color',cfg.linecolors(max(1,mod(line_index,length(cfg.linecolors)))),'LineStyle',cfg.linetype{max(1,mod(line_index,length(cfg.linetype)))},'erase','background','xdata',(0:cfg.ntime-1)*cfg.dt,'ydata',plot_Y(:,line_index),'zdata',[],'tag','simview_trace');
0906           catch
0907             handles.line_data(plot_index,line_index)=line('parent',handles.axes_data_trace(plot_index),'color',cfg.linecolors(max(1,mod(line_index,length(cfg.linecolors)))),'LineStyle',cfg.linetype{max(1,mod(line_index,length(cfg.linetype)))},'xdata',(0:cfg.ntime-1)*cfg.dt,'ydata',plot_Y(:,line_index),'zdata',[],'tag','simview_trace');
0908           end
0909         end
0910       end
0911       ax=handles.axes_data_trace(plot_index);
0912       ylims=[cfg.ymin(plot_index) cfg.ymax(plot_index)];
0913       % hide other lines
0914       if size(handles.line_data,2)>num_elems
0915         ind=num_elems+1:size(handles.line_data,2);
0916         ind=ind(handles.line_data(plot_index,ind)~=0);
0917         set(handles.line_data(plot_index,ind),'visible','off');
0918       end
0919     case 'image'
0920       set(handles.img_data(plot_index),'cdata',plot_Y','ydata',1:num_elems,'xdata',(0:cfg.ntime-1)*cfg.dt);
0921       ax=handles.axes_data_image(plot_index);
0922       set(ax,'clim',[cfg.ymin(plot_index) cfg.ymax(plot_index)]);
0923       if num_elems>1, ylims=[.5 num_elems+.5]; else ylims=[.5 1.5]; end
0924   end
0925   % generic axis settings (todo: move to UpdateSimView?)
0926   % y-limits:
0927   if ylims(1)~=ylims(2)
0928     set(ax,'ylim',ylims);
0929   end
0930   % x-limits:
0931   set(ax,'xlim',[0 cfg.ntime*cfg.dt]);
0932   % xticks:
0933   set(handles.axes_data_trace(plot_index),'xticklabel',cfg.xticklabel,'xtick',cfg.xtick);
0934   set(handles.axes_data_image(plot_index),'xticklabel',cfg.xticklabel,'xtick',cfg.xtick);  
0935 % end
0936 end
0937 
0938 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
0939 function AutoscaleSimPlot(src,evnt,plot_index)
0940 global handles cfg
0941 
0942 % get max/min
0943 if plot_index==0
0944   % autoscale all plots based on max/min of current limits across individual plots
0945   datmax=-inf;
0946   datmin=inf;
0947   for i=1:length(handles.edit_ymin)
0948     if strcmp('on',get(handles.axes_data_trace(i),'visible'))
0949       plot_Y=SelectPlotData(i);
0950       datmax=max(datmax,max(plot_Y(:)));
0951       datmin=min(datmin,min(plot_Y(:)));
0952     end
0953   end
0954   plot_index=1:length(handles.edit_ymin);
0955   %datmax=max(str2double(get(handles.edit_ymin,'string')));
0956   %datmin=min(str2double(get(handles.edit_ymax,'string')));
0957 else
0958   % autoscale individual plot based on max/min of current data in the plot
0959   plot_Y=SelectPlotData(plot_index);
0960   datmax=max(plot_Y(:));
0961   datmin=min(plot_Y(:));  
0962 end
0963 % update plots
0964 for i=1:length(plot_index)
0965   % what kind of plot? (trace, image)
0966   switch get(get(handles.radio_plot_type,'SelectedObject'),'String')
0967     case 'trace'
0968       % if phaseplot
0969         % scale xlim and ylim
0970       % else
0971         set(handles.axes_data_trace(plot_index(i)),'ylim',[datmin datmax]);
0972       % end
0973     case 'image'
0974       set(handles.axes_data_image(plot_index(i)),'clim',[datmin datmax]);
0975   end
0976   set(handles.edit_ymin(plot_index(i)),'string',datmin);
0977   set(handles.edit_ymax(plot_index(i)),'string',datmax);
0978   cfg.ymin(plot_index(i))=datmin;
0979   cfg.ymax(plot_index(i))=datmax;
0980 end
0981 
0982 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
0983 function AutoscaleMechPlot(src,evnt)
0984 global handles
0985 ymin=inf;
0986 ymax=-inf;
0987 if isfield(handles,'static_traces')
0988   for i=1:length(handles.static_traces)
0989     ymin=min(ymin,min(get(handles.static_traces(i),'ydata')));
0990     ymax=max(ymax,max(get(handles.static_traces(i),'ydata')));
0991   end
0992   set(handles.ax_static_plot,'ylim',[ymin ymax]);
0993 end
0994 
0995 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
0996 function ZoomFunction(src,evnt)
0997 global handles cfg
0998 % get info on caller plot
0999 if ismember(gco,handles.axes_data_trace)
1000   plot_index=find(gco==handles.axes_data_trace);
1001   hplot=handles.axes_data_trace(plot_index);
1002   LIM=[cfg.ymin(plot_index) cfg.ymax(plot_index)];
1003   property='ylim';
1004 elseif ismember(gco,handles.img_data)
1005   disp('asdf')
1006   plot_index=find(gco==handles.img_data);
1007   hplot=handles.axes_data_image(plot_index);
1008   LIM=[cfg.ymin(plot_index) cfg.ymax(plot_index)];
1009   property='clim';
1010 elseif isequal(gco,handles.ax_static_plot)
1011   hplot=handles.ax_static_plot;
1012   LIM=get(hplot,'ylim');
1013   property='ylim';
1014 else 
1015   LIM=[];
1016 end
1017 % get new limits
1018 if isempty(LIM) || LIM(1)>=LIM(2) || any(isnan(LIM)) || any(isinf(LIM)), return; end
1019 if evnt.VerticalScrollCount < 0           % zoom in
1020   if LIM(1)>0, LIM(1)=LIM(1)*1.5; else LIM(1)=LIM(1)/1.5; end
1021   if LIM(2)>0, LIM(2)=LIM(2)/1.5; else LIM(1)=LIM(1)*1.5; end  
1022 else                                      % zoom out
1023   if LIM(1)>0, LIM(1)=LIM(1)/1.5; else LIM(1)=LIM(1)*1.5; end
1024   if LIM(2)>0, LIM(2)=LIM(2)*1.5; else LIM(1)=LIM(1)/1.5; end
1025 end
1026 % update plots and cfg
1027 set(hplot,property,LIM);
1028 if ismember(gco,handles.axes_data_trace) || ismember(gco,handles.img_data)
1029   set(handles.edit_ymin(plot_index),'string',LIM(1));
1030   set(handles.edit_ymax(plot_index),'string',LIM(2));
1031   cfg.ymin(plot_index)=LIM(1);
1032   cfg.ymax(plot_index)=LIM(2);
1033 end
1034 
1035 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1036 function plot_Y=SelectPlotData(plot_index)
1037 % purpose: select sim data (from cfg.Y) to plot
1038 global cfg handles
1039 % collect listbox info
1040 all_var_names=get(handles.list_vars(plot_index),'string');
1041 if ~isempty(all_var_names)
1042   sel_var_names=all_var_names(get(handles.list_vars(plot_index),'value'));
1043 else
1044   sel_var_names=all_var_names;
1045 end
1046 sel_cell_inds=get(handles.list_cells(plot_index),'value');
1047 
1048 % get list of elements for select variables in this pop
1049 vind=find(ismember(cfg.elem_names,sel_var_names));
1050 elem_names=cfg.elem_names(vind);
1051 
1052 % get indices into Y (elem_names) for select cells in this pop
1053 yind=[]; 
1054 for i=1:length(sel_var_names)
1055   cind=find(strcmp(sel_var_names{i},elem_names)); % all indices to this var
1056   if max(sel_cell_inds)>length(cind)    
1057     sel_cell_inds=sel_cell_inds(sel_cell_inds<=length(cind));
1058   end
1059   yind=[yind vind(cind(sel_cell_inds))];
1060 end
1061 plot_Y=cfg.Y(cfg.t_plot_indices,yind);
1062 sel_elem_names=cfg.elem_names(yind);
1063 
1064 % calculate zscore
1065 if get(handles.check_zscore,'value')==1
1066   uniq_elem_names=unique(sel_elem_names);
1067   for i=1:length(uniq_elem_names)
1068     idx=ismember(sel_elem_names,uniq_elem_names{i});
1069     tmp=plot_Y(:,idx);
1070     plot_Y(:,idx)=(tmp-mean(tmp(:)))/std(tmp(:));
1071   end
1072 end
1073 
1074 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1075 function RunSim(src,evnt)
1076 % Purpose: control ongoing simulation that updates cfg.Y and cfg.t
1077 global cfg handles t
1078 set(handles.btn_start,'visible','off');
1079 set(handles.btn_pause,'visible','on');
1080 set(handles.btn_stop,'visible','on');
1081 set(handles.btn_quicksim,'Enable','off');
1082 set(handles.btn_start,'Enable','off');
1083 % Initialize data for simulation
1084 % cfg.ntime=str2num(get(handles.edit_ntime,'string'));
1085 cfg.Y=nan(cfg.ntime,length(cfg.IC));
1086 cfg.Y(1,:)=cfg.IC;
1087 cfg.t=(0:cfg.ntime-1)'*cfg.dt;
1088 X=cfg.IC;
1089 t=0;
1090 t_pointer=2;
1091 cfg.xtick=linspace(cfg.t(1),cfg.t(end),cfg.num_xticks);
1092 cfg.xticklabel=linspace(cfg.t(1),cfg.t(end),cfg.num_xticks);
1093 
1094 % Run simulation
1095 while cfg.sim_stopped~=1
1096   % Pause simulation
1097   if cfg.sim_paused==1
1098     set(handles.btn_pause,'string','Resume');
1099     while cfg.sim_paused==1
1100       pause(.1);
1101       %drawnow
1102     end
1103     set(handles.btn_pause,'string','Pause');
1104   end
1105   % Integration
1106   t=t+cfg.dt;
1107   X=X+cfg.dt*cfg.ODEFUN(t,X);
1108   % store new state
1109   cfg.Y(t_pointer,:)=X;
1110   cfg.t=cfg.t+cfg.dt;
1111   % increment time index
1112   t_pointer=t_pointer+1;
1113   if t_pointer>cfg.ntime
1114     t_pointer=1;
1115   end
1116   % draw sim data
1117   if mod(t_pointer,cfg.num_steps_per_plot)==0
1118     % update indices to select chronological cfg.Y to plot
1119     if t<(cfg.ntime*cfg.dt)
1120       cfg.t_plot_indices=1:cfg.ntime;
1121     else
1122       cfg.xticklabel=cfg.xticklabel+cfg.dt*cfg.num_steps_per_plot;
1123       cfg.t_plot_indices=[t_pointer:cfg.ntime 1:t_pointer-1];
1124     end
1125     % update plots
1126     UpdateSimPlots;
1127     drawnow;
1128   end
1129 end
1130 cfg.sim_stopped=0;
1131 set(handles.btn_start,'visible','on');
1132 set(handles.btn_pause,'visible','off');
1133 set(handles.btn_stop,'visible','off');
1134 set(handles.btn_quicksim,'Enable','on');
1135 set(handles.btn_start,'Enable','on');
1136 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1137 function QuickSim(src,evnt)
1138 % purpose: quick simulation using dsSimulate, display results in GUI
1139 global DATA SPEC cfg handles MODEL
1140 set(handles.btn_quicksim,'Enable','off');
1141 set(handles.btn_start,'Enable','off');
1142 % start quick simulation
1143 % if get(handles.check_compile,'value')
1144   verbose_flag=1;
1145 % else
1146 %   verbose_flag=0;
1147 % end
1148 try
1149   DATA=dsSimulate(SPEC,'time_limits',[cfg.t0 cfg.tf],'dt',cfg.dt,'solver','euler','compile_flag',get(handles.check_compile,'value'),'verbose_flag',verbose_flag);
1150 catch
1151   set(handles.btn_quicksim,'Enable','on');
1152   set(handles.btn_start,'Enable','on');  
1153 end
1154 % convert data to GUI state for updating sim view plots
1155 cfg=data2cfg(DATA);
1156 MODEL=dsGenerateModel(SPEC);
1157 UpdateSimView;
1158 set(handles.btn_quicksim,'Enable','on');
1159 set(handles.btn_start,'Enable','on');
1160 set(handles.edit_ntime,'string',num2str(cfg.ntime));
1161 
1162 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1163 function cfg=data2cfg(data)
1164 global cfg
1165 elem_names={};
1166 Y=[]; % TODO: speed up by preallocating full data matrix
1167 for i=1:length(data.labels)
1168   Y=cat(2,Y,data.(data.labels{i}));
1169   elem_names=cat(2,elem_names,repmat(data.labels(i),[1 size(data.(data.labels{i}),2)]));
1170 end
1171 cfg.t=data.time;
1172 cfg.Y=Y;
1173 cfg.elem_names=elem_names;
1174 cfg.ntime=length(data.time);
1175 cfg.t_plot_indices=1:cfg.ntime;
1176 cfg.dt=data.simulator_options.dt;
1177 cfg.xtick=linspace(cfg.t(1),cfg.t(end),cfg.num_xticks);
1178 cfg.xticklabel=linspace(cfg.t(1),cfg.t(end),cfg.num_xticks);
1179 
1180 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1181 % function data=cfg2data(cfg)
1182 % ...
1183 % if nargin==0, global cfg; end
1184 % data.labels=unique(cfg.elem_names);
1185 
1186 % Menu Callback usage: PlotData(cfg2data,'plot_type','__');
1187 
1188 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1189 function AddPopulation(src,evnt,base_pop_index)
1190 global SPEC LASTSPEC handles
1191 LASTSPEC=SPEC;
1192 % create new population based on the one associated with the clicked "+" button
1193 SPEC.populations(end+1)=SPEC.populations(base_pop_index);
1194 % give a unique name to the new population
1195 name=sprintf('%s%g',SPEC.populations(end).name,length(SPEC.populations));
1196 SPEC.populations(end).name=name;
1197 % update population controls
1198 val = get(handles.list_pops,'value');
1199 str = get(handles.list_pops,'string');
1200 set(handles.list_pops,'value',[val length(SPEC.populations)]);
1201 set(handles.list_pops,'string',{str{:} name});
1202 % update GUI models/views
1203 UpdateModel;
1204 UpdatePopSelection;
1205 
1206 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1207 function RemovePopulation(src,evnt,base_pop_index)
1208 global SPEC LASTSPEC handles
1209 LASTSPEC=SPEC;
1210 name=SPEC.populations(base_pop_index).name;
1211 % remove population
1212 SPEC.populations(base_pop_index)=[];
1213 % remove associated connections
1214 if ~isempty(SPEC.connections)
1215   idx=ismember({SPEC.connections.source},name) | ismember({SPEC.connections.target},name);
1216   SPEC.connections(idx)=[];
1217   if isempty(SPEC.connections)
1218     SPEC.connections=[];
1219   end
1220 end
1221 % update population controls
1222 val = get(handles.list_pops,'value');
1223 str = get(handles.list_pops,'string');
1224 new_str=setdiff(str,name,'stable');
1225 new_val=find(ismember(new_str,str(val)));
1226 set(handles.list_pops,'value',new_val);
1227 set(handles.list_pops,'string',new_str);
1228 % update GUI models/views
1229 UpdateModel;
1230 UpdatePopSelection;
1231 
1232 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1233 function RenamePopulation(src,evnt)
1234 global SPEC handles
1235 val = get(handles.list_pops,'value');
1236 str = get(handles.list_pops,'string');
1237 if length(val)>1
1238   % cannot rename populations >1 are selected
1239   return;
1240 end
1241 new_name=inputdlg(['Rename Population: ' str{val}],'New name');
1242 drawnow; pause(0.05);  % this innocent line prevents the Matlab hang
1243 if isempty(new_name), return; end
1244 new_name=new_name{1};
1245 old_name=str{val};
1246 % update population name
1247 idx=ismember({SPEC.populations.name},old_name);
1248 SPEC.populations(idx).name=new_name;
1249 % update name in connections
1250 if ~isempty(SPEC.connections)
1251   idx=ismember({SPEC.connections.source},old_name);
1252   [SPEC.connections(idx).source]=deal(new_name);
1253   idx=ismember({SPEC.connections.target},old_name);
1254   [SPEC.connections(idx).target]=deal(new_name);
1255 end
1256 % update population list
1257 str{val}=new_name;
1258 set(handles.list_pops,'string',str);
1259 % update GUI models/views
1260 UpdateModel;
1261 UpdatePopSelection;
1262 
1263 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1264 function RenameMechanism(src,evnt)
1265 global SPEC handles
1266 ud=get(src,'userdata');
1267 v=get(src,'value');
1268 s=get(src,'string');
1269 if length(v)>1, return; end
1270 this=ud(v);
1271 newname=inputdlg(['Rename Mechanism: ' s{v}],'New name');
1272 drawnow; pause(0.05);  % this innocent line prevents the Matlab hang
1273 if isempty(newname), return; end
1274 newname=newname{1};
1275 
1276 % edit ().mechanisms and ().mechanism_list
1277 SPEC.(this.object_type)(this.object_index).mechanism_list{this.mechanism_index}=newname;
1278 idx=ismember({SPEC.(this.object_type)(this.object_index).mechanisms.name},this.mechanism_name);
1279 SPEC.(this.object_type)(this.object_index).mechanisms(idx).name=newname;
1280 
1281 % copy to .mechanisms
1282 if ~isfield(SPEC,'mechanisms') || isempty(SPEC.mechanisms)
1283   SPEC.mechanisms=SPEC.(this.object_type)(this.object_index).mechanisms(idx);
1284 elseif ~ismember(newname,{SPEC.mechanisms.name})
1285   SPEC.mechanisms(end+1)=SPEC.(this.object_type)(this.object_index).mechanisms(idx);
1286 end
1287   
1288 % update mech editor listbox
1289 s{v}=[this.object_name '.' newname];
1290 set(src,'string',s);
1291 
1292 % update mech editor userdata
1293 this.mechanism_name=newname;
1294 this.mechanism_list_name = [this.object_name '.' newname];
1295 ud(v)=this;
1296 set(src,'userdata',ud);
1297 
1298 % update intrinsic mechanism list
1299 m=SPEC.(this.object_type)(this.object_index).mechanism_list;
1300 [~,str]=fileparts(m{1}); 
1301 for j=2:length(m)
1302   [~,name]=fileparts(m{j});
1303   str=[str ', ' name]; 
1304 end    
1305 if strcmp(this.object_type,'populations')
1306   set(handles.edit_pop_mechlist(this.object_index),'string',str);
1307 else
1308   % get (i,j) index into con mech controls from source/target of object_index
1309   % ...
1310   
1311 end
1312 
1313 UpdateModel;
1314 
1315 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1316 function SaveModel(src,evnt)
1317 % function Save_Spec(src,evnt)
1318 [filename,pathname] = uiputfile({'*.mat;'},'Save as','model-specification.mat');
1319 if isequal(filename,0) || isequal(pathname,0)
1320   return;
1321 end
1322 outfile = fullfile(pathname,filename);
1323 [fpath,fname,fext] = fileparts(outfile);
1324 global SPEC
1325 specification=SPEC;
1326 fprintf('Saving model ''specification'': %s\n',outfile);
1327 save(outfile,'specification');
1328 
1329 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1330 function OpenModel(src,evnt)
1331 % Load and/or Append models
1332 
1333 [filename,pathname] = uigetfile({'*.mat'},'Pick a model specification file.','MultiSelect','off');
1334 
1335 if isequal(filename,0) || isequal(pathname,0), return; end
1336 if iscell(filename)
1337   datafile = cellfun(@(x)fullfile(pathname,x),filename,'uniformoutput',false);
1338   filename = filename{1};
1339 else
1340   datafile = [pathname filename];
1341 end
1342 if exist(datafile,'file')
1343   fprintf('Loading file: %s\n',datafile);
1344   try
1345     o=load(datafile); % load file
1346     fprintf('Looking for ''specification'' structure...\n');
1347     if isfield(o,'specification')
1348       fprintf('specification found.\n');
1349       global SPEC handles
1350       SPEC=o.specification;
1351       close(handles.fig_main); 
1352       dynasim(SPEC);
1353       %InitializeMainGUI;
1354       %UpdateModel;
1355     else
1356       fprintf('specification not found\n');
1357     end
1358   catch
1359     fprintf('failed to load file. check that it is a valid matlab file: %s\n',datafile);
1360     return;
1361   end
1362 end
1363 %
1364 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1365 function eqns=dsExtractModelStrings(MODEL,display_mode,display_flag)
1366 % Purpose: construct string to display DynaSim model equations:
1367 %   ODEs
1368 %   ICs
1369 %   conditionals
1370 %   functions
1371 %   fixed_variables
1372 %   parameters
1373 %   monitors
1374 %   comments
1375 %
1376 % display_mode {'model' (default),'specification','odefun','xpp'}
1377 % OPTIONS (todo: add options 2 and 3):
1378 % 1. Display resulting model equations from DynaSim model structure
1379 % 2. Display ODEFUN (function handle string for ODE system: @(X,t)...)
1380 %     tip: use fun=str2func(eqns{1}) to obtain function handle from output
1381 %          and ic=eval(eqns{2}) to obtain initial condition vector.
1382 % 3. Display script defining the DynaSim specification structure
1383 % 4. Display XPP .ode model implementation (see notes below)
1384 %
1385 % Example: display DynaSim model equations
1386 % dsExtractModelStrings(MODEL,'model',1);
1387 %
1388 % Example: display and use script defining DynaSim specification structure
1389 % eqns=dsExtractModelStrings(MODEL,'specification',1);
1390 % spec=eval(eqns); % note: equivalent to MODEL.specification
1391 %
1392 % Example: integrate system using built-in Matlab solver
1393 %   eqns=dsExtractModelStrings(MODEL,'odefun',0);
1394 %   fun=eval(eqns{1});
1395 %   ic=eqns{2};
1396 %   [t,y]=ode23(fun,[0 100],ic);
1397 %   figure; plot(t,y);
1398 
1399 if nargin<3
1400   display_flag=0;
1401 end
1402 if nargin<2 || isempty(display_mode)
1403   display_mode='model';
1404 end
1405 
1406 eqns={};
1407 switch lower(display_mode)
1408   case 'model' % Display resulting model equations from DynaSim model structure
1409     % standardize DynaSim model structure
1410     MODEL=dsCheckModel(MODEL);
1411     % ODEs and ICs:
1412     if ~isempty(MODEL.state_variables)
1413       eqns{end+1}='% DIFFERENTIAL EQUATIONS:';
1414       vars=MODEL.state_variables;
1415       for i=1:length(vars)
1416         eqns{end+1}=sprintf('%%  %s'' = %s',vars{i},MODEL.ODEs.(vars{i}));
1417       end
1418       eqns{end+1}='%';
1419       eqns{end+1}='% Initial conditions:';
1420       for i=1:length(vars)
1421         eqns{end+1}=sprintf('%%  %s(0) = %s',vars{i},MODEL.ICs.(vars{i}));
1422       end
1423       eqns{end+1}='';
1424     end
1425     % conditionals
1426     if ~isempty(MODEL.conditionals)
1427       eqns{end+1}='% CONDITIONALS:';
1428       for i=1:length(MODEL.conditionals)
1429         str=sprintf('  if(%s)then(%s)',MODEL.conditionals(i).condition,MODEL.conditionals(i).action);
1430         if ~isempty(MODEL.conditionals(i).else)
1431           str=sprintf('%selse(%s)',str,MODEL.conditionals(i).else);
1432         end
1433         eqns{end+1}=sprintf('\t%s',str);
1434       end
1435       eqns{end+1}='';
1436     end
1437     types={'parameters','fixed_variables','functions'};%,'monitors'
1438     type_headers={'% PARAMETERS:','% FIXED VARIABLES:','% FUNCTIONS:','% MONITORS:'};
1439     for p=1:length(types)
1440       type=types{p};
1441       header=type_headers{p};
1442       if ~isempty(MODEL.(type))
1443         eqns{end+1}=header;
1444         fields=fieldnames(MODEL.(type));
1445         for i=1:length(fields)
1446           val=MODEL.(type).(fields{i});
1447           if ~ischar(val)
1448             val=toString(val,'compact');
1449           end
1450           eqns{end+1}=sprintf('  %s = %s',fields{i},val);
1451         end
1452       end
1453       eqns{end+1}='';
1454     end
1455   case 'odefun' % Display ODEFUN (function handle string for ODE system: @(X,t)...)
1456     % Approach:
1457     % 1. evaluate params -> fixed_vars -> funcs
1458     % 2. evaluate ICs to get (# elems) per state var
1459     % 3. prepare state vector X
1460     % 4. replace state vars in ODEs by X
1461     % 5. combine X ODEs into ODEFUN
1462 
1463     % evaluate params -> fixed_vars -> funcs
1464     types={'parameters','fixed_variables','functions'};
1465     for p=1:length(types)
1466       type=types{p};
1467       if ~isempty(MODEL.(type))
1468         fields=fieldnames(MODEL.(type));
1469         for i=1:length(fields)
1470           val=MODEL.(type).(fields{i});
1471           if ~ischar(val)
1472             val=toString(val,'compact');
1473           end
1474           % evaluate
1475           eval(sprintf('%s = %s;',fields{i},val));
1476         end
1477       end
1478     end
1479     
1480     % evaluate ICs to get (# elems) per state var and set up generic state var X
1481     num_vars=length(MODEL.state_variables);
1482     num_elems=zeros(1,num_vars);
1483     old_vars=MODEL.state_variables;
1484     new_vars=cell(1,num_vars);
1485     new_inds=cell(1,num_vars);
1486     all_ICs=cell(1,num_vars);
1487     IC_names={};
1488     state_var_index=0;
1489     for i=1:num_vars
1490       var=MODEL.state_variables{i};
1491       % evaluate ICs to get (# elems) per state var
1492       ic=eval([MODEL.ICs.(var) ';']);
1493       num_elems(i)=length(ic);
1494       % set state var indices a variables for generic state vector X
1495       all_ICs{i}=ic;
1496       IC_names{i}=repmat({var},[1 num_elems(i)]);
1497       new_inds{i}=state_var_index+(1:length(ic));
1498       new_vars{i}=sprintf('X(%g:%g)',new_inds{i}(1),new_inds{i}(end));
1499       state_var_index=state_var_index+length(ic);
1500     end
1501 
1502     % prepare ODE system (comma-separated ODEs)
1503     ODEs=strtrim(struct2cell(MODEL.ODEs));
1504     idx=cellfun(@isempty,regexp(ODEs,';$')); % lines that need semicolons
1505     ODEs(idx)=cellfun(@(x)[x ';'],ODEs(idx),'uni',0);
1506     ODEs=[ODEs{:}]; % concatenate ODEs into a single string
1507     ODEs=strrep(ODEs,';',','); % replace semicolons by commas
1508     
1509     % substitute in generic state vector X
1510     for i=1:num_vars
1511       ODEs=dynasim_strrep(ODEs,old_vars{i},new_vars{i});
1512     end
1513 
1514     % prepare outputs (function handle string, ICs, and element names for
1515     % mapping each X(i) to a particular state variable):
1516     ODEFUN = eval(['@(t,X) [' ODEs '];']);
1517     IC=cat(2,all_ICs{:});
1518     elem_names=cat(2,IC_names{:});
1519     
1520     eqns{1}=ODEFUN;
1521     eqns{2}=IC;
1522     eqns{3}=elem_names;
1523     
1524     %{
1525       % usage:
1526     
1527       eqns=dsExtractModelStrings(MODEL,'odefun',0);
1528       ODEFUN=eqns{1};
1529       IC=eqns{2};
1530       elem_names=eqns{3};
1531     
1532       dt=.01; t=0:dt:100;
1533       y=zeros(length(t),length(IC));
1534       y(1,:)=IC;
1535       for i=2:length(t)
1536         y(i,:)=y(i-1,:)+dt*ODEFUN(t,y(i-1,:));
1537       end
1538       figure; plot(t,y); legend(elem_names{:},'Location','EastOutside');
1539 
1540       y=IC; 
1541       for i=1:1e4
1542         y=y+dt*ODEFUN(0,y);
1543       end;
1544     
1545     %}
1546     
1547   otherwise
1548     error('options ''specification'' and ''xpp'' not implemented yet.');
1549 end
1550 
1551 if display_flag
1552   cellfun(@disp,eqns);
1553 end
1554 
1555 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1556 function undo(src,evnt)
1557 global SPEC LASTSPEC cfg LASTCFG handles MODEL
1558 s=SPEC; 
1559 SPEC=LASTSPEC; 
1560 LASTSPEC=s; 
1561 c=cfg;
1562 cfg=LASTCFG;
1563 LASTCFG=c;
1564 MODEL=dsGenerateModel(SPEC);
1565 
1566 InitializeMainGUI;
1567 UpdateModel; 
1568 
1569 % close(handles.fig_main);
1570 % dynasim(SPEC);
1571 
1572 
1573 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1574 % SWEEPS
1575 % ...
1576 
1577 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1578 % function SPEC=ApplyPopulationParameters(spec)
1579 % % apply global population parameters to pop-specific mechanism equations
1580 % fields={'populations','connections'};
1581 % % update population and connection mechanism lists
1582 % for f=1:length(fields)
1583 %   object=fields{f};
1584 %   for i=1:length(spec.(object))
1585 %     for j=1:length(spec.(object)(i).mechanism_list)
1586 %       if ~isempty(spec.(object)(i).parameters)
1587 %         % approach: set key=val for all keys in eqns
1588 %         eqns=spec.(object)(i).mechanisms(j).equations;
1589 %         keys=spec.(object)(i).parameters(1:2:end);
1590 %         vals=spec.(object)(i).parameters(2:2:end);
1591 %         % get list of parameters/variables/functions in population equations
1592 %         words=unique(regexp(eqns,'[a-zA-Z]+\w*','match'));
1593 %         % find words in user-supplied parameters (keys)
1594 %         found_words=words(ismember(words,keys));
1595 %         if ~isempty(found_words)
1596 %           for ff=1:length(found_words)
1597 %             found_word=found_words{ff};
1598 %             % new parameter assignment
1599 %             precision=8; % number of digits allowed for user-supplied values
1600 %             found_value=toString(vals{strcmp(found_word,keys)},precision);
1601 %             rep=sprintf(' %s=%s;',found_word,found_value);
1602 %             % replace old parameter assignment in the middle of equations
1603 %             pat=['([^\w]{1})' found_word '\s*=\s*\w+;']; % find in the middle
1604 %             eqns=regexprep(eqns,pat,['$1' rep]);
1605 %             % replace old parameter assignment at the beginning of equations
1606 %             pat=['^' found_word '\s*=\s*\w+;']; % find at the beginning
1607 %             eqns=regexprep(eqns,pat,rep);
1608 %           end
1609 %         end
1610 %         spec.(object)(i).mechanisms(j).equations=eqns;
1611 %         % remove global population parameters: spec.(object)(#).parameters=[];
1612 %         spec.(object)(i).parameters=[];
1613 %       end
1614 %     end
1615 %   end
1616 % end

Generated on Tue 12-Dec-2017 11:32:10 by m2html © 2005