Home > functions > internal > dsCheckModel.m

dsCheckModel

PURPOSE ^

CHECKMODEL - Standardize model structure and auto-populate missing fields

SYNOPSIS ^

function model = dsCheckModel(model, varargin)

DESCRIPTION ^

CHECKMODEL - Standardize model structure and auto-populate missing fields

 Usage:
   model=dsCheckModel(model)

 Input: DynaSim model structure or equations

 Output:
   - DynaSim model structure (standardized)
     model.parameters      : substructure with model parameters
     model.fixed_variables : substructure with fixed variable definitions
     model.functions       : substructure with function definitions
     model.monitors        : substructure with monitor definitions
     model.state_variables : cell array listing state variables
     model.ODEs            : substructure with one ordinary differential 
                             equation (ODE) per state variable
     model.ICs             : substructure with initial conditions (ICs) for 
                             each state variable
     model.conditionals(i) : structure array with each element indicating
                             conditional actions specified in subfields 
                             "condition","action","else" (see NOTE 1)
     model.linkers(i)      : structure array with each element indicating
                             an "expression" that should be inserted 
                             (according to "operation") into any equations 
                             where the "target" appears. (see NOTE 2)
       .target    : string giving the target where expression should be inserted
       .expression: string giving the expression to insert
       .operation : string giving the operation to use to insert expression
     model.comments{i}     : cell array of comments found in model files
     model.specification   : specification used to generate the model (see dsCheckSpecification)
     model.namespaces      : (see NOTE 3)

   - NOTE 1: "action" may include multiple statements separated by semicolons.
       "condition" must be an expression that evaluates to true or false.

   - NOTE 2: "linkers" are used only when a model contains external model files.
       Equations and state variables defined in external files can be combined with
       equations in other model files (associated with the same population) or
       population equations in the specification. Recommended practice is to begin
       targets with the '@' character.
     - Example: linking mechanism to equations in specification: TODO
     - Example: linking mechanism to equations in a different mechanism: TODO

   - NOTE 3: all variables and functions have prefixes added to them that
     indicate their namespace; a mapping from original names found in equations to
     the names appearing in the model structure is available in model.namespaces.
     - Namespaces in the model structure:
       model.parameters      .([namespace param_name])=expression
       model.fixed_variables .([namespace var_name])=expression
       model.functions       .([namespace func_name])=@(variables)expression
       model.monitors        .([namespace monitor_name])=expression
       model.state_variables = {namespace_var1,namespace_var2,...}
       model.ODEs            .([namespace state_variable])=expression
       model.ICs             .([namespace state_variable])=expression
       model.conditionals(i) .namespace,condition,action,else
       model.linkers(i)      .namespace,target,expression,operation
       model.comments{i}     string
       .specification,.namespaces

 Examples:
 - Example 1: obtain empty model structure with all fields
     model=dsCheckModel([])

 - Example 2: standardize existing model
     model=dsCheckModel(model)

 see also: dsGenerateModel, dsCheckSpecification, dsCheckData

 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 function model = dsCheckModel(model, varargin)
0002 %CHECKMODEL - Standardize model structure and auto-populate missing fields
0003 %
0004 % Usage:
0005 %   model=dsCheckModel(model)
0006 %
0007 % Input: DynaSim model structure or equations
0008 %
0009 % Output:
0010 %   - DynaSim model structure (standardized)
0011 %     model.parameters      : substructure with model parameters
0012 %     model.fixed_variables : substructure with fixed variable definitions
0013 %     model.functions       : substructure with function definitions
0014 %     model.monitors        : substructure with monitor definitions
0015 %     model.state_variables : cell array listing state variables
0016 %     model.ODEs            : substructure with one ordinary differential
0017 %                             equation (ODE) per state variable
0018 %     model.ICs             : substructure with initial conditions (ICs) for
0019 %                             each state variable
0020 %     model.conditionals(i) : structure array with each element indicating
0021 %                             conditional actions specified in subfields
0022 %                             "condition","action","else" (see NOTE 1)
0023 %     model.linkers(i)      : structure array with each element indicating
0024 %                             an "expression" that should be inserted
0025 %                             (according to "operation") into any equations
0026 %                             where the "target" appears. (see NOTE 2)
0027 %       .target    : string giving the target where expression should be inserted
0028 %       .expression: string giving the expression to insert
0029 %       .operation : string giving the operation to use to insert expression
0030 %     model.comments{i}     : cell array of comments found in model files
0031 %     model.specification   : specification used to generate the model (see dsCheckSpecification)
0032 %     model.namespaces      : (see NOTE 3)
0033 %
0034 %   - NOTE 1: "action" may include multiple statements separated by semicolons.
0035 %       "condition" must be an expression that evaluates to true or false.
0036 %
0037 %   - NOTE 2: "linkers" are used only when a model contains external model files.
0038 %       Equations and state variables defined in external files can be combined with
0039 %       equations in other model files (associated with the same population) or
0040 %       population equations in the specification. Recommended practice is to begin
0041 %       targets with the '@' character.
0042 %     - Example: linking mechanism to equations in specification: TODO
0043 %     - Example: linking mechanism to equations in a different mechanism: TODO
0044 %
0045 %   - NOTE 3: all variables and functions have prefixes added to them that
0046 %     indicate their namespace; a mapping from original names found in equations to
0047 %     the names appearing in the model structure is available in model.namespaces.
0048 %     - Namespaces in the model structure:
0049 %       model.parameters      .([namespace param_name])=expression
0050 %       model.fixed_variables .([namespace var_name])=expression
0051 %       model.functions       .([namespace func_name])=@(variables)expression
0052 %       model.monitors        .([namespace monitor_name])=expression
0053 %       model.state_variables = {namespace_var1,namespace_var2,...}
0054 %       model.ODEs            .([namespace state_variable])=expression
0055 %       model.ICs             .([namespace state_variable])=expression
0056 %       model.conditionals(i) .namespace,condition,action,else
0057 %       model.linkers(i)      .namespace,target,expression,operation
0058 %       model.comments{i}     string
0059 %       .specification,.namespaces
0060 %
0061 % Examples:
0062 % - Example 1: obtain empty model structure with all fields
0063 %     model=dsCheckModel([])
0064 %
0065 % - Example 2: standardize existing model
0066 %     model=dsCheckModel(model)
0067 %
0068 % see also: dsGenerateModel, dsCheckSpecification, dsCheckData
0069 %
0070 % Author: Jason Sherfey, PhD <jssherfey@gmail.com>
0071 % Copyright (C) 2016 Jason Sherfey, Boston University, USA
0072 
0073 %% auto_gen_test_data_flag argin
0074 options = dsCheckOptions(varargin,{'auto_gen_test_data_flag',0,{0,1}},false);
0075 if options.auto_gen_test_data_flag
0076   varargs = varargin;
0077   varargs{find(strcmp(varargs, 'auto_gen_test_data_flag'))+1} = 0;
0078   varargs(end+1:end+2) = {'unit_test_flag',1};
0079   argin = [{model}, varargs]; % specific to this function
0080 end
0081 
0082 field_order={'parameters','fixed_variables','functions','monitors',...
0083   'state_variables','ODEs','ICs','conditionals','linkers','comments',...
0084   'specification','namespaces'};
0085 field_defaults={struct(''),struct(''),struct(''),struct(''),{},struct(''),...
0086                 struct(''),struct(''),struct(''),{},struct(''),{}};
0087 
0088 if isempty(model)
0089   % prepare empty model structure
0090   for i=1:length(field_order)
0091     model.(field_order{i})=field_defaults{i};
0092   end
0093 end
0094 
0095 % % check if input is string with name of file containing model
0096 % if ischar(model) && exist(model,'file')
0097 %   model=dsImportModel(model);
0098 % end
0099 
0100 % check if input is string or cell with equations or spec struct and convert to model structure
0101 if ischar(model) || iscell(model) || ~isfield(model,'state_variables')
0102   model=dsGenerateModel(model);
0103 end
0104 
0105 % check back compatibility
0106 model=backward_compatibility(model);
0107 
0108 %% auto_gen_test_data_flag argout
0109 if options.auto_gen_test_data_flag
0110   argout = {model}; % specific to this function
0111   
0112   dsUnitSaveAutoGenTestData(argin, argout);
0113 end
0114 
0115 % % auto-populate missing data
0116 % for i=1:length(field_order)
0117 %   if ~isfield(model,field_order{i})
0118 %     model.(field_order{i})=field_defaults{i};
0119 %   end
0120 % end
0121 %
0122 % % standardize field order
0123 % model=orderfields(model,field_order);
0124 
0125 % note: auto-populating and standardization of field order may not be
0126 % necessary or beneficial for DynaSim model structures. It only adds extra
0127 % time... if the above is uncommented-out, then dsCombineModels() should also
0128 % be edited by uncommenting-out the call to dsCheckModel() and commenting-out
0129 % the call to orderfields according to first input (at the end of the
0130 % function).
0131 
0132 
0133 function model=backward_compatibility(model)
0134 % account for change in state variable dimensions:
0135 % cells used to be along rows in a column; now columns across a row.
0136 % replace cols (Npop,1) by rows (1,Npop). similar for Npre,Npost
0137 % do string substitution in ODEs and ICs
0138 target_types={'ODEs','ICs'};
0139 % loop over types of model data
0140 for type_index=1:length(target_types)
0141   type=target_types{type_index};
0142   % info for this type
0143   s=model.(type);
0144   if isstruct(s)
0145     update_these=fieldnames(s);
0146     expressions=struct2cell(s);
0147     % loop over target expressions from which to eliminate internal function calls
0148     updated=0;
0149     for i=1:length(expressions)
0150       if isempty(expressions{i})
0151         continue;
0152       end
0153       % update expressions of this type
0154       % note: do single check first b/c will not normally be needed -->
0155       % reduces 3 conditional checks to 1 in most cases.
0156       if ~isempty(regexp(expressions{i},'\((\w+_)?(Npop|Npre|Npost),1\)','once'))
0157         updated=1;
0158         if ~isempty(regexp(expressions{i},'\((\w+_)?Npop,1\)','once'))
0159           expressions{i}=regexprep(expressions{i},'\((\w+_)Npop,1\)','\(1,$1Npop\)');
0160         end
0161         if ~isempty(regexp(expressions{i},'\((\w+_)?Npre,1\)','once'))
0162           expressions{i}=regexprep(expressions{i},'\((\w+_)Npre,1\)','\(1,$Npre\)');
0163         end
0164         if ~isempty(regexp(expressions{i},'\((\w+_)?Npost,1\)','once'))
0165           expressions{i}=regexprep(expressions{i},'\((\w+_)Npost,1\)','\(1,$Npost\)');
0166         end
0167       end
0168     end
0169     if updated
0170       % update model with expressions that have parameter values in them
0171       model.(type)=cell2struct(expressions,update_these,1);
0172     end
0173   end
0174 end

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