def plot_histogram_Y_all( self, default_Y, bin_min=None, bin_max=None, num_bins=60, fig_format=(), ): fig = plot_histogram_Y( Y=self.Y_all, default_Y=default_Y, bin_min=bin_min, bin_max=bin_max, num_bins=num_bins, color=COLORS_DICT["all"], xaxes_title_text=self.model_output_name, trace_name="All parameters vary", ) if "pdf" in fig_format: fig.write_image( self.create_figure_Y_all_histogram_filepath("pdf").as_posix() ) if "html" in fig_format: fig.write_html( self.create_figure_Y_all_histogram_filepath("html").as_posix() ) if "pickle" in fig_format: filepath = self.create_figure_Y_all_histogram_filepath("pickle").as_posix() write_pickle(fig, filepath) return fig
def plot_convergence( self, sa_convergence_dict, parameter_inds=None, fig_format=[], ): """Plots sensitivity indices for model inputs ``parameter_inds`` for all convergence steps.""" if parameter_inds is None: parameter_inds = np.random.randint( 0, self.num_params, max(10, self.num_params // 10) ) # Assign color to each parameter colors = {} for parameter in parameter_inds: colors[parameter] = "rgb({0},{1},{2})".format( np.random.randint(0, 256), np.random.randint(0, 256), np.random.randint(0, 256), ) # Plot x = sa_convergence_dict["iterations"] sa_convergence_dict.pop("iterations") fig = make_subplots( rows=len(sa_convergence_dict), cols=1, subplot_titles=list(sa_convergence_dict.keys()), ) for parameter in parameter_inds: row = 1 for sa_index_name, sa_array in sa_convergence_dict.items(): showlegend = False if row == 1: showlegend = True fig.add_trace( go.Scatter( x=x, y=sa_array[:, parameter], mode="lines+markers", showlegend=showlegend, marker=dict(color=colors[parameter]), name="Parameter " + str(parameter), legendgroup=str(parameter), ), row=row, col=1, ) row += 1 fig.show() if "pdf" in fig_format: fig.write_image(self.create_figure_convergence_filepath("pdf").as_posix()) if "html" in fig_format: fig.write_html(self.create_figure_convergence_filepath("html").as_posix()) if "pickle" in fig_format: filepath = self.create_figure_convergence_filepath("pickle").as_posix() write_pickle(fig, filepath) return fig
def get_cf_params_local_sa(lca, write_dir, const_factors=(0.1, 10)): """Local SA for characterization factors.""" path_lsa_cf = Path(write_dir) / "LSA_scores_cf.pickle" if not path_lsa_cf.exists(): bio_x_tech_x_demand = lca.biosphere_matrix * spsolve( lca.technosphere_matrix, lca.demand_array ) path_lsa_include_inds_cf = Path(write_dir) / "include_inds_cf.pickle" inds_uncertain = np.where(lca.cf_params["uncertainty_type"] > 1)[0] if not path_lsa_include_inds_cf.exists(): uncertain_cf_params_temp = lca.cf_params[inds_uncertain] # Exclude characterization factors that are not affected by given demand exclude_flows = np.where(bio_x_tech_x_demand == 0)[0] exclude_inds = np.array([]) for flow in exclude_flows: exclude_inds = np.hstack( [exclude_inds, np.where(uncertain_cf_params_temp["row"] == flow)[0]] ) include_inds_temp = np.setdiff1d( np.arange(len(uncertain_cf_params_temp)), exclude_inds ) write_pickle(include_inds_temp, path_lsa_include_inds_cf) else: include_inds_temp = read_pickle(path_lsa_include_inds_cf) include_inds = inds_uncertain[include_inds_temp] uncertain_cf_params = lca.cf_params[include_inds] flows = uncertain_cf_params["row"] bio_reverse_dict = lca.reverse_dict()[WHERE_BIO_REVERSE_DICT] lsa_scores_cf = {} for i, param in enumerate(uncertain_cf_params): flow = flows[i] input_ = bio_reverse_dict[flow] scores = [] for const_factor in const_factors: characterization_vector = sum(deepcopy(lca.characterization_matrix)) characterization_vector[0, flow] *= const_factor score = characterization_vector * bio_x_tech_x_demand scores.append(score[0]) lsa_scores_cf[include_inds[i]] = { "input": input_, "scores": np.array(scores), } write_pickle(lsa_scores_cf, path_lsa_cf) else: lsa_scores_cf = read_pickle(path_lsa_cf) return lsa_scores_cf
def get_graph_traversal_params(self, cutoff=1e-16, max_calc=1e16): fp_graph_traversal = self.write_dir / self.create_graph_traversal_filename( cutoff, max_calc ) if fp_graph_traversal.exists(): res = read_pickle(fp_graph_traversal) else: res = bc.GraphTraversal().calculate( self.lca, cutoff=cutoff, max_calc=max_calc ) write_pickle(res, fp_graph_traversal) return res
def run_convergence(self, parameter_inds=None, fig_format=()): """Calls function that computes converging indices, saves them and plots for model inputs ``parameter_inds``.""" t0 = time.time() filepath_convergence_dict = self.create_convergence_dict_filepath() if filepath_convergence_dict.exists(): print("{} already exists".format(filepath_convergence_dict.name)) sa_convergence_dict = read_pickle(filepath_convergence_dict) else: sa_convergence_dict = self.generate_converging_gsa_indices() write_pickle(sa_convergence_dict, filepath_convergence_dict) t1 = time.time() print("Total convergence time -> {:8.3f} s".format(t1 - t0)) fig = self.plot_convergence(sa_convergence_dict, parameter_inds, fig_format) return fig
def write_X_chunks(gsa, n_workers): X = gsa.generate_unitcube_samples_based_on_method(gsa.iterations) print(X.shape, gsa.dirpath_Y) iter_chunk = gsa.iterations // n_workers for i in range(n_workers): start = iter_chunk * i end = iter_chunk * (i + 1) if i == n_workers - 1: end = max(iter_chunk * (i + 1), gsa.iterations) print(i, start, end) X_chunk = X[start:end, :] filepath_X_chunk = gsa.dirpath_Y / "X.unitcube.{}.{}.pickle".format( i, n_workers) write_pickle(X_chunk, filepath_X_chunk)
def plot_histogram_Y_all_Y_inf( self, influential_Y, num_influential, tag=None, fig_format=(), bin_min=None, bin_max=None, num_bins=60, showtitle=True, ): fig = plot_histogram_Y1_Y2( self.Y_all, influential_Y, default_Y=None, bin_min=bin_min, bin_max=bin_max, num_bins=num_bins, trace_name1="All parameters vary", trace_name2="Only influential vary", color1="#636EFA", color2="#EF553B", color_default_Y="red", opacity=0.65, xaxes_title_text=self.model_output_name, showtitle=showtitle, ) if "pdf" in fig_format: fig.write_image( self.create_figure_Y_all_Y_inf_histogram_filepath( num_influential, tag, "pdf" ).as_posix() ) if "html" in fig_format: fig.write_html( self.create_figure_Y_all_Y_inf_histogram_filepath( num_influential, tag, "html" ).as_posix() ) if "pickle" in fig_format: filepath = self.create_figure_Y_all_Y_inf_histogram_filepath( num_influential, tag, "pickle" ).as_posix() write_pickle(fig, filepath) return fig
def get_tech_params_local_sa( where_tech_lsa, lca, write_dir, const_factors=(0.1, 10), tag=None ): """Local SA for technosphere exchanges.""" path_lsa_tech = Path(write_dir) / "LSA_scores_tech_{}.pickle".format(tag) if not path_lsa_tech.exists(): # 1. lca related d = lca.demand_array B = lca.biosphere_matrix C = sum(lca.characterization_matrix) reverse_dict = lca.reverse_dict()[0] # 2. Find zero indices using Local SA where_tech_lsa.sort() num_params = len(where_tech_lsa) tech_params_lsa = lca.tech_params[where_tech_lsa] rows = tech_params_lsa["row"] cols = tech_params_lsa["col"] # 3. Constant factor const_factor = np.tile(const_factors, (num_params, 1)) N = const_factor.shape[1] # 4. Preparation for saving of the results lsa_scores_tech = {} # 5. Run LSA for i, where in enumerate(where_tech_lsa): scores = np.empty(N) scores[:] = np.nan for j in range(N): A = deepcopy(lca.technosphere_matrix) A[rows[i], cols[i]] *= const_factor[i, j] scores[j] = C * B * spsolve(A, d) del A lsa_scores_tech[int(where)] = dict( input=reverse_dict[rows[i]], output=reverse_dict[cols[i]], scores=deepcopy(scores), ) # 6. Save results write_pickle(lsa_scores_tech, path_lsa_tech) else: lsa_scores_tech = read_pickle(path_lsa_tech) return lsa_scores_tech
def compute_scores_per_worker(option, num_params, iterations, i_worker, n_workers, setup_lca_model, path_base): if option == "corr": gsa = setup_corr(num_params, iterations, setup_lca_model, path_base) elif option == "salt": gsa = setup_salt(num_params, iterations, setup_lca_model, path_base) elif option == "delt": gsa = setup_delt(num_params, iterations, setup_lca_model, path_base) elif option == "xgbo": gsa = setup_xgbo(num_params, iterations, setup_lca_model, path_base) gsa.dirpath_Y.mkdir(parents=True, exist_ok=True) filepath_X_chunk = gsa.dirpath_Y / "X.unitcube.{}.{}.pickle".format( i_worker, n_workers) X_chunk_unitcube = read_pickle(filepath_X_chunk) X_chunk_rescaled = gsa.model.rescale(X_chunk_unitcube) del X_chunk_unitcube scores = gsa.model(X_chunk_rescaled) Y_filename = "{}.{}.pickle".format(i_worker, n_workers) filepath = gsa.dirpath_Y / Y_filename write_pickle(scores, filepath) return scores
def plot_correlation_Y_all_Y_inf( self, influential_Y, num_influential, tag=None, fig_format=(), showtitle=True, ): fig = plot_correlation_Y1_Y2( Y1=self.Y_all, Y2=influential_Y, start=0, end=80, trace_name1="All parameters vary", trace_name2="Only influential vary", yaxes1_title_text=self.model_output_name, xaxes2_title_text=self.model_output_name, yaxes2_title_text=self.model_output_name, showtitle=showtitle, ) if "pdf" in fig_format: fig.write_image( self.create_figure_Y_all_Y_inf_correlation_filepath( num_influential, tag, "pdf" ).as_posix() ) if "html" in fig_format: fig.write_html( self.create_figure_Y_all_Y_inf_correlation_filepath( num_influential, tag, "html" ).as_posix() ) if "pickle" in fig_format: filepath = self.create_figure_Y_all_Y_inf_correlation_filepath( num_influential, tag, "pickle" ).as_posix() write_pickle(fig, filepath) return fig
def get_bootstrap_rankings_2( self, bootstrap_data, sa_mean_results, tag, num_ranks=10, rho_choice="spearmanr" ): """Get clustered rankings from bootstrap sensitivity indices. Parameters ---------- bootstrap_data : dict Dictionary where keys are sensitivity methods names and values are arrays with sensitivity indices from bootstrapping in rows for each model input in columns. sa_mean_results : dict Dictionary where keys are sensitivity methods names and values are mean results for each model input over all bootstrap samples. tag : str Tag to save clustered rankings. num_ranks : int Number of clusters. Returns ------- bootstrap_rankings : dict Dictionary where keys are sensitivity methods names and values are clustered ranks for all model inputs. """ bootstrap_rankings = {} for sa_name in self.sa_names: num_bootstrap = bootstrap_data[sa_name][0].shape[0] filepath_bootstrap_rankings = self.create_bootstrap_rankings_filepath( num_ranks, "{}_v2".format(tag), sa_name, num_bootstrap, ) if filepath_bootstrap_rankings.exists(): bootstrap_rankings_arr = read_pickle(filepath_bootstrap_rankings) else: num_combinations = num_bootstrap * (num_bootstrap - 1) // 2 bootstrap_rankings_arr = np.zeros((0, num_combinations)) bootstrap_rankings_arr[:] = np.nan # TODO change smth here if sa_name == "total_gain": means = self.bootstrap_data[sa_name][-1][0, :] else: means = sa_mean_results[sa_name][-1, :] breaks = jenkspy.jenks_breaks(means, nb_class=num_ranks) # mean_ranking = self.get_one_clustered_ranking(means, num_ranks, breaks) # mean_ranking = mean_ranking.astype(int) for i in range(len(self.iterations[sa_name])): bootstrap_data_sa = bootstrap_data[sa_name][i] rankings = np.zeros((0, self.num_params)) for data in bootstrap_data_sa: rankings = np.vstack( [ rankings, self.get_one_clustered_ranking(data, num_ranks, breaks), ] ) rankings = rankings.astype(int) rho_arr = np.zeros(num_combinations) rho_arr[:] = np.nan k = 0 for i, r1 in enumerate(rankings[:-1]): rho, _ = compute_rho_choice( rankings[i + 1 :, :], r1, rho_choice=rho_choice ) rho_arr[k : k + num_bootstrap - i - 1] = rho k += num_bootstrap - i - 1 bootstrap_rankings_arr = np.vstack( [bootstrap_rankings_arr, rho_arr] ) write_pickle(bootstrap_rankings_arr, filepath_bootstrap_rankings) bootstrap_rankings[sa_name] = bootstrap_rankings_arr return bootstrap_rankings
lca.lcia() ei_tech_group = [ g for g in lca.technosphere_mm.groups if "tech" in g.label and "ecoinvent" in g.label ] assert len(ei_tech_group) == 1 ei_tech_group = ei_tech_group[0] tech_params = ei_tech_group.package.data[2] cutoff = 0.01 max_calc = 1e3 sct_tech_params_filename = "tech_params_cutoff{}_maxcalc{}.pickle".format( cutoff, int(max_calc)) sct_tech_params_filepath = write_dir_sct / sct_tech_params_filename if not sct_tech_params_filepath.exists(): tech_params_sct = filter_uncertain_technosphere_exchanges(lca, cutoff=1e-6) write_pickle(tech_params_sct, sct_tech_params_filepath) else: tech_params_sct = read_pickle(sct_tech_params_filepath) # Local SA model = LCAModel( demand, uncertain_method, write_dir, ) print()
# -> salib filename = "saltelli.sampling.salib.k{}.kstep{}.N{}.pickle".format( input_last, input_step, iterations_const) filepath = path_base / filename if filepath.exists(): saltelli_sampling_salib_inputs = read_pickle(filepath) else: saltelli_sampling_salib_inputs = {} for ind, k in enumerate(inputs): problem = {"num_vars": k, "bounds": [[0, 1] * k]} t1 = time.time() x = salib_saltelli_sample(problem, saltelli_lcm // (ind + 1), calc_second_order, seed, skip_values) t2 = time.time() saltelli_sampling_salib_inputs[k] = t2 - t1 write_pickle(saltelli_sampling_salib_inputs, filepath) # -> gsa_framework filename = "saltelli.sampling.gsafr.k{}.kstep{}.N{}.pickle".format( input_last, input_step, iterations_const) filepath = path_base / filename if filepath.exists(): saltelli_sampling_gsafr_inputs = read_pickle(filepath) else: saltelli_sampling_gsafr_inputs = {} for ind, k in enumerate(inputs): saltelli_iterations = (k + 2) * saltelli_lcm // (ind + 1) t1 = time.time() x = saltelli_samples(saltelli_iterations, k, skip_values) t2 = time.time() saltelli_sampling_gsafr_inputs[k] = t2 - t1 write_pickle(saltelli_sampling_gsafr_inputs, filepath)
def get_bio_params_local_sa(lca, write_dir, const_factors=(0.1, 10)): """Local SA for biosphere parameters.""" path_lsa_bio = Path(write_dir) / "LSA_scores_bio.pickle" if not path_lsa_bio.exists(): tech_x_demand = spsolve(lca.technosphere_matrix, lca.demand_array) characterization_vector = sum(lca.characterization_matrix) path_include_inds_bio = Path(write_dir) / "include_inds_bio.pickle" inds_uncertain = np.where(lca.bio_params["uncertainty_type"] > 1)[0] if not path_include_inds_bio.exists(): uncertain_bio_params_temp = lca.bio_params[inds_uncertain] # Exclude bio exchanges that are not selected with the demand vector exclude_cols = np.where(tech_x_demand == 0)[0] exclude_inds = np.array([]) for col in exclude_cols: exclude_inds = np.hstack( [exclude_inds, np.where(uncertain_bio_params_temp["col"] == col)[0]] ) # Exclude bio exchanges that are not included in the given lcia method exclude_rows = np.where(characterization_vector.toarray()[0] == 0)[0] for row in exclude_rows: exclude_inds = np.hstack( [exclude_inds, np.where(uncertain_bio_params_temp["row"] == row)[0]] ) print( "Excluding {}/{} biosphere exchanges".format( len(exclude_inds), len(uncertain_bio_params_temp) ) ) exclude_inds = np.sort(exclude_inds) include_inds_temp = np.setdiff1d( np.arange(len(uncertain_bio_params_temp)), exclude_inds ) write_pickle(include_inds_temp, path_include_inds_bio) else: include_inds_temp = read_pickle(path_include_inds_bio) include_inds = inds_uncertain[include_inds_temp] uncertain_bio_params = lca.bio_params[include_inds] nbio = len(uncertain_bio_params) rows = uncertain_bio_params["row"] cols = uncertain_bio_params["col"] bio_reverse_dict = lca.reverse_dict()[2] tech_reverse_dict = lca.reverse_dict()[0] lsa_scores_bio = {} for i, param in enumerate(uncertain_bio_params): if i % 1000 == 0: print("{}/{}".format(i, nbio)) row, col = rows[i], cols[i] input_ = bio_reverse_dict[row] output_ = tech_reverse_dict[col] scores = [] for const_factor in const_factors: biosphere_matrix = deepcopy(lca.biosphere_matrix) biosphere_matrix[row, col] *= const_factor score = characterization_vector * (biosphere_matrix * tech_x_demand) scores.append(score[0]) lsa_scores_bio[include_inds[i]] = { "input": input_, "output": output_, "scores": np.array(scores), } write_pickle(lsa_scores_bio, path_lsa_bio) else: lsa_scores_bio = read_pickle(path_lsa_bio) return lsa_scores_bio