def test_log_level_pass(self): """Test log level context manager passes""" #Check loggers are set to level with self.assertLogs('climada', level='INFO') as cm: with log_level('WARNING'): logging.getLogger('climada').info('info') logging.getLogger('climada').error('error') self.assertEqual(cm.output, ['ERROR:climada:error']) #Check if only climada loggers level change with self.assertLogs('matplotlib', level='DEBUG') as cm: with log_level('ERROR', name_prefix='climada'): logging.getLogger('climada').info('info') logging.getLogger('matplotlib').debug('debug') self.assertEqual(cm.output, ['DEBUG:matplotlib:debug'])
def uncertainty(self, unc_sample, rp=None, calc_eai_exp=False, calc_at_event=False, pool=None): """ Computes the impact for each sample in unc_data.sample_df. By default, the aggregated average annual impact (impact.aai_agg) and the excees impact at return periods rp (imppact.calc_freq_curve(self.rp).impact) is computed. Optionally, eai_exp and at_event is computed (this may require a larger amount of memory if the number of samples and/or the number of centroids and/or exposures points is large). This sets the attributes self.rp, self.calc_eai_exp, self.calc_at_event, self.metrics. This sets the attributes: unc_output.aai_agg_unc_df, unc_output.freq_curve_unc_df unc_output.eai_exp_unc_df unc_output.at_event_unc_df unc_output.tot_value_unc_df unc_output.unit Parameters ---------- unc_sample : climada.engine.uncertainty.unc_output.UncOutput Uncertainty data object with the input parameters samples rp : list(int), optional Return periods in years to be computed. The default is [5, 10, 20, 50, 100, 250]. calc_eai_exp : boolean, optional Toggle computation of the impact at each centroid location. The default is False. calc_at_event : boolean, optional Toggle computation of the impact for each event. The default is False. pool : pathos.pools.ProcessPool, optional Pool of CPUs for parralel computations. The default is None. Returns ------- unc_output : climada.engine.uncertainty.unc_output.UncImpactOutput Uncertainty data object with the impact outputs for each sample and all the sample data copied over from unc_sample. Raises ------ ValueError: If no sampling parameters defined, the distribution cannot be computed. See Also -------- climada.engine.impact: Compute risk. """ if unc_sample.samples_df.empty: raise ValueError("No sample was found. Please create one first" "using UncImpact.make_sample(N)") samples_df = unc_sample.samples_df.copy(deep=True) unit = self.value_unit if rp is None: rp = [5, 10, 20, 50, 100, 250] self.rp = rp self.calc_eai_exp = calc_eai_exp self.calc_at_event = calc_at_event start = time.time() one_sample = samples_df.iloc[0:1].iterrows() imp_metrics = map(self._map_impact_calc, one_sample) [ aai_agg_list, freq_curve_list, eai_exp_list, at_event_list, tot_value_list ] = list(zip(*imp_metrics)) elapsed_time = (time.time() - start) self.est_comp_time(unc_sample.n_samples, elapsed_time, pool) #Compute impact distributions with log_level(level='ERROR', name_prefix='climada'): if pool: LOGGER.info('Using %s CPUs.', pool.ncpus) chunksize = min(unc_sample.n_samples // pool.ncpus, 100) imp_metrics = pool.map(self._map_impact_calc, samples_df.iterrows(), chunsize=chunksize) else: imp_metrics = map(self._map_impact_calc, samples_df.iterrows()) #Perform the actual computation with log_level(level='ERROR', name_prefix='climada'): [ aai_agg_list, freq_curve_list, eai_exp_list, at_event_list, tot_value_list ] = list(zip(*imp_metrics)) # Assign computed impact distribution data to self aai_agg_unc_df = pd.DataFrame(aai_agg_list, columns=['aai_agg']) freq_curve_unc_df = pd.DataFrame(freq_curve_list, columns=['rp' + str(n) for n in rp]) eai_exp_unc_df = pd.DataFrame(eai_exp_list) # Setting to sparse dataframes is not compatible with .to_hdf5 # if np.count_nonzero(df_eai_exp.to_numpy()) / df_eai_exp.size < 0.5: # df_eai_exp = df_eai_exp.astype(pd.SparseDtype("float", 0.0)) #eai_exp_unc_df = df_eai_exp at_event_unc_df = pd.DataFrame(at_event_list) # Setting to sparse dataframes is not compatible with .to_hdf5 # if np.count_nonzero(df_at_event.to_numpy()) / df_at_event.size < 0.5: # df_at_event = df_at_event.astype(pd.SparseDtype("float", 0.0)) #at_event_unc_df = df_at_event tot_value_unc_df = pd.DataFrame(tot_value_list, columns=['tot_value']) if calc_eai_exp: exp = self.exp_input_var.evaluate() coord_df = exp.gdf[['latitude', 'longitude']] else: coord_df = pd.DataFrame([]) return UncImpactOutput(samples_df=samples_df, unit=unit, aai_agg_unc_df=aai_agg_unc_df, freq_curve_unc_df=freq_curve_unc_df, eai_exp_unc_df=eai_exp_unc_df, at_event_unc_df=at_event_unc_df, tot_value_unc_df=tot_value_unc_df, coord_df=coord_df)
def calc_distribution(self, pool=None, **kwargs): """ Computes the cost benefit for each of the parameters set defined in uncertainty.samples. By default, imp_meas_present, imp_meas_future, tot_climate_risk, benefit, cost_ben_ratio are computed. This sets the attribute self.metrics. Parameters ---------- pool : pathos.pools.ProcessPool, optional Pool of CPUs for parralel computations. Default is None. The default is None. **kwargs : keyword arguments Any keyword arguments of climada.engine.CostBenefit.calc() EXCEPT: haz, ent, haz_fut, ent_fut """ if self.samples_df.empty: raise ValueError("No sample was found. Please create one first" + "using UncImpact.make_sample(N)") start = time.time() one_sample = self.samples_df.iloc[0:1].iterrows() cb_metrics = map(self._map_costben_calc, one_sample) [ imp_meas_present, imp_meas_future, tot_climate_risk, benefit, cost_ben_ratio ] = list(zip(*cb_metrics)) elapsed_time = (time.time() - start) est_com_time = self.est_comp_time(elapsed_time, pool) #Compute impact distributions with log_level(level='ERROR', name_prefix='climada'): if pool: LOGGER.info('Using %s CPUs.', pool.ncpus) chunksize = min(self.n_samples // pool.ncpus, 100) cb_metrics = pool.map(partial(self._map_costben_calc, **kwargs), self.samples_df.iterrows(), chunsize=chunksize) else: cb_metrics = map(partial(self._map_costben_calc, **kwargs), self.samples_df.iterrows()) #Perform the actual computation with log_level(level='ERROR', name_prefix='climada'): [ imp_meas_present, imp_meas_future, tot_climate_risk, benefit, cost_ben_ratio ] = list(zip(*cb_metrics)) #Transpose list of list # Assign computed impact distribution data to self self.metrics['tot_climate_risk'] = \ pd.DataFrame(tot_climate_risk, columns = ['tot_climate_risk']) self.metrics['benefit'] = pd.DataFrame(benefit) self.metrics['cost_ben_ratio'] = pd.DataFrame(cost_ben_ratio) imp_metric_names = ['risk', 'risk_transf', 'cost_meas', 'cost_ins'] for imp_meas, name in zip([imp_meas_present, imp_meas_future], ['imp_meas_present', 'imp_meas_future']): df_imp_meas = pd.DataFrame() if imp_meas[0]: for imp in imp_meas: met_dic = {} for meas, imp_dic in imp.items(): metrics = [ imp_dic['risk'], imp_dic['risk_transf'], *imp_dic['cost'] ] dic_tmp = { meas + '-' + m_name: [m_value] for m_name, m_value in zip(imp_metric_names, metrics) } met_dic.update(dic_tmp) df_imp_meas = df_imp_meas.append(pd.DataFrame(met_dic)) self.metrics[name] = df_imp_meas LOGGER.info("Currently the freq_curve is not saved. Please " "change the risk_func if return period information " "needed") self.check()
def calc_distribution(self, rp=None, calc_eai_exp=False, calc_at_event=False, pool=None): """ Computes the impact for each of the parameters set defined in uncertainty.samples. By default, the aggregated average annual impact (impact.aai_agg) and the excees impact at return periods rp (imppact.calc_freq_curve(self.rp).impact) is computed. Optionally, eai_exp and at_event is computed (this may require a larger amount of memory if n_samples and/or the number of centroids is large). This sets the attributes self.rp, self.calc_eai_exp, self.calc_at_event, self.metrics. Parameters ---------- rp : list(int), optional Return periods in years to be computed. The default is [5, 10, 20, 50, 100, 250]. calc_eai_exp : boolean, optional Toggle computation of the impact at each centroid location. The default is False. calc_at_event : boolean, optional Toggle computation of the impact for each event. The default is False. pool : pathos.pools.ProcessPool, optional Pool of CPUs for parralel computations. Default is None. The default is None. Raises ------ ValueError: If no sampling parameters defined, the distribution cannot be computed. """ if self.samples_df.empty: raise ValueError("No sample was found. Please create one first" "using UncImpact.make_sample(N)") if rp is None: rp = [5, 10, 20, 50, 100, 250] self.rp = rp self.calc_eai_exp = calc_eai_exp self.calc_at_event = calc_at_event start = time.time() one_sample = self.samples_df.iloc[0:1].iterrows() imp_metrics = map(self._map_impact_calc, one_sample) [ aai_agg_list, freq_curve_list, eai_exp_list, at_event_list, tot_value_list ] = list(zip(*imp_metrics)) elapsed_time = (time.time() - start) est_com_time = self.est_comp_time(elapsed_time, pool) LOGGER.info("\n\nEstimated computation time: %.2f s\n", est_com_time) #Compute impact distributions with log_level(level='ERROR', name_prefix='climada'): if pool: LOGGER.info('Using %s CPUs.', pool.ncpus) chunksize = min(self.n_samples // pool.ncpus, 100) imp_metrics = pool.map(self._map_impact_calc, self.samples_df.iterrows(), chunsize=chunksize) else: imp_metrics = map(self._map_impact_calc, self.samples_df.iterrows()) #Perform the actual computation with log_level(level='ERROR', name_prefix='climada'): [ aai_agg_list, freq_curve_list, eai_exp_list, at_event_list, tot_value_list ] = list(zip(*imp_metrics)) # Assign computed impact distribution data to self self.metrics['aai_agg'] = pd.DataFrame(aai_agg_list, columns=['aai_agg']) self.metrics['freq_curve'] = pd.DataFrame( freq_curve_list, columns=['rp' + str(n) for n in rp]) self.metrics['eai_exp'] = pd.DataFrame(eai_exp_list) self.metrics['at_event'] = pd.DataFrame(at_event_list) self.metrics['tot_value'] = pd.DataFrame(tot_value_list, columns=['tot_value']) self.check()
def uncertainty(self, unc_data, pool=None, **cost_benefit_kwargs): """ Computes the cost benefit for each sample in unc_output.sample_df. By default, imp_meas_present, imp_meas_future, tot_climate_risk, benefit, cost_ben_ratio are computed. This sets the attributes: unc_output.imp_meas_present_unc_df, unc_output.imp_meas_future_unc_df unc_output.tot_climate_risk_unc_df unc_output.benefit_unc_df unc_output.cost_ben_ratio_unc_df unc_output.unit unc_output.cost_benefit_kwargs Parameters ---------- unc_data : climada.engine.uncertainty.unc_output.UncOutput Uncertainty data object with the input parameters samples pool : pathos.pools.ProcessPool, optional Pool of CPUs for parralel computations. Default is None. The default is None. cost_benefit_kwargs : keyword arguments Keyword arguments passed on to climada.engine.CostBenefit.calc() Returns ------- unc_output : climada.engine.uncertainty.unc_output.UncCostBenefitOutput Uncertainty data object in with the cost benefit outputs for each sample and all the sample data copied over from unc_sample. Raises ------ ValueError: If no sampling parameters defined, the uncertainty distribution cannot be computed. See Also -------- climada.engine.cost_benefit: Compute risk and adptation option cost benefits. """ if unc_data.samples_df.empty: raise ValueError("No sample was found. Please create one first" + "using UncImpact.make_sample(N)") samples_df = unc_data.samples_df.copy(deep=True) unit = self.value_unit LOGGER.info("The freq_curve is not saved. Please " "change the risk_func (see climada.engine.cost_benefit) " "if return period information is needed") start = time.time() one_sample = samples_df.iloc[0:1].iterrows() cb_metrics = map(self._map_costben_calc, one_sample) [imp_meas_present, imp_meas_future, tot_climate_risk, benefit, cost_ben_ratio] = list(zip(*cb_metrics)) elapsed_time = (time.time() - start) self.est_comp_time(unc_data.n_samples, elapsed_time, pool) #Compute impact distributions with log_level(level='ERROR', name_prefix='climada'): if pool: LOGGER.info('Using %s CPUs.', pool.ncpus) chunksize = min(unc_data.n_samples // pool.ncpus, 100) cb_metrics = pool.map(partial(self._map_costben_calc, **cost_benefit_kwargs), samples_df.iterrows(), chunsize = chunksize) else: cb_metrics = map(partial(self._map_costben_calc, **cost_benefit_kwargs), samples_df.iterrows()) #Perform the actual computation with log_level(level='ERROR', name_prefix='climada'): [imp_meas_present, imp_meas_future, tot_climate_risk, benefit, cost_ben_ratio] = list(zip(*cb_metrics)) #Transpose list of list # Assign computed impact distribution data to self tot_climate_risk_unc_df = \ pd.DataFrame(tot_climate_risk, columns = ['tot_climate_risk']) benefit_unc_df = pd.DataFrame(benefit) benefit_unc_df.columns = [ column + ' Benef' for column in benefit_unc_df.columns] cost_ben_ratio_unc_df = pd.DataFrame(cost_ben_ratio) cost_ben_ratio_unc_df.columns = [ column + ' CostBen' for column in cost_ben_ratio_unc_df.columns] imp_metric_names = ['risk', 'risk_transf', 'cost_meas', 'cost_ins'] im_periods = dict() for imp_meas, period in zip([imp_meas_present, imp_meas_future], ['present', 'future']): df_imp_meas = pd.DataFrame() name = 'imp_meas_' + period if imp_meas[0]: for imp in imp_meas: met_dic = {} for meas, imp_dic in imp.items(): metrics = [imp_dic['risk'], imp_dic['risk_transf'], *imp_dic['cost']] dic_tmp = {meas + ' - ' + m_name + ' - ' + period: [m_value] for m_name, m_value in zip(imp_metric_names, metrics) } met_dic.update(dic_tmp) df_imp_meas = df_imp_meas.append( pd.DataFrame(met_dic), ignore_index=True ) im_periods[name + '_unc_df'] = df_imp_meas cost_benefit_kwargs = { key: str(val) for key, val in cost_benefit_kwargs.items()} cost_benefit_kwargs = tuple(cost_benefit_kwargs.items()) return UncCostBenefitOutput(samples_df=samples_df, imp_meas_present_unc_df=im_periods['imp_meas_present_unc_df'], imp_meas_future_unc_df=im_periods['imp_meas_future_unc_df'], tot_climate_risk_unc_df=tot_climate_risk_unc_df, cost_ben_ratio_unc_df=cost_ben_ratio_unc_df, benefit_unc_df=benefit_unc_df, unit=unit, cost_benefit_kwargs=cost_benefit_kwargs)