IMPORTMODEL - import model from raw equations, other program source, etc. Usage: [model,map] = dsImportModel(source,'option',value,...) Inputs: - source: [string] 1. file with model equations (DynaSim .mech or .eqns, XPP, ...) 2. string with equations 3. reference to DB model with equations - options (optional): 'namespace' : namespace to prepend to all parameter, variable, and function names 'ic_pop' : name of population with state variables defined in this model - note: connection mechanisms in target pop can have ic_pop=source 'host' : name of database hosting the model to import 'user_parameters': cell array of key/value pairs to override model parameters Output: DynaSim model structure (see dsGenerateModel) See also: dsGenerateModel, dsCheckModel Author: Jason Sherfey, PhD <jssherfey@gmail.com> Copyright (C) 2016 Jason Sherfey, Boston University, USA
0001 function [model,map] = dsImportModel(source,varargin) 0002 %IMPORTMODEL - import model from raw equations, other program source, etc. 0003 % 0004 % Usage: 0005 % [model,map] = dsImportModel(source,'option',value,...) 0006 % 0007 % Inputs: 0008 % - source: [string] 0009 % 1. file with model equations (DynaSim .mech or .eqns, XPP, ...) 0010 % 2. string with equations 0011 % 3. reference to DB model with equations 0012 % - options (optional): 0013 % 'namespace' : namespace to prepend to all parameter, variable, and function names 0014 % 'ic_pop' : name of population with state variables defined in this model 0015 % - note: connection mechanisms in target pop can have ic_pop=source 0016 % 'host' : name of database hosting the model to import 0017 % 'user_parameters': cell array of key/value pairs to override model parameters 0018 % 0019 % Output: 0020 % DynaSim model structure (see dsGenerateModel) 0021 % 0022 % See also: dsGenerateModel, dsCheckModel 0023 % 0024 % Author: Jason Sherfey, PhD <jssherfey@gmail.com> 0025 % Copyright (C) 2016 Jason Sherfey, Boston University, USA 0026 0027 % Check inputs 0028 options=dsCheckOptions(varargin,{... 0029 'host','local',[],... % database, eg: infbrain, modeldb 0030 'namespace',[],[],... % namespace, eg: E, I 0031 'ic_pop',[],[],... % eg: E, I 0032 'user_parameters',[],[],... % eg: {'Cm',1,'gNa',100} 0033 },false); 0034 0035 % ------------------------------------------------------------------ 0036 %% 1.0 Download model if not stored locally 0037 % host: 0038 % check if source string has form HOST:MODEL; update options.host 0039 tmp=regexp(source,':','split'); 0040 if numel(tmp)>1 0041 host=tmp{1}; 0042 ModelID=str2num(tmp{2}); 0043 else 0044 host='local'; 0045 end 0046 % download model if source host is known 0047 switch host 0048 case {'infbrain','infinitebrain','ib'} 0049 source=downloadModel(ModelID); 0050 end 0051 0052 % ------------------------------------------------------------------ 0053 %% 2.0 Convert to DynaSim model structure 0054 % if DynaSim .mech, .eqns, .txt: 0055 % parse model equations 0056 [model,map]=dsParseModelEquations(source,'namespace',options.namespace, varargin{:}); 0057 0058 % if DynaSim .mat: load MAT-file 0059 % ... load(source) ... 0060 0061 % if XPP .ode file: load and convert to DynaSim structure 0062 % ... xpp2dynasim() ... 0063 0064 % if NEURON .modl file: ... neuron2dynasim() ... 0065 0066 % if NeuroML: ... neuroml2dynasim() ... 0067 0068 % if Brian: ... brian2dynasim() ... 0069 0070 % ------------------------------------------------------------------ 0071 %% 3.0 Post-process model 0072 % override default parameter values by user-supplied values 0073 if ~isempty(options.user_parameters) 0074 model=set_user_parameters(model,options.user_parameters,options.namespace); % set user parameters 0075 end 0076 0077 % check initial conditions of state variables defined in this (sub-)model 0078 if ~isempty(options.ic_pop) 0079 model=add_missing_ICs(model,options.ic_pop); % add missing ICs 0080 end 0081 0082 %% 4.0 cleanup 0083 if ~strcmp(host,'local') && exist(source,'file') 0084 delete(source); 0085 end 0086 0087 % ---------------------------------- 0088 function modl=set_user_parameters(modl,params,namespace) 0089 precision=8; % number of digits allowed for user-supplied values 0090 if isempty(params) || isempty(modl.parameters) 0091 return; 0092 end 0093 % prepend namespace to user-supplied params 0094 user_keys=cellfun(@(x)[namespace '_' x],params(1:2:end),'uni',0); 0095 user_vals=params(2:2:end); 0096 0097 % check for mechanism-specific parameters 0098 if any(~cellfun(@isempty,regexp(user_keys,'\.'))) 0099 % at least one key has MECH.PARAM 0100 rem_inds=[]; % inds to user_keys not to be updated in this namespace 0101 key_inds=find(~cellfun(@isempty,regexp(user_keys,'\.'))); % indices into user_keys with . 0102 par_inds=2*key_inds-1; % indices into params for keys with . 0103 % check whether MECH is in this namespace 0104 for i=1:length(key_inds) 0105 % split params key to obtain MECH and PARAM names 0106 o=regexp(params{par_inds(i)},'\.','split'); 0107 MECH=o{1}; 0108 PARM=o{2}; 0109 % check that MECH is in namespace (pat='\_MECH$') 0110 o=regexp(namespace,['\_' MECH '$'],'once'); 0111 if ~isempty(o) 0112 % yes: set user_keys{key_inds(i)}=[namespace '_' PARAM] 0113 user_keys{key_inds(i)}=[namespace '_' PARM]; 0114 else 0115 % store key_inds(i) to remove from user_keys and user_vals 0116 rem_inds=[rem_inds key_inds(i)]; 0117 end 0118 end 0119 % exclude parameters not meant for this namespace 0120 if ~isempty(rem_inds) 0121 user_keys(rem_inds)=[]; 0122 user_vals(rem_inds)=[]; 0123 end 0124 end 0125 0126 % HACK 0127 % remove duplicate namespace from user-supplied params 0128 % for iKey = 1:length(user_keys) 0129 % locs = regexp(user_keys{iKey}, namespace, 'end'); 0130 % if length(locs) > 1 %then duplicated namespace 0131 % user_keys{iKey}(1:locs(1)+1) = []; %remove duplicate and trailing _ 0132 % end 0133 % end 0134 0135 % get list of parameters in modl 0136 param_names=fieldnames(modl.parameters); 0137 0138 % find adjusted user-supplied param names in this sub-model 0139 ind=find(ismember(user_keys,param_names)); 0140 for p=1:length(ind) 0141 if isnumeric(user_vals{ind(p)}) && size(user_vals{ind(p)},2)>1 0142 modl.parameters.(user_keys{ind(p)})=user_vals{ind(p)}; 0143 else 0144 modl.parameters.(user_keys{ind(p)})=toString(user_vals{ind(p)},precision); 0145 end 0146 end 0147 0148 % repeat for fixed_variables (e.g., connection matrix) 0149 if ~isempty(modl.fixed_variables) 0150 % get list of fixed_variables in modl 0151 fixvars_names=fieldnames(modl.fixed_variables); 0152 0153 % find adjusted user-supplied param names in this sub-model 0154 ind=find(ismember(user_keys,fixvars_names)); 0155 for p=1:length(ind) 0156 if ~ischar(user_vals{ind(p)}) 0157 modl.fixed_variables.(user_keys{ind(p)})=toString(user_vals{ind(p)},precision); 0158 else 0159 modl.fixed_variables.(user_keys{ind(p)})=user_vals{ind(p)}; 0160 end 0161 end 0162 end 0163 % ---------------------------------- 0164 function modl=add_missing_ICs(modl,popname) 0165 if isempty(modl.state_variables) 0166 return; 0167 end 0168 Npopstr=[popname '_Npop']; 0169 % add default ICs if missing (do not evaluate ICs in dsGenerateModel; do that in dsSimulate before saving params.mat) 0170 if isstruct(modl.ICs) 0171 missing_ICs=setdiff(modl.state_variables,fieldnames(modl.ICs)); 0172 else 0173 missing_ICs=modl.state_variables; 0174 end 0175 0176 % add default ICs 0177 for ic=1:length(missing_ICs) 0178 modl.ICs(1).(missing_ICs{ic})=sprintf('zeros(1,%s)',Npopstr); 0179 end 0180 0181 % convert scalar ICs to vectors of population size 0182 ICfields=fieldnames(modl.ICs); 0183 for ic=1:length(ICfields) 0184 % check if scalar (scientific notation or decimal) 0185 if ~isempty(regexp(modl.ICs.(ICfields{ic}),'^((\d+e[\-\+]?\d+)|([\d.-]+))$','once')) 0186 modl.ICs(1).(ICfields{ic})=sprintf('%s*ones(1,%s)',modl.ICs.(ICfields{ic}),Npopstr); 0187 end 0188 end 0189 0190 function source=downloadModel(ModelID) 0191 % Set path to your MySQL Connector/J JAR 0192 jarfile = '/usr/share/java/mysql-connector-java.jar'; 0193 javaaddpath(jarfile); % WARNING: this might clear global variables 0194 0195 % set connection parameters 0196 cfg.mysql_connector = 'database'; 0197 cfg.webhost = '104.131.218.171'; % 'infinitebrain.org','104.131.218.171' 0198 cfg.dbname = 'modulator'; 0199 cfg.dbuser = 'querydb'; % have all users use root to connect to DB and self to transfer files 0200 cfg.dbpassword = 'publicaccess'; % 'publicaccess' 0201 cfg.xfruser = 'publicuser'; 0202 cfg.xfrpassword = 'publicaccess'; 0203 cfg.ftp_port=21; 0204 cfg.MEDIA_PATH = '/project/infinitebrain/media'; 0205 target = pwd; % local directory for temporary files 0206 0207 % Create the database connection object 0208 jdbcString = sprintf('jdbc:mysql://%s/%s',cfg.webhost,cfg.dbname); 0209 jdbcDriver = 'com.mysql.jdbc.Driver'; 0210 dbConn = database(cfg.dbname,cfg.dbuser,cfg.dbpassword,jdbcDriver,jdbcString); 0211 0212 % list all mechanism metadata from DB 0213 %query='select id,name,level,notes,ispublished,project_id from modeldb_model where level=''mechanism'''; % and privacy='public' 0214 %data = get(fetch(exec(dbConn,query)), 'Data'); 0215 % get file info associated with this ModelID 0216 query=sprintf('select file from modeldb_modelspec where model_id=%g',ModelID); 0217 data = get(fetch(exec(dbConn,query)), 'Data'); 0218 jsonfile=data{1}; 0219 [usermedia,modelfile,ext] = fileparts2(jsonfile); % remote server media directory 0220 usermedia=fullfile(cfg.MEDIA_PATH,usermedia); 0221 modelfile=[modelfile ext];%'.json']; 0222 0223 % Open ftp connection and download mechanism file 0224 f=ftp([cfg.webhost ':' num2str(cfg.ftp_port)],cfg.xfruser,cfg.xfrpassword); 0225 pasv(f); 0226 cd(f,usermedia); 0227 mget(f,modelfile,target); 0228 0229 % parse mechanism file 0230 tempfile = fullfile(target,modelfile); 0231 source=tempfile; 0232 [model,map]=dsParseModelEquations(source, varargin{:}); 0233 % if isequal(ext,'.json') 0234 % [spec,jsonspec] = json2spec(tempfile); 0235 % spec.model_uid=ModelID; 0236 % elseif isequal(ext,'.txt') 0237 % spec = parse_mech_spec(tempfile,[]); 0238 % else 0239 % spec = []; 0240 % end 0241 % delete(tempfile); 0242 %close ftp connection 0243 close(f);