0001 function [output,modifications] = dsApplyModifications(model, modifications, varargin)
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077 if ~nargin
0078 output = localfunctions;
0079 return
0080 end
0081
0082
0083 options = dsCheckOptions(varargin,{'auto_gen_test_data_flag',0,{0,1}},false);
0084 if options.auto_gen_test_data_flag
0085 varargs = varargin;
0086 varargs{find(strcmp(varargs, 'auto_gen_test_data_flag'))+1} = 0;
0087 varargs(end+1:end+2) = {'unit_test_flag',1};
0088 argin = [{model},{modifications}, varargs];
0089 end
0090
0091
0092
0093 if isempty(modifications)
0094
0095 output = model;
0096 return;
0097 end
0098
0099
0100 if ~isfield(model,'state_variables')
0101 ismodel = 0;
0102 else
0103 ismodel = 1;
0104 end
0105
0106
0107 if ismodel
0108 specification=dsCheckSpecification(model.specification, varargin{:});
0109 else
0110 specification=dsCheckSpecification(model, varargin{:});
0111 end
0112
0113
0114 modifications = standardize_modifications(modifications,specification,varargin{:});
0115
0116 specification = modify_specification(specification,modifications,varargin{:});
0117
0118
0119
0120 if ismodel
0121 output=dsGenerateModel(specification);
0122 else
0123 output = specification;
0124 end
0125
0126
0127
0128 if options.auto_gen_test_data_flag
0129 argout = {output, modifications};
0130
0131 dsUnitSaveAutoGenTestData(argin, argout);
0132 end
0133
0134 end
0135
0136 function modifications = standardize_modifications(modifications,specification, varargin)
0137
0138
0139
0140
0141
0142
0143
0144 options = dsCheckOptions(varargin,{'auto_gen_test_data_flag',0,{0,1}},false);
0145 if options.auto_gen_test_data_flag
0146 varargs = varargin;
0147 varargs{find(strcmp(varargs, 'auto_gen_test_data_flag'))+1} = 0;
0148 varargs(end+1:end+2) = {'unit_test_flag',1};
0149 argin = [{modifications},{specification}, varargs];
0150 end
0151
0152 if isstruct(modifications)
0153
0154
0155
0156 end
0157
0158
0159 modifications=backward_compatibility(modifications);
0160
0161
0162 missing_objects=find(cellfun(@isempty,modifications(:,1)));
0163 if any(missing_objects)
0164
0165 for i=1:length(missing_objects)
0166 modifications{missing_objects(i),1}=specification.populations(1).name;
0167 end
0168 end
0169
0170
0171
0172
0173
0174 if any(~cellfun(@isempty,regexp(modifications(:,1),'^\(.*\)$'))) || ...
0175 any(~cellfun(@isempty,regexp(modifications(:,2),'^\(.*\)$')))
0176
0177
0178 modifications_={};
0179 for i=1:size(modifications,1)
0180
0181 namespaces=regexp(modifications{i,1},'[\w\.\-<>]+','match');
0182
0183
0184 variables=regexp(modifications{i,2},'[\w\.-]+','match');
0185
0186 if ischar(modifications{i,3})
0187
0188
0189 for j=1:length(namespaces)
0190 for k=1:length(variables)
0191 modifications_(end+1,1:3)={namespaces{j},variables{k},modifications{i,3}};
0192 end
0193 end
0194
0195 elseif isnumeric(modifications{i,3})
0196
0197
0198 if isscalar(modifications{i,3})
0199 modifications{i,3} = repmat(modifications{i,3},length(variables),length(namespaces));
0200 else
0201 if size(modifications{i,3},1) ~= length(variables) || size(modifications{i,3},2) ~= length(namespaces)
0202
0203 if size(modifications{i,3},1) == length(variables) && size(modifications{i,3},2) == 1
0204 modifications{i,3} = repmat(modifications{i,3},1,length(namespaces));
0205
0206 elseif size(modifications{i,3},2) == length(namespaces) && size(modifications{i,3},1) == 1
0207 modifications{i,3} = repmat(modifications{i,3},length(variables),1);
0208
0209
0210
0211 else
0212 error(['Numerical values varied over must be in array format,',...
0213 'where dimensions 1, 2, and 3 correspond to mechanisms, values, and populations varied over.'])
0214 end
0215 end
0216 end
0217
0218
0219 for j=1:length(namespaces)
0220 for k=1:length(variables)
0221 modifications_(end+1,1:3)={namespaces{j},variables{k},modifications{i,3}(k,j)};
0222 end
0223 end
0224
0225 end
0226
0227 end
0228
0229 modifications=modifications_;
0230
0231 end
0232
0233
0234 if options.auto_gen_test_data_flag
0235 argout = {modifications};
0236
0237 dsUnitSaveAutoGenTestDataLocalFn(argin, argout);
0238 end
0239
0240 end
0241
0242
0243 function spec = modify_specification(spec,mods, varargin)
0244
0245 options = dsCheckOptions(varargin,{'auto_gen_test_data_flag',0,{0,1}},false);
0246 if options.auto_gen_test_data_flag
0247 varargs = varargin;
0248 varargs{find(strcmp(varargs, 'auto_gen_test_data_flag'))+1} = 0;
0249 varargs(end+1:end+2) = {'unit_test_flag',1};
0250 argin = [{spec},{mods}, varargs];
0251 end
0252
0253 precision=8;
0254 predefined_variables={'name','size','parameters','mechanism_list','equations'};
0255 pop_names={spec.populations.name};
0256 if ~isempty(spec.connections)
0257 con_names=arrayfun(@(x)[x.source '->' x.target],spec.connections,'uni',0);
0258 else
0259 con_names=[];
0260 end
0261
0262
0263 for i=1:size(mods,1)
0264 obj=mods{i,1};
0265 fld=mods{i,2};
0266
0267 if ~ischar(obj)
0268 error('modification must be applied to population name or connection source-target');
0269 end
0270
0271 if ~ischar(fld)
0272 error('modification must be applied to population ''name'',''size'',or a parameter referenced by its name');
0273 end
0274
0275
0276 if any(strfind(obj,'<-'))
0277 ind=strfind(obj,'<-');
0278 obj=[obj(ind(1)+2:end) '->' obj(1:ind(1)-1)];
0279 end
0280
0281
0282
0283 if any(obj=='.')
0284 tmp=regexp(obj,'\.','split');
0285 obj=tmp{1};
0286 MECH=tmp{2};
0287 fld=[MECH '.' fld];
0288 end
0289
0290
0291
0292
0293
0294
0295
0296
0297
0298 val=mods{i,3};
0299 if ismember(obj,pop_names)
0300 type='populations';
0301 names=pop_names;
0302 elseif ismember(obj,con_names)
0303 type='connections';
0304 names=con_names;
0305 else
0306 warning('name of object to modify not found in populations or connections.');
0307 continue
0308 end
0309
0310 index=ismember(names,obj);
0311
0312 if strcmp(fld,'mechanism_list')
0313
0314
0315
0316
0317
0318
0319
0320 elems=regexp(val,'[\w@]+','match');
0321
0322 if strcmp(val(1),'+')
0323
0324 spec.(type)(index).mechanism_list=unique_wrapper(cat(2,spec.(type)(index).mechanism_list,elems),'stable');
0325 elseif strcmp(val(1),'-')
0326
0327 spec.(type)(index).mechanism_list=setdiff(spec.(type)(index).mechanism_list,elems,'stable');
0328 else
0329
0330 spec.(type)(index).mechanism_list=elems;
0331 end
0332 elseif strcmp(fld,'equations') && ~isempty(regexp(val,'^cat(','once'))
0333
0334 eqns=spec.(type)(index).equations;
0335 args=regexp(val,'cat\((.+)\)','tokens','once');
0336 ind=find(args{1}==',',1,'first');
0337 target=args{1}(1:ind-1);
0338 expression=args{1}(ind+1:end);
0339
0340
0341
0342
0343 if strncmp('ODE',target,3)
0344
0345
0346 lines=cellfun(@strtrim,strsplit(eqns,';'),'uni',0);
0347 lines=lines(~cellfun(@isempty,lines));
0348 pattern='^((\w+'')|(d\w+/dt))\s*=';
0349 inds=regexp(lines,pattern,'once');
0350 inds=find(~cellfun(@isempty,inds));
0351
0352 if strcmp(target,'ODE')
0353 ind=inds(1);
0354 else
0355 n=str2num(target(4:end));
0356 ind=inds(n);
0357 end
0358
0359
0360 LHS=regexp(lines{ind},'^([^=]+)=','tokens','once');
0361 target=LHS{1};
0362 elseif strncmp('FUNCTION',target,8)
0363
0364
0365 lines=cellfun(@strtrim,strsplit(eqns,';'),'uni',0);
0366 lines=lines(~cellfun(@isempty,lines));
0367 pattern='^\w+\([a-zA-Z][\w,]*\)\s*=';
0368 inds=regexp(lines,pattern,'once');
0369 inds=find(~cellfun(@isempty,inds));
0370
0371
0372 if strcmp(target,'FUNCTION')
0373 ind=inds(1);
0374 else
0375 n=str2num(target(9:end));
0376 ind=inds(n);
0377 end
0378
0379
0380 LHS=regexp(lines{ind},'^([^=]+)=','tokens','once');
0381 target=LHS{1};
0382 end
0383
0384 target=strrep(target,'(','\(');
0385 target=strrep(target,')','\)');
0386
0387
0388 old=regexp(eqns,[target '\s*=[^;]+'],'match');
0389 if ~isempty(old)
0390 eqns=strrep(eqns,old{1},[old{1} expression]);
0391 spec.(type)(index).equations=eqns;
0392 end
0393 elseif ismember(fld,predefined_variables)
0394 spec.(type)(index).(fld)=val;
0395 if strcmp(type,'populations') && strcmp(fld,'name')
0396
0397 for j=1:length(spec.connections)
0398 if strcmp(pop_names{index},spec.connections(j).source)
0399 spec.connections(j).source=val;
0400 end
0401
0402 if strcmp(pop_names{index},spec.connections(j).target)
0403 spec.connections(j).target=val;
0404 end
0405 end
0406 end
0407 else
0408 param_names=spec.(type)(index).parameters(1:2:end);
0409 if isempty(spec.(type)(index).parameters)
0410
0411 spec.(type)(index).parameters={fld,val};
0412 elseif ismember(fld,param_names)
0413
0414 val_pos=2*find(ismember(param_names,fld));
0415 spec.(type)(index).parameters{val_pos}=val;
0416 else
0417
0418 spec.(type)(index).parameters{end+1}=fld;
0419 spec.(type)(index).parameters{end+1}=val;
0420 end
0421 end
0422 end
0423
0424
0425
0426
0427 if options.auto_gen_test_data_flag
0428 argout = {spec};
0429
0430 dsUnitSaveAutoGenTestDataLocalFn(argin, argout);
0431 end
0432
0433 end
0434
0435
0436 function modifications=backward_compatibility(modifications)
0437
0438 if size(modifications,2)==2
0439 tmp={};
0440 for i=1:size(modifications,1)
0441 tmp{i,1}='';
0442 tmp{i,2}=modifications{i,1};
0443 tmp{i,3}=modifications{i,2};
0444 end
0445 modifications=tmp;
0446 end
0447
0448
0449 if size(modifications,2)==4
0450 for i=1:size(modifications,1)
0451 if strcmp(modifications{i,2},'parameters')
0452
0453 modifications{i,2}=modifications{i,3};
0454
0455
0456 modifications{i,3}=modifications{i,4};
0457 end
0458 end
0459
0460
0461 modifications=modifications(:,1:3);
0462 end
0463
0464
0465 if any(~cellfun(@isempty,regexp(modifications(:,1),'\w-\w')))
0466
0467 inds=find(~cellfun(@isempty,regexp(modifications(:,1),'\w-\w')));
0468 for i=1:length(inds)
0469 modifications{inds(i),1}=strrep(modifications{inds(i),1},'-','->');
0470 end
0471 end
0472
0473 end