Analysis
f_analysis
Code
1function [rst,stg] = f_analysis(stg,analysis,mmf,analysis_options,rst) 2% This function performs a specific analysis based on the given analysis 3% options. The function calls the appropriate analysis functions 4% (f_diagnostics, f_opt, f_sim_score, f_lsa, f_gsa, f_PL_m) depending on 5% the selected analysis type. The analysis results are stored in an updated 6% 'rst' structure, and the settings are updated as needed. 7% 8% Inputs: 9% - stg: Settings to use in the analysis 10% - analysis: Type of analysis to be performed 11% - mmf: Main model files 12% - analysis_options: List of possible analysis options 13% - rst: Structure for storing analysis results 14% 15% Outputs: 16% - rst: Updated structure containing the results of the analysis 17% - stg: Updated settings after the analysis 18% 19% Used Functions: 20% - f_diagnostics: Performs diagnostic analysis 21% - f_opt: Performs optimization analysis 22% - f_sim_score: Runs simulation for a given option 23% - f_lsa: Performs Local sensititivity Analysis (LSA) 24% - f_gsa: Performs Global ensititivity Analysis (GSA) 25% - f_PL_m: Performs Profile Likelihood Analysisa (PLA) 26% 27% Variables: 28% Initialized: 29% - matching_option_idx: Index of the selected analysis option 30% - sim_results: Cell array for storing simulation results 31% - valid_options: Array of valid optimization options 32% 33% Persistent: None 34% analysis 35% analysis_options 36% matching_option_idx 37matching_option_idx = find(contains(analysis_options, analysis), 1); 38 39% display start message 40disp("Starting " + {analysis_options(matching_option_idx)}) 41 42% Perform the analysis based on the current analysis option index 43switch matching_option_idx 44 case 1 45 % run diagnostic analysis 46 rst.diag = f_diagnostics(stg,mmf); 47 case 2 48 % run optimization analysis 49 [rst.opt,pa] = f_opt(stg,mmf); 50 % find valid optimization options 51 valid_options = find(pa(:,1) ~= 0); 52 % update settings with valid options 53 stg.pat = transpose(valid_options); 54 % create cell array for simulation results 55 sim_results = cell(length(valid_options),1); 56 % parallelize simulation runs 57 for j = stg.pat 58 % run simulation for current valid option 59 [~,sim_results{j},~] = f_sim_score(pa(j,:),stg,mmf); 60 end 61 % store simulation results in results structure 62 rst.diag(stg.pat) = [sim_results{:}]; 63 case 3 64 % run LSA analysis 65 rst.lsa = f_lsa(stg,mmf); 66 case 4 67 % run GSA analysis 68 rst.gsa = f_gsa(stg,mmf); 69 case 5 70 % run PLA analysis 71 rst.PLA = f_PL_m(stg,mmf); 72end 73 74% display completion message 75disp(analysis_options(matching_option_idx) + " completed successfully") 76end
The f_analysis function performs a specific analysis based on the given analysis options. It takes settings, analysis type, main model files, a list of possible analysis options, and a structure for storing analysis results as input arguments. The function outputs the results of the analysis and updates the settings as needed. The function calls the appropriate analysis functions (f_diagnostics, f_opt, f_sim_score, f_lsa, f_gsa, f_PL_m) depending on the selected analysis type.
Inputs
stg: Settings to use in the analysis.
analysis: Type of analysis to be performed.
mmf: Main model files.
analysis_options: List of possible analysis options.
rst: Structure for storing analysis results.
Outputs
rst: Updated structure containing the results of the analysis.
stg: Updated settings after the analysis.
Usage
[rst, stg] = f_analysis(stg, analysis, mmf, analysis_options, rst)
Example
settings = :ref:`stg<stg>`;
analysis_type = 'diagnostics';
model_files = 'path/to/model/files';
options = ["Diagnostics","Parameter Estimation",...
"Local Sensitivity Analysis","Global Sensitivity Analysis",...
"Profile Likelihood Analysis","Reproduce a previous analysis",...
"Reproduce the plots of a previous analysis","Import model files"];
results = :ref:`stg<stg>`;
[results, settings] = f_analysis(settings, analysis_type, model_files, options, results);
Diagnostics
f_diagnostics
Code
1function rst = f_diagnostics(stg,mmf) 2% Description: This function runs a model for given parameters and 3% settings, and computes the scores for fitness, both in multi-core and 4% single-core mode. The function uses f_sim_score() to obtain the score for 5% each parameter array. The mode (multi-core or single-core) is determined 6% by the 'optmc' field in the 'stg' input. 7% 8% Inputs: 9% - stg: A structure containing settings for the model, such as: 10% * pa: An array of parameter arrays to be tested. 11% * pat: Indices of the parameter arrays to be tested. 12% * optmc: A boolean flag, if true the function runs in multi-core 13% mode, otherwise it runs in single-core mode. 14% - mmf: A custom memory-mapped file object, used for reading or writing 15% data. 16% 17% Outputs: 18% - rst: A vector containing the computed scores for each parameter array. 19% 20% Used Functions: 21% - f_sim_score: A function that takes a parameter array, model settings 22% (stg), and a custom memory-mapped file object (mmf) as inputs and returns 23% the computed score for that parameter array. 24% 25% Variables: 26% Loaded: 27% (None) 28% 29% Initialized: 30% - par_array_idx: The current index of the parameter array being tested. 31% 32% Persistent: 33% (None) 34 35% Run the model and obtain scores for fitness Multi Core 36if stg.optmc 37 disp("Running the model and obtaining Scores (Multicore)") 38 39 pa = stg.pa; 40 % Iterate over the parameter arrays to be tested 41 parfor par_array_idx = stg.pat 42 [~,rst(par_array_idx),~] =... 43 f_sim_score(pa(par_array_idx,:),stg,mmf); 44 end 45 46 % Run the model and obtain scores for fitness single Core 47else 48 disp("Running the model and obtaining Scores (Singlecore)") 49 50 % Iterate over the parameter arrays to be tested 51 for par_array_idx = stg.pat 52 [~,rst(par_array_idx),~] =... 53 f_sim_score(stg.pa(par_array_idx,:),stg,mmf); 54 end 55end 56end
Inputs
Outputs - rst (diagnostics results)
Optimization
f_opt
Code
1function [result,parameter_array] = f_opt(settings,model_folders) 2% This function performs optimization on a given objective function using 3% different optimization algorithms. The available algorithms include 4% fmincon, Simulated annealing, Pattern search, Genetic algorithm, Particle 5% swarm, and Surrogate optimization. It iterates through the 6% optimization_algorithms cell array and calls the appropriate optimization 7% algorithm if its flag is set in the 'settings'. 8% 9% Inputs: 10% - settings: A struct containing settings for the optimization algorithms. 11% - model_folders: An array containing information about the models to be 12% optimized. 13% 14% Outputs: 15% - result: A vector containing the results of each optimization algorithm. 16% - parameter_array: A matrix containing the parameters for each 17% optimization algorithm result. 18% 19% Used Functions: 20% - run_algorithm: Handles the execution of a specific optimization 21% algorithm. 22% - optimize_algorithm: Sets up the optimization algorithm and executes it. 23% - run_optimization: Runs the selected optimization algorithm with 24% appropriate settings. 25% - run_optimizer: Executes the chosen optimization algorithm. 26% - prepare_optimization_options: Prepares the optimization options based 27% on the algorithm. 28% - get_plot_functions: Returns the appropriate plotting function for the 29% optimization algorithm. 30% - f_opt_start: Returns the starting point and the starting population for 31% optimization algorithms. 32% 33% Loaded Variables: 34% - optimization_algorithms: A cell array containing optimization algorithm 35% names and flags. 36% - algorithm_flag: The flag corresponding to the optimization algorithm. 37% - objective_function: A function handle to the objective function for 38% optimization. 39% - options: A struct containing options for the optimization algorithm. 40% - plot_functions: A cell array containing plot functions specific to each 41% optimization algorithm. 42 43 44% Set the random seed for reproducibility 45rng(settings.rseed); 46 47% Initialize the cell array containing optimization algorithm names and 48% corresponding settings flags 49optimization_algorithms = { 50 'Genetic algorithm', 'ga'; 51 'fmincon', 'fmincon'; 52 'Simulated annealing', 'sa'; 53 'Pattern search', 'psearch'; 54 'Particle swarm', 'pswarm'; 55 'Surrogate optimization', 'sopt' 56 }; 57 58p = gcp(); % If no pool, do not create new one. 59poolsize = p.NumWorkers; 60settings.pat = 1:poolsize; 61for n = 1:poolsize 62settings.pa(n,:) = settings.pa(1,:); 63end 64parfor n = 1:poolsize 65[~] = f_diagnostics(settings,model_folders); 66end 67 68% Iterate through the optimization_algorithms cell array and call the 69% corresponding algorithms if their flag is set in the settings 70for i = 1:size(optimization_algorithms, 1) 71 % algorithm_func = optimization_algorithms{i, 1}; 72 algorithm_flag = optimization_algorithms{i, 2}; 73 74 if settings.(algorithm_flag) 75 [result(i), parameter_array(i, :)] = ... 76 run_algorithm(@optimize_algorithm,... 77 optimization_algorithms{i, 1}, settings, model_folders); 78 end 79end 80end 81 82function [algorithm_result, algorithm_parameter_array] =... 83 run_algorithm(algorithm_func, optimization_algorithms_names,... 84 settings, model_folders) 85 86% Define the objective function 87objective_function = @(x)f_sim_score(x, settings, model_folders); 88 89% Call the optimization algorithm 90algorithm_result = algorithm_func(optimization_algorithms_names,... 91 settings, objective_function); 92 93% Find the minimum value and its corresponding parameters 94[~, min_index] = min(algorithm_result.fval); 95algorithm_parameter_array = algorithm_result.x(min_index, :); 96end 97 98function result_opt = optimize_algorithm(algorithm_name,... 99 settings, objective_function) 100p = gcp(); % If no pool, do not create new one. 101poolsize = p.NumWorkers; 102mst = settings.mst; 103if contains(algorithm_name,{'fmincon','Simulated annealing','Pattern search','Surrogate optimization'}) 104settings.mst = true; 105settings.msts = poolsize; 106else 107settings.mst = mst; 108settings.msts = poolsize; 109end 110% Determine the starting point for the optimization 111[startpoint, ~, spop] = f_opt_start(settings); 112 113% Prepare optimization options based on settings and algorithm_name 114options = prepare_optimization_options(settings, algorithm_name); 115 116% Execute the optimization algorithm 117[x, fval, exitflag, output] = run_optimization(settings, algorithm_name,... 118 objective_function, startpoint, spop, settings.lb,... 119 settings.ub, options); 120 121% Save optimization results 122result_opt.name = algorithm_name; 123result_opt.x = x; 124result_opt.fval = fval; 125result_opt.exitflag = exitflag; 126result_opt.output = output; 127end 128 129function [x, fval, exitflag, output] = run_optimization(settings,... 130 algorithm_name, objective_function, startpoint, spop, lb, ub,... 131 options) 132 133% Run the optimization algorithm using either multiple starting points (mst) 134% or a single starting point (the average of the lower and upper bounds) 135if settings.mst 136 parfor n = 1:settings.msts 137 disp(string(n)) 138 [x(n,:), fval(n), exitflag(n), output(n)] = ... 139 run_optimizer(algorithm_name, objective_function,... 140 startpoint(n,:), spop{n}, lb, ub, options); 141 end 142else 143 [x(1,:), fval(1), exitflag(1), output(1)] = ... 144 run_optimizer(algorithm_name, objective_function,... 145 (lb + ub) / 2, spop, lb, ub, options); 146end 147end 148 149function [x, fval, exitflag, output] = ... 150 run_optimizer(algorithm_name, objective_function, startpoint, spop,... 151 lb, ub, options) 152 153% Execute the appropriate optimization algorithm based on algorithm_name 154switch algorithm_name 155 case 'fmincon' 156 [x, fval, exitflag, output] = ... 157 fmincon(objective_function, startpoint, [], [], [], [], lb, ub, [], options); 158 case 'Simulated annealing' 159 [x, fval, exitflag, output] = ... 160 simulannealbnd(objective_function, startpoint, lb, ub, options); 161 case 'Pattern search' 162 [x, fval, exitflag, output] = ... 163 patternsearch(objective_function, startpoint, ... 164 [], [], [], [], lb, ub, [], options); 165 case 'Genetic algorithm' 166 parnum = length(lb); 167 [x, fval] = ga(objective_function, parnum, ... 168 [], [], [], [], lb, ub, [], options); 169 exitflag = [" "]; 170 output = [" "]; 171 case 'Particle swarm' 172 parnum = length(lb); 173 [x, fval, exitflag, output] = ... 174 particleswarm(objective_function, parnum, lb, ub, options); 175 case 'Surrogate optimization' 176 options.InitialPoints = spop; 177 [x, fval, exitflag, output] = ... 178 surrogateopt(objective_function, lb, ub, options); 179 otherwise 180 error('Unsupported optimization algorithm.'); 181end 182end 183 184function options = prepare_optimization_options(settings, algorithm_name) 185 186% Set options for each algorithm 187switch algorithm_name 188 case 'fmincon' 189 options = settings.fm_options; 190 options.UseParallel = settings.optmc; 191 case 'Simulated annealing' 192 options = settings.sa_options; 193 options.MaxTime = settings.optt; 194 options.InitialTemperature = ones(1,settings.parnum)*2; 195 case 'Pattern search' 196 options = settings.psearch_options; 197 options.MaxTime = settings.optt; 198 options.UseParallel = settings.optmc; 199 case 'Genetic algorithm' 200 options = settings.ga_options; 201 options.MaxTime = settings.optt; 202 options.PopulationSize = settings.popsize; 203 options.UseParallel = settings.optmc; 204 [~,startpop,~] = f_opt_start(settings); 205 options.InitialPopulationMatrix = startpop; 206 case 'Particle swarm' 207 options = settings.pswarm_options; 208 options.MaxTime = settings.optt; 209 options.SwarmSize = settings.popsize; 210 options.UseParallel = settings.optmc; 211 [~,startpop,~] = f_opt_start(settings); 212 options.InitialSwarmMatrix = startpop; 213 case 'Surrogate optimization' 214 options = settings.sopt_options; 215 options.MaxTime = settings.optt; 216 options.UseParallel = settings.optmc; 217 otherwise 218 error('Unsupported optimization algorithm.'); 219end 220 221% Enable plots if chosen in settings 222if settings.optplots 223 % Set the appropriate PlotFcn based on the optimization algorithm 224 options.PlotFcn = get_plot_functions(algorithm_name); 225end 226 227% Enable console messages if chosen in settings 228if settings.optcsl 229 options.Display = 'iter'; 230end 231end 232 233function plot_functions = get_plot_functions(algorithm_name) 234 235% Set the appropriate PlotFcn based on the optimization algorithm 236switch algorithm_name 237 case 'fmincon' 238 plot_functions = ... 239 {@optimplotx, @optimplotfunccount, @optimplotfval, ... 240 @optimplotstepsize, @optimplotfirstorderopt}; 241 case 'Simulated annealing' 242 plot_functions = ... 243 {@saplotbestf, @saplottemperature, @saplotf, ... 244 @saplotstopping, @saplotx}; 245 case 'Pattern search' 246 plot_functions = ... 247 {@psplotbestf, @psplotfuncount, @psplotmeshsize, @psplotbestx}; 248 case 'Genetic algorithm' 249 plot_functions = ... 250 {@gaplotbestf, @gaplotexpectation, @gaplotrange, ... 251 @gaplotscorediversity, @gaplotstopping, ... 252 @gaplotscores, @gaplotdistance, @gaplotselection}; 253 case 'Particle swarm' 254 plot_functions = {@pswplotbestf}; 255 case 'Surrogate optimization' 256 plot_functions = {@surrogateoptplot}; 257 otherwise 258 error('Unsupported optimization algorithm.'); 259end 260end 261 262function [spoint,spop_mc,spop_sc] = f_opt_start(stg) 263% Set the randomm seed for reproducibility 264rng(stg.rseed); 265 266% Optimization Start method 1 267if stg.osm == 1 268 269 % Get a random starting point or group of starting points, if using 270 % multistart, inside the bounds 271 spoint = lhsdesign(stg.msts,stg.parnum).*(stg.ub-stg.lb)+stg.lb; 272 273 % Get a group of ramdom starting points inside the bounds 274 spop_mc = lhsdesign(stg.popsize,stg.parnum).*(stg.ub-stg.lb)+stg.lb; 275 276 % Get a group of ramdom starting points inside the bounds 277 for n = 1:stg.msts 278 spop_sc{n} = lhsdesign(ceil(stg.popsize/36),stg.parnum).*(stg.ub-stg.lb)+stg.lb; 279 end 280 % Optimization Start method 2 281elseif stg.osm == 2 282 283 % Get a random starting point or group of starting points, if using 284 % multistart, near the best point 285 spoint = stg.bestpa - stg.dbs +... 286 (stg.dbs*2*lhsdesign(stg.msts,stg.parnum)); 287 288 % Get a group of ramdom starting points near the best point 289 spop_mc = stg.bestpa - stg.dbs +... 290 (stg.dbs*2*lhsdesign(stg.popsize,stg.parnum)); 291 292 for n = 1:stg.msts 293 spop_sc{n} = stg.bestpa - stg.dbs +... 294 (stg.dbs*2*lhsdesign(ceil(stg.popsize/36),stg.parnum)); 295 end 296end 297end
Calls the correct optmizer or optimizers that have been chosen in the settings file.
Inputs
Outputs - rst (optimization results)
f_opt_start
Code
Inputs
Outputs
spoint - (double) starting parameter set for the optimization
spop - (double) Starting parameter sets for multiple start optimizations
f_opt_fmincon/sa/psearch/ga/pswarm/sopt
Code
f_opt_fmincon
f_opt_sa
f_opt_psearch
f_opt_ga
f_opt_pswarm
f_opt_sopt
These functions call built in MATLAB® functions that perform parameter optimization . For furher information relating to how these optimizers work please follow the links to the MATLAB® documentation. Optimizers used:
f_opt_fmincon - fmincon
f_opt_sa - Simmulated annealing
f_opt_psearch - Pattern search
f_opt_ga - Genetic algorihtm
f_opt_pswarm - Particle swarm
f_opt_sopt - Surrogate optmization
Inputs - stg
Outputs - Optimization results
Global Sensitivity Analysis
f_gsa
Code
1function results = f_gsa(settings,model_folders) 2% f_gsa - Performs global sensitivity analysis (GSA) using the 3% Sobol-Saltelli method on a given model 4% 5% This function conducts a GSA based on the Sobol-Saltelli method for a 6% given model, as inspired by Geir Halnes et al.'s 2009 paper (J. comp. 7% neuroscience 27.3 (2009): 471). The function takes two inputs: 8% 'settings', a structure containing various settings for the analysis, and 9% 'model_folders', the model folders structure. The function returns 10% 'results', a structure containing the GSA results, including sensitivity 11% indices (Si) and total sensitivity indices (SiT) for each score type. 12% 13% Inputs: 14% - settings: A structure containing settings for the GSA, such as 15% parameter bounds, sampling mode, and random seed. 16% - model_folders: A structure containing the necessary model folder paths. 17% 18% Outputs: 19% - results: A structure containing the GSA results, including sensitivity 20% indices (Si) and total sensitivity indices (SiT) for each score type. 21% 22% Functions called: 23% - f_make_par_samples(settings): Generates sample matrices of model 24% parameters. 25% - f_make_output_sample(results, settings, model_folders): Calculates the 26% outputs for three different matrices (GSA M1, GSA M2, and GSA N) based on 27% the input parameters, settings, and mathematical model. 28% - f_calc_sensitivities(results, settings): Removes simulation errors 29% from the data and calculates Si and SiT using the bootstrap method. 30 31results = f_make_par_samples(settings); 32 33results = f_make_output_sample(results,settings,model_folders); 34 35results = f_calc_sensitivities(results,settings); 36end
Calls the global sensitivity analysis functions in the correct order.
f_make_par_samples
Code
1function results= f_make_par_samples(settings) 2% This function creates sample matrices of model parameters according to 3% specified distributions and settings, based on Geir Halnes et al.'s 2009 4% paper (J. comp. neuroscience 27.3 (2009): 471). It generates two sample 5% matrices M1 and M2, and a 3D matrix N, where N(:,:,i) is M2 with its i:th 6% column replaced by M1(:,i). 7% 8% Inputs: 9% - settings: A structure containing fields for generating samples, 10% including sansamples, parnum, rseed, sasamplemode, lb, ub, bestpa, and 11% sasamplesigma. 12% 13% Outputs: 14% - results: A structure containing the following fields: 15% - M1: Sample matrix 1. 16% - M2: Sample matrix 2. 17% - N: A 3D matrix where N(:,:,i) is M2 with its i:th column replaced by 18% M1(:,i). 19% 20% Functions called: 21% - makedist: Create a probability distribution object. 22% - truncate: Truncate a probability distribution. 23% - random: Generate random numbers from a probability distribution. 24% 25% Variables: 26% Initialized: 27% - M1: Sample matrix 1. 28% - M2: Sample matrix 2. 29% - N: A 3D matrix where N(:,:,i) is M2 with its i:th column replaced by 30% M1(:,i). 31% - pd: An array of probability distribution objects for each parameter. 32% 33% Loaded (from settings structure): 34% - sansamples: Number of samples to generate for each parameter. 35% - parnum: Number of model parameters. 36% - rseed: Seed for the random number generator. 37% - sasamplemode: Sampling mode. 38% - lb: Vector containing lower bounds for each parameter. 39% - ub: Vector containing upper bounds for each parameter. 40% - bestpa: Vector containing the best parameter values. 41% - sasamplesigma: Standard deviation for normal distribution-based 42% sampling modes. 43 44% Pre-allocate memory for sample matrices 45M1 = zeros(settings.sansamples, settings.parnum); 46M2 = zeros(settings.sansamples, settings.parnum); 47N = zeros(settings.sansamples, settings.parnum, settings.parnum); 48rng(settings.rseed) 49 50% Loop through each parameter and create a distribution based on the 51% specified settings(Note that the sampling is being performed in log space 52% as the parameters and its bounds are in log space) 53for i = 1:settings.parnum 54 % Initialize distribution parameters depending on the sample mode 55 switch settings.sasamplemode 56 case 0 57 % Uniform distribution with bounds defined by parameter limits 58 lb = settings.lb(i); 59 ub = settings.ub(i); 60 case {1, 2} 61 % Normal distribution centered at the best parameter value with 62 % specified standard deviation 63 mu = settings.bestpa(i); 64 sigma = settings.sasamplesigma; 65 case {3, 4} 66 % Normal distribution centered at the mean of parameter bounds 67 % with specified standard deviation 68 mu = settings.lb(i) + (settings.ub(i) - settings.lb(i)) / 2; 69 sigma = settings.sasamplesigma; 70 end 71 % Generate samples based on the distribution parameters 72 if settings.sasamplemode == 0 73 % Uniform distribution 74 M1(:, i) = lb + (ub - lb) .* rand(1, settings.sansamples); 75 M2(:, i) = lb + (ub - lb) .* rand(1, settings.sansamples); 76 else 77 % Normal distribution 78 pd(i) = makedist('Normal', 'mu', mu, 'sigma', sigma); 79 80 % Truncate the distribution if specified 81 if ismember(settings.sasamplemode, [1, 3]) 82 pd(i) = truncate(pd(i), settings.lb(i), settings.ub(i)); 83 end 84 M1(:, i) = random(pd(i), settings.sansamples, 1); 85 M2(:, i) = random(pd(i), settings.sansamples, 1); 86 end 87end 88% Replace the i:th column in M2 by the i:th column from M1 to create N 89% matrices 90for i=1:settings.parnum 91 N(:,:,i) = M2; 92 N(:,i,i) = M1(:,i); 93end 94 95% Store resulting matrices in the output structure 96results.M1=M1; 97results.M2=M2; 98results.N=N; 99end
Creates parameter sets samples with specific parameter distributions that are used to perform the global sensitivity analysis.
Inputs
stg - stg.sansamples, stg.parnum, stg.sasamplemode, stg.ub, stg.lb
Code inspired by Geir Halnes et al. 2009 paper.
f_make_output_sample
Code
1function results = f_make_output_sample(results,settings,model_folders) 2% This function calculates the outputs for three different matrices (GSA 3% M1, GSA M2, and GSA N) based on the input parameters, settings, and a 4% mathematical model. This code is inspired by Geir Halnes et al. 2009 5% paper. 6% 7% Inputs: 8% - results: A structure containing M1, M2, and N matrices 9% - settings: A structure with settings, including sansamples and parnum 10% - model_folders: A variable containing folders for the models 11% 12% Outputs: 13% - results: A structure containing fM1, fM2, and fN fields, each 14% containing computed outputs for corresponding GSA methods 15% 16% Used Functions : 17% - compute_f: Compute the results for GSA M1, GSA M2, and GSA N methods 18% - f_sim_score: Simulation score calculation function 19% - progress_track: Track progress of the calculations 20% 21% Variables 22% Loaded: 23% - nSamples: Number of samples (loaded from settings.sansamples) 24% - nPars: Number of parameters (loaded from settings.parnum) 25% 26% Initialized: 27% - time_begin: The start time of the function 28% - f_out: Structure holding the computed values for fM1, fM2, and fN 29% 30% Persistent: 31% - current_sample: Keeps track of the current sample number for progress 32% tracking 33% - last_time: Keeps track of the last time progress was printed 34 35% Number of samples 36nSamples = settings.sansamples; 37 38% Number of parameters 39nPars = settings.parnum; 40 41% Start time of the function 42time_begin = datetime; 43 44% Compute the results for GSA M1, GSA M2, and GSA N methods 45results.fM1 = compute_f(results.M1, nSamples, settings, model_folders, nPars, time_begin,"GSA M1","fM"); 46results.fM2 = compute_f(results.M2, nSamples, settings, model_folders, nPars, time_begin,"GSA M2","fM"); 47results.fN = compute_f(results.N, nSamples, settings, model_folders, nPars, time_begin,"GSA N","fN"); 48end 49 50function [f_out] =... 51 compute_f(parameter_array, nSamples, settings, model_folders, nPars, time_begin, task_name, matrix_type) 52 53% Create a DataQueue for parallel processing 54D = parallel.pool.DataQueue; 55 56% Set up the progress tracker for the DataQueue 57afterEach(D, @progress_track); 58 59clear R RN 60 61% Choose the matrix type and perform the calculations accordingly 62switch matrix_type 63 case 'fM' 64 R = cell(nSamples,1); 65 66 % Parallel loop for computing the output 67 parfor i = 1:nSamples 68 [~,~,R{i}] = f_sim_score(parameter_array(i,:), settings, model_folders); 69 send(D, {task_name, 1, time_begin, nSamples, nPars}); 70 end 71 % Extract the computed values 72 73 sd = zeros(nSamples,size(R{1}.sd,1)*size(R{1}.sd,2)); 74 se = zeros(nSamples,size(R{1}.se,1)); 75 st = zeros(nSamples,size(R{1}.st,1)); 76 xfinal = zeros(nSamples,size(R{1}.sd,1)*(max(settings.exprun)-min(settings.exprun)+1)); 77 78 for i = 1:nSamples 79 sd(i,:) = reshape(R{i}.sd(:,:), 1, []); 80 se(i,:) = R{i}.se(:); 81 st(i,:) = R{i}.st; 82 xfinal(i,:) = [R{i}.xfinal{:}]; 83 end 84 85 case 'fN' 86 % Nested parallel loop for computing the output 87 RN = cell(nSamples,nPars); 88 89 parfor i = 1:nSamples 90 for j = 1:nPars 91 [~,~,RN{i,j}] = f_sim_score(parameter_array(i,:,j), settings, model_folders); 92 93 end 94 send(D, {task_name, 1, time_begin, nSamples, nPars}); 95 96 end 97 98 sd = zeros(nSamples,size(RN{1,1}.sd,1)*size(RN{1,1}.sd,2),nPars); 99 se = zeros(nSamples,size(RN{1,1}.se,1),nPars); 100 st = zeros(nSamples,size(RN{1,1}.st,1),nPars); 101 xfinal = zeros(nSamples,size(RN{1,1}.sd,1)*(max(settings.exprun)-min(settings.exprun)+1),nPars); 102 103 for i = 1:nSamples 104 for j = 1:nPars 105 sd(i,:,j) = reshape(RN{i,j}.sd, 1, []); 106 se(i,:,j) = RN{i,j}.se; 107 st(i,:,j) = RN{i,j}.st; 108 xfinal(i,:,j) = [RN{i,j}.xfinal{:}]; 109 end 110 end 111end 112 113f_out.sd = sd; 114f_out.se = se; 115f_out.st = st; 116f_out.xfinal = xfinal; 117 118% Display the runtime information for the task 119disp(task_name + " Runtime: " + string(datetime - time_begin) +... 120 " All " + nSamples + " samples executed") 121end 122 123% Function to track progress of the LSA 124function progress_track(arg) 125persistent current_sample 126persistent last_time 127 128% Initialize or update the current sample counter 129if isempty(current_sample) || current_sample == arg{4} 130 current_sample = arg{2}; 131end 132 133% Retrieve other required arguments 134task_name = arg{1}; 135start_time = arg{3}; 136num_samples = arg{4}; 137par_n = arg{5}; 138current_sample = current_sample + 1; 139 140% Print progress information at each step 141if mod(current_sample,ceil(num_samples/10)) == 0 &&... 142 current_sample ~= num_samples 143 144 if ((num_samples-current_sample)/num_samples)*10 <... 145 ((num_samples-(num_samples/10))/num_samples)*10 146 % Calculate the remaining time 147 dt = (datetime-last_time); 148 149 remaining_time = seconds(dt); 150 remaining_time =... 151 remaining_time*(num_samples-current_sample)/num_samples*10; 152 remaining_time = seconds(remaining_time); 153 remaining_time.Format = 'hh:mm:ss'; 154 155 % Print the progress and remaining time 156 fprintf('%s Runtime: %s Time to finish: %s Samples: %d/%d\n', ... 157 task_name, string(datetime - start_time), string(remaining_time), ... 158 current_sample, num_samples); 159 else 160 161 % Print the progress without remaining time 162 fprintf('%s Runtime: %s Samples: %d/%d\n', ... 163 task_name, string(datetime - start_time), ... 164 current_sample, num_samples); 165 end 166 167 last_time = datetime; 168end 169end
For each parameter set given in the matrices M1, M2, and N it runs the function f_sim_score generating new matrices fM1, fM2, and fN respectively.
Inputs - M1, M2, N, stg.sansamples, stg.parnum,
Code inspired by Geir Halnes et al. 2009 paper.
f_calc_sensitivities
Code
1function results = f_calc_sensitivities(results,settings) 2% Computes the first-order (Si) and total-order (SiT) sensitivity indices 3% for each score type present in the input data using the bootstrap method. 4% This function takes in the raw data and various settings for the 5% calculation process, and returns the results structure with calculated Si 6% and SiT for each score type. 7% 8% Inputs: 9% - results: a structure containing raw data (fM1, fM2, and fN) for 10% different score types 11% - settings: a structure containing settings for the calculation, such as 12% bootstrap size, random seed, and error score 13% 14% Outputs: 15% - results: a modified version of the input results structure containing 16% the computed Si and SiT for each score type 17% 18% Functions called: 19% - remove_sim_error: removes simulation errors from the input data 20% - bootstrap: calculates Si and SiT using the bootstrap method 21% - bootstrap_q: creates bootstrapped samples and calculates Si and SiT for 22% the bootstrapped samples 23% - calcSobolSaltelli: calculates Si and SiT using the Sobol-Saltelli 24% method 25% 26% Loaded variables: 27% - None 28% 29% Initialized variables: 30% - fM1: a structure containing the first-order score data for each score type 31% - fM2: a structure containing the total-order score data for each score type 32% - fN: a structure containing the score data for each score type and parameter 33% - settings: a structure containing settings for the calculation 34% 35% Persistent variables: 36% - None 37 38% Remove simulation errors from the input data 39results = remove_sim_error(results,settings); 40 41% Calculate Si and SiT using the bootstrap method and store them in the results 42% structure 43[results.SiQ,results.SiTQ,results.Si,results.SiT] = bootstrap(results,settings); 44end 45 46function [SiQ,SiTQ,Si,SiT]=bootstrap(results,settings) 47% calculates confidence intervals for the sensitivity indices using the 48% bootstrap method. 49 50% Initialize variables 51fM1 = results.fM1; 52fM2 = results.fM2; 53fN = results.fN; 54 55% Set the number of resamples for bootstrapping if not provided 56if (isempty(settings.gsabootstrapsize)) 57 settings.gsabootstrapsize=ceil(sqrt(size(fM1.sd,2))); 58end%if 59 60% Define the list of scores to be used in the calculation 61scores_list = ["sd","se","st","xfinal"]; 62 63% Generate random indices for bootstrapping 64for j=1:settings.gsabootstrapsize 65 rng(j*settings.rseed) 66 I(j,:)=ceil(rand(size(fM1.sd,1),1)*size(fM1.sd,1)); 67end 68 69% Calculate Si and SiT for each score type and perform bootstrapping 70for n = 1:size(scores_list,2) 71 fM1h = fM1.(scores_list(n)); 72 fM2h = fM2.(scores_list(n)); 73 fNh = fN.(scores_list(n)); 74 75 % Calculate Si and SiT without bootstrapping 76 [Sih,SiTh] = calcSobolSaltelli(fM1h,fM2h,fNh,settings); 77 Si.(scores_list(n)) = Sih; 78 SiT.(scores_list(n)) = SiTh; 79 80 % Initialize variables for bootstrapped Si and SiT 81 SiQh = cell(1, settings.gsabootstrapsize); 82 SiTQh = cell(1, settings.gsabootstrapsize); 83 84 % Perform bootstrapping for the current score type 85 parfor j=1:settings.gsabootstrapsize 86 [SiQh{j},SiTQh{j}] = bootstrap_q(fM1h,fM2h,fNh,settings,j,I); 87 end%parfor 88 89 % Store bootstrapped Si and SiT values in the output structures 90 for j=1:settings.gsabootstrapsize 91 SiQ.(scores_list(n))(j,:,:) = SiQh{j}; 92 SiTQ.(scores_list(n))(j,:,:) = SiTQh{j}; 93 end 94end 95end%function 96 97function [Si,SiT] = bootstrap_q(fM1,fM2,fN,settings,j,I) 98 % Create bootstrapped samples using the generated indices 99 fM1q = fM1(I(j,:),:); 100 fM2q = fM2(I(j,:),:); 101 fNq = fN(I(j,:),:,:); 102 103 % Calculate Si and SiT for the bootstrapped samples 104 [Si,SiT] = calcSobolSaltelli(fM1q,fM2q,fNq,settings); 105end 106 107function [Si,SiT] = calcSobolSaltelli(fM1,fM2,fN,settings) 108% Calculates Si and SiT using the Sobol-Saltelli method. 109% Code inspired by Geir Halnes et al. 2009 paper. (Halnes, Geir, et al. J. 110% comp. neuroscience 27.3 (2009): 471.) 111 112% Get the dimensions of the input data 113[Nsamples,Nvars,Npars]=size(fN); 114 115% Optionally subtract the mean to stabilize the model 116if(settings.sasubmean) 117 fM1 = fM1 - mean(fM1,1); 118 fM2 = fM2 - mean(fM2,1); 119 for i=1:Npars 120 fN(:,:,i) = fN(:,:,i) - mean(fN(:,:,i),1); 121 end 122end 123 124% Calculate EY2 and variances 125EY2 = mean(fM1.*fM2); % Valid definition (see Halnes et. al. Appendix) 126VY = sum(fM1.^2)/(Nsamples-1) - EY2; 127VYT = sum(fM2.^2)/(Nsamples-1) - EY2; 128 129% Initialize Si and SiT arrays 130Si = zeros(Nvars,Npars); 131SiT= zeros(Nvars,Npars); 132 133% Calculate Si and SiT for each parameter 134for i=1:Npars 135 Si(:,i) = (sum(fM1.*fN(:,:,i))/(Nsamples-1) - EY2)./VY; 136 SiT(:,i) = 1 - (sum(fM2.*fN(:,:,i))/(Nsamples-1) - EY2)./VYT; 137end 138end 139 140function results = remove_sim_error(results,settings) 141% Removes any simulation errors present in the input data. 142 143error_indices = any(results.fM1.sd == settings.errorscore, 2) | ... 144 any(results.fM2.sd == settings.errorscore, 2) | ... 145 any(any(results.fN.sd == settings.errorscore, 3), 2); 146 147% Remove error rows from all fields of the input data 148fields = fieldnames(results.fM1); 149for i = 1:numel(fields) 150 results.fM1.(fields{i})(error_indices, :) = []; 151 results.fM2.(fields{i})(error_indices, :) = []; 152 results.fN.(fields{i})(error_indices, :, :) = []; 153end 154end
Takes the matrices fM1, fM2, and fN and calculates sensitivity indexes. It calculates indexes based on the following oputputs of the f_sim_score function:
Code modified from the Geir Halnes et al. 2009 paper.