Source code for sensitivity_tools
"""
Functions for setting up and carrying out a Sobol sensitivity analysis
on your model.
This module requires the package SALib. If you don't have SALib you can
use the other functionality in savvy but will not be able to perform new
sensitivity analyses.
"""
from subprocess import call
try:
from SALib.sample import saltelli
except ImportError:
print ('----\nSALib is not installed - please install it to use '
'sensitivity_tools.\nOther modules in savvy are independent of '
'SALib.')
[docs]def gen_params(num_vars, names, bounds, n, save_loc, second_ord=True):
"""
Generate the parameter sets for the Sobol sensitivity analysis.
Saves a file with the information required for the analysis
that will be performed later.
Parameters
-----------
num_vars : int
the number of parameters you will vary.
names : list
list of strings with the names of the parameters
bounds : list
list of lists, where each inner list contains the
upper and lower bounds for a given parameter.
n : int
number of initial samples to generate from
the pseudo-random Sobol sequence. n parameter sets
will be generated using the Sobol sequence, then the
Saltelli cross-sampling method will be applied to give a
total of 2n(p+1) parameter sets to be run if second_ord =
True.
save_loc : str
path to the directory where you would like to save the
parameters.
second_ord : bool, optional
a boolean to indicate whether or not to calculate second
order sensitivity indices. If False, only 1st and total
order indices will be calculated and n(p+2) parameter sets
will be generated.
Returns
--------
param_sets : numpy ndarray
an ndarray where each row is one set of parameter
values. You must run your model (in whatever environment
is appropriate) with each of the sets of parameters from
this array. The output must be stored in the same order
as given in this parameter set array (one row of results
for each row of parameters).
"""
# Check that num_vars is an integer
if not isinstance(num_vars, int):
raise TypeError('num_vars must be an integer')
# Check that bounds are specified for every variable
if num_vars != len(bounds):
raise ValueError('bounds must be same length as num_vars')
# Check that a name is given for every parameter
if num_vars != len(names):
raise ValueError('length of `names` must equal num_vars')
problem = {'num_vars': num_vars, 'names': names, 'bounds': bounds}
param_sets = saltelli.sample(problem, n, calc_second_order=second_ord)
if second_ord:
print '%s simulations will be run' % (2*n * (problem['num_vars'] + 1))
elif second_ord is False:
print '%s simulations will be run' % (n * (problem['num_vars'] + 2))
# Write the problem description to a file (required to run the analysis
# after your model has been run with all the generated parameter sets)
body = ''
for i, name in enumerate(problem['names']):
body += '%s %s %s\n' % (name, problem['bounds'][i][0],
problem['bounds'][i][1])
with open(save_loc+'/saparams_%s-parameters_%s-n.txt'
% (num_vars, n), 'wb') as params:
params.write(body)
return param_sets
[docs]def analyze_sensitivity(problem, Y, column, delimiter, order, name,
parallel=False, processors=4):
"""
Perform the sensitivity analysis after you have run your model
with all the parameters from gen_params(). This is done from
the command line because it is faster and gives the option to
specify the column of the results file to analyze. Parallel
processing is possible. Results are saved to a file using the
name parameter.
Parameters
----------
problem : str
the path to the saparams* file that contains
the problem definition.
Y : str
the path to the results file. Results should
be in a file without a header. Each line of the file must
contain results that correspond to the same line of the
param_sets generated in gen_params().
column : int
integer specifying the column number of the results to
analyze (zero indexed).
delimiter : str
string specifying the column delimiter used in the results.
order : int
the maximum order of sensitivity indices [1 or 2].
name : str
the name of the output measure to use when saving
the sensitivity analysis results to a file.
parallel : bool, optional
boolean indicating whether to use parallel processing.
processors : int, optional
if parallel is True, this is an integer specifying the number
of processors to use.
Returns
--------
None
"""
if parallel:
call('python -m SALib.analyze.sobol -p %s -Y %s -c %i --delimiter %s '
'--max-order %i --parallel --processors %i > analysis_%s.txt'
% (problem, Y, column, delimiter, order, processors, name),
shell=True)
else:
call('python -m SALib.analyze.sobol -p %s -Y %s'
' -c %s --delimiter %s --max-order %s > analysis_%s.txt' %
(problem, Y, column, delimiter, order, name), shell=True)