Example #1
0
 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()
Example #4
0
    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()
Example #5
0
    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)