VARY2MODIFICATIONS - convert specification of things to vary into a set of modifications indicating how to vary the desired things. The returned set of modifications has one element per point in search space; each element can be passed along with DynaSim model or specification to dsApplyModifications to produce the modified object. If passed a modifications set as an input, returns the input as an output. Usage: modifications_set=dsVary2Modifications(vary) modifications_set=dsVary2Modifications(modifications_set) Inputs: - vary: {object, variable, values; ...} - modifications_set: see below Outputs: - modifications_set: {{object,variable,value1;...},{object,variable,value2;...},...} Examples: vary={'pop1','gNa',[100 120]}; mod_set=dsVary2Modifications(vary); % {{'pop1','gNa',100},{'pop1','gNa',120}} for i=1:length(mod_set) data(i)=dsSimulate('dv/dt=@current+10; {iNa,iK}','modifications',mod_set{i}); figure; plot(data(i).time,data(i).(data(i).labels{1})) end % note: the same data set can be obtained directly from dsSimulate by: data=dsSimulate('dv/dt=@current+10; {iNa,iK}','vary',vary); vary={'E','gNa',[100 120]}; vary={'E','gNa',[100 120];'E->I','gSYN',[0 1]}; vary={'E','mechanism_list','+[iNa,iK]'}; vary={'E','mechanism_list','-{iNa,iK}'}; vary={'(E,I)','gNa',[100 120]}; vary={'(E,I)','(EK1,EK2)',[-80 -60]}; vary={'(E,I)','(EK1,EK2)',[-80 -60; -85 -65]}; vary_values(:, :, 1) = [-80 -60]; vary_values(:, :, 2) = [-85 -65]; vary={'(E,I)','(EK1,EK2)',vary_values}, vary_values(:, :, 1) = [-75 -55; -80 -60]; vary_values(:, :, 2) = [-85 -65; -90 -70] vary={'(E,I)','(EK1,EK2)',vary_values}, % This sets modifications: % * E_EK1, E_EK2, I_EK1, I_EK2 = -80 % * E_EK1, E_EK2, I_EK1, I_EK2 = -60 vary={'(E,I)','(EK1,EK2)',[-80 -60]}; vary={'(E,I)','(EK1,EK2)',[-80 -60; -85 -65]}; % This sets modifications: % * E_EK1, I_EK1 = -80 and E_EK2, I_EK2 = -85 % * E_EK1, I_EK1 = -60 and E_EK2, I_EK2 = -65 mod_set=dsVary2Modifications(vary); mod_set{:} celldisp(mod_set) % Take home message: X (rows) of vary_values are individual simulations; Y (columns) are parameters. clear vary_values vary_values(:, :, 1) = [-80 -60]; vary_values(:, :, 2) = [-85 -65] vary={'(E,I)','(EK1,EK2)',vary_values}; % This sets modifications: % * E_EK1, E_EK2 = -80 and I_EK1, I_EK2 = -85 % * E_EK1, E_EK2 = -60 and I_EK1, I_EK2 = -65 mod_set=dsVary2Modifications(vary); mod_set{:} celldisp(mod_set) % Take home message: X (rows) of vary_values are individual simulations; Z (height) is populations. clear vary_values vary_values(:, :, 1) = [-75 -55; -80 -60]; vary_values(:, :, 2) = [-85 -65; -90 -70]; vary={'(E,I)','(EK1,EK2)',vary_values}; % This sets modifications: % * E_EK1 = -75, E_EK2 = -80, I_EK1 = -85, I_EK2 = -90. % * E_EK1 = -55, E_EK2 = -60, I_EK1 = -65, I_EK2 = -70. mod_set=dsVary2Modifications(vary); mod_set{:} celldisp(mod_set) % Take home message: X (rows) of vary_values are individual simulations; Y (columns) are parameters; Z (height) is populations. Notes: - valid groupings: - for namespace, variable: (), [] - for values: [],{} - groupings: [] - iterate over set; numerical row vectors allow iteration over a single set of values; 2-D arrays allow iteration over different sets of values for a set of simultaneously varied parameters; 3-D arrays allow iteration over different sets of values for a set of simultaneously varied populations. () - modify objects the same way simultaneously {} - use all combinations of one or more elements (e.g., varying mechanism_list) note: can be prepended by '+' or '-' to indicate how to vary mechanism_list - valid value types: - for parameters: numeric ([1 2 3], linspace(0,1,10), rand(1,10,3)) - for mechanisms: strings ('+[M1,M2]', '-[M1,M2]', '+{M1,M2}', '-{M1,M2}') - for connection mechanisms: indicate namespace by "source->target" - if there is only one population in the model, the object name can be set to '' or be omitted all together. (e.g., {'gNa',[100 120]}). More Examples: vary={'[E,I]','mechanism_list','{iNa,iK}'}; modifications_set = dsVary2Modifications(vary); modifications_set{:} vary={'{E,I}','mechanism_list','{iNa,iK}'}; modifications_set = dsVary2Modifications(vary); modifications_set{:} vary={'{E,I}','mechanism_list','+[iNa,iK]'; 'E','gNa',[100 120]}; modifications_set = dsVary2Modifications(vary); modifications_set{:} vary={'[E,I]','gNa',linspace(100,130,3); 'E->I','gSYN',[0 1]}; modifications_set = dsVary2Modifications(vary); modifications_set{:} vary={'(E,I)','(gNa,gK)',rand(2,5); 'E->I','gSYN',[0 1]}; modifications_set = dsVary2Modifications(vary); modifications_set{:} vary={'(E,I)','(gNa,gK)',rand(1,5,2); 'E->I','gSYN',[0 1]}; modifications_set = dsVary2Modifications(vary); modifications_set{:} vary={'(E,I)','(gNa,gK)',rand(2,5,2); 'E->I','gSYN',[0 1]}; modifications_set = dsVary2Modifications(vary); modifications_set{:} See also: dsApplyModifications, dsSimulate, dsGenerateModel Author: Jason Sherfey, PhD <jssherfey@gmail.com> Copyright (C) 2016 Jason Sherfey, Boston University, USA
0001 function modifications_set = dsVary2Modifications(vary,model) 0002 %VARY2MODIFICATIONS - convert specification of things to vary into a set of modifications indicating how to vary the desired things. 0003 % 0004 % The returned set of modifications has one element per point in search space; 0005 % each element can be passed along with DynaSim model or specification to 0006 % dsApplyModifications to produce the modified object. If passed a 0007 % modifications set as an input, returns the input as an output. 0008 % 0009 % Usage: 0010 % modifications_set=dsVary2Modifications(vary) 0011 % modifications_set=dsVary2Modifications(modifications_set) 0012 % 0013 % Inputs: 0014 % - vary: {object, variable, values; ...} 0015 % - modifications_set: see below 0016 % 0017 % Outputs: 0018 % - modifications_set: 0019 % {{object,variable,value1;...},{object,variable,value2;...},...} 0020 % 0021 % Examples: 0022 % vary={'pop1','gNa',[100 120]}; 0023 % mod_set=dsVary2Modifications(vary); % {{'pop1','gNa',100},{'pop1','gNa',120}} 0024 % for i=1:length(mod_set) 0025 % data(i)=dsSimulate('dv/dt=@current+10; {iNa,iK}','modifications',mod_set{i}); 0026 % figure; plot(data(i).time,data(i).(data(i).labels{1})) 0027 % end 0028 % % note: the same data set can be obtained directly from dsSimulate by: 0029 % data=dsSimulate('dv/dt=@current+10; {iNa,iK}','vary',vary); 0030 % 0031 % vary={'E','gNa',[100 120]}; 0032 % vary={'E','gNa',[100 120];'E->I','gSYN',[0 1]}; 0033 % vary={'E','mechanism_list','+[iNa,iK]'}; 0034 % vary={'E','mechanism_list','-{iNa,iK}'}; 0035 % vary={'(E,I)','gNa',[100 120]}; 0036 % vary={'(E,I)','(EK1,EK2)',[-80 -60]}; 0037 % vary={'(E,I)','(EK1,EK2)',[-80 -60; -85 -65]}; 0038 % 0039 % vary_values(:, :, 1) = [-80 -60]; 0040 % vary_values(:, :, 2) = [-85 -65]; 0041 % vary={'(E,I)','(EK1,EK2)',vary_values}, 0042 % 0043 % vary_values(:, :, 1) = [-75 -55; -80 -60]; 0044 % vary_values(:, :, 2) = [-85 -65; -90 -70] 0045 % vary={'(E,I)','(EK1,EK2)',vary_values}, 0046 % 0047 % % This sets modifications: 0048 % % * E_EK1, E_EK2, I_EK1, I_EK2 = -80 0049 % % * E_EK1, E_EK2, I_EK1, I_EK2 = -60 0050 % vary={'(E,I)','(EK1,EK2)',[-80 -60]}; 0051 % 0052 % 0053 % vary={'(E,I)','(EK1,EK2)',[-80 -60; -85 -65]}; 0054 % % This sets modifications: 0055 % % * E_EK1, I_EK1 = -80 and E_EK2, I_EK2 = -85 0056 % % * E_EK1, I_EK1 = -60 and E_EK2, I_EK2 = -65 0057 % mod_set=dsVary2Modifications(vary); mod_set{:} 0058 % celldisp(mod_set) 0059 % % Take home message: X (rows) of vary_values are individual simulations; Y (columns) are parameters. 0060 % 0061 % clear vary_values 0062 % vary_values(:, :, 1) = [-80 -60]; 0063 % vary_values(:, :, 2) = [-85 -65] 0064 % vary={'(E,I)','(EK1,EK2)',vary_values}; 0065 % % This sets modifications: 0066 % % * E_EK1, E_EK2 = -80 and I_EK1, I_EK2 = -85 0067 % % * E_EK1, E_EK2 = -60 and I_EK1, I_EK2 = -65 0068 % mod_set=dsVary2Modifications(vary); mod_set{:} 0069 % celldisp(mod_set) 0070 % % Take home message: X (rows) of vary_values are individual simulations; Z (height) is populations. 0071 % 0072 % 0073 % clear vary_values 0074 % vary_values(:, :, 1) = [-75 -55; -80 -60]; 0075 % vary_values(:, :, 2) = [-85 -65; -90 -70]; 0076 % vary={'(E,I)','(EK1,EK2)',vary_values}; 0077 % % This sets modifications: 0078 % % * E_EK1 = -75, E_EK2 = -80, I_EK1 = -85, I_EK2 = -90. 0079 % % * E_EK1 = -55, E_EK2 = -60, I_EK1 = -65, I_EK2 = -70. 0080 % mod_set=dsVary2Modifications(vary); mod_set{:} 0081 % celldisp(mod_set) 0082 % % Take home message: X (rows) of vary_values are individual simulations; Y (columns) are parameters; Z (height) is populations. 0083 % 0084 % Notes: 0085 % - valid groupings: 0086 % - for namespace, variable: (), [] 0087 % - for values: [],{} 0088 % 0089 % - groupings: 0090 % [] - iterate over set; numerical row vectors allow iteration over a 0091 % single set of values; 2-D arrays allow iteration over different sets 0092 % of values for a set of simultaneously varied parameters; 3-D arrays 0093 % allow iteration over different sets of values for a set of 0094 % simultaneously varied populations. 0095 % () - modify objects the same way simultaneously 0096 % {} - use all combinations of one or more elements (e.g., varying mechanism_list) 0097 % note: can be prepended by '+' or '-' to indicate how to vary mechanism_list 0098 % 0099 % - valid value types: 0100 % - for parameters: numeric ([1 2 3], linspace(0,1,10), rand(1,10,3)) 0101 % - for mechanisms: strings ('+[M1,M2]', '-[M1,M2]', '+{M1,M2}', '-{M1,M2}') 0102 % - for connection mechanisms: indicate namespace by "source->target" 0103 % 0104 % - if there is only one population in the model, the object name can be set 0105 % to '' or be omitted all together. (e.g., {'gNa',[100 120]}). 0106 % 0107 % More Examples: 0108 % vary={'[E,I]','mechanism_list','{iNa,iK}'}; 0109 % modifications_set = dsVary2Modifications(vary); 0110 % modifications_set{:} 0111 % vary={'{E,I}','mechanism_list','{iNa,iK}'}; 0112 % modifications_set = dsVary2Modifications(vary); 0113 % modifications_set{:} 0114 % vary={'{E,I}','mechanism_list','+[iNa,iK]'; 'E','gNa',[100 120]}; 0115 % modifications_set = dsVary2Modifications(vary); 0116 % modifications_set{:} 0117 % vary={'[E,I]','gNa',linspace(100,130,3); 'E->I','gSYN',[0 1]}; 0118 % modifications_set = dsVary2Modifications(vary); 0119 % modifications_set{:} 0120 % vary={'(E,I)','(gNa,gK)',rand(2,5); 'E->I','gSYN',[0 1]}; 0121 % modifications_set = dsVary2Modifications(vary); 0122 % modifications_set{:} 0123 % vary={'(E,I)','(gNa,gK)',rand(1,5,2); 'E->I','gSYN',[0 1]}; 0124 % modifications_set = dsVary2Modifications(vary); 0125 % modifications_set{:} 0126 % vary={'(E,I)','(gNa,gK)',rand(2,5,2); 'E->I','gSYN',[0 1]}; 0127 % modifications_set = dsVary2Modifications(vary); 0128 % modifications_set{:} 0129 % 0130 % See also: dsApplyModifications, dsSimulate, dsGenerateModel 0131 % 0132 % Author: Jason Sherfey, PhD <jssherfey@gmail.com> 0133 % Copyright (C) 2016 Jason Sherfey, Boston University, USA 0134 0135 % check inputs 0136 if iscell(vary) && iscell(vary{1}) 0137 % this is already a set of modifications varying things 0138 modifications_set=vary; 0139 return; 0140 end 0141 0142 if nargin<2, model=[]; end 0143 % todo: use model to get mechanism_list for special search spaces 0144 % (e.g., leave-one-out / -1). 0145 0146 % expand each 'vary' specification (namespace,variable,values) into a list of modifications 0147 modification_sets = {}; 0148 for i=1:size(vary,1) 0149 modification_sets{i}=expand_vary(vary(i,:)); 0150 %modification_sets{i}{:} 0151 end 0152 0153 % prepare cartesian product of all modification lists 0154 % get size of each set 0155 sizes=cellfun(@numel,modification_sets,'uni',0); 0156 % create matched-length vector for each set 0157 size_vectors=cellfun(@(x)1:x,sizes,'uni',0); 0158 % get indices for cartesian product of all sets 0159 cartprod=setprod(size_vectors{:}); 0160 % combine sets 0161 modifications_set={}; 0162 for i=1:size(cartprod,1) 0163 tmp={}; 0164 for j=1:length(modification_sets) 0165 tmp=cat(1,tmp,modification_sets{j}{cartprod(i,j)}); 0166 end 0167 modifications_set{i}=tmp; 0168 end 0169 0170 function list = expand_vary(specification) 0171 % purpose: get list of modifications for this specification of things to vary. 0172 % standardize specification 0173 if length(specification)==2 0174 % convert 2-element specification to 3-element with empty object name 0175 specification={'',specification{1},specification{2}}; 0176 end 0177 0178 % set default object name 0179 if isempty(specification{1}) 0180 specification{1}='pop1'; % default population 0181 end 0182 0183 % expand elements in cell arrays 0184 namespace=expand_elem(specification{1}); 0185 variable=expand_elem(specification{2}); 0186 values=expand_elem(specification{3}); 0187 0188 % combine elements into list of modifications 0189 list={}; 0190 for i=1:length(namespace) 0191 for j=1:length(variable) 0192 for k=1:length(values) 0193 list{end+1}={namespace{i},variable{j},values{k}}; 0194 end 0195 end 0196 end 0197 0198 function list = expand_elem(item) 0199 % return cell array of elements 0200 if isnumeric(item) 0201 % checking serves to remove warnings if third condition is always executed 0202 if size(item, 1) == 1 && size(item, 3) == 1 0203 list = num2cell(item); 0204 elseif size(item, 1) > 1 && size(item, 3) == 1 0205 list=mat2cell(item, size(item, 1), ones(1, size(item, 2))); 0206 elseif size(item, 3) > 1 0207 list=mat2cell(item, size(item, 1), ones(1, size(item, 2)), size(item, 3)); 0208 list=cellfun(@(x) permute(x, [1 3 2]), list, 'UniformOutput', 0); 0209 end 0210 elseif ischar(item) 0211 elems=regexp(item,'[\w->\.]+','match'); 0212 operator=regexp(item,'^([\+\-\*/^])','tokens','once'); 0213 if isempty(operator) 0214 operator=''; 0215 else 0216 operator=operator{1}; 0217 end 0218 if any(regexp(item,'^[\+-]?\[.+\]$')) 0219 % [] 0220 list=elems; 0221 % add operator back for adding/removing mechanisms from mechanism_list 0222 list=cellfun(@(x)[operator x],list,'uni',0); 0223 elseif any(regexp(item,'^[\+-]?\{.+\}$')) 0224 % {} 0225 list=getcombos(elems); 0226 for i=1:length(list) 0227 % convert to comma-separated list string 0228 tmp=cellfun(@(x)[x ','],list{i},'uni',0); 0229 tmp=[tmp{:}]; 0230 % add operator back for adding/removing mechanisms from mechanism_list 0231 % also group in () in case there are multiple mechanisms to add/remove 0232 list{i}=[operator '(' tmp(1:end-1) ')']; 0233 end 0234 else 0235 list={item}; 0236 end 0237 end 0238 0239 function list = getcombos(elems) 0240 % purpose: get list of all combinations of one or more input elements 0241 % example: 0242 % elems: {A,B,C} 0243 % list: {A,B,C,{A,B},{A,C},{B,C},{A,B,C}} 0244 list={}; 0245 n=length(elems); 0246 for i=1:n 0247 inds=nchoosek(1:n,i); % one row per set 0248 for j=1:size(inds,1) % loop over rows 0249 list{end+1}=elems(inds(j,:)); 0250 end 0251 end