def test_Delta_with_NAN(): ''' Test if delta.analyze raise a ValueError when nan are passed in the Y values ''' problem, model_results, param_values = setup_samples() # Should raise a ValueError type of error with pytest.raises(ValueError): delta.analyze(problem, param_values, model_results)
def calcSindices(param_bounds, policy): x1 = np.linspace(param_bounds[0, 0], param_bounds[0, 1], 100) y1 = np.linspace(param_bounds[1, 0], param_bounds[1, 1], 100) xv, yv = np.meshgrid(x1, y1) x = xv.flatten() y = yv.flatten() if policy == 1: z = (x + 1) + -4 * y + (x + 1) * y + 1 else: z = (x + 1) + -3 * y + (x + 1) * y param_names = ['x', 'y'] params_no = len(param_names) problem = { 'num_vars': params_no, 'names': param_names, 'bounds': param_bounds.tolist() } samples = np.transpose(np.array([x, y])) result = delta.analyze(problem, samples, z, print_to_console=False, num_resamples=2) return result, x1, y1, z
def x_near__SA(ensemble_dir, these_varnames, thresh=1.05, varname='p_infect', last_scenario='none'): X, problem, labs = get_X(ensemble_dir, these_varnames, last_scenario='none') default_case_options = {'acr_enhancement': 1.} dxs, vardat_default = get_ensemble_dat(varname, ensemble_dir, default_case_options, dispersion_type='both', dxval='all', last_scenario=last_scenario) dxs, vardat_reflections = get_ensemble_dat(varname, ensemble_dir, default_case_options, dispersion_type='reflections', dxval='all') x_near = np.zeros(vardat_default.shape[0]) for ii in range(vardat_default.shape[0]): x_near[ii] = interp1d((vardat_default / vardat_reflections)[ii, :], dxs, fill_value='extrapolate')(thresh) idx, = np.where(~np.isnan(x_near)) output_delta = delta.analyze(problem, X[idx, :], x_near[idx]) return output_delta
def sensitivity_analysis_per_structure(ID): ''' Perform analysis for shortage magnitude ''' DELTA = pd.DataFrame(np.zeros((params_no, len(percentiles))), columns = percentiles) DELTA_conf = pd.DataFrame(np.zeros((params_no, len(percentiles))), columns = percentiles) S1 = pd.DataFrame(np.zeros((params_no, len(percentiles))), columns = percentiles) S1_conf = pd.DataFrame(np.zeros((params_no, len(percentiles))), columns = percentiles) R2_scores = pd.DataFrame(np.zeros((params_no, len(percentiles))), columns = percentiles) DELTA.index=DELTA_conf.index=S1.index=S1_conf.index = R2_scores.index = param_names SYN_short = np.zeros([len(HIS_short), samples * realizations]) for j in range(samples): data= np.loadtxt('../../../'+design+'/Infofiles/' + ID + '/' + ID + '_info_' + str(rows_to_keep[j]+1) + '.txt') # replace failed runs with np.nan (currently -999.9) data[data < 0] = np.nan try: SYN_short[:,j*realizations:j*realizations+realizations]=data[:,idx] except IndexError: print(ID + '_info_' + str(j+1)) # Reshape into water years # Create matrix of [no. years x no. months x no. experiments] f_SYN_short = np.zeros([int(np.size(HIS_short)/n),n, samples*realizations]) for i in range(samples*realizations): f_SYN_short[:,:,i]= np.reshape(SYN_short[:,i], (int(np.size(SYN_short[:,i])/n), n)) # Shortage per water year f_SYN_short_WY = np.sum(f_SYN_short,axis=1) # Identify droughts at percentiles syn_magnitude = np.zeros([len(percentiles),samples*realizations]) for j in range(samples*realizations): syn_magnitude[:,j]=[np.percentile(f_SYN_short_WY[:,j], i) for i in percentiles] # Delta Method analysis for i in range(len(percentiles)): if syn_magnitude[i,:].any(): try: result= delta.analyze(problem, np.repeat(LHsamples, realizations, axis = 0), syn_magnitude[i,:], print_to_console=False, num_resamples=2) DELTA[percentiles[i]]= result['delta'] DELTA_conf[percentiles[i]] = result['delta_conf'] S1[percentiles[i]]=result['S1'] S1_conf[percentiles[i]]=result['S1_conf'] except: pass S1.to_csv('../../../'+design+'/Magnitude_Sensitivity_analysis/'+ ID + '_S1.csv') S1_conf.to_csv('../../../'+design+'/Magnitude_Sensitivity_analysis/'+ ID + '_S1_conf.csv') DELTA.to_csv('../../../'+design+'/Magnitude_Sensitivity_analysis/'+ ID + '_DELTA.csv') DELTA_conf.to_csv('../../../'+design+'/Magnitude_Sensitivity_analysis/'+ ID + '_DELTA_conf.csv') # OLS regression analysis dta = pd.DataFrame(data = np.repeat(LHsamples, realizations, axis = 0), columns=param_names) for i in range(len(percentiles)): dta['Shortage']=syn_magnitude[i,:] for m in range(params_no): predictors = dta.columns.tolist()[m:(m+1)] result = fitOLS(dta, predictors) R2_scores.at[param_names[m],percentiles[i]]=result.rsquared R2_scores.to_csv('../../../'+design+'/Magnitude_Sensitivity_analysis/'+ ID + '_R2.csv')
def calculate_sensitivities(trace, spec): """Calculates delta moment-independent sensitivities for specified inputs and outputs.""" ins_list = list(spec.ins) ins = np.stack([trace[i] for i in ins_list], axis=1) problem = {"num_vars": len(spec.ins), "names": ins_list} return [ sort_sensitivities(delta.analyze(problem, ins, trace[out])) for out in spec.outs ]
def fit(self, X, y): """ Fits the regressor to the data `(X, y)` and performs a sensitivity analysis on the result of the regression. :param X: Training data :param y: Target values :return: `self` """ from numpy import argpartition N = len(X[0]) if (self.domain is None) or (self.probs is None): self._avg_fucn(X, y) if self.regressor is None: from sklearn.svm import SVR self.regressor = SVR() self.regressor.fit(self.domain, self.probs) bounds = [[ min(self.domain[:, idx]) - self.margin, max(self.domain[:, idx]) + self.margin ] for idx in range(N)] problem = dict(num_vars=N, names=['x%d' % idx for idx in range(N)], bounds=bounds) res = [] if self.method == 'sobol': from SALib.sample import saltelli from SALib.analyze import sobol param_values = saltelli.sample(problem, self.num_smpl) y_ = self.regressor.predict(param_values) res = sobol.analyze(problem, y_)['ST'] self.weights_ = res elif self.method == 'morris': from SALib.sample import morris as mrs from SALib.analyze import morris param_values = mrs.sample(problem, self.num_smpl, num_levels=self.num_levels) y_ = self.regressor.predict(param_values) res = morris.analyze(problem, param_values, y_, num_levels=self.num_levels)['mu_star'] self.weights_ = res elif self.method == 'delta-mmnt': from SALib.sample import latin from SALib.analyze import delta param_values = latin.sample(problem, self.num_smpl) y_ = self.regressor.predict(param_values) res = delta.analyze(problem, param_values, y_, num_resamples=self.num_resmpl)['delta'] self.weights_ = res self.top_features_ = argpartition( res, -self.n_features_to_select)[-self.n_features_to_select:] return self
def Sobol_per_structure(design, ID): # get problem parameters (parameters, ranges, samples) param_bounds, param_names, params_no, problem = setupProblem(design) samples, rows_to_keep = getSamples(design, params_no, param_bounds) # constants percentiles = np.arange(0,100) nsamples = len(rows_to_keep) nrealizations = 10 idx = np.arange(2,22,2) nyears = 105 nmonths = 12 # initiate dataframes to store sensitivity results S1 = pd.DataFrame(np.zeros((params_no, len(percentiles))), columns = percentiles) S1_conf = pd.DataFrame(np.zeros((params_no, len(percentiles))), columns = percentiles) R2_scores = pd.DataFrame(np.zeros((params_no, len(percentiles))), columns = percentiles) S1.index=S1_conf.index = R2_scores.index = param_names # load shortage data for this experimental design SYN_short = np.load('../Simulation_outputs/' + design + '/' + ID + '_info.npy') # remove columns for year (0) and demand (odd columns) and convert to m^3 SYN_short = SYN_short[:,idx,:]*1233.48 SYN_short = SYN_short[:,:,rows_to_keep] # replace failed runs with np.nan (currently -999.9) SYN_short[SYN_short < 0] = np.nan # Identify droughts at percentiles syn_magnitude = calc_syn_magnitude(nyears, nmonths, nrealizations, nsamples, percentiles, SYN_short) # Delta Method analysis for i in range(len(percentiles)): if syn_magnitude[i,:].any(): try: result = delta.analyze(problem, np.repeat(samples, nrealizations, axis = 0), syn_magnitude[i,:], print_to_console=False, num_resamples=2) S1[percentiles[i]] = result['S1'] S1_conf[percentiles[i]] = result['S1_conf'] except: pass S1.to_csv('../Simulation_outputs/' + design + '/'+ ID + '_S1.csv') S1_conf.to_csv('../Simulation_outputs/' + design + '/'+ ID + '_S1_conf.csv') # OLS regression analysis dta = pd.DataFrame(data = np.repeat(samples, nrealizations, axis = 0), columns=param_names) for i in range(len(percentiles)): dta['Shortage'] = syn_magnitude[i,:] for m in range(params_no): predictors = dta.columns.tolist()[m:(m+1)] result = fitOLS(dta, predictors) R2_scores.at[param_names[m],percentiles[i]]=result.rsquared R2_scores.to_csv('../Simulation_outputs/' + design + '/' + ID + '_R2.csv') return None
def sensitivity_analysis_per_structure(ID): # if not path.exists('../'+design+'/Max_Duration_Sensitivity_analysis/'+ ID + '_DELTA_conf.csv'): ''' Perform analysis for max shortage duration at each magnitude ''' durations = np.load('../' + design + '/Max_Duration_Curves/' + ID + '.npy') dta = pd.DataFrame(data=LHsamples, columns=param_names) DELTA = pd.DataFrame(np.zeros((params_no, len(percentiles))), columns=percentiles) DELTA_conf = pd.DataFrame(np.zeros((params_no, len(percentiles))), columns=percentiles) S1 = pd.DataFrame(np.zeros((params_no, len(percentiles))), columns=percentiles) S1_conf = pd.DataFrame(np.zeros((params_no, len(percentiles))), columns=percentiles) R2_scores = pd.DataFrame(np.zeros((params_no, len(percentiles))), columns=percentiles) DELTA.index = DELTA_conf.index = S1.index = S1_conf.index = R2_scores.index = param_names for i in range(len(percentiles)): if durations[i].any(): output = np.mean(durations[i].reshape(-1, 10), axis=1) output = output[rows_to_keep] # Delta Method analysis try: result = delta.analyze(problem, LHsamples, output, print_to_console=False) DELTA[percentiles[i]] = result['delta'] DELTA_conf[percentiles[i]] = result['delta_conf'] S1[percentiles[i]] = result['S1'] S1_conf[percentiles[i]] = result['S1_conf'] except: pass # OLS regression analysis dta['Shortage'] = output try: for m in range(params_no): predictors = dta.columns.tolist()[m:(m + 1)] result = fitOLS(dta, predictors) R2_scores.at[param_names[m], percentiles[i]] = result.rsquared except: pass R2_scores.to_csv('../' + design + '/Max_Duration_Sensitivity_analysis/' + ID + '_R2.csv') S1.to_csv('../' + design + '/Max_Duration_Sensitivity_analysis/' + ID + '_S1.csv') S1_conf.to_csv('../' + design + '/Max_Duration_Sensitivity_analysis/' + ID + '_S1_conf.csv') DELTA.to_csv('../' + design + '/Max_Duration_Sensitivity_analysis/' + ID + '_DELTA.csv') DELTA_conf.to_csv('../' + design + '/Max_Duration_Sensitivity_analysis/' + ID + '_DELTA_conf.csv')
def test_regression_delta(): param_file = 'src/SALib/test_functions/params/Ishigami.txt' problem = read_param_file(param_file) param_values = latin.sample(problem, 10000) Y = Ishigami.evaluate(param_values) Si = delta.analyze(problem, param_values, Y, num_resamples=10, conf_level=0.95, print_to_console=True) assert_allclose(Si['delta'], [0.210, 0.358, 0.155], atol=5e-2, rtol=1e-1) assert_allclose(Si['S1'], [0.31, 0.44, 0.00], atol=5e-2, rtol=1e-1)
def analyze(self): """Initiate the analysis, and stores the result at data directory. Generates: Analysis result at 'acbm/data/output/delta.txt'. """ X = latin.sample(self.problem, self.n_samples, seed=self.seed_sample) Y = ACBM.evaluate(X) si = delta.analyze(self.problem, X, Y, seed=self.seed_analyze) pickle.dump(si, open(self.path_output + 'delta.txt', 'wb'))
def test_regression_delta(): param_file = 'src/SALib/test_functions/params/Ishigami.txt' problem = read_param_file(param_file) param_values = latin.sample(problem, 10000) Y = Ishigami.evaluate(param_values) Si = delta.analyze(problem, param_values, Y, num_resamples=10, conf_level=0.95, print_to_console=True) assert_allclose(Si['delta'], [0.210, 0.358, 0.155], atol=5e-2, rtol=1e-1) assert_allclose(Si['S1'], [0.31, 0.44, 0.00], atol=5e-2, rtol=1e-1)
def _parallel_analyze(index, method, problem, samples, data, seed): if method == 'sobol': result = sobol.analyze(problem, data, calc_second_order=True, print_to_console=False, seed=seed) elif method == 'fast': result = fast.analyze(problem, data, print_to_console=False, seed=seed) elif method == 'rbd-fast': result = rbd_fast.analyze(problem, samples, data, print_to_console=False, seed=seed) elif method == 'morris': result = morris_analyze(problem, samples, data, print_to_console=False, seed=seed) elif method == 'delta': result = delta.analyze(problem, samples, data, print_to_console=False, seed=seed) elif method == 'dgsm': result = dgsm.analyze(problem, samples, data, print_to_console=False, seed=seed) elif method == 'frac': result = ff_analyze(problem, samples, data, second_order=True, print_to_console=False, seed=seed) else: return 0 for key in result.keys(): result[key] = result[key].tolist() with open('{:s}.json'.format(index), 'w') as outfile: json.dump(result, outfile) return 0
def _analizar(símismo, vec_res, muestra, ops): if símismo.método == 'sobol': return sobol.analyze(problem=símismo.problema, Y=vec_res, **ops) elif símismo.método == 'fast': return fast.analyze(problem=símismo.problema, Y=vec_res, **ops) elif símismo.método == 'morris': return morris_anlz.analyze(problem=símismo.problema, X=muestra, Y=vec_res, **ops) elif símismo.método == 'dmim': return delta.analyze(problem=símismo.problema, X=muestra, Y=vec_res, **ops) elif símismo.método == 'dgsm': return dgsm.analyze(problem=símismo.problema, X=muestra, Y=vec_res, **ops) elif símismo.método == 'ff': return ff_anlz.analyze(problem=símismo.problema, X=muestra, Y=vec_res, **ops) else: raise ValueError('Método de análisis de sensibilidad "{}" no reconocido.'.format(símismo.método))
def delta(self): """Morris Method sensitivity of the objective function. This function estimates the sensitivity with the Morris Method of the objective function with changes in the parameters using SALib: https://salib.readthedocs.io/en/latest/api.html#delta-moment-independent-measure Returns: dict: sensitivity values of parameters; dict has keys 'delta', 'delta_conf', 'S1', and 'S1_conf' """ X, y, problem = self._sensitivity_prep() n_sample = 2000 param_values = latin.sample(problem, n_sample) X_s, y_s = self._closest_points(problem, X, y, param_values) Si = delta.analyze(problem, X_s, y_s) return Si
def _parallel_analyze(data): seed = int(opts['seed']) samples = population['problem', 'samples'] problem = population['problem', 'definition'] if opts['method'] == 'sobol': return sobol.analyze(problem, data, calc_second_order=True, print_to_console=False) elif opts['method'] == 'fast': return fast.analyze(problem, data, print_to_console=False, seed=seed) elif opts['method'] == 'rbd-fast': return rbd_fast.analyze(problem, samples, data, print_to_console=False, seed=seed) elif opts['method'] == 'morris': return morris_analyze(problem, samples, data, print_to_console=False, seed=seed) elif opts['method'] == 'delta': return delta.analyze(problem, samples, data, print_to_console=False, seed=seed) elif opts['method'] == 'dgsm': return dgsm.analyze(problem, samples, data, print_to_console=False, seed=seed) elif opts['method'] == 'frac': return ff_analyze(problem, samples, data, second_order=True, print_to_console=False, seed=seed) else: return 0
def salib_wrapper(problem, y_val, x, analysis_type='sobol', **kwargs): ''' Backend wrapper for sobol, fast and delta analysis. :meta private: ''' if analysis_type == 'sobol': return sobol.analyze(problem, y_val, **kwargs) elif analysis_type == 'fast': return fast.analyze(problem, y_val, **kwargs) elif analysis_type == 'delta': return delta.analyze(problem, x, y_val, **kwargs) elif analysis_type == 'rbd-fast': return rbd_fast.analyze(problem, x, y_val, **kwargs) else: raise Exception( 'Could not find analyzer. analysis_type must be sobol, fast, rbd-fast or delta.' )
def analyze(filename): print("Processing {}".format(filename)) # Load the response file response = pandas.read_table(filename, delimiter=",", index_col=0, squeeze=True) print(response) try: id = [True for k in response.values if k < 800 and k is not str] except: print(filename) pass # Convert data frame into numpy array response_matrix = response.as_matrix()[id].astype(float).ravel() # Convert parameter values into numpy array params_matrix = params.as_matrix()[response.index[id]].astype(float) # Define a salib "problem" problem = { "num_vars": params.shape[1], # Number of parameters "names": params.columns.values, # Parameter names "bounds": zip(params.min(), params.max()), # Parameter bounds } # Compute S1 sobol indices using the method of Plischke (2013, doi: https://doi.org/10.1016/j.ejor.2012.11.047) # as implemented in SALib Si = delta.analyze(problem, params_matrix, response_matrix, num_resamples=100, print_to_console=False) # Save responses as text files outfile = join(output_dir, os.path.split(filename)[-1][:-4] + "_sobel.txt") np.savetxt( outfile, np.c_[params.columns.values, Si["S1"], Si["S1_conf"]], delimiter=" ", header="Parameter S1 S1_conf", fmt=["%s", "%.03f", "%.03f"], )
def delta_mim(parameters, candidates_dict_log): samples = [] losses = [] for candidate, loss in candidates_dict_log: sample = parameters.from_dict(candidate) if parameters.defaults: sample.drop(parameters.defaults, inplace=True) sample = sample.to_numpy() samples.append(sample) losses.append(loss) samples = np.asarray(samples) losses = np.asarray(losses) bounds = {key: value for key, value in parameters.bounds.items() if key not in parameters.defaults} problem = {'num_vars': len(bounds), 'names': list(bounds), 'bounds': bounds} return delta.analyze(problem, samples, losses).to_df()
def analyzeSampleSensitivity(args): """ Analysis map function """ index = args[0] problem = args[1] X = args[2] Y = np.array(args[3]) queue = args[4] # Find sensitive parameters try: S = delta.analyze(problem, X, Y, print_to_console=False) except Exception as e: print "Error: %s" % str(e) queue.put( (index,None) ) return # Return the 'most correlated' parameters queue.put( (index, S['S1']) )
def objective_function_delta(problem, pars, OF): from SALib.analyze import delta import numpy as np import csv # convert pandas dataframe to numpy matrix params = pars.to_numpy() # initialize an empty list to save Sobol Indices results = [] # loop through each OF and calculate the Delta Indices and Sobol first-order index for each parameter for j in np.arange(len(OF.columns)): # subset the OF of interest Y = np.array(OF.iloc[:, j]) # calculate Sobol indices DI = delta.analyze(problem, params, Y) # hard code any negative indices to 0 DI['delta'][DI['delta'] < 0] = 0 DI['S1'][DI['S1'] < 0] = 0 # save output to text file keys = DI.keys() with open('output/raw/delta_' + OF.columns[j] + '.csv', 'w') as csvfile: fieldnames = keys writer = csv.DictWriter(csvfile, fieldnames=fieldnames) writer.writeheader() writer.writerow(DI) # save in results list results.append([DI]) return results
from SALib.sample import latin from SALib.analyze import delta, sobol from SALib.test_functions import Ishigami import numpy as np import random # Define the model inputs problem = { 'num_vars': 4, 'names': ['apprecition', 'cost', 'returns', 'interest'], } with open("data.csv") as f: data = f.read().splitlines() data = list(map(lambda x: list(map(float, x.split(","))), data)) print(data[:10]) X = np.array(data) Y = X[:, 4] X = X[:, 0:4] print(X) # Perform analysis Si = delta.analyze(problem, X, Y, print_to_console=True) # Print the first-order sensitivity indices print(Si['S1']) s = sobol.analyze(problem, X, Y, print_to_console=True) print(s)
def sa(model, response, policy={}, method="sobol", nsamples=1000, **kwargs): if len(model.uncertainties) == 0: raise ValueError("no uncertainties defined in model") problem = { 'num_vars' : len(model.uncertainties), 'names' : model.uncertainties.keys(), 'bounds' : [[0.0, 1.0] for u in model.uncertainties], 'groups' : kwargs.get("groups", None) } # estimate the argument N passed to the sampler that produces the requested # number of samples N = _predict_N(method, nsamples, problem["num_vars"], kwargs) # generate the samples if method == "sobol": samples = saltelli.sample(problem, N, **_cleanup_kwargs(saltelli.sample, kwargs)) elif method == "morris": samples = morris_sampler.sample(problem, N, **_cleanup_kwargs(morris_sampler.sample, kwargs)) elif method == "fast": samples = fast_sampler.sample(problem, N, **_cleanup_kwargs(fast_sampler.sample, kwargs)) elif method == "ff": samples = ff_sampler.sample(problem, **_cleanup_kwargs(ff_sampler.sample, kwargs)) elif method == "dgsm": samples = finite_diff.sample(problem, N, **_cleanup_kwargs(finite_diff.sample, kwargs)) elif method == "delta": if "samples" in kwargs: samples = kwargs["samples"] else: samples = latin.sample(problem, N, **_cleanup_kwargs(latin.sample, kwargs)) # convert from samples in [0, 1] to uncertainty domain for i, u in enumerate(model.uncertainties): samples[:,i] = u.ppf(samples[:,i]) # run the model and collect the responses responses = np.empty(samples.shape[0]) for i in range(samples.shape[0]): sample = {k : v for k, v in zip(model.uncertainties.keys(), samples[i])} responses[i] = evaluate(model, overwrite(sample, policy))[response] # run the sensitivity analysis method if method == "sobol": result = sobol.analyze(problem, responses, **_cleanup_kwargs(sobol.analyze, kwargs)) elif method == "morris": result = morris_analyzer.analyze(problem, samples, responses, **_cleanup_kwargs(morris_analyzer.analyze, kwargs)) elif method == "fast": result = fast.analyze(problem, responses, **_cleanup_kwargs(fast.analyze, kwargs)) elif method == "ff": result = ff_analyzer.analyze(problem, samples, responses, **_cleanup_kwargs(ff_analyzer.analyze, kwargs)) elif method == "dgsm": result = dgsm.analyze(problem, samples, responses, **_cleanup_kwargs(dgsm.analyze, kwargs)) elif method == "delta": result = delta.analyze(problem, samples, responses, **_cleanup_kwargs(delta.analyze, kwargs)) # convert the SALib results into a form allowing pretty printing and # lookups using the parameter name pretty_result = SAResult(result["names"] if "names" in result else problem["names"]) if "S1" in result: pretty_result["S1"] = {k : float(v) for k, v in zip(problem["names"], result["S1"])} if "S1_conf" in result: pretty_result["S1_conf"] = {k : float(v) for k, v in zip(problem["names"], result["S1_conf"])} if "ST" in result: pretty_result["ST"] = {k : float(v) for k, v in zip(problem["names"], result["ST"])} if "ST_conf" in result: pretty_result["ST_conf"] = {k : float(v) for k, v in zip(problem["names"], result["ST_conf"])} if "S2" in result: pretty_result["S2"] = _S2_to_dict(result["S2"], problem) if "S2_conf" in result: pretty_result["S2_conf"] = _S2_to_dict(result["S2_conf"], problem) if "delta" in result: pretty_result["delta"] = {k : float(v) for k, v in zip(problem["names"], result["delta"])} if "delta_conf" in result: pretty_result["delta_conf"] = {k : float(v) for k, v in zip(problem["names"], result["delta_conf"])} if "vi" in result: pretty_result["vi"] = {k : float(v) for k, v in zip(problem["names"], result["vi"])} if "vi_std" in result: pretty_result["vi_std"] = {k : float(v) for k, v in zip(problem["names"], result["vi_std"])} if "dgsm" in result: pretty_result["dgsm"] = {k : float(v) for k, v in zip(problem["names"], result["dgsm"])} if "dgsm_conf" in result: pretty_result["dgsm_conf"] = {k : float(v) for k, v in zip(problem["names"], result["dgsm_conf"])} if "mu" in result: pretty_result["mu"] = {k : float(v) for k, v in zip(result["names"], result["mu"])} if "mu_star" in result: pretty_result["mu_star"] = {k : float(v) for k, v in zip(result["names"], result["mu_star"])} if "mu_star_conf" in result: pretty_result["mu_star_conf"] = {k : float(v) for k, v in zip(result["names"], result["mu_star_conf"])} if "sigma" in result: pretty_result["sigma"] = {k : float(v) for k, v in zip(result["names"], result["sigma"])} return pretty_result
Si = sobol.analyze(problem, Y, print_to_console=False) figure_keys = { 'ax1_title': 'S1', 'ax2_title': 'S1_conf', 'ax2_lable': 'Parameter index', 'ax3_title': 'ST', 'ax4_title': 'ST_conf', 'ax4_lable': 'Parameter index', 'ax5_parm': 'S2', 'ax5_title': 'Second order sensitivity', 'ax5_lable': 'Parameter index', } elif method_flag == 2: Si = delta.analyze(problem, param_values, Y, num_resamples=10, conf_level=0.95, print_to_console=False) figure_keys = { 'ax1_title': 'S1', 'ax2_title': 'S1_conf', 'ax2_lable': 'Parameter index', 'ax3_title': 'delta', 'ax4_title': 'delta_conf', 'ax4_lable': 'Parameter index', } Si_con = delta.analyze(problem, param_values, Y_con, num_resamples=10, conf_level=0.95,
import sys sys.path.append('../..') from SALib.analyze import delta # Read the parameter range file and generate samples # Since this is "given data", the bounds in the parameter file will not be used # but the columns are still expected param_file = '../../SALib/test_functions/params/Ishigami.txt' # Perform the sensitivity analysis using the model output # Specify which column of the output file to analyze (zero-indexed) Si = delta.analyze(param_file, 'model_input.txt', 'model_output.txt', column=0, num_resamples=10, conf_level=0.95, print_to_console=False) # Returns a dictionary with keys 'delta', 'delta_conf', 'S1', 'S1_conf' print(str(Si['delta']))
import sys from SALib.analyze import delta from SALib.util import read_param_file import numpy as np sys.path.append('../..') # Read the parameter range file and generate samples # Since this is "given data", the bounds in the parameter file will not be used # but the columns are still expected problem = read_param_file('../../src/SALib/test_functions/params/Ishigami.txt') X = np.loadtxt('../data/model_input.txt') Y = np.loadtxt('../data/model_output.txt') # Perform the sensitivity analysis using the model output # Specify which column of the output file to analyze (zero-indexed) Si = delta.analyze(problem, X, Y, num_resamples=10, conf_level=0.95, print_to_console=False) # Returns a dictionary with keys 'delta', 'delta_conf', 'S1', 'S1_conf' print(str(Si['delta']))
def read_outcomes_sens_analysis(): """ Function to write the output of the sensitivity analysis to figures. """ # load some basics data_path = load_config()['paths']['data'] # specify country countries = [ 'LU', 'CZ', 'CH', 'EE', 'LV', 'LT', 'PT', 'ES', 'AT', 'BE', 'DK', 'IE', 'NL', 'NO', 'SE' ] # done: LU country_full_names = { 'CZ': 'Czech Republic', 'CH': 'Switzerland', 'EE': 'Estonia', 'LV': 'Latvia', 'LT': 'Lithuania', 'PT': 'Portugal', 'ES': 'Spain', 'AT': 'Austria', 'BE': 'Belgium', 'DK': 'Denmark', 'LU': 'Luxembourg', 'NL': 'Netherlands', 'IE': 'Ireland', 'UK': 'United Kingdom', 'NO': 'Norway', 'SE': 'Sweden' } storms = { '19991203': 'Anatol', '19900125': 'Daria', '20090124': 'Klaus', '20070118': 'Kyrill', '19991226': 'Lothar' } # set parameters for sensitivity analysis problem = { 'num_vars': 5, 'names': ['c2', 'c3', 'c4', 'lu1', 'lu2'], 'bounds': [[0, 100], [0, 100], [0, 100], [0, 50], [0, 50]] } # select storms to assess storm_name_list = [ '19991203', '19900125', '20090124', '20070118', '19991226' ] storm_list = [] for root, dirs, files in os.walk(os.path.join(data_path, 'STORMS')): for file in files: for storm in storm_name_list: if storm in file: storm_list.append(os.path.join(data_path, 'STORMS', file)) for country in countries: dirlist = os.listdir(os.path.join(data_path, 'output_sens')) country_list = [x for x in dirlist if country in x] k = 0 for i in range(int(len(country_list) / 2)): if i < 1: out = pd.read_csv( os.path.join(data_path, 'output_sens', country_list[k], index_col=0)) else: out2 = (os.path.join(data_path, 'output_sens', country_list[k], index_col=0)).fillna(0) out += out2 k += 2 param_values = pd.read_csv(os.path.join(data_path, 'output_sens', country_list[1]), delim_whitespace=True, header=None) #Estimate outcome of sensitvity analysis param_values = np.asarray(param_values) for l in range(5): try: storm = np.asarray(out.ix[:, l]) Si = delta.analyze(problem, param_values, storm, print_to_console=True) # create histogram plt.hist(storm, bins='auto', ec="k", lw=0.1) plt.autoscale(tight=True) plt.title(country_full_names[country] + ', ' + storms[out.ix[:, l].name]) plt.ylabel('Frequency') plt.xlabel('Total damage in Million Euro') plt.savefig(os.path.join( data_path, 'Figures', country + '_' + storms[out.ix[:, l].name] + '.png'), dpi=300) plt.clf() # create pie chart delta_ = (Si['delta']) / sum(Si['delta']) * 100 colors = [ 'yellowgreen', 'gold', 'lightskyblue', 'lightcoral', 'peru' ] labels = ['c2', 'c3', 'c4', 'lu1', 'lu2'] patches, texts = plt.pie(delta_, colors=colors, startangle=90, radius=0.4, center=(0.5, 0.5)) plt.axis('equal') plt.legend(patches, loc="best", labels=[ '%s : %1.1f%%' % (l, s) for l, s in zip(labels, delta_) ]) plt.title(country_full_names[country] + ', ' + storms[out.ix[:, l].name]) plt.savefig(os.path.join( data_path, 'Figures', country + '_' + storms[out.ix[:, l].name] + '_SA.png'), dpi=300) plt.clf() except Exception: continue
import sys sys.path.append('../..') from SALib.analyze import delta # Read the parameter range file and generate samples # Since this is "given data", the bounds in the parameter file will not be used # but the columns are still expected param_file = '../../SALib/test_functions/params/Ishigami.txt' # Perform the sensitivity analysis using the model output # Specify which column of the output file to analyze (zero-indexed) Si = delta.analyze(param_file, 'model_input.txt', 'model_output.txt', column = 0, num_resamples=10, conf_level = 0.95, print_to_console=False) # Returns a dictionary with keys 'delta', 'delta_conf', 'S1', 'S1_conf' print Si['delta']
def sensitivity_analysis_per_structure(ID): ''' Perform analysis for shortage frequency ''' HIS_short = np.loadtxt('../' + design + '/Infofiles/' + ID + '/' + ID + '_info_0.txt')[:, 2] DELTA = pd.DataFrame(np.zeros((params_no, len(percentiles))), columns=percentiles) DELTA_conf = pd.DataFrame(np.zeros((params_no, len(percentiles))), columns=percentiles) S1 = pd.DataFrame(np.zeros((params_no, len(percentiles))), columns=percentiles) S1_conf = pd.DataFrame(np.zeros((params_no, len(percentiles))), columns=percentiles) R2_scores = pd.DataFrame(np.zeros((params_no, len(percentiles))), columns=percentiles) DELTA.index = DELTA_conf.index = S1.index = S1_conf.index = R2_scores.index = param_names SYN_short = np.zeros([len(HIS_short), samples * realizations]) for j in range(samples): data = np.loadtxt('../' + design + '/Infofiles/' + ID + '/' + ID + '_info_' + str(j + 1) + '.txt') try: SYN_short[:, j * realizations:j * realizations + realizations] = data[:, idx] except IndexError: print(ID + '_info_' + str(j + 1)) # Reshape into water years # Create matrix of [no. years x no. months x no. experiments] f_HIS_short = np.reshape(HIS_short, (int(np.size(HIS_short) / n), n)) f_SYN_short = np.zeros( [int(np.size(HIS_short) / n), n, samples * realizations]) for i in range(samples * realizations): f_SYN_short[:, :, i] = np.reshape(SYN_short[:, i], (int(np.size(SYN_short[:, i]) / n), n)) # Shortage per water year f_HIS_short_WY = np.sum(f_HIS_short, axis=1) f_SYN_short_WY = np.sum(f_SYN_short, axis=1) # Identify historic shortages at percentiles HIS_magnitude = [np.percentile(f_HIS_short_WY, i) for i in percentiles] # Identify synthetic frequencies of historic shortages syn_magnitude = np.zeros([len(percentiles), samples * realizations]) for p in percentiles: if HIS_magnitude[p] > 0: for j in range(samples * realizations): syn_magnitude[p, j] = scipy.stats.percentileofscore( f_SYN_short_WY[:, j], HIS_magnitude[p], kind='strict') else: syn_magnitude[p, :] = 0 # Delta Method analysis for p in percentiles: if HIS_magnitude[p] > 0: try: output = np.mean(syn_magnitude[p, :].reshape(-1, 10), axis=1) output = output[rows_to_keep] result = delta.analyze(problem, LHsamples, output, print_to_console=False, num_resamples=10) DELTA[p] = result['delta'] DELTA_conf[p] = result['delta_conf'] S1[p] = result['S1'] S1_conf[p] = result['S1_conf'] except: pass S1.to_csv('../' + design + '/Frequency_Sensitivity_analysis/' + ID + '_S1.csv') S1_conf.to_csv('../' + design + '/Frequency_Sensitivity_analysis/' + ID + '_S1_conf.csv') DELTA.to_csv('../' + design + '/Frequency_Sensitivity_analysis/' + ID + '_DELTA.csv') DELTA_conf.to_csv('../' + design + '/Frequency_Sensitivity_analysis/' + ID + '_DELTA_conf.csv') # OLS regression analysis dta = pd.DataFrame(data=LHsamples, columns=param_names) for p in percentiles: if HIS_magnitude[p] > 0: output = np.mean(syn_magnitude[p, :].reshape(-1, 10), axis=1) dta['Shortage'] = output[rows_to_keep] for m in range(params_no): predictors = dta.columns.tolist()[m:(m + 1)] result = fitOLS(dta, predictors) R2_scores.at[param_names[m], p] = result.rsquared R2_scores.to_csv('../' + design + '/Frequency_Sensitivity_analysis/' + ID + '_R2.csv')
import sys from SALib.analyze import delta from SALib.util import read_param_file import numpy as np sys.path.append('../..') # Read the parameter range file and generate samples # Since this is "given data", the bounds in the parameter file will not be used # but the columns are still expected problem = read_param_file('../../SALib/test_functions/params/Ishigami.txt') X = np.loadtxt('model_input.txt') Y = np.loadtxt('model_output.txt') # Perform the sensitivity analysis using the model output # Specify which column of the output file to analyze (zero-indexed) Si = delta.analyze(problem, X, Y, num_resamples=10, conf_level=0.95, print_to_console=False) # Returns a dictionary with keys 'delta', 'delta_conf', 'S1', 'S1_conf' print(str(Si['delta']))
def perform_GSA(self, act_number=0, method_number=0, cutoff_technosphere=0.01, cutoff_biosphere=0.01): """Perform GSA for specific reference flow and impact category.""" start = time() # set FU and method try: self.act_number = act_number self.method_number = method_number self.cutoff_technosphere = cutoff_technosphere self.cutoff_biosphere = cutoff_biosphere self.fu = self.mc.cs['inv'][act_number] self.activity = bw.get_activity(self.mc.rev_activity_index[act_number]) self.method = self.mc.cs['ia'][method_number] except Exception as e: traceback.print_exc() # todo: QMessageBox.warning(self, 'Could not perform Delta analysis', str(e)) print('Initializing the GSA failed.') return None print('-- GSA --\n Project:', bw.projects.current, 'CS:', self.mc.cs_name, 'Activity:', self.activity, 'Method:', self.method) # get non-stochastic LCA object with reverse dictionaries self.lca = get_lca(self.fu, self.method) # ============================================================================= # Filter exchanges and get metadata DataFrames # ============================================================================= dfs = [] # technosphere if self.mc.include_technosphere: self.t_indices = filter_technosphere_exchanges(self.fu, self.method, cutoff=cutoff_technosphere, max_calc=1e4) self.t_exchanges, self.t_indices = get_exchanges(self.lca, self.t_indices) self.dft = get_exchanges_dataframe(self.t_exchanges, self.t_indices) if not self.dft.empty: dfs.append(self.dft) # biosphere if self.mc.include_biosphere: self.b_indices = filter_biosphere_exchanges(self.lca, cutoff=cutoff_biosphere) self.b_exchanges, self.b_indices = get_exchanges(self.lca, self.b_indices, biosphere=True) self.dfb = get_exchanges_dataframe(self.b_exchanges, self.b_indices, biosphere=True) if not self.dfb.empty: dfs.append(self.dfb) # characterization factors if self.mc.include_cfs: self.dfcf = get_CF_dataframe(self.lca, only_uncertain_CFs=True) # None if no stochastic CFs if not self.dfcf.empty: dfs.append(self.dfcf) # parameters # todo: if parameters, include df, but remove exchanges from T and B (skipped for now) self.dfp = get_parameters_DF(self.mc) # Empty df if no parameters if not self.dfp.empty: dfs.append(self.dfp) # Join dataframes to get metadata self.metadata = pd.concat(dfs, axis=0, ignore_index=True, sort=False) self.metadata.set_index('GSA name', inplace=True) # ============================================================================= # GSA # ============================================================================= # Get X (Technosphere, Biosphere and CF values) X_list = list() if self.mc.include_technosphere and self.t_indices: self.Xa = get_X(self.mc.A_matrices, self.t_indices) X_list.append(self.Xa) if self.mc.include_biosphere and self.b_indices: self.Xb = get_X(self.mc.B_matrices, self.b_indices) X_list.append(self.Xb) if self.mc.include_cfs and not self.dfcf.empty: self.Xc = get_X_CF(self.mc, self.dfcf, self.method) X_list.append(self.Xc) if self.mc.include_parameters and not self.dfp.empty: self.Xp = get_X_P(self.dfp) X_list.append(self.Xp) self.X = np.concatenate(X_list, axis=1) # print('X', self.X.shape) # Get Y (LCA scores) self.Y = self.mc.get_results_dataframe(act_key=self.activity.key)[self.method].to_numpy() # log-transformation. This makes it more robust for very uneven distributions of LCA results (e.g. toxicity related impacts). # Can only be applied if all Monte-Carlo LCA scores are either positive or negative. # Should not be used when LCA scores overlap zero (sometimes positive and sometimes negative) # if np.all(self.Y > 0) if self.Y[0] > 0 else np.all(self.Y < 0): # check if all LCA scores are of the same sign # self.Y = np.log(np.abs(self.Y)) # this makes it more robust for very uneven distributions of LCA results if np.all(self.Y > 0): # all positive numbers self.Y = np.log(np.abs(self.Y)) print('All positive LCA scores. Log-transformation performed.') elif np.all(self.Y < 0): # all negative numbers self.Y = -np.log(np.abs(self.Y)) print('All negative LCA scores. Log-transformation performed.') else: # mixed positive and negative numbers print('Log-transformation cannot be applied as LCA scores overlap zero.') # print('Filtering took {} seconds'.format(np.round(time() - start, 2))) # define problem self.names = self.metadata.index # ['GSA name'] # print('Names:', len(self.names)) self.problem = get_problem(self.X, self.names) # perform delta analysis time_delta = time() self.Si = delta.analyze(self.problem, self.X, self.Y, print_to_console=False) print('Delta analysis took {} seconds'.format(np.round(time() - time_delta, 2), )) # put GSA results in to dataframe self.dfgsa = pd.DataFrame(self.Si, index=self.names).sort_values(by='delta', ascending=False) self.dfgsa.index.names = ['GSA name'] # join with metadata self.df_final = self.dfgsa.join(self.metadata, on='GSA name') self.df_final.reset_index(inplace=True) self.df_final['pedigree'] = [str(x) for x in self.df_final['pedigree']] print('GSA took {} seconds'.format(np.round(time() - start, 2)))
def run(self, input_ids=None, output_ids=None, method=None, calc_second_order=None, conf_level=None, **kwargs): self._update_parameters(method, calc_second_order, conf_level) self.other_parameters = kwargs if input_ids is None: input_ids = range(self.n_inputs) self.problem = { "num_vars": len(input_ids), "names": np.array(self.input_names)[input_ids].tolist(), "bounds": np.array(self.input_bounds)[input_ids].tolist() } if output_ids is None: output_ids = range(self.n_outputs) n_outputs = len(output_ids) if self.method.lower() == "sobol": self.logger.warning( "'sobol' method requires 'saltelli' sampling scheme!") # Additional keyword parameters and their defaults: # calc_second_order (bool): Calculate second-order sensitivities (default True) # num_resamples (int): The number of resamples used to compute the confidence intervals (default 1000) # conf_level (float): The confidence interval level (default 0.95) # print_to_console (bool): Print results directly to console (default False) # parallel: False, # n_processors: None self.analyzer = lambda output: sobol.analyze( self.problem, output, calc_second_order=self.calc_second_order, conf_level=self.conf_level, num_resamples=self.other_parameters.get("num_resamples", 1000), parallel=self.other_parameters.get("parallel", False), n_processors=self.other_parameters.get("n_processors", None), print_to_console=self.other_parameters.get( "print_to_console", False)) elif np.in1d(self.method.lower(), ["latin", "delta"]): self.logger.warning( "'latin' sampling scheme is recommended for 'delta' method!") # Additional keyword parameters and their defaults: # num_resamples (int): The number of resamples used to compute the confidence intervals (default 1000) # conf_level (float): The confidence interval level (default 0.95) # print_to_console (bool): Print results directly to console (default False) self.analyzer = lambda output: delta.analyze( self.problem, self.input_samples[:, input_ids], output, conf_level=self.conf_level, num_resamples=self.other_parameters.get("num_resamples", 1000), print_to_console=self.other_parameters.get( "print_to_console", False)) elif np.in1d(self.method.lower(), ["fast", "fast_sampler"]): self.logger.warning( "'fast' method requires 'fast_sampler' sampling scheme!") # Additional keyword parameters and their defaults: # M (int): The interference parameter, # i.e., the number of harmonics to sum in the Fourier series decomposition (default 4) # print_to_console (bool): Print results directly to console (default False) self.analyzer = lambda output: fast.analyze( self.problem, output, M=self.other_parameters.get("M", 4), print_to_console=self.other_parameters.get( "print_to_console", False)) elif np.in1d(self.method.lower(), ["ff", "fractional_factorial"]): # Additional keyword parameters and their defaults: # second_order (bool, default=False): Include interaction effects # print_to_console (bool, default=False): Print results directly to console self.logger.warning( "'fractional_factorial' method requires 'fractional_factorial' sampling scheme!" ) self.analyzer = lambda output: ff.analyze( self.problem, self.input_samples[:, input_ids], output, calc_second_order=self.calc_second_order, conf_level=self.conf_level, num_resamples=self.other_parameters.get("num_resamples", 1000), print_to_console=self.other_parameters.get( "print_to_console", False)) elif self.method.lower().lower() == "morris": self.logger.warning( "'morris' method requires 'morris' sampling scheme!") # Additional keyword parameters and their defaults: # num_resamples (int): The number of resamples used to compute the confidence intervals (default 1000) # conf_level (float): The confidence interval level (default 0.95) # print_to_console (bool): Print results directly to console (default False) # grid_jump (int): The grid jump size, must be identical to the value passed to # SALib.sample.morris.sample() (default 2) # num_levels (int): The number of grid levels, must be identical to the value passed to # SALib.sample.morris (default 4) self.analyzer = lambda output: morris.analyze( self.problem, self.input_samples[:, input_ids], output, conf_level=self.conf_level, grid_jump=self.other_parameters.get("grid_jump", 2), num_levels=self.other_parameters.get("num_levels", 4), num_resamples=self.other_parameters.get("num_resamples", 1000), print_to_console=self.other_parameters.get( "print_to_console", False)) elif self.method.lower() == "dgsm": # num_resamples (int): The number of resamples used to compute the confidence intervals (default 1000) # conf_level (float): The confidence interval level (default 0.95) # print_to_console (bool): Print results directly to console (default False) self.analyzer = lambda output: dgsm.analyze( self.problem, self.input_samples[:, input_ids], output, conf_level=self.conf_level, num_resamples=self.other_parameters.get("num_resamples", 1000), print_to_console=self.other_parameters.get( "print_to_console", False)) else: raise_value_error("Method " + str(self.method) + " is not one of the available methods " + str(METHODS) + " !") output_names = [] results = [] for io in output_ids: output_names.append(self.output_names[io]) results.append(self.analyzer(self.output_values[:, io])) # TODO: Adjust list_of_dicts_to_dicts_of_ndarrays to handle ndarray concatenation results = list_of_dicts_to_dicts_of_ndarrays(results) results.update({"output_names": output_names}) return results
R2_scores = pd.DataFrame(np.zeros((params_no, len(percentiles))), columns = percentiles) DELTA.index=DELTA_conf.index=S1.index=S1_conf.index = R2_scores.index = param_names # Read in experiment data expData = np.loadtxt('./experiment_data.txt') # Identify magnitude at each percentiles syn_magnitude = np.zeros([len(percentiles),len(LHsamples[:,0])]) for j in range(len(LHsamples[:,0])): syn_magnitude[:,j]=[np.percentile(expData[:,j], i) for i in percentiles] # Delta Method analysis for i in range(len(percentiles)): if syn_magnitude[i,:].any(): try: result= delta.analyze(problem, LHsamples, syn_magnitude[i,:], print_to_console=False, num_resamples=2) DELTA[percentiles[i]]= result['delta'] DELTA_conf[percentiles[i]] = result['delta_conf'] S1[percentiles[i]]=result['S1'] S1_conf[percentiles[i]]=result['S1_conf'] except: pass S1.to_csv('./S1_scores.csv') S1_conf.to_csv('./S1_conf_scores.csv') DELTA.to_csv('./DELTA_scores.csv') DELTA_conf.to_csv('./DELTA_conf_scores.csv') # OLS regression analysis dta = pd.DataFrame(data = LHsamples, columns=param_names) # fig = plt.figure()
def perform_GSA(self, act_number=0, method_number=0, cutoff_technosphere=0.01, cutoff_biosphere=0.01): """Perform GSA for specific functional unit and LCIA method.""" start = time() # set FU and method try: self.act_number = act_number self.method_number = method_number self.cutoff_technosphere = cutoff_technosphere self.cutoff_biosphere = cutoff_biosphere self.fu = self.mc.cs['inv'][act_number] self.activity = bw.get_activity(self.mc.rev_activity_index[act_number]) self.method = self.mc.cs['ia'][method_number] except Exception as e: traceback.print_exc() print('Initializing the GSA failed.') return None print('-- GSA --\n Project:', bw.projects.current, 'CS:', self.mc.cs_name, 'Activity:', self.activity, 'Method:', self.method) # get non-stochastic LCA object with reverse dictionaries self.lca = get_lca(self.fu, self.method) # ============================================================================= # Filter exchanges and get metadata DataFrames # ============================================================================= dfs = [] # technosphere if self.mc.include_technosphere: self.t_indices = filter_technosphere_exchanges(self.fu, self.method, cutoff=cutoff_technosphere, max_calc=1e4) self.t_exchanges, self.t_indices = get_exchanges(self.lca, self.t_indices) self.dft = get_exchanges_dataframe(self.t_exchanges, self.t_indices) if not self.dft.empty: dfs.append(self.dft) # biosphere if self.mc.include_biosphere: self.b_indices = filter_biosphere_exchanges(self.lca, cutoff=cutoff_biosphere) self.b_exchanges, self.b_indices = get_exchanges(self.lca, self.b_indices, biosphere=True) self.dfb = get_exchanges_dataframe(self.b_exchanges, self.b_indices, biosphere=True) if not self.dfb.empty: dfs.append(self.dfb) # characterization factors if self.mc.include_cfs: self.dfcf = get_CF_dataframe(self.lca, only_uncertain_CFs=True) # None if no stochastic CFs if not self.dfcf.empty: dfs.append(self.dfcf) # parameters # remark: the exchanges affected by parameters are NOT removed in this implementation. Thus the GSA results # will potentially show both the parameters AND the dependent exchanges self.dfp = get_parameters_DF(self.mc) # Empty df if no parameters if not self.dfp.empty: dfs.append(self.dfp) # Join dataframes to get metadata self.metadata = pd.concat(dfs, axis=0, ignore_index=True, sort=False) self.metadata.set_index('GSA name', inplace=True) # ============================================================================= # GSA # ============================================================================= # Get X (Technosphere, Biosphere and CF values) X_list = list() if self.mc.include_technosphere and self.t_indices: self.Xa = get_X(self.mc.A_matrices, self.t_indices) X_list.append(self.Xa) if self.mc.include_biosphere and self.b_indices: self.Xb = get_X(self.mc.B_matrices, self.b_indices) X_list.append(self.Xb) if self.mc.include_cfs and not self.dfcf.empty: self.Xc = get_X_CF(self.mc, self.dfcf, self.method) X_list.append(self.Xc) if self.mc.include_parameters and not self.dfp.empty: self.Xp = get_X_P(self.dfp) X_list.append(self.Xp) self.X = np.concatenate(X_list, axis=1) # print('X', self.X.shape) # Get Y (LCA scores) self.Y = self.mc.get_results_dataframe(act_key=self.activity.key)[self.method].to_numpy() self.Y = np.log(self.Y) # this makes it more robust for very uneven distributions of LCA results # (e.g. toxicity related impacts); for not so large differences in LCIA results it should not matter # define problem self.names = self.metadata.index # ['GSA name'] # print('Names:', len(self.names)) self.problem = get_problem(self.X, self.names) # perform delta analysis time_delta = time() self.Si = delta.analyze(self.problem, self.X, self.Y, print_to_console=False) print('Delta analysis took {} seconds'.format(np.round(time() - time_delta, 2), )) # put GSA results in to dataframe self.dfgsa = pd.DataFrame(self.Si, index=self.names).sort_values(by='delta', ascending=False) self.dfgsa.index.names = ['GSA name'] # join with metadata self.df_final = self.dfgsa.join(self.metadata, on='GSA name') self.df_final.reset_index(inplace=True) self.df_final['pedigree'] = [str(x) for x in self.df_final['pedigree']] print('GSA took {} seconds'.format(np.round(time() - start, 2)))
def analyze_delta(self): # Delta Moment-Independent Measure return delta.analyze(self.sa_problem, self.samples_x, self.samples_y, print_to_console=self.options["print_to_console"])
def sa(model, response, policy={}, method="sobol", nsamples=1000, **kwargs): if len(model.uncertainties) == 0: raise ValueError("no uncertainties defined in model") problem = { 'num_vars': len(model.uncertainties), 'names': model.uncertainties.keys(), 'bounds': [[0.0, 1.0] for u in model.uncertainties], 'groups': kwargs.get("groups", None) } # estimate the argument N passed to the sampler that produces the requested # number of samples N = _predict_N(method, nsamples, problem["num_vars"], kwargs) # generate the samples if method == "sobol": samples = saltelli.sample(problem, N, **_cleanup_kwargs(saltelli.sample, kwargs)) elif method == "morris": samples = morris_sampler.sample( problem, N, **_cleanup_kwargs(morris_sampler.sample, kwargs)) elif method == "fast": samples = fast_sampler.sample( problem, N, **_cleanup_kwargs(fast_sampler.sample, kwargs)) elif method == "ff": samples = ff_sampler.sample( problem, **_cleanup_kwargs(ff_sampler.sample, kwargs)) elif method == "dgsm": samples = finite_diff.sample( problem, N, **_cleanup_kwargs(finite_diff.sample, kwargs)) elif method == "delta": if "samples" in kwargs: samples = kwargs["samples"] else: samples = latin.sample(problem, N, **_cleanup_kwargs(latin.sample, kwargs)) # convert from samples in [0, 1] to uncertainty domain for i, u in enumerate(model.uncertainties): samples[:, i] = u.ppf(samples[:, i]) # run the model and collect the responses responses = np.empty(samples.shape[0]) for i in range(samples.shape[0]): sample = {k: v for k, v in zip(model.uncertainties.keys(), samples[i])} responses[i] = evaluate(model, overwrite(sample, policy))[response] # run the sensitivity analysis method if method == "sobol": result = sobol.analyze(problem, responses, **_cleanup_kwargs(sobol.analyze, kwargs)) elif method == "morris": result = morris_analyzer.analyze( problem, samples, responses, **_cleanup_kwargs(morris_analyzer.analyze, kwargs)) elif method == "fast": result = fast.analyze(problem, responses, **_cleanup_kwargs(fast.analyze, kwargs)) elif method == "ff": result = ff_analyzer.analyze( problem, samples, responses, **_cleanup_kwargs(ff_analyzer.analyze, kwargs)) elif method == "dgsm": result = dgsm.analyze(problem, samples, responses, **_cleanup_kwargs(dgsm.analyze, kwargs)) elif method == "delta": result = delta.analyze(problem, samples, responses, **_cleanup_kwargs(delta.analyze, kwargs)) # convert the SALib results into a form allowing pretty printing and # lookups using the parameter name pretty_result = SAResult( list(result["names"] if "names" in result else problem["names"])) if "S1" in result: pretty_result["S1"] = { k: float(v) for k, v in zip(problem["names"], result["S1"]) } if "S1_conf" in result: pretty_result["S1_conf"] = { k: float(v) for k, v in zip(problem["names"], result["S1_conf"]) } if "ST" in result: pretty_result["ST"] = { k: float(v) for k, v in zip(problem["names"], result["ST"]) } if "ST_conf" in result: pretty_result["ST_conf"] = { k: float(v) for k, v in zip(problem["names"], result["ST_conf"]) } if "S2" in result: pretty_result["S2"] = _S2_to_dict(result["S2"], problem) if "S2_conf" in result: pretty_result["S2_conf"] = _S2_to_dict(result["S2_conf"], problem) if "delta" in result: pretty_result["delta"] = { k: float(v) for k, v in zip(problem["names"], result["delta"]) } if "delta_conf" in result: pretty_result["delta_conf"] = { k: float(v) for k, v in zip(problem["names"], result["delta_conf"]) } if "vi" in result: pretty_result["vi"] = { k: float(v) for k, v in zip(problem["names"], result["vi"]) } if "vi_std" in result: pretty_result["vi_std"] = { k: float(v) for k, v in zip(problem["names"], result["vi_std"]) } if "dgsm" in result: pretty_result["dgsm"] = { k: float(v) for k, v in zip(problem["names"], result["dgsm"]) } if "dgsm_conf" in result: pretty_result["dgsm_conf"] = { k: float(v) for k, v in zip(problem["names"], result["dgsm_conf"]) } if "mu" in result: pretty_result["mu"] = { k: float(v) for k, v in zip(result["names"], result["mu"]) } if "mu_star" in result: pretty_result["mu_star"] = { k: float(v) for k, v in zip(result["names"], result["mu_star"]) } if "mu_star_conf" in result: pretty_result["mu_star_conf"] = { k: float(v) for k, v in zip(result["names"], result["mu_star_conf"]) } if "sigma" in result: pretty_result["sigma"] = { k: float(v) for k, v in zip(result["names"], result["sigma"]) } return pretty_result
sel_LAMBDA_DF = comp_df[(comp_df['decision_type'] == decision) & (comp_df['auction_type'] == auc) & (comp_df['layer'] == 'nan')] X = pd.concat([ sel_LAMBDA_DF[' No. Nodes'], sel_LAMBDA_DF[' Interconnection Prob'], sel_LAMBDA_DF[' Damage Prob'], sel_LAMBDA_DF[' Resource Cap '] ], axis=1, keys=['N', 'pi', 'pd', 'Rc']).to_numpy() Y = pd.concat([sel_LAMBDA_DF['lambda_U']], axis=1, keys=['lambda_U']).to_numpy().ravel() delta_perf = delta.analyze(problem, X, Y, num_resamples=100, conf_level=0.95, print_to_console=True, seed=None) for idx, para in enumerate(delta_perf['names']): sens_perf = sens_perf.append( { 'config_param': para, 'auction': auc, 'decision': decision, 'delta': delta_perf['delta'][idx], 'delta_CI': delta_perf['delta_conf'][idx] }, ignore_index=True) delta_dict_perf[auc, decision] = pd.DataFrame.from_dict({ x: delta_perf['delta_vec'][idx]