function [model,map] = ImportModel(source,varargin)
% [model,map] = ImportModel(source,'option',value,...)
% Purpose: import model
% 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 GenerateModel)
%
% See also: GenerateModel, CheckModel
% Check inputs
options=CheckOptions(varargin,{...
'host','local',[],... % database, eg: infbrain, modeldb
'namespace',[],[],... % namespace, eg: E, I
'ic_pop',[],[],... % eg: E, I
'user_parameters',[],[],... % eg: {'Cm',1,'gNa',100}
},false);
% ------------------------------------------------------------------
%% 1.0 Download model if not stored locally
% host:
% check if source string has form HOST:MODEL; update options.host
tmp=regexp(source,':','split');
if numel(tmp)>1
host=tmp{1};
ModelID=str2num(tmp{2});
else
host='local';
end
% download model if source host is known
switch host
case {'infbrain','infinitebrain','ib'}
source=DownloadModel(ModelID);
end
% ------------------------------------------------------------------
%% 2.0 Convert to DynaSim model structure
% if DynaSim .mech, .eqns, .txt:
% parse model equations
[model,map]=ParseModelEquations(source,'namespace',options.namespace);
% if DynaSim .mat: load MAT-file
% ... load(source) ...
% if XPP .ode file: load and convert to DynaSim structure
% ... xpp2dynasim() ...
% if NEURON .modl file: ... neuron2dynasim() ...
% if NeuroML: ... neuroml2dynasim() ...
% if Brian: ... brian2dynasim() ...
% ------------------------------------------------------------------
%% 3.0 Post-process model
% override default parameter values by user-supplied values
if ~isempty(options.user_parameters)
model=set_user_parameters(model,options.user_parameters,options.namespace); % set user parameters
end
% check initial conditions of state variables defined in this (sub-)model
if ~isempty(options.ic_pop)
model=add_missing_ICs(model,options.ic_pop); % add missing ICs
end
%% 4.0 cleanup
if ~strcmp(host,'local') && exist(source,'file')
delete(source);
end
% ----------------------------------
function modl=set_user_parameters(modl,params,namespace)
precision=8; % number of digits allowed for user-supplied values
if isempty(params) || isempty(modl.parameters)
return;
end
% prepend namespace to user-supplied params
user_keys=cellfun(@(x)[namespace '_' x],params(1:2:end),'uni',0);
user_vals=params(2:2:end);
% get list of parameters in modl
param_names=fieldnames(modl.parameters);
% find adjusted user-supplied param names in this sub-model
ind=find(ismember(user_keys,param_names));
for p=1:length(ind)
modl.parameters.(user_keys{ind(p)})=toString(user_vals{ind(p)},precision);
end
% repeat for fixed_variables (e.g., connection matrix)
if ~isempty(modl.fixed_variables)
% get list of fixed_variables in modl
fixvars_names=fieldnames(modl.fixed_variables);
% find adjusted user-supplied param names in this sub-model
ind=find(ismember(user_keys,fixvars_names));
for p=1:length(ind)
if ~ischar(user_vals{ind(p)})
modl.fixed_variables.(user_keys{ind(p)})=toString(user_vals{ind(p)},precision);
else
modl.fixed_variables.(user_keys{ind(p)})=user_vals{ind(p)};
end
end
end
% ----------------------------------
function modl=add_missing_ICs(modl,popname)
if isempty(modl.state_variables)
return;
end
Npopstr=[popname '_Npop'];
% add default ICs if missing (do not evaluate ICs in GenerateModel; do that in SimulateModel before saving params.mat)
if isstruct(modl.ICs)
missing_ICs=setdiff(modl.state_variables,fieldnames(modl.ICs));
else
missing_ICs=modl.state_variables;
end
% add default ICs
for ic=1:length(missing_ICs)
modl.ICs.(missing_ICs{ic})=sprintf('zeros(1,%s)',Npopstr);
end
% convert scalar ICs to vectors of population size
ICfields=fieldnames(modl.ICs);
for ic=1:length(ICfields)
% check if scalar (scientific notation or decimal)
if ~isempty(regexp(modl.ICs.(ICfields{ic}),'^((\d+e[\-\+]?\d+)|([\d.-]+))$','once'))
modl.ICs.(ICfields{ic})=sprintf('%s*ones(1,%s)',modl.ICs.(ICfields{ic}),Npopstr);
end
end
function source=DownloadModel(ModelID)
% Set path to your MySQL Connector/J JAR
jarfile = '/usr/share/java/mysql-connector-java.jar';
javaaddpath(jarfile); % WARNING: this might clear global variables
% set connection parameters
cfg.mysql_connector = 'database';
cfg.webhost = '104.131.218.171'; % 'infinitebrain.org','104.131.218.171'
cfg.dbname = 'modulator';
cfg.dbuser = 'querydb'; % have all users use root to connect to DB and self to transfer files
cfg.dbpassword = 'publicaccess'; % 'publicaccess'
cfg.xfruser = 'publicuser';
cfg.xfrpassword = 'publicaccess';
cfg.ftp_port=21;
cfg.MEDIA_PATH = '/project/infinitebrain/media';
target = pwd; % local directory for temporary files
% Create the database connection object
jdbcString = sprintf('jdbc:mysql://%s/%s',cfg.webhost,cfg.dbname);
jdbcDriver = 'com.mysql.jdbc.Driver';
dbConn = database(cfg.dbname,cfg.dbuser,cfg.dbpassword,jdbcDriver,jdbcString);
% list all mechanism metadata from DB
%query='select id,name,level,notes,ispublished,project_id from modeldb_model where level=''mechanism'''; % and privacy='public'
%data = get(fetch(exec(dbConn,query)), 'Data');
% get file info associated with this ModelID
query=sprintf('select file from modeldb_modelspec where model_id=%g',ModelID);
data = get(fetch(exec(dbConn,query)), 'Data');
jsonfile=data{1};
[usermedia,modelfile,ext] = fileparts(jsonfile); % remote server media directory
usermedia=fullfile(cfg.MEDIA_PATH,usermedia);
modelfile=[modelfile ext];%'.json'];
% Open ftp connection and download mechanism file
f=ftp([cfg.webhost ':' num2str(cfg.ftp_port)],cfg.xfruser,cfg.xfrpassword);
pasv(f);
cd(f,usermedia);
mget(f,modelfile,target);
% parse mechanism file
tempfile = fullfile(target,modelfile);
source=tempfile;
[model,map]=ParseModelEquations(source);
% if isequal(ext,'.json')
% [spec,jsonspec] = json2spec(tempfile);
% spec.model_uid=ModelID;
% elseif isequal(ext,'.txt')
% spec = parse_mech_spec(tempfile,[]);
% else
% spec = [];
% end
% delete(tempfile);
%close ftp connection
close(f);