Setup and Import

f_user_input

Code

  1function [settings, results, sb] = f_user_input(model_folders, analysis_options, user_choices)
  2% This function processes user input for model, analysis options, and
  3% settings files, and returns settings, results, and sbTab data structures.
  4% It utilizes helper functions to validate user input, apply settings, and
  5% manage persistent variables.
  6%
  7% Inputs:
  8% - model_folders: Model folders structure
  9% - analysis_options: Array of available analysis options
 10% - user_choices: Cell array of user input choices for model folder,
 11% analysis, and settings
 12%
 13% Outputs:
 14% - settings: Struct containing all settings for the chosen analysis
 15% - results: Struct containing the results of the analysis
 16% - sbTab: Struct containing SBtab data
 17%
 18% Used Functions:
 19% - getValidInput: Validates user input for model folder, analysis option,
 20% and settings file
 21% - apply_settings: Updates settings based on chosen settings file and
 22% checks for changes
 23% - choose_options: Helps user choose valid options from available choices
 24% - parse_choices: Presents list of choices to user and validates input
 25% - compare_and_update: Checks if current and previous values are different
 26% and clears functions if necessary
 27%
 28% Variables:
 29% Loaded:
 30% - None
 31%
 32% Initialized:
 33% - results: Empty struct for storing analysis results
 34% - settings: Empty struct for storing analysis settings
 35% - sbTab: Empty struct for storing SBtab data
 36%
 37% Persistent:
 38% - last_settings_file_text: Stores the last settings file text
 39% - last_settings_file_date: Stores the last settings file date
 40% - last_model_folder: Stores the last chosen model folder
 41% - last_analysis_text: Stores the last chosen analysis option
 42% - last_settings_file_text: Stores the last chosen settings file text
 43% - last_SBtab_date: Stores the last SBtab date
 44% - functions_cleared: Flag indicating if functions have been cleared or
 45% not
 46
 47
 48
 49% Define persistent variables to store the last settings file text and
 50% date.
 51persistent last_settings_file_text
 52persistent last_settings_file_date
 53
 54% Initialize the results, settings and sbTab variables.
 55results = [];
 56settings = [];
 57sb = [];
 58functions_cleared = 0;
 59
 60% Set model folder paths
 61general_model_folder = model_folders.main + "Model/";
 62
 63% Get the valid model folder based on user input.
 64model_folder =...
 65    getValidInput(general_model_folder, user_choices{1}, "model folder");
 66specific_model_folder = general_model_folder + model_folder;
 67
 68% Get the valid analysis option based on user input.
 69analysis_text =...
 70    getValidInput(analysis_options, user_choices{2}, "analysis option");
 71
 72% Store the name of the chosen analysis in the settings struct
 73settings.analysis = analysis_text;
 74
 75% Process user input for analysis options 1-5 and 8
 76if any(contains(analysis_options([1:5, 8]), analysis_text))
 77
 78    % Set settings folder path based on user input
 79    settings_folder = specific_model_folder + "/Matlab/Settings/";
 80    settings_file_text =...
 81        getValidInput(settings_folder, user_choices{3}, "settings file");
 82
 83    % Apply settings and return the settings struct
 84    [settings,last_settings_file_text,last_settings_file_date] = ...
 85        apply_settings(settings, settings_folder, settings_file_text,...
 86        last_settings_file_date,last_settings_file_text, analysis_options,...
 87        analysis_text, specific_model_folder, functions_cleared);
 88
 89    % Process user input for analysis options 6-7
 90elseif any(contains(analysis_options(6:7), analysis_text))
 91
 92    % Set results folder path
 93    results_folder = specific_model_folder + "/Matlab/Results";
 94
 95    % Get the analysis to be reproduced based on user input.
 96    last_choice = [];
 97    prompt = "\nWhat analysis should be reproduced?\n";
 98
 99    [r_analysis_text,~] =...
100        choose_options(results_folder,prompt,last_choice);
101
102    specific_results_folder = results_folder + "/" + ...
103        r_analysis_text;
104
105    % Get the date of the original analysis based on user input.
106    last_choice = [];
107    prompt = "\nWhen was this analysis run originaly?\n";
108
109    [r_analysis_date_text,~] =...
110        choose_options(specific_results_folder,prompt,last_choice);
111
112    specific_results_folder_date = specific_results_folder + "/" + ...
113        r_analysis_date_text;
114
115    % Load the settings file and the SBtab struct
116    load(specific_results_folder_date + "/Analysis.mat","settings","sb")
117
118    % Set inport to false since we don't want to overwrite anything
119    settings.import = false;
120
121    % If the reproduction of an analysis is chosen, clear the functions
122    % because the settings most likely changed.
123        f_functions_to_clear()
124
125    % If the reproduction of the plots of an analysis is chosen, set the
126    % code to produce plots and load the results that were previously
127    % obtained.
128    if contains(analysis_options(7),analysis_text)
129        % Store the name of the chosen analysis in the settings struct
130        settings.analysis = analysis_text;
131
132        settings.plot = true;
133        load(specific_results_folder_date + "/Analysis.mat","results")
134    end
135end
136
137% % Store the name of the chosen analysis in the settings struct
138% settings.analysis = analysis_text;
139
140% Set the chosen model folder in the settings struct
141settings.folder_model = model_folder;
142end
143
144function [settings, last_settings_file_text, last_settings_file_date] = ...
145    apply_settings(settings, settings_folder, settings_file_text, ...
146    last_settings_file_date, last_settings_file_text, analysis_options, ...
147    analysis_text, specific_model_folder, functions_cleared)
148% Function apply_settings updates the settings based on the chosen settings
149% file and checks if any changes have been made to the settings file or the
150% SBtab since the last analysis
151
152persistent last_SBtab_date
153
154settings_file = strrep(settings_file_text, ".m", "");
155
156% Add the default settings to the struct
157stg_add_default = eval("default_settings()");
158
159% Iterate through the fields of the default settings struct and add them to
160% the settings struct
161f = fieldnames(stg_add_default);
162for i = 1:length(f)
163    settings.(f{i}) = stg_add_default.(f{i});
164end
165
166% Add chosen settings to the struct overwriting defaults when appropriate
167[stg_add] = eval(settings_file + "()");
168
169% Iterate through the fields of the chosen settings struct and add them to
170% the settings struct, overwriting the default values if necessary
171f = fieldnames(stg_add);
172for i = 1:length(f)
173    settings.(f{i}) = stg_add.(f{i});
174end
175
176% Check if the date of the settings file changed, if so clear functions
177listing = dir(settings_folder);
178for n = 1:size(listing, 1)
179    if matches(settings_file_text, listing(n).name, "IgnoreCase", true)
180        settings_file_date = listing(n).date;
181    end
182end
183
184if isempty(last_settings_file_date)
185    settings.import = true;
186else
187    settings.import = false;
188end
189
190% Check if the date of the settings file changed, if so clear functions
191[last_settings_file_date, functions_cleared] = ...
192    compare_and_update(settings_file_date, last_settings_file_date, functions_cleared);
193
194% Check if the name of the settings file changed, if so clear functions
195[last_settings_file_text, functions_cleared] = ...
196    compare_and_update(settings_file_text, last_settings_file_text, functions_cleared);
197
198% Check if the date of the SBtab changed, if so clear functions
199listing = dir(specific_model_folder);
200
201for n = 1:size(listing, 1)
202    if matches(settings.sbtab_excel_name, listing(n).name, "IgnoreCase", true)
203        sbtab_date = listing(n).date;
204    end
205end
206
207[last_SBtab_date, functions_cleared] = ...
208    compare_and_update(sbtab_date, last_SBtab_date, functions_cleared);
209
210if functions_cleared == 1
211    settings.import = true;
212end
213
214if contains(analysis_options(8), analysis_text)
215    settings.import = true;
216    settings.save_results = false;
217    settings.plot = false;
218end
219end
220
221function valid_input = getValidInput(options, user_choice, input_type)
222% Function getValidInput validates the user input for the model folder,
223% settings file, and analysis option
224
225persistent last_model_folder
226persistent last_analysis_text
227persistent last_settings_file_text
228
229valid_input = user_choice;
230
231% Check the validity of the input based on the input_type
232switch input_type
233    case "model folder"
234
235        % If the input is a valid model folder, return it
236        if isstring(user_choice) && isfolder(options + valid_input)
237            disp("The " + input_type + " chosen was: " + valid_input)
238            return;
239            % Otherwise, prompt the user to choose a valid one
240        else
241            disp("The chosen " + input_type + " is not valid, please choose a valid " + input_type)
242            prompt = "What " + input_type + " should be used?\n";
243            [valid_input, last_model_folder] = choose_options(options, prompt, last_model_folder);
244        end
245
246    case "settings file"
247        % If the input is a valid settings file, return it
248        if isstring(user_choice) && isfile(options + valid_input)
249            disp("The " + input_type + " chosen was: " + valid_input)
250            return;
251            % Otherwise, prompt the user to choose a valid one
252        else
253            disp("The chosen " + input_type + " is not valid, please choose a valid " + input_type)
254            prompt = "What " + input_type + " should be used?\n";
255            [valid_input, last_settings_file_text] = choose_options(options, prompt, last_settings_file_text);
256        end
257    case "analysis option"
258        % If the input is not a valid analysis, prompt the user to choose a
259        % valid analysis
260        if isstring(user_choice) || ~(user_choice >= 1) || ~(user_choice <= 8)
261            disp("The chosen " + input_type + " is not valid, please choose a valid " + input_type)
262            prompt = "What " + input_type + " should be used?\n";
263            [valid_input, last_analysis_text] = parse_choices(prompt, options, last_analysis_text);
264            % Otherwise, if the analysis is valid, return it
265        else
266            valid_input = options(user_choice);
267            disp("The " + input_type + " chosen was: " + valid_input)
268        end
269end
270end
271
272function [choice, last_choice] = choose_options(folder, prompt, last_choice)
273% Function choose_options helps user to choose valid options from available
274% choices
275
276listing = dir(folder);
277
278% Remove unnecessary entries from the listing
279for n = size(listing, 1):-1:1
280    if any(matches(listing(n).name, [".", "..", "Place models here.txt"]))
281        listing(n) = [];
282    end
283end
284
285% Create an options array containing the names of the valid choices
286for n = 1:size(listing, 1)
287    folder(n) = string(listing(n).name);
288end
289
290% Call parse_choices to handle user input
291[choice, last_choice] = parse_choices(prompt, folder, last_choice);
292end
293
294function [choice, last_choice] = parse_choices(prompt, options, last_choice)
295% Function parse_choices presents a list of choices to the user and
296% validates their input, then returns the chosen option
297
298% Build the prompt string with the available options
299for n = 1:size(options, 2)
300    prompt = prompt + "\n" + n + ": " + options(n);
301end
302
303% If there's a last_choice, include it in the prompt as the default
304if ~isempty(last_choice)
305    if any(contains(options, last_choice))
306        prompt = prompt + "\n\nPress enter to use " + last_choice;
307    else
308        last_choice = [];
309    end
310end
311
312prompt = prompt + "\n";
313
314% Get userinput and handle it accordingly
315i = input(prompt);
316
317% If the user input is empty, set the choice to an empty array
318if isempty(i)
319    choice = [];
320    % If the user input is a valid index, set the choice to the
321    % corresponding option
322elseif i > 0 && i < size(options, 2) + 1
323    choice = options(i);
324    disp("The option chosen was: " + choice)
325    % If the user input is invalid, call parse_choices recursively with an
326    % updated prompt
327else
328    prompt = "Please choose from the provided options";
329    [choice, last_choice] = parse_choices(prompt, options, last_choice);
330end
331
332% If the choice is empty and there's a last_choice, set the choice to
333% last_choice
334if isempty(choice)
335    if ~isempty(last_choice)
336        choice = last_choice;
337        disp("The option chosen was: " + last_choice)
338    else
339        prompt = "Please choose from the provided options";
340        [choice, last_choice] = parse_choices(prompt, options, last_choice);
341    end
342else
343    last_choice = choice;
344end
345end
346
347function [previous, is_cleared] = compare_and_update(current, previous, is_cleared)
348% Function compare_and_update checks if the current and previous values are
349% different and clears the functions if necessary
350
351% If there's a previous value, compare it with the current value
352if ~isempty(previous)
353    % If the current and previous values are different, clear functions if
354    % not already cleared
355    if ~contains(current, previous)
356        if is_cleared == false
357            disp("Settings file changed, clearing functions")
358            f_functions_to_clear()
359            is_cleared = true;
360        end
361    end
362end
363% Update the previous value to the current value
364previous = current;
365end

In this code, the main function f_user_input is responsible for processing user inputs related to model folder, analysis options, and settings file. Based on these inputs, the function returns the necessary settings, results, and SBtab data.

Inputs:

  • mmf: a struct containing the main folder path.

  • analysis_options: an array containing the available analysis options.

  • user_choices: a cell array containing user inputs for the model folder, analysis option, and settings file.

Outputs:

  • settings: a struct containing the necessary settings for the chosen analysis.

  • results: a struct containing the results (if any) of the chosen analysis.

  • sbTab: a struct containing the SBtab data (if any) associated with the chosen analysis.

The main function relies on several helper functions to process the user input, update settings, and handle user choices.

  1. apply_settings: This function updates the settings based on the chosen settings file, and checks if any changes have been made to the settings file or SBtab since the last analysis.

    Inputs: settings, settings_folder, settings_file_text, last_settings_file_date, last_settings_file_text, analysis_options, analysis_text, specific_model_folder, functions_cleared

    Outputs: settings, last_settings_file_text, last_settings_file_date

  2. getValidInput: This function validates the user input for the model folder, settings file, and analysis option, and returns the valid input.

    Inputs: options, user_choice, input_type

    Outputs: valid_input

  3. choose_options: This function helps the user to choose valid options from available choices in a folder.

    Inputs: folder, prompt, last_choice

    Outputs: choice, last_choice

  4. parse_choices: This function presents a list of choices to the user, validates their input, and returns the chosen option.

    Inputs: prompt, options, last_choice

    Outputs: choice, last_choice

  5. compare_and_update: This function compares the current and previous values, and clears functions if necessary.

    Inputs: current, previous, is_cleared

    Outputs: previous, is_cleared

The main function starts by initializing the results, settings, and sbTab variables, and setting the model folder paths. It then calls the getValidInput function to obtain valid user input for the model folder and analysis option. Depending on the user’s chosen analysis option, the code proceeds differently. For analysis options 1-5 and 8, the apply_settings function is called to update the settings. For analysis options 6-7, the function loads the settings file and SBtab struct from a previous analysis, and processes the user input accordingly. Finally, the chosen model folder is set in the settings struct, and the function returns the updated settings, results, and sbTab data.

f_import

Code

 1function [settings,sb] = f_import(settings,model_folder)
 2% Function f_import: Import a model from an SBtab file, generate model
 3% files, and setup necessary inputs for experiments
 4%
 5% Inputs:
 6% - settings: A struct containing settings for the model import process
 7% - model_folder: A string specifying the folder where the model and
 8% related files should be saved
 9%
10% Outputs:
11% - settings: Updated struct with additional information about the number
12% of experiments and outputs
13% - sb: A struct containing data from the imported SBtab file
14%
15% Used Functions:
16% - f_excel_sbtab_importer: Converts an SBtab file into a .mat file and tsv
17% files
18% - f_generate_sbtab_struct: Generates a struct based on the SBtab and
19% updates settings with the number of experiments and outputs
20% - f_sbtab_to_model: Saves the model in .mat, .sbproj, and .xml formats,
21% and creates a data file with required settings for running the model in
22% various experimental settings
23% - f_setup_input: Generates code to load inputs for each experiment into a
24% .mat file and creates code to read these inputs during simulation
25% - f_build_model_exp: Creates .mat files for each experiment containing
26% rules, species, and parameters based on the SBtab for equilibrium,
27% default, and detailed simulation runs
28%
29% Variables:
30% Loaded:
31% - None
32%
33% Initialized:
34% - None
35%
36% Persistent:
37% - None
38
39disp("Generating model files and folder from SBtab")
40
41% Convert the SBtab file into a .mat file and tsv files
42f_excel_sbtab_importer(model_folder);
43
44% Creates a struct based on the SBtab that is used elswhere in the code and
45% also adds the number of experiments and outputs to the settings struct
46[settings,sb] = f_generate_sbtab_struct(settings,model_folder);
47
48% Save the model in .mat, .sbproj, and .xml formats, and create a data file
49% with the required settings for running the model in various  experimental
50% settings defined in the SBtab
51f_sbtab_to_model(settings,sb,model_folder)
52
53% Generate code to load inputs for each experiment into a .mat file, and
54% create code to read these inputs during simulation, stored in the Input
55% functions folder
56f_setup_input(settings,model_folder)
57
58% Create three .mat files for each experiment containing the necessary
59% rules, species, and parameters based on the SBtab, for equilibrium,
60% default, and detailed simulation runs
61f_build_model_exp(settings,sb,model_folder)
62
63disp("Model files and folders generated successfully")
64end

Creates the necessary folders inside the model folder. Calls subfunctions that convert the SBtab from an Excel into MATLAB® files useful for the workflow, TSVs and a SBML.

f_excel_sbtab_importer

Code

  1function f_excel_sbtab_importer(model_folders)
  2% This function, f_excel_sbtab_importer, takes a model_folders structure as
  3% input, which contains paths to the source Excel SBtab file and the
  4% destination folders for the parsed data (MATLAB .mat file) and TSV files.
  5% The function processes the Excel file with multiple sheets in the SBtab
  6% format, imports the data from each sheet, replaces missing values with
  7% empty spaces, and exports the processed data as .mat and TSV files.
  8%
  9% Inputs:
 10% - model_folders: A structure containing the following fields:
 11% - model.sbtab: Path to the source Excel SBtab file.
 12% - model.data.sbtab: Path to the destination folder for the parsed .mat
 13% file.
 14% - model.tsv.model_name: Path to the destination folder for the TSV files.
 15%
 16% Outputs: - No direct output. The parsed data is saved as .mat and TSV
 17% files in the specified folders.
 18%
 19% Functions called:
 20% - impexp: This function is called for each sheet in the Excel SBtab file.
 21% It imports the sheet's data, replaces missing values with empty spaces,
 22% and exports the processed data as a TSV file.
 23% - cell_write_tsv: This function writes the data in a cell array to a TSV
 24% file, taking care of transposing the array and converting numeric values
 25% to strings.
 26% 
 27% Variables:
 28% Loaded:
 29% - Source_sbtab: Path to the source Excel SBtab file.
 30% - Matlab_sbtab: Path to the destination folder for the parsed .mat file.
 31% - sheets: Cell array containing the names of sheets in the Excel SBtab
 32% file.
 33% - sbtab_excel: A cell array containing the processed data for each sheet.
 34%
 35% Initialized:
 36% - None
 37%
 38% Persistent:
 39% - None
 40
 41
 42% Get the folders for the model SBtab file and the destination for the
 43% parsed data
 44Source_sbtab = model_folders.model.sbtab;
 45Matlab_sbtab = model_folders.model.data.sbtab;
 46
 47% Get the total number of sheets in the SBTAB
 48sheets = sheetnames(Source_sbtab);
 49
 50% Attempt to run the import of sheets in parallel, depending on the version
 51% of Excel being used, this may not work
 52try
 53    parfor i = 1:size(sheets,1)
 54        sbtab_excel{i} = impexp (i,model_folders);
 55    end
 56catch
 57    for i = 1:size(sheets,1)
 58        sbtab_excel{i} = impexp (i,model_folders);
 59    end
 60end
 61
 62% Save the parsed SBTAB tables in .mat format
 63save(Matlab_sbtab,'sbtab_excel');
 64disp("SBtab with " + size(sheets,1) + " sheets parsed successfully")
 65end
 66
 67function sbtab_excel = impexp (i,model_folders)
 68
 69% Load the source SBTAB file and the folder to save the TSV files
 70Source_sbtab = model_folders.model.sbtab;
 71tsv_name_folder = model_folders.model.tsv.model_name;
 72
 73% Import the SBTAB sheet as a cell array
 74sbtab_excel = readcell(Source_sbtab,'sheet',i);
 75
 76% Replace missing values with empty spaces
 77mask = cellfun(@ismissing, sbtab_excel,'UniformOutput',false);
 78mask = cellfun(@min, mask);
 79mask = logical(mask);
 80sbtab_excel(mask) = {[]};
 81
 82% Get the name for the TSV file to be exported
 83field = regexp(sbtab_excel{1,2},"TableName='[^']*'",'match');
 84field = string(replace(field,["TableName='","'"," "],["","","_"]));
 85
 86% Export the TSV file
 87cell_write_tsv(tsv_name_folder + field + ".tsv",sbtab_excel)
 88end
 89
 90function cell_write_tsv(filename,origCell)
 91
 92% Create a new version of the cell for reference
 93modCell = origCell;
 94
 95% Find the indices of numeric cells
 96iNum = cellfun(@isnumeric,origCell);
 97
 98% % Replace numeric cells with cell strings
 99for n = 1:size(iNum,1)
100    for m = 1:size(iNum,2)
101        modCell(n,m) = cellstr(num2str(origCell{n,m}));
102    end
103end
104
105% Transpose the cell array to have the correct orientation
106modCell = transpose(modCell);
107
108% Create a format string for saving the TSV file
109[rNum,cNum] = size(origCell);
110frmt = repmat([repmat('%s\t',1,cNum-1),'%s\n'],1,rNum);
111fid = fopen(filename,'wt');
112
113% Save the TSV file using the format string
114fprintf(fid,frmt,modCell{:});
115fclose(fid);
116end

Loads the information in the SBtab and creates a . mat file that contains the sbtab and TSVs corresponding to all the SBtab tabs.

f_generate_sbtab_struct

Code

 1function [stg,sb] = f_generate_sbtab_struct(stg,mmf)
 2% This function is used to load an SBtab data file, convert the SBtab data
 3% into a structure, and extract the number of experiments and outputs. The
 4% function takes two input arguments, stg and mmf, and returns two output
 5% arguments, the modified stg and the generated sb structure. The function
 6% calls the helper function convert_sbtab_to_struct to convert the SBtab
 7% data into a structure. The SBtab data file is loaded into the variable
 8% sbtab_excel.
 9%
10% Inputs:
11% - stg: An existing structure that will be updated with the number of
12% experiments and outputs.
13% - mmf: A structure containing the model information, including the SBtab
14% data file name.
15%
16% Outputs:
17% - stg: The updated structure containing the number of experiments
18% and outputs.
19% - sb: A structure generated from the SBtab data.
20%
21% Called functions:
22% - convert_sbtab_to_struct: A helper function that converts SBtab data
23% into a structure.
24%
25% Variables:
26% Loaded:
27% sbtab_excel: A variable that holds the loaded SBtab data from the
28% specified file.
29%
30% Initialized:
31% - None
32%
33% Persistent:
34% - None
35
36
37% Extract the sbtab file name from the mmf structure
38Matlab_sbtab = mmf.model.data.sbtab;
39
40% Check if the sbtab file exists
41if isfile(Matlab_sbtab)
42
43    % Load the sbtab data into a variable called 'sbtab_excel'
44    load(Matlab_sbtab,'sbtab_excel');
45
46    % Convert the sbtab data into a structure
47    sb = convert_sbtab_to_struct(sbtab_excel);
48
49    % Extract the number of experiments and outputs
50    stg.expn = size(sb.Experiments.ID,1);
51    stg.outn = size(sb.Output.ID,1);
52end
53end
54
55% Helper function that converts sbtab data into a structure
56function sb = convert_sbtab_to_struct(sbtab_excel)
57
58% Initialize an empty structure
59sb = struct();
60
61% Loop through all columns in the sbtab data
62for col = 1:size(sbtab_excel,2)
63
64    % Check if the first row of the column contains a table name
65    if ~isempty(sbtab_excel{1,col}{1,2})
66
67        % Extract the table name from the first row of the column
68        field =...
69            regexp(sbtab_excel{1,col}{1,2},...
70            "TableName='([^']*)'", 'tokens');
71        field = string(replace(field{1}, " ", "_"));
72
73        % Loop through all rows in the column
74        for row = 1:size(sbtab_excel{1,col},2)
75
76            % Check if the current row contains a subfield name
77            if ~isempty(sbtab_excel{1,col}{2,row})
78                % Extract the subfield name from the current row
79                subfield = sbtab_excel{1,col}{2,row};
80                subfield = regexprep(subfield, '[!>]', '');
81                subfield = regexprep(subfield, '[:\s]', '_');
82
83                % Extract the subfield values from the column
84                sb.(field).(subfield)(:,1) = sbtab_excel{1,col}(3:end,row)';
85
86                % Remove empty values from the subfield
87                sb.(field).(subfield) = sb.(field).(subfield)...
88                    (~cellfun('isempty', sb.(field).(subfield)));
89            end
90        end
91    end
92end
93end

Loads the SBtab saved in the .mat file and creates a MATLAB® struct that can be more easily parsed.

f_sbtab_to_model

Code

  1function f_sbtab_to_model(stg,sb,mmf)
  2% This function, f_sbtab_to_model, converts an SBtab data structure into a
  3% model format that can be used for simulations and analysis. It then saves
  4% the model in .mat, .sbproj, and .xml formats for future use. The function
  5% also processes experimental settings defined in the SBtab data structure,
  6% adding compartments, species, parameters, reactions, expressions, inputs,
  7% constants, and boundary conditions to the model.
  8% 
  9% Inputs:
 10% - stg: Settings structure containing configuration information
 11% - sb: SBtab data structure containing information about species,
 12% reactions, compartments, and parameters
 13% - mmf: Model management files structure containing the paths to save the
 14% model
 15%
 16% Outputs:
 17% - No direct outputs, but the function saves the model in .mat, .sbproj,
 18% and .xml formats
 19%
 20% Used Functions:
 21% - add_reactions_to_model: Adds reactions from the SBtab data structure to
 22% the model object
 23% - set_boundary_Condition: Sets boundary conditions for the model
 24% - add_expressions_to_model: Adds expressions from the SBtab data
 25% structure to the model object
 26% - add_inputs_to_model: Adds inputs from the SBtab data structure to the
 27% model object
 28% - add_constants_to_model: Adds constants from the SBtab data structure to
 29% the model object
 30% - process_experiments: Processes experimental data from the SBtab data
 31% structure
 32%
 33% Variables
 34% Loaded:
 35% - sbtab.species: Species related data from the SBtab data structure
 36% - sbtab.defpar: Default parameter related data from the SBtab data
 37% structure
 38% - sbtab.sim_time: Simulation time extracted from the SBtab data structure
 39%
 40% Initialized:
 41% - modelobj: Initialized model object
 42% - compobj: Initialized compartment object
 43%
 44% Persistent:
 45% - None
 46
 47% Initialize the model object and compartment object
 48modelobj = sbiomodel(stg.name);
 49compobj = [];
 50
 51% Combine species related data into sbtab.species
 52sbtab.species = [sb.Compound.Name, sb.Compound.InitialValue, sb.Compound.IsConstant, sb.Compound.Unit, sb.Compound.Location];
 53% Combine default parameter related data into sbtab.defpar
 54sbtab.defpar = [sb.Parameter.Comment, sb.Parameter.Value_linspace, sb.Parameter.Unit];
 55
 56% Add compartments to the model Iterate through each compartment in the
 57% SBtab data structure and add it to the model
 58for n = 1:size(sb.Compartment.ID,2)
 59    compobj{n} = addcompartment(modelobj, sb.Compartment.Name{n});
 60    set(compobj{n}, 'CapacityUnits', sb.Compartment.Unit{n});
 61    set(compobj{n}, 'Value', sb.Compartment.Size{n});
 62end
 63
 64% Add species to the compartments Iterate through each species in the SBtab
 65% data structure and add it to the appropriate compartment
 66for n = 1:size(sbtab.species,1)
 67    compartment_number_match = find_compartment_number(compobj, sb.Compound.Location{n});
 68    addspecies (compobj{compartment_number_match}, sb.Compound.Name{n},...
 69        sb.Compound.InitialValue{n}, 'InitialAmountUnits', sb.Compound.Unit{n});
 70end
 71
 72% Add species to the compartments Iterate through each species in the SBtab
 73% data structure and add it to the appropriate compartment
 74for n = 1:size(sbtab.defpar,1)
 75    addparameter(modelobj,sb.Parameter.Name{n},...
 76        sb.Parameter.Value_linspace{n},'ValueUnits',sb.Parameter.Unit{n},'Notes',sb.Parameter.Comment{n});
 77end
 78
 79% Add reactions, expressions, inputs, constants, and boundary conditions to
 80% the model
 81modelobj = add_reactions_to_model(sb,modelobj);
 82modelobj = set_boundary_Condition(sb,modelobj);
 83modelobj = add_expressions_to_model(sb,modelobj);
 84modelobj = add_inputs_to_model(sb,modelobj);
 85modelobj = add_constants_to_model(sb,modelobj);
 86
 87% Extract simulation time from the SBtab data structure
 88sbtab.sim_time = [sb.Experiments.Sim_Time{:}];
 89% Process experimental data from the SBtab data structure
 90[sbtab,Data] = process_experiments(sb,sbtab);
 91
 92% Save the model in .mat, .sbproj, and .xml formats
 93sbproj_model = mmf.model.data.sbproj_model;
 94matlab_model = mmf.model.data.mat_model;
 95data_model = mmf.model.data.data_model;
 96xml_model = mmf.model.data.xml_model;
 97
 98sbiosaveproject(sbproj_model,'modelobj')
 99save(matlab_model,'modelobj')
100save(data_model,'Data','sbtab','sb')
101sbmlexport(modelobj,xml_model)
102end
103
104function modelobj = add_constants_to_model(sb,modelobj)
105% This function adds constants from sb to the given model object. This
106% function checks if the sb structure has a "Constant" field, and if so,
107% iterates through the constants and adds them as parameters to the model
108% object.
109
110% Check if the sb object has a "Constant" field
111if isfield(sb,"Constant")
112    % Iterate through the constants and add them to the model object
113    for m = 1:size(sb.Constant.ID,1)
114        addparameter(modelobj,char(sb.Constant.Name(m)),...
115            str2double(string(sb.Constant.Value{m})),...
116            'ValueUnits',sb.Constant.Unit{m});
117    end
118end
119end
120
121function modelobj = add_inputs_to_model(sb,modelobj)
122% This function adds inputs from sb to the given model object. This
123% function checks if the sb structure has an "Input" field, and if so,
124% iterates through the inputs and adds them as parameters, species, and
125% rules to the model object according to the input properties.
126
127% Check if the sb structure contains the 'Input' field
128if isfield(sb,"Input")
129    % Iterate through all inputs
130    for m = 1:size(sb.Input.ID,1)
131        % Check if the input contains the 'Formula' field
132        if isfield(sb.Input,'Formula')
133            % If the input formula is a double, add it as a species
134            if isa(sb.Input.Formula{m},'double')
135                addspecies (modelobj, char(sb.Input.Name(m)),...
136                    str2double(string(sb.Input.DefaultValue{m})),...
137                    'InitialAmountUnits',sb.Input.Unit{m});
138                % Otherwise, try adding it as a species with initial amount
139                % 0
140            else
141                try
142                    addspecies (modelobj, char(sb.Input.Name(m)),0,...
143                        'InitialAmountUnits',sb.Input.Unit{m});
144                catch
145                end
146                % Add a rule for the species using the input formula
147                addrule(modelobj, char({convertStringsToChars(...
148                    string(sb.Input.Location{m}) + "." +...
149                    string(sb.Input.Name{m}) + " = " +...
150                    string(sb.Input.DefaultValue{m}))}),...
151                    'repeatedAssignment');
152            end
153        else
154            % If no 'Formula' field, add the input as a parameter
155            addparameter(modelobj,char(sb.Input.Name(m)),...
156                str2double(string(sb.Input.DefaultValue{m})),...
157                'ValueUnits',sb.Input.Unit{m});
158        end
159    end
160end
161end
162
163function compartment_number = find_compartment_number(compobj, location)
164% This function finds the compartment number in compobj corresponding to
165% the given location. This function iterates through all compartments in
166% compobj and returns the index of the compartment whose name matches the
167% given location.
168
169% Iterate through all compartments
170for m = 1:size(compobj,2)
171    % Check if the current compartment's name matches the given location
172    if strcmp(compobj{m}.Name,location)
173        % If it matches, return the index and break the loop
174        compartment_number = m;
175        break;
176    end
177end
178end
179
180function [sbtab,Data] = process_experiments(sb,sbtab)
181% This function processes experiments from sb and stores data in sbtab and
182% Data. This function extracts relevant data from sb, a structured
183% representation of an SBML model, and stores it in sbtab, a structured
184% representation of an SBtab file, and Data structures, used for further
185% analysis and processing.
186
187% Initialize species_inp_indices to store the indices of species present in
188% sb.Experiments
189species_inp_indices = {};
190% Iterate through sb.Compound.ID to find species present in sb.Experiments
191for n = 1:size(sb.Compound.ID, 1)
192    field_name = "S" + (n - 1);
193    % Check if sb.Experiments has the field specified in field_name
194    if isfield(sb.Experiments, field_name)
195        species_inp_indices{end + 1, 1} = n;
196    end
197end
198% Iterate through sb.Experiments.ID to process each experiment
199for n = 1:size(sb.Experiments.ID,1)
200    start_amount = cell(1,size(species_inp_indices,1));
201    n_start_amount = 0;
202    n_input_time = 0;
203    n_input = 0;
204    n_output = 0;
205
206    % Check if sb.Experiments has a Normalize field, and store it in
207    % sbtab.datasets(n).Normalize
208    if isfield(sb.Experiments,"Normalize")
209        sbtab.datasets(n).Normalize = sb.Experiments.Normalize{n};
210    else
211        sbtab.datasets(n).Normalize = [];
212    end
213
214    % Retrieve the Time data for the current experiment and store it in
215    % Data(n).Experiment.t
216    experiment_field_name = "E" + (n - 1);
217    if isfield(sb.(experiment_field_name), "Time")
218        Data(n).Experiment.t = transpose([sb.(experiment_field_name).Time{:}]);
219    end
220
221    % Process input species data for the current experiment
222    experiment_input_field_name = "E" + (n - 1) + "I";
223    start_amount_name = cell(1, size(species_inp_indices, 1));
224    for m = 1:size(sb.Compound.ID, 1)
225        field_name = "S" + (m - 1);
226        if isfield(sb.Experiments, field_name)
227            n_start_amount = n_start_amount + 1;
228            start_amount{n_start_amount} = sb.Experiments.(field_name)(n);
229            start_amount_name{n_start_amount} = sb.Compound.Name(m);
230        end
231        % Retrieve input time data for the current experiment and species
232        if isfield(sb.(experiment_input_field_name), "Input_Time_S" + (m - 1))
233            n_input_time = n_input_time + 1;
234            sbtab.datasets(n).input_time{1, n_input_time} = ...
235                [sb.(experiment_input_field_name).("Input_Time_S" + (m - 1)){:}];
236        end
237        % Retrieve input value data for the current experiment and species
238        if isfield(sb.(experiment_input_field_name), "S" + (m - 1))
239            n_input = n_input + 1;
240            sbtab.datasets(n).input_value{1, n_input} = ...
241                [sb.(experiment_input_field_name).("S" + (m - 1)){:}];
242            sbtab.datasets(n).input{n_input} = char("S" + (m - 1));
243        end
244    end
245
246    % Process output data for the current experiment
247    for m = 1:size(sb.Output.ID, 1)
248        if isfield(sb.(experiment_field_name), "Y" + (m - 1))
249            n_output = n_output + 1;
250            % Retrieve output values for the current experiment and output
251            Data(n).Experiment.x(:, n_output) = ...
252                [sb.(experiment_field_name).("Y" + (m - 1)){:}];
253            % Retrieve standard deviation of output values for the current
254            % experiment and output
255            Data(n).Experiment.x_SD(:, n_output) = ....
256                [sb.(experiment_field_name).("SD_Y" + (m - 1)){:}];
257            % Store output related information in sbtab.datasets(n)
258            sbtab.datasets(n).output{n_output} = sb.Output.Name(m);
259            sbtab.datasets(n).output_value{n_output} = ...
260                {convertStringsToChars(...
261                strrep(string(sb.Output.Location{m}) + "." + ...
262                string(sb.Output.Name{m}) + " = " + ...
263                string(sb.Output.Formula{m}), 'eps', '0.0001'))};
264            sbtab.datasets(n).output_unit{n_output} = sb.Output.Unit{m};
265            sbtab.datasets(n).output_name{n_output} = sb.Output.Name(m);
266            sbtab.datasets(n).output_ID{n_output} = sb.Output.ID(m);
267            sbtab.datasets(n).output_location{n_output} = sb.Output.Location(m);
268        end
269    end
270    % Store output count and start amount information in sbtab.datasets(n)
271    sbtab.datasets(n).stg.outnumber = n_output;
272    sbtab.datasets(n).start_amount = cat(2,start_amount_name(:),...
273        transpose([start_amount{:}]),species_inp_indices);
274end
275end
276
277
278function model_obj = add_expressions_to_model(sb,model_obj)
279% This function adds expressions to the given model object by iterating
280% through sb.Expression fields and populating the model object with
281% parameters, species, and rules according to the expression properties
282
283% Check if the sb structure contains the 'Expression' field
284if isfield(sb,"Expression")
285    % Iterate through all expressions
286    for m = 1:size(sb.Expression.ID,1)
287        % Check if the expression contains the 'Formula' field
288        if isfield(sb.Expression,'Formula')
289            % If the expression formula is a double, add it as a species
290            if isa(sb.Expression.Formula{m},'double')
291                addspecies (model_obj, char(sb.Expression.Name(m)),...
292                    str2double(string(sb.Expression.Formula{m})),...
293                    'InitialAmountUnits',sb.Expression.Unit{m});
294                % Otherwise, try adding it as a species with initial amount
295                % 0
296            else
297                try
298                    addspecies (model_obj, char(sb.Expression.Name(m)),0,...
299                        'InitialAmountUnits',sb.Expression.Unit{m});
300                catch
301                end
302                % Add a rule for the species using the expression formula
303                addrule(model_obj, char({convertStringsToChars(...
304                    string(sb.Expression.Location{m}) + "." +...
305                    string(sb.Expression.Name{m}) + " = " +...
306                    string(sb.Expression.Formula{m}))}),...
307                    'repeatedAssignment');
308            end
309        else
310            % If no 'Formula' field, add the expression as a parameter
311            addparameter(model_obj,char(sb.Expression.Name(m)),...
312                str2double(string(sb.Expression.DefaultValue{m})),...
313                'ValueUnits',sb.Expression.Unit{m});
314        end
315    end
316end
317end
318
319function model_obj = add_reactions_to_model(sb,model_obj)
320
321num_reactions = size(sb.Reaction.ID, 1);
322num_compounds = size(sb.Compound.Name, 1);
323
324% Add reactions to the model
325for reaction_idx = 1:num_reactions
326
327    is_reversible = sb.Reaction.IsReversible{reaction_idx};
328    reaction_formula = sb.Reaction.ReactionFormula{reaction_idx};
329    location = sb.Reaction.Location{reaction_idx};
330
331    % Determine reaction reversibility and modify reaction_name accordingly
332    if ischar(is_reversible)
333        if contains(is_reversible, "true",'IgnoreCase',true)
334            arrow = ' <-> ';
335        else
336            arrow = ' -> ';
337        end
338    else
339        if is_reversible
340            arrow = ' <-> ';
341        else
342            arrow = ' -> ';
343        end
344    end
345    reaction = strrep(reaction_formula, '<=>', arrow);
346    % Add compartment location to the reaction name
347    for compound_idx = 1:num_compounds
348        compound_name = string(sb.Compound.Name{compound_idx});
349        reaction = insertBefore(string(reaction), " " + compound_name,...
350            " " + location);
351    end
352
353    % Remove extra locations that were added when patterns get recognized
354    % twice because we are not matching properly
355    while contains(reaction, location + " " + location)
356        reaction = strrep(reaction, location + " " + location," " + location);
357    end
358
359    % Remove unnecessary spaces and characters
360    while contains(reaction,"  ")
361        reaction = strrep(reaction,"  "," ");
362    end
363
364    % Replace the space between the location and the species with a dot
365    reaction = strrep(reaction,...
366        location + " ", location+".");
367
368    % Add the location to the first species of the reaction
369    reaction = location + "." + reaction;
370
371    % Add the reaction to the model
372    reaction_object = addreaction(model_obj,reaction);
373    set(reaction_object,'ReactionRate',sb.Reaction.KineticLaw{reaction_idx});
374end
375end
376
377function model_obj = set_boundary_Condition(sb,model_obj)
378% This function sets the boundary conditions for the species in a model
379% object based on information in the sb structure.
380
381% Loop over each compound in the sb structure
382for n = 1:size(sb.Compound.ID, 1)
383
384    % Extract information about the boundary condition for the current
385    % compound
386    assignment = sb.Compound.Assignment{n};
387    interpolation = sb.Compound.Interpolation{n};
388    is_constant = sb.Compound.IsConstant{n};
389
390    % Determine whether the current compound has a boundary condition set
391    if ischar(assignment) && contains(lower(assignment), "true")
392        % If the assignment field is the string "true", set the boundary
393        % condition to 1
394        Boundary_Condition = 1;
395    elseif isnumeric(assignment) && assignment == 1
396        % If the assignment field is the number 1, set the boundary
397        % condition to 1
398        Boundary_Condition = 1;
399    elseif assignment
400        Boundary_Condition = 1;
401    elseif ischar(interpolation) && contains(lower(interpolation), "true")
402        % If the interpolation field is the string "true", set the boundary
403        % condition to 1
404        Boundary_Condition = 1;
405    elseif isnumeric(interpolation) && interpolation == 1
406        % If the interpolation field is the number 1, set the boundary
407        % condition to 1
408        Boundary_Condition = 1;
409    elseif interpolation
410        Boundary_Condition = 1;
411    elseif ischar(is_constant) && contains(lower(is_constant), "true")
412        % If the is_constant field is the string "true", set the boundary
413        % condition to 1
414        Boundary_Condition = 1;
415    elseif isnumeric(is_constant) && is_constant == 1
416        % If the is_constant field is the number 1, set the boundary
417        % condition to 1
418        Boundary_Condition = 1;
419    elseif is_constant
420        Boundary_Condition = 1;
421    else
422        % If none of the fields indicate a boundary condition, set the
423        % boundary condition to 0
424        Boundary_Condition = 0;
425    end
426
427    model_obj.species(n).BoundaryCondition = Boundary_Condition;
428end
429end

This function, f_sbtab_to_model, converts an SBtab data structure into a model format that can be used for simulations and analysis. It then saves the model in .mat, .sbproj, and .xml formats for future use. The function also processes experimental settings defined in the SBtab data structure, adding compartments, species, parameters, reactions, expressions, inputs, constants, and boundary conditions to the model.

Inputs

  • stg: A structure containing the settings for the model conversion.

  • sb: An SBtab data structure containing the model data.

  • mmf: A structure containing the file names for saving the model in different formats.

Outputs

The function saves the generated model in .mat, .sbproj, and SBML(.xml) formats.

Functions called:

  • addcompartment: Adds a compartment to the SimBiology model object.

  • addspecies: Adds a species to a specific compartment within the model.

  • addparameter: Adds a parameter to the model, including its value, unit, and associated notes.

  • find_compartment_number: Locates the index of the compartment based on its name within the compobj cell array.

  • add_reactions_to_model: Adds reactions to the model by processing the reaction-related data in the SBtab data structure.

  • set_boundary_Condition: Sets the boundary conditions for the model using the information provided in the SBtab data structure.

  • add_expressions_to_model: Adds algebraic expressions to the model using the information provided in the SBtab data structure.

  • add_inputs_to_model: Adds input variables to the model using the information provided in the SBtab data structure.

  • add_constants_to_model: Adds constant variables to the model using the information provided in the SBtab data structure.

  • process_experiments: Processes experimental data from the SBtab data structure and returns the updated SBtab and a Data structure containing the processed experimental data.

  • sbiosaveproject: Saves the SimBiology model object as an .sbproj file.

  • save: Saves the SimBiology model object as a .mat file, and the experimental data as a separate .mat file.

  • sbmlexport: Exports the SimBiology model object as an .xml file in the Systems Biology Markup Language (SBML) format.

Loaded variables:

  • modelobj: A SimBiology model object.

  • compobj: A cell array containing compartment objects.

  • sbtab.species: A table containing species-related data.

  • sbtab.defpar: A table containing default parameter-related data.

  • sbtab.sim_time: A table containing simulation time data.

  • Data: A structure containing processed experimental data.

  • sbproj_model, matlab_model, data_model, xml_model: Variables for saving the model in .sbproj, .mat, SBML(.xml) formats, and the experimental data(file), respectively.

f_setup_input

Code

  1function f_setup_input(stg,mmf)
  2% The f_setup_input function is designed to generate code for loading
  3% experiment inputs into a .mat file and create code to read these inputs
  4% during the simulation of the experiments. The generated code is stored in
  5% the "Input_functions" folder.
  6% 
  7% Inputs:
  8% - stg: A structure containing information about the simulation settings.
  9% - mmf: A structure containing information about the model, including the
 10% model data, main folder, and input functions.
 11%
 12% Outputs:
 13% - This function creates input function files and an input creator function
 14% file in the "Input_functions" folder. The input functions are used to
 15% calculate input values based on the simulation time, while the input
 16% creator function is used to create input data from the sbtab.datasets.
 17%
 18% Used Functions :
 19% - template1: Generates code for input functions.
 20% - template2: Generates code for the first input of the first experiment in
 21% the input creator function.
 22% - template3: Generates code for the rest of the inputs in the input creator
 23% function.
 24%
 25% Loaded Variables:
 26% - matlab_model: Loaded from mmf.model.data.mat_model.
 27% - data_model: Loaded from mmf.model.data.data_model.
 28% - inp_model_data: Loaded from mmf.model.data.input_model_data.
 29% - Model_folder: Loaded from mmf.model.main.
 30% - model_input: Loaded from mmf.model.input_functions.input.
 31% - sbtab: Loaded from the data_model file.
 32% - modelobj: Loaded from the matlab_model file.
 33
 34
 35% Load required data from mmf.model.data:
 36matlab_model = mmf.model.data.mat_model;
 37data_model = mmf.model.data.data_model;
 38inp_model_data = mmf.model.data.input_model_data;
 39Model_folder = mmf.model.main;
 40model_input = mmf.model.input_functions.input;
 41
 42% Load the sbtab and modelobj variables from the respective files:
 43load(data_model,'sbtab')
 44load(matlab_model,'modelobj');
 45
 46% Iterate over the experiments and their inputs to generate input functions
 47% and an input creator function:
 48for Exp_n = 1:size(sbtab.datasets,2)
 49    for index = 1:size(sbtab.datasets(Exp_n).input,2)
 50        % If input size is larger than 100, generate input function file
 51        % for each input
 52        if size(sbtab.datasets(Exp_n).input_value{index},2) > 100
 53            
 54            % Generate input names by replacing "." with an empty string,
 55            % and concatenating the "X", "T", "h1", and "h2" suffixes:
 56            input_name = strrep(modelobj.species(1+str2double(strrep(...
 57                sbtab.datasets(Exp_n).input(index),'S',''))).name,".","");
 58            input_X = input_name + "X";
 59            input_T = input_name + "T";
 60            input_h1 = input_name + "h1";
 61            input_h2 = input_name + "h2";
 62            input_h3 = input_name + "h3";
 63
 64            % Create a new .m file for each input and write the generated
 65            % code to that file, based on the template1() function:
 66            fullFileName = sprintf('%s.m',...
 67                model_input + Exp_n + "_" + input_name  );
 68
 69            fileID = fopen(fullFileName, 'wt');
 70
 71            inp_str = template1();
 72            inp_str = replace(inp_str,...
 73                ["SBtab_name","Exp_n","input_name",...
 74                "input_X", "input_T", "input_h1", "input_h2","input_h3", "inp_model_data",...
 75                "sbtab.sim_time(Exp_n)"],[stg.name,Exp_n,...
 76                input_name, input_X, input_T, input_h1,...
 77                input_h2,input_h3, inp_model_data,...
 78                sbtab.sim_time(Exp_n)]);
 79
 80            fprintf(fileID,inp_str);
 81            fclose(fileID);
 82        end
 83    end
 84end
 85
 86% Create the input creator function file:
 87fullFileName = sprintf('%s.m',model_input + "_creator"  );
 88fileID = fopen(fullFileName, 'wt');
 89
 90% Write the content of the input creator function:
 91fprintf(fileID, "function " + stg.name + "_input_creator(~)\n");
 92helper = 0;
 93for Exp_n = 1:size(sbtab.datasets,2)
 94    for index =1:size(sbtab.datasets(Exp_n).input,2)
 95        if size(sbtab.datasets(Exp_n).input_value{index},2) > 100
 96            input_name = strrep(modelobj.species(1+str2double(strrep(...
 97                sbtab.datasets(Exp_n).input(index),'S',''))).name,".","");
 98            if helper == 0
 99                helper = 1;
100                helper2 = Exp_n;
101            end
102            % Write code to the input creator function file, using either
103            % template2() or template3() functions:
104            if index == 1 && Exp_n == helper2
105                fprintf(fileID,"load('" + data_model + "','sbtab');\n");
106                inp_creator_str = template2();
107                inp_creator_str = replace(inp_creator_str,...
108                    ["Exp_n", "input_name", "index", "inp_model_data"],...
109                    [Exp_n, input_name, index, inp_model_data]);
110            else
111                inp_creator_str = template3();
112                inp_creator_str = replace(inp_creator_str,...
113                    ["Exp_n", "input_name", "index", "inp_model_data"],...
114                    [Exp_n, input_name, index, inp_model_data]);
115            end
116            fprintf(fileID,inp_creator_str);
117        end
118    end
119end
120fprintf(fileID, "end\n");
121fclose(fileID);
122
123eval(stg.name + "_input_creator()");
124end
125
126% The template1() function generates the code for the input functions,
127% which calculate the input based on the simulation time.
128function inp_str = template1()
129inp_str =...
130    "function thisAmp = SBtab_name_inputExp_n_input_name(times)\n"+...
131    "persistent input_X\n"+...
132    "persistent input_T\n"+...
133    "persistent input_h1\n"+...
134    "persistent input_h2\n"+...
135    "if isempty(input_X)\n"+...
136    "Data = coder.load('inp_model_data','expExp_n_input_name');\n"+...
137    "input_X = Data.expExp_n_input_name(:,2);\n"+...
138    "input_T = Data.expExp_n_input_name(:,1);\n"+...
139    "input_h2 = input_T(2)-input_T(1);\n"+...
140    "input_h1 = 1;\n"+...
141    "thisAmp = input_X(1);\n"+...
142    "elseif times <= 0\n"+...
143    "thisAmp = input_X(1);\n"+...
144    "elseif times >= 20\n"+...
145    "thisAmp = input_X(end);\n"+...
146    "else\n"+...
147    "while times > input_T(input_h1)\n"+...
148    "input_h1 = input_h1 + 1;\n"+...
149    "end\n"+...
150    "while times < input_T(input_h1-1)\n"+...
151    "input_h1  = input_h1-1;\n"+...
152    "end\n"+...
153    "input_h3 = (input_T(input_h1)-times)/input_h2;\n"+...
154    "thisAmp = input_X(input_h1-1)*input_h3 + input_X(input_h1)*(1-input_h3);\n"+...
155    "end\n"+...
156    "end";
157end
158   
159% The template2() function generates the code for the first input of the
160% first experiment in the "_input_creator()" function.
161function inp_creator_str = template2()
162inp_creator_str = ...
163    "expExp_n_input_name(:,1) = sbtab.datasets(Exp_n).input_time{index};\n"+...
164    "expExp_n_input_name(:,2) = sbtab.datasets(Exp_n).input_value{index};\n"+...
165    "save('inp_model_data','expExp_n_input_name');\n";
166end
167
168% The template3() function generates the code for the rest of the inputs in
169% the "_input_creator()" function.
170function inp_creator_str = template3()
171inp_creator_str = ...
172    "expExp_n_input_name(:,1) = sbtab.datasets(Exp_n).input_time{index};\n"+...
173    "expExp_n_input_name(:,2) = sbtab.datasets(Exp_n).input_value{index};\n"+...
174    "save('inp_model_data','expExp_n_input_name','-append');\n";
175end

The f_setup_input function is designed to generate code for loading experiment inputs into a .mat file and create code to read these inputs during the simulation of the experiments. The generated code is stored in the “Input_functions” folder.

param stg:

A structure containing information about the simulation settings.

type stg:

structure

param mmf:

A structure containing information about the model, including the model data, main folder, and input functions.

type mmf:

structure

return:

This function creates input function files and an input creator function file in the “Input_functions” folder. The input functions are used to calculate input values based on the simulation time, while the input creator function is used to create input data from the sbtab.datasets.

rtype:

None

The function calls the following helper functions:

  • template1: Generates code for input functions.

  • template2: Generates code for the first input of the first experiment in the input creator function.

  • template3: Generates code for the rest of the inputs in the input creator function.

The function loads the following variables:

  • matlab_model: Loaded from mmf.model.data.mat_model.

  • data_model: Loaded from mmf.model.data.data_model.

  • inp_model_data: Loaded from mmf.model.data.input_model_data.

  • Model_folder: Loaded from mmf.model.main.

  • model_input: Loaded from mmf.model.input_functions.input.

  • sbtab: Loaded from the data_model file.

  • modelobj: Loaded from the matlab_model file.

f_build_model_exp

Code

  1function f_build_model_exp(stg,sb,mmf)
  2% This function generates .mat files for equilibrium and proper simulation
  3% runs for a set of experiments. It reads experiment settings from an sbtab
  4% structure, configures the simulation settings, processes input and output
  5% species, and saves the resulting .mat files.
  6%
  7% Inputs:
  8% - stg: A structure containing settings for the simulations, including
  9% maximum wall clock time, stop times, dimensional analysis, unit
 10% conversion, tolerances, step sizes, and time units.
 11% - sb: An sbtab structure containing information about experiments, such
 12% as output values, output species, output units, input times, input
 13% values, and input species.
 14% - mmf: A model management framework structure containing the data and mat
 15% models, which include data_model, mat_model, model_exp_eq,
 16% model_exp_default, and model_exp_detail.
 17%
 18% Outputs:
 19% - Equilibrium and proper simulation run .mat files for each experiment,
 20% saved with filenames based on model_exp_eq, model_exp_default, and
 21% model_exp_detail.
 22%
 23% Called Functions:
 24% - getconfigset: Retrieves the configuration set object from a SimBiology
 25% model.
 26% - copyobj: Creates a copy of a SimBiology model object.
 27% - set: Sets properties of a SimBiology object.
 28% - load: Loads variables from .mat files.
 29% - save: Saves variables to .mat files.
 30% - addspecies: Adds species to a SimBiology model compartment.
 31% - addrule: Adds rules to a SimBiology model.
 32% - addparameter: Adds parameters to a SimBiology model.
 33% - addevent: Adds events to a SimBiology model.
 34% 
 35% Variables:
 36% Loaded:
 37% - data_model: File path of the data_model .mat file containing Data and
 38% sbtab.
 39% - mat_model: File path of the mat_model .mat file containing the
 40% SimBiology model object.
 41% - model_exp_eq: File path prefix for saving equilibrium simulation run
 42% .mat files.
 43% - model_exp_default: File path prefix for saving proper simulation run
 44% .mat files.
 45% - model_exp_detail: File path prefix for saving detailed simulation run
 46% .mat files.
 47% - Data: Data structure containing experiment time points.
 48% - sbtab: sbtab structure containing experiment settings and information.
 49% - modelobj: SimBiology model object loaded from the mat_model file.
 50%
 51% Initialized:
 52% - None
 53%
 54% Persistent:
 55% - None
 56%
 57% Notes:
 58% - The function iterates through all experiments, configuring simulation
 59% settings and processing species for each experiment, then saves the
 60% corresponding .mat files.
 61
 62% Load data_model and mat_model files
 63data_model = mmf.model.data.data_model;
 64mat_model = mmf.model.data.mat_model;
 65model_exp_eq = mmf.model.data.model_exp.equilibration;
 66model_exp_default = mmf.model.data.model_exp.default;
 67model_exp_detail = mmf.model.data.model_exp.detail;
 68
 69% Load Data and modelobj from data_model and mat_model files
 70load(data_model,'Data','sbtab')
 71load(mat_model,'modelobj');
 72
 73% Initialize model_run and configsetObj arrays
 74model_run = cell(size(sb.Experiments.ID,1),1);
 75configsetObj = cell(size(sb.Experiments.ID,1),1);
 76
 77% Loop through all experiments
 78for number_exp = 1:size(sb.Experiments.ID,1)
 79    
 80    % Load sbtab dataset information
 81    output_value = sbtab.datasets(number_exp).output_value;
 82    output = sbtab.datasets(number_exp).output;
 83    output_unit = sbtab.datasets(number_exp).output_unit;
 84    input_time = sbtab.datasets(number_exp).input_time;
 85    input_value = sbtab.datasets(number_exp).input_value;
 86    input_species = sbtab.datasets(number_exp).input;
 87    
 88    % Initialize model and configuration set objects for the current experiment
 89    model_run{number_exp} = copyobj(modelobj);
 90    configsetObj{number_exp} = getconfigset(model_run{number_exp});
 91    
 92    % Configure simulation settings for the equilibrium simulation run
 93    set(configsetObj{number_exp}, 'MaximumWallClock', stg.maxt);
 94    set(configsetObj{number_exp}, 'StopTime', stg.eqt);
 95    set(configsetObj{number_exp}.CompileOptions,...
 96        'DimensionalAnalysis', stg.dimenanal);
 97    set(configsetObj{number_exp}.CompileOptions,...
 98        'UnitConversion', stg.UnitConversion);
 99    set(configsetObj{number_exp}.SolverOptions,...
100        'AbsoluteToleranceScaling', stg.abstolscale);
101    set(configsetObj{number_exp}.SolverOptions,...
102        'RelativeTolerance', stg.reltol);
103    set(configsetObj{number_exp}.SolverOptions,...
104        'AbsoluteTolerance', stg.abstol);
105    set(configsetObj{number_exp}.SolverOptions,...
106        'AbsoluteToleranceStepSize', stg.abstolstepsize_eq);
107    set(configsetObj{number_exp}.SolverOptions, 'OutputTimes', stg.eqt);
108    set(configsetObj{number_exp}, 'TimeUnits', stg.simtime);
109    set(configsetObj{number_exp}.SolverOptions, 'MaxStep', stg.maxstepeq);
110
111    % Save equilibrium simulation run .mat file
112    model_exp = model_run{number_exp};
113    config_exp = configsetObj{number_exp};
114    save(model_exp_eq + number_exp + ".mat",'model_exp','config_exp')
115    
116    % Update simulation settings for the proper simulation run
117    set(configsetObj{number_exp}, 'StopTime', sbtab.sim_time(number_exp));
118    set(configsetObj{number_exp}.SolverOptions, 'OutputTimes',...
119        Data(number_exp).Experiment.t);
120    set(configsetObj{number_exp}.SolverOptions, 'MaxStep', stg.maxstep);
121    
122    % Process output species. Adds output species and rules
123    for n = 1:size(output,2)
124        % Check if output species exist in the model
125        m = 0;
126        for k = 1:size(model_run{number_exp}.species,1)
127            if model_run{number_exp}.species(k).name == string(output{1,n})
128                model_run{number_exp}.species(k).BoundaryCondition = 1;
129                m = 1;
130            end
131        end
132        % If output species does not exist, add it to the model
133        if m == 0
134            if strcmp( output_unit{1,n},'dimensionless' )
135                warning('off','SimBiology:InvalidSpeciesInitAmtUnits')
136            else
137                warning('on','SimBiology:InvalidSpeciesInitAmtUnits')
138            end
139            addspecies (model_run{number_exp}.Compartments(1),...
140                char(output{1,n}),0,...
141                'InitialAmountUnits',output_unit{1,n});
142        end
143        % Add repeated assignment rule for output species
144        addrule(model_run{number_exp}, char(output_value{1,n}),...
145            'repeatedAssignment');
146    end
147    
148    % Process input species. Adds input species and rules, either as events
149    % or repeated assignments
150    for j = 1:size(input_species,2)
151        
152        input_indexcode = str2double(strrep(input_species(j),'S',''));
153        input_name = string(model_run{number_exp}.species(1 +...
154                input_indexcode).name);
155        
156        % If the input time is less than 100, add events
157        if size(input_time{j},2) < 100
158            
159            model_run{number_exp}.species(...
160                1 + input_indexcode).BoundaryCondition = 1;
161            for n = 1:size(input_time{j},2)
162                if ~isnan(input_time{j}(n))
163
164                    % Add parameters for time and input values
165                    addparameter(model_run{number_exp},char("time_event_t_" + j + "_" +  n),...
166                        str2double(string(input_time{j}(n))),...
167                        'ValueUnits',char(stg.simtime));
168                    
169                    addparameter(model_run{number_exp},char("time_event_r_" + j + "_" +  n),...
170                        str2double(string(input_value{j}(n))),...
171                        'ValueUnits',char(model_run{number_exp}.species(1 +...
172                        input_indexcode).InitialAmountUnits));
173
174                    % Add event for input species
175                    addevent(model_run{number_exp}, ...
176                        char("time>=time_event_t_" + j + "_" +  n),...
177                        cellstr(sbtab.datasets(number_exp).output_location{1} +...
178                        "." + input_name + " = time_event_r_" + j + "_" +  n));
179                end
180            end
181        else
182            % If the input time is greater than or equal to 100, add repeated assignment rule
183            addrule(model_run{number_exp}, char(sbtab.datasets(...
184                number_exp).output_location{1} + "." + input_name +...
185                "=" + string(model_run{number_exp}.name)+ "_input" + ...
186                number_exp + "_" + input_name + "(time)"), 'repeatedAssignment');
187        end
188    end
189
190    % Save proper simulation run .mat file (default)
191    model_exp = model_run{number_exp};
192    config_exp = configsetObj{number_exp};
193    save(model_exp_default + number_exp + ".mat",'model_exp','config_exp')
194
195    % Update simulation settings for detailed simulation run
196    set(configsetObj{number_exp}.SolverOptions,'OutputTimes', []);
197    set(configsetObj{number_exp}.SolverOptions,'MaxStep', stg.maxstepdetail);
198
199    % Save detailed simulation run .mat file
200    model_exp = model_run{number_exp};
201    config_exp = configsetObj{number_exp};
202    save(model_exp_detail + number_exp + ".mat",'model_exp','config_exp')
203    
204end
205end

Creates two .mat files for each experiment, one for the equilibrium simulation run and one for the proper simulation. These files have all the added rules, species and parameters needed depending on the inputs and outputs specified on the SBtab.

Function: f_build_model_exp Description: This function creates two .mat files for each experiment: one for the equilibrium simulation run and one for the proper run. The .mat files contain necessary rules, species, and parameters based on the inputs and outputs specified in the sbtab. The function also configures simulation settings for the equilibrium and proper simulation runs, processes output and input species, and saves the .mat files for each experiment.

Inputs: - stg: A structure containing settings for the simulations - sb: An sbtab structure containing information about experiments - mmf: A model management framework structure containing the data and mat models

Outputs: - .mat files for equilibrium and proper runs for each experiment

Called Functions: - getconfigset - copyobj - set - load - save - addspecies - addrule - addparameter - addevent

Loaded Variables: - data_model - mat_model - model_exp_eq - model_exp_default - model_exp_detail - Data - sbtab - modelobj

Notes: - The function has a loop that iterates through all experiments and saves the corresponding .mat files.

Usage example:

% Initialize stg, sb, and mmf structures
stg = ...
sb = ...
mmf = ...

% Call the f_build_model_exp function
f_build_model_exp(stg, sb, mmf);

This will create .mat files for equilibrium and proper runs for each experiment based on the information provided in the stg, sb, and mmf structures. The function f_build_model_exp processes the input structures stg, sb, and mmf to create .mat files for each experiment. The stg structure contains simulation settings such as time units, maximum wall clock, and tolerances. The sb structure contains information about the experiments, while the mmf structure contains data and mat models.

The function loads data from the data_model and mat_model files and initializes arrays for model_run and configsetObj. It then iterates through all experiments, configuring the simulation settings for both the equilibrium and proper simulation runs.

For each experiment, the function processes the output species, adding them to the model if they don’t already exist and setting up the appropriate rules. It then processes the input species, adding them either as events or repeated assignments based on the input time.

Finally, the function saves the .mat files for each experiment, creating separate files for the equilibrium, proper (default), and detailed simulation runs.