def test_plumeplot_non_unique_lines(plumeplot_scmrun):
    quantile_over = "climate_model"
    quantile = 0.05
    scenario = "a_scenario"
    variable = "Surface Air Temperature Change"

    summary_stats = ScmRun(
        plumeplot_scmrun.quantiles_over(quantile_over, quantiles=(0.05, 0.5, 0.95))
    )

    error_msg = re.escape(
        "More than one timeseries for "
        "quantile: {}, "
        "scenario: {}, "
        "variable: {}.\n"
        "Please process your data to create unique quantile timeseries "
        "before calling :meth:`plumeplot`.\n"
        "Found: {}".format(
            quantile,
            scenario,
            variable,
            summary_stats.filter(
                quantile=quantile, scenario=scenario, variable=variable
            ),
        )
    )
    with pytest.raises(ValueError, match=error_msg):
        summary_stats.plumeplot(pre_calculated=True)
def test_plumeplot_pre_calculated(plumeplot_scmrun, quantiles_plumes):
    quantiles = [v for qv in quantiles_plumes for v in qv[0]]
    summary_stats = ScmRun(
        plumeplot_scmrun.quantiles_over("ensemble_member", quantiles=quantiles)
    )
    summary_stats.plumeplot(
        quantiles_plumes=quantiles_plumes, pre_calculated=True,
    )
    def test_run_scenarios_multiple(self):
        ts1_erf = np.linspace(0, 4, 101)
        ts2_erf = np.sin(np.linspace(0, 4, 101))

        inp = ScmRun(
            data=np.vstack([ts1_erf, ts2_erf]).T,
            index=np.linspace(1750, 1850, 101).astype(int),
            columns={
                "scenario": ["test_scenario_1", "test_scenario_2"],
                "model": "unspecified",
                "climate_model": "junk input",
                "variable": "Effective Radiative Forcing",
                "unit": "W/m^2",
                "region": "World",
            },
        )

        model = self.tmodel()

        res = model.run_scenarios(inp)

        for scenario_ts in inp.groupby("scenario"):
            scenario = scenario_ts.get_unique_meta("scenario",
                                                   no_duplicates=True)

            model.set_drivers(
                scenario_ts.values.squeeze() *
                ur(inp.get_unique_meta("unit", no_duplicates=True)))
            model.reset()
            model.run()

            res_scen = res.filter(scenario=scenario)

            npt.assert_allclose(
                res_scen.filter(
                    variable="Surface Temperature|Upper").values.squeeze(),
                model._temp_upper_mag,
            )
            assert (res.filter(
                variable="Surface Temperature|Upper").get_unique_meta(
                    "unit", no_duplicates=True) == "delta_degC")

            npt.assert_allclose(
                res_scen.filter(
                    variable="Surface Temperature|Lower").values.squeeze(),
                model._temp_lower_mag,
            )
            assert (res.filter(
                variable="Surface Temperature|Lower").get_unique_meta(
                    "unit", no_duplicates=True) == "delta_degC")

            npt.assert_allclose(
                res_scen.filter(variable="Heat Uptake").values.squeeze(),
                model._rndt_mag,
            )
            assert (res.filter(variable="Heat Uptake").get_unique_meta(
                "unit", no_duplicates=True) == "W/m^2")
Exemple #4
0
def test_convert_to_scen_units():
    var_start_units_scen_units_conv_factor = (
        ("Emissions|CO2", "Mt CO2/yr", "Gt C/yr", 12 / 44000, None),
        ("Emissions|CH4", "Mt C/yr", "Mt CH4/yr", (12 + 4) / 12,
         "CH4_conversions"),
        (
            "Emissions|N2O",
            "kt N2O/yr",
            "Mt N2ON/yr",
            (2 * 14) / (1000 * (2 * 14 + 16)),
            None,
        ),
        ("Emissions|SOx", "Mt SO2/yr", "Mt S/yr", 32 / (32 + 2 * 16), None),
        ("Emissions|CO", "Mt CO/yr", "Mt CO/yr", 1, None),
        ("Emissions|NMVOC", "Mt VOC/yr", "Mt NMVOC/yr", 1, None),
        (
            "Emissions|NOx",
            "Mt NOx/yr",
            "Mt N/yr",
            14 / (14 + 2 * 16),
            "NOx_conversions",
        ),
        ("Emissions|BC", "Mt BC/yr", "Mt BC/yr", 1, None),
        ("Emissions|OC", "Mt OC/yr", "Mt OC/yr", 1, None),
        ("Emissions|NH3", "Mt NH3/yr", "Mt N/yr", 14 / (14 + 3), None),
        ("Emissions|CF4", "Mt CF4/yr", "kt CF4/yr", 1000, None),
        ("Emissions|HFC4310mee", "kt HFC4310mee/yr", "kt HFC4310/yr", 1, None),
        ("Emissions|SF6", "t SF6/yr", "kt SF6/yr", 1 / 1000, None),
    )

    start = ScmRun(
        data=np.ones((1, len(var_start_units_scen_units_conv_factor))),
        index=np.array([2015]),
        columns={
            "model": ["unspecified"],
            "scenario": ["test"],
            "region": ["World"],
            "variable": [v[0] for v in var_start_units_scen_units_conv_factor],
            "unit": [v[1] for v in var_start_units_scen_units_conv_factor],
        },
    )

    res = start.copy()
    for variable, _, target_unit, _, context in var_start_units_scen_units_conv_factor:
        res = res.convert_unit(target_unit, context=context, variable=variable)

    for (
            variable,
            _,
            target_unit,
            conv_factor,
            _,
    ) in var_start_units_scen_units_conv_factor:
        np.testing.assert_allclose(res.filter(variable=variable).timeseries(),
                                   conv_factor,
                                   rtol=1e-15)
Exemple #5
0
    def values(self):
        """Emissions values from historical joint with ssp245"""
        if not self._loaded:
            tmp = ScmRun(
                os.path.join(
                    os.path.dirname(__file__),
                    "rcmip-emissions-annual-means-v5-1-0-historical-ssp245.csv",
                ),
                lowercase_cols=True,
            )
            self._values = tmp.interpolate(
                [dt.datetime(y, 1, 1) for y in tmp["year"]])

        self._loaded = True
        return self._values
Exemple #6
0
def _single_fair_iteration(cfg):  # pylint: disable=R0914
    scenario = cfg.pop("scenario")
    model = cfg.pop("model")
    run_id = cfg.pop("run_id")
    factors = {}
    factors["gmst"] = cfg.pop("gmst_factor")
    factors["ohu"] = cfg.pop("ohu_factor")
    startyear = cfg.pop("startyear")
    output_vars = cfg.pop("output_vars")

    data, unit, nt = _process_output(fair_scm(**cfg), output_vars, factors)

    data_scmrun = []
    variables = []
    units = []
    for key, variable in data.items():
        variables.append(key)
        data_scmrun.append(variable)
        units.append(unit[key])

    tempres = ScmRun(
        np.vstack(data_scmrun).T,
        index=np.arange(startyear, startyear + nt),
        columns={
            "scenario": scenario,
            "model": model,
            "region": "World",
            "variable": variables,
            "unit": units,
            "run_id": run_id,
        },
    )

    return tempres
Exemple #7
0
def test_scenario_ssp370_world(test_data_dir):
    scenario = ScmRun(
        os.path.join(test_data_dir,
                     "rcmip-emissions-annual-means-v5-1-0-ssp370-world.csv"),
        lowercase_cols=True,
    )

    return scenario
Exemple #8
0
    def _check_heat_content_heat_uptake_consistency(res):
        hc_deltas = ScmRun(
            res.filter(variable="Heat Content", region="World")
            .timeseries(time_axis="year")
            .diff(axis="columns")
        )
        hc_deltas["unit"] = "{} / yr".format(hc_deltas.get_unique_meta("unit", True))

        ratio = hc_deltas.divide(
            res.filter(variable="Heat Uptake", region="World"),
            op_cols={"variable": "Heat Content / Heat Uptake"},
        )

        earth_surface_area = 5.100536e14
        npt.assert_allclose(
            earth_surface_area,
            ratio.convert_unit("m^2").timeseries(drop_all_nan_times=True),
        )
Exemple #9
0
def test_run_to_nc_dimensions_cover_all_metadata():
    start = ScmRun(
        np.arange(6).reshape(3, 2),
        index=[2010, 2020, 2030],
        columns={
            "variable": "Surface Temperature",
            "unit": "K",
            "model": ["model_a", "model_b"],
            "scenario": "scen_a",
            "region": "World",
        },
    )

    with tempfile.TemporaryDirectory() as tempdir:
        out_fname = join(tempdir, "out.nc")

        start.to_nc(out_fname, dimensions=("region", "model", "scenario"))
        loaded = ScmRun.from_nc(out_fname)

    assert_scmdf_almost_equal(start, loaded, check_ts_names=False)
Exemple #10
0
def run_fair(cfgs, output_vars):  # pylint: disable=R0914
    """
    Run FaIR

    Parameters
    ----------
    cfgs : list[dict]
        List of configurations with which to run FaIR

    output_vars : list[str]
        Variables to output

    Returns
    -------
    :obj:`ScmRun`
        :obj:`ScmRun` instance with all results.
    """
    res = []

    for cfg in cfgs:
        scenario = cfg.pop("scenario")
        model = cfg.pop("model")
        run_id = cfg.pop("run_id")
        factors = {}
        factors["gmst"] = cfg.pop("gmst_factor")
        factors["ohu"] = cfg.pop("ohu_factor")
        data, unit, nt = _process_output(fair_scm(**cfg), output_vars, factors)

        data_scmrun = []
        variables = []
        units = []
        for key, variable in data.items():
            variables.append(key)
            data_scmrun.append(variable)
            units.append(unit[key])

        tempres = ScmRun(
            np.vstack(data_scmrun).T,
            index=np.arange(1765, 1765 + nt),
            columns={
                "scenario": scenario,
                "model": model,
                "region": "World",
                "variable": variables,
                "unit": units,
                "run_id": run_id,
            },
        )

        res.append(tempres)

    res = run_append(res)

    return res
Exemple #11
0
    def _run(self, scenarios, cfgs, output_variables, output_config):
        if output_config is not None:
            raise NotImplementedError(
                "`output_config` not implemented for FaIR")

        fair_df = ScmRun(scenarios.timeseries())
        full_cfgs = self._make_full_cfgs(fair_df, cfgs)

        res = run_fair(full_cfgs, output_variables)
        res["climate_model"] = "FaIRv{}".format(self.get_version())

        return res
Exemple #12
0
def test_run_to_nc_extra_instead_of_dimension_run_id(scm_run):
    with tempfile.TemporaryDirectory() as tempdir:
        out_fname = join(tempdir, "out.nc")
        scm_run["run_id"] = [1, 2, 1]

        run_to_nc(scm_run,
                  out_fname,
                  dimensions=("scenario", ),
                  extras=("run_id", ))
        loaded = ScmRun.from_nc(out_fname)

    assert_scmdf_almost_equal(scm_run, loaded, check_ts_names=False)
Exemple #13
0
    def run_over_cfgs(self, cfgs, output_variables):
        """
        Run over each configuration parameter set
        write parameterfiles, run, read results
        and make an ScmRun with results
        """
        runs = []
        for i, pamset in enumerate(cfgs):
            self.pamfilewriter.write_parameterfile(
                pamset,
                os.path.join(self.rundir, re.sub("[^a-zA-Z0-9_-]", "", self.scen)),
            )
            call = "{executable} {pamfile}".format(
                executable=os.path.join(self.rundir, "scm_vCH4fb"),
                pamfile=os.path.join(
                    self.rundir,
                    re.sub("[^a-zA-Z0-9_-]", "", self.scen),
                    "inputfiles",
                    "pam_current.scm",
                ),
            )
            LOGGER.debug("Call, %s", call)
            subprocess.check_call(
                call, cwd=self.rundir, shell=True,  # nosec # have to use subprocess
            )
            for variable in output_variables:
                (
                    years,
                    timeseries,
                    unit,
                ) = self.resultsreader.read_variable_timeseries(
                    self.scen, variable, self.sfilewriter
                )
                if years.empty:  # pragma: no cover
                    continue  # pragma: no cover

                runs.append(
                    ScmRun(
                        pd.Series(timeseries, index=years),
                        columns={
                            "climate_model": "CICERO-SCM",
                            "model": self.model,
                            "run_id": pamset.get("Index", i),
                            "scenario": self.scen,
                            "region": ["World"],
                            "variable": [variable],
                            "unit": [unit],
                        },
                    )
                )

        return run_append(runs)
Exemple #14
0
    def load(self, key):
        """

        Parameters
        ----------
        key: str

        Returns
        -------
        :class:`scmdata.ScmRun`

        """
        return ScmRun.from_nc(key)
Exemple #15
0
def test_groupby_integer_metadata():
    def increment_ensemble_member(scmrun):
        scmrun["ensemble_member"] += 10

        return scmrun

    start = ScmRun(
        data=[[1, 2], [0, 1]],
        index=[2010, 2020],
        columns={
            "model": "model",
            "scenario": "scenario",
            "variable": "variable",
            "unit": "unit",
            "region": "region",
            "ensemble_member": [0, 1],
        },
    )

    res = start.groupby(["variable", "region", "scenario",
                         "ensemble_member"]).map(increment_ensemble_member)

    assert (res["ensemble_member"] == start["ensemble_member"] + 10).all()
Exemple #16
0
def start_scmrun():
    return ScmRun(
        np.arange(6).reshape(3, 2),
        [2010, 2020, 2030],
        columns={
            "scenario": "scenario",
            "model": "model",
            "climate_model": ["cmodel_a", "cmodel_b"],
            "variable": "variable",
            "unit": "unit",
            "region": "region",
            "ensemble_member": 0,
        },
    )
Exemple #17
0
    def values(self):
        if not self._loaded:
            self._values = (ScmRun(os.path.join(
                os.path.dirname(__file__),
                '../SSPs/data/rcmip-emissions-annual-means-4-0-0-ssp-only.csv'
            ),
                                   lowercase_cols=True).filter(
                                       scenario="ssp245",
                                       region="World",
                                       variable="Emissions*"))
            self._values = self._values.interpolate(
                [dt.datetime(y, 1, 1) for y in self._values["year"]])

        self._loaded = True

        return self._values
Exemple #18
0
def test_run_to_nc_loop_tricky_variable_name(scm_run, start_variable):
    # tests that the mapping between variable and units works even with
    # tricky variable names that get renamed in various was before serialising to
    # disk
    assert "Primary Energy|Coal" in scm_run.get_unique_meta("variable")
    scm_run["variable"] = scm_run["variable"].apply(
        lambda x: x.replace("Primary Energy|Coal", start_variable))
    scm_run["unit"] = scm_run["variable"].apply(
        lambda x: "EJ/yr" if x != start_variable else "MJ / yr")

    with tempfile.TemporaryDirectory() as tempdir:
        out_fname = join(tempdir, "out.nc")

        scm_run.to_nc(out_fname, dimensions=("scenario", ))
        loaded = ScmRun.from_nc(out_fname)

    assert_scmdf_almost_equal(scm_run, loaded, check_ts_names=False)
Exemple #19
0
    def _run(self, scenarios, cfgs, output_variables, output_config):
        # TODO: add use of historical data properly  # pylint:disable=fixme
        LOGGER.warning("Historical data has not been checked")

        magicc_df = scenarios.timeseries().reset_index()
        magicc_df["variable"] = magicc_df["variable"].apply(
            lambda x: x.replace("Sulfur", "SOx")
            .replace("HFC4310mee", "HFC4310")
            .replace("VOC", "NMVOC")
        )

        magicc_scmdf = pymagicc.io.MAGICCData(magicc_df)
        emms_units = pymagicc.definitions.MAGICC7_EMISSIONS_UNITS
        emms_units["openscm_variable"] = emms_units["magicc_variable"].apply(
            lambda x: pymagicc.definitions.convert_magicc7_to_openscm_variables(
                "{}_EMIS".format(x)
            )
        )
        emms_units = emms_units.set_index("openscm_variable")
        for variable in magicc_scmdf["variable"].unique():
            magicc_unit = emms_units.loc[variable, "emissions_unit"]
            magicc_scmdf = magicc_scmdf.convert_unit(
                magicc_unit, variable=variable, context="NOx_conversions"
            )

        full_cfgs = self._write_scen_files_and_make_full_cfgs(magicc_scmdf, cfgs)

        pymagicc_vars = [
            _VARIABLE_MAP[v] if v in _VARIABLE_MAP else v for v in output_variables
        ]
        res = run_magicc_parallel(full_cfgs, pymagicc_vars, output_config)

        LOGGER.debug("Dropping todo metadata")
        res = res.drop_meta("todo")
        res["climate_model"] = "MAGICC{}".format(self.get_version())

        res = self._fix_pint_incompatible_units(res)
        LOGGER.debug("Mapping variables to OpenSCM conventions")
        inverse_map = {v: k for k, v in _VARIABLE_MAP.items()}
        res["variable"] = res["variable"].apply(
            lambda x: inverse_map[x] if x in inverse_map else x
        )

        res = ScmRun(res)

        return res
Exemple #20
0
    def save(self, sr):
        """
        Save a ScmRun to the database

        The dataset should not contain any duplicate metadata for the
        database levels

        Parameters
        ----------
        sr : :class:`scmdata.ScmRun`
            Data to save

        Raises
        ------
        ValueError
            If duplicate metadata are present for the requested database levels

        KeyError
            If metadata for the requested database levels are not found

        Returns
        -------
        str
            Key where the data is saved
        """
        key = self.get_key(sr)

        ensure_dir_exists(key)
        if os.path.exists(key):
            existing_run = ScmRun.from_nc(key)

            sr = run_append([existing_run, sr])

        # Check for required extra dimensions
        dimensions = self.kwargs.get("dimensions", None)
        if not dimensions:
            nunique_meta_vals = sr.meta.nunique()
            dimensions = nunique_meta_vals[
                nunique_meta_vals > 1].index.tolist()
        sr.to_nc(key, dimensions=dimensions)
        return key
Exemple #21
0
def calc_dGSAT(var, ds, ds_out, scenario='scenario'):
    s_y = int(ds.isel(year=0)['year'].values)
    _erf_tmp = ds['ERF'].sel(variable=var).to_pandas()
    unit = "W/m^2"

    driver = ScmRun(
        data=_erf_tmp,
        index=s_y + np.arange(len(_erf_tmp)),
        columns={
            "unit": unit,
            "model": "custom",
            "scenario": scenario,
            "region": "World",
            "variable": "Effective Radiative Forcing",
        },
    )

    impulse_res = ImpulseResponseModel(
        d1=d1 * unit_registry("yr"),
        d2=d2 * unit_registry("yr"),
        q1=q1 * unit_registry("delta_degC / (W / m^2)"),
        q2=q2 * unit_registry("delta_degC / (W / m^2)"),
        efficacy=eff * unit_registry("dimensionless"),
    )
    dt_tmp = impulse_res.run_scenarios(driver)

    df_tmp = dt_tmp.filter(
        variable='Surface Temperature').timeseries()  #.lineplot()#['Surface']
    #_ds_dT[var] =df_tmp.transpose()

    #ds_out[var]  =
    df_tmp = df_tmp.reset_index().iloc[:, 12:].transpose().rename(
        {0: var}, axis=1)  #.to_xarray()
    year_index = pd.to_datetime(df_tmp.index).year
    df_tmp['year'] = year_index
    df_tmp = df_tmp.set_index('year')

    ds_out[var] = df_tmp.to_xarray()[var]

    return ds_out
Exemple #22
0
class TwoLayerVariantIntegrationTester(ModelIntegrationTester):

    tinp = ScmRun(
        data=np.linspace(0, 4, 101),
        index=np.linspace(1750, 1850, 101).astype(int),
        columns={
            "scenario": "test_scenario",
            "model": "unspecified",
            "climate_model": "junk input",
            "variable": "Effective Radiative Forcing",
            "unit": "W/m^2",
            "region": "World",
        },
    )

    def test_run_unit_handling(self, check_scmruns_allclose):
        inp = self.tinp.copy()

        model = self.tmodel()

        res = model.run_scenarios(inp)

        # scmdata bug
        # inp.convert_unit("kW/m^2") blows up
        inp_other_unit = inp.copy()
        inp_other_unit *= 10**-3
        inp_other_unit["unit"] = "kW/m^2"
        res_other_unit = model.run_scenarios(inp_other_unit)

        assert res.get_unique_meta("climate_model",
                                   no_duplicates=True) == model._name

        check_scmruns_allclose(
            res.filter(variable="Effective Radiative Forcing", keep=False),
            res_other_unit.filter(variable="Effective Radiative Forcing",
                                  keep=False),
        )

    def test_run_wrong_units(self):
        inp = self.tinp.copy()
        inp["unit"] = "W"

        model = self.tmodel()

        with pytest.raises(UnitError):
            model.run_scenarios(inp)

    def test_run_wrong_region(self):
        inp = self.tinp.copy()
        inp["region"] = "World|R5LAM"

        model = self.tmodel()

        error_msg = (
            "No World data available for driver_var `Effective Radiative Forcing`"
        )

        with pytest.raises(ValueError, match=error_msg):
            model.run_scenarios(inp)

    def test_run_wrong_driver(self):
        inp = self.tinp.copy()

        model = self.tmodel()

        error_msg = (
            "No World data available for driver_var `Effective Radiative Forcing|CO2`"
        )

        with pytest.raises(ValueError, match=error_msg):
            model.run_scenarios(inp,
                                driver_var="Effective Radiative Forcing|CO2")
Exemple #23
0
    def _make_full_cfgs(self, scenarios, cfgs):  # pylint: disable=R0201,R0914
        full_cfgs = []
        run_id_block = 0
        startyear = _check_startyear(cfgs)

        for (scenario, model), smdf in progress(
                scenarios.timeseries().groupby(["scenario", "model"]),
                desc="Creating FaIR emissions inputs",
        ):
            smdf_in = ScmRun(smdf)
            scen_startyear = smdf_in.time_points.years()[0]
            endyear = smdf_in.time_points.years()[-1]

            if startyear < 1750:
                raise ValueError(
                    "startyear must be 1750 or later (%d specified)" %
                    startyear)
            if endyear > 2500:
                raise ValueError(
                    "endyear must be 2500 or earlier (%d implied by scenario data)"
                    % endyear)
            emissions = scmdf_to_emissions(
                smdf_in,
                startyear=startyear,
                scen_startyear=scen_startyear,
                endyear=endyear,
            )
            nt = emissions.shape[0]

            natural_components = _get_natural_emissions_and_forcing(
                startyear, nt)
            ch4_n2o = natural_components["ch4_n2o"]
            solar_forcing = natural_components["solar_forcing"]
            volcanic_forcing = natural_components["volcanic_forcing"]

            scenario_cfg = [{
                "scenario":
                scenario,
                "model":
                model,
                "run_id":
                run_id_block + i,
                "emissions":
                emissions,
                "natural":
                ch4_n2o,
                "F_volcanic":
                volcanic_forcing,
                "F_solar":
                solar_forcing,
                "efficacy":
                np.ones(45),
                "diagnostics":
                "AR6",
                "gir_carbon_cycle":
                True,
                "temperature_function":
                "Geoffroy",
                "aerosol_forcing":
                "aerocom+ghan2",
                "fixPre1850RCP":
                False,
                "b_tro3":
                np.array([
                    1.77871043e-04, 5.80173377e-05, 1.94458719e-04,
                    2.09151270e-03
                ]),
                "tropO3_forcing":
                "cmip6",
                "aCO2land":
                0.0006394631886297174,
                "b_aero":
                np.array([-0.00503, 0.0, 0.0, 0.0, 0.0385, -0.0104, 0.0]),
                "ghan_params":
                np.array([1.232, 73.9, 63.0]),
                "gmst_factor":
                1 / 1.04,
                "ohu_factor":
                0.92,
                "startyear":
                startyear,
                **cfg,
            } for i, cfg in enumerate(cfgs)]
            run_id_block += len(scenario_cfg)

            full_cfgs += scenario_cfg

        return full_cfgs
Exemple #24
0
    def test_run(
        self,
        test_scenarios,
        test_data_dir,
        update_expected_values,
        shuffle_column_order,
    ):
        expected_output_file = os.path.join(
            test_data_dir,
            "expected-integration-output",
            "expected_ciceroscm_test_run_output.json",
        )

        if shuffle_column_order:
            tmp = test_scenarios.data
            cols = tmp.columns.tolist()
            tmp = tmp[cols[1:] + cols[:1]]
            test_scenarios = ScmRun(test_scenarios)

        res = run(
            scenarios=test_scenarios.filter(
                scenario=["ssp126", "ssp245", "ssp370"]),
            climate_models_cfgs={
                "CICEROSCM": [
                    {
                        "model_end": 2100,
                        "Index": 30040,
                        "lambda": 0.540,
                        "akapa": 0.341,
                        "cpi": 0.556,
                        "W": 1.897,
                        "rlamdo": 16.618,
                        "beto": 3.225,
                        "mixed": 107.277,
                        "dirso2_forc": -0.457,
                        "indso2_forc": -0.514,
                        "bc_forc": 0.200,
                        "oc_forc": -0.103,
                    },
                    {
                        "model_end": 2100,
                        "Index": 1,
                        "lambda": 0.3925,
                        "akapa": 0.2421,
                        "cpi": 0.3745,
                        "W": 0.8172,
                        "rlamdo": 16.4599,
                        "beto": 4.4369,
                        "mixed": 35.4192,
                        "dirso2_forc": -0.3428,
                        "indso2_forc": -0.3856,
                        "bc_forc": 0.1507,
                        "oc_forc": -0.0776,
                    },
                ]
            },
            output_variables=(
                "Surface Air Temperature Change",
                "Surface Air Ocean Blended Temperature Change",
                "Heat Content|Ocean",
                "Effective Radiative Forcing",
                "Effective Radiative Forcing|Anthropogenic",
                "Effective Radiative Forcing|Aerosols",
                "Effective Radiative Forcing|Greenhouse Gases",
                "Heat Uptake",
                "Atmospheric Concentrations|CO2",
                "Atmospheric Concentrations|CH4",
                "Atmospheric Concentrations|N2O",
                "Emissions|CO2",
                "Emissions|CH4",
                "Emissions|N2O",
            ),
            out_config=None,
        )
        assert isinstance(res, ScmRun)
        assert res["run_id"].min() == 1
        assert res["run_id"].max() == 30040
        assert res.get_unique_meta("climate_model",
                                   no_duplicates=True) == "CICERO-SCM"

        assert set(res.get_unique_meta("variable")) == set([
            "Surface Air Temperature Change",
            "Surface Air Ocean Blended Temperature Change",
            "Heat Content|Ocean",
            "Effective Radiative Forcing",
            "Effective Radiative Forcing|Anthropogenic",
            "Effective Radiative Forcing|Aerosols",
            "Effective Radiative Forcing|Greenhouse Gases",
            "Heat Uptake",
            "Atmospheric Concentrations|CO2",
            "Atmospheric Concentrations|CH4",
            "Atmospheric Concentrations|N2O",
            "Emissions|CO2",
            "Emissions|N2O",
            "Emissions|CH4",
        ])

        # check we can also calcluate quantiles
        assert "run_id" in res.meta
        quantiles = calculate_quantiles(res,
                                        [0, 0.05, 0.17, 0.5, 0.83, 0.95, 1])
        assert "run_id" not in quantiles.meta

        assert (res.filter(
            variable="Atmospheric Concentrations|CO2").get_unique_meta(
                "unit", True) == "ppm")
        assert (res.filter(
            variable="Atmospheric Concentrations|CH4").get_unique_meta(
                "unit", True) == "ppb")
        assert (res.filter(
            variable="Atmospheric Concentrations|N2O").get_unique_meta(
                "unit", True) == "ppb")
        assert (res.filter(variable="Emissions|CO2").get_unique_meta(
            "unit", True) == "PgC / yr")
        assert (res.filter(variable="Emissions|CH4").get_unique_meta(
            "unit", True) == "TgCH4 / yr")
        assert (res.filter(variable="Emissions|N2O").get_unique_meta(
            "unit", True) == "TgN2ON / yr")

        # check that emissions were passed through correctly
        for (scen, variable, unit, exp_val) in (
            ("ssp126", "Emissions|CO2", "PgC/yr", -2.3503),
            ("ssp370", "Emissions|CO2", "PgC/yr", 22.562),
            ("ssp126", "Emissions|CH4", "TgCH4/yr", 122.195),
            ("ssp370", "Emissions|CH4", "TgCH4/yr", 777.732),
            ("ssp126", "Emissions|N2O", "TgN2ON/yr", 5.318),
            ("ssp370", "Emissions|N2O", "TgN2ON/yr", 13.144),
        ):
            res_scen_2100_emms = res.filter(variable=variable,
                                            year=2100,
                                            scenario=scen).convert_unit(unit)
            if res_scen_2100_emms.empty:
                raise AssertionError("No {} data for {}".format(
                    variable, scen))

            npt.assert_allclose(
                res_scen_2100_emms.values,
                exp_val,
                rtol=1e-4,
            )
        for (scen, variable, unit, exp_val14, exp_val16) in (
            ("ssp126", "Emissions|CH4", "TgCH4/yr", 387.874, 379.956),
            ("ssp370", "Emissions|CH4", "TgCH4/yr", 387.874, 394.149),
            ("ssp126", "Emissions|N2O", "TgN2ON/yr", 6.911, 6.858),
            ("ssp370", "Emissions|N2O", "TgN2ON/yr", 6.911, 7.0477),
        ):
            res_scen_2014_emms = res.filter(variable=variable,
                                            year=2014,
                                            scenario=scen).convert_unit(unit)
            if res_scen_2014_emms.empty:
                raise AssertionError("No {} data for {}".format(
                    variable, scen))

            res_scen_2016_emms = res.filter(variable=variable,
                                            year=2016,
                                            scenario=scen).convert_unit(unit)
            if res_scen_2016_emms.empty:
                raise AssertionError("No {} data for {}".format(
                    variable, scen))

            npt.assert_allclose(
                res_scen_2014_emms.values,
                exp_val14,
                rtol=1e-4,
            )
            npt.assert_allclose(
                res_scen_2016_emms.values,
                exp_val16,
                rtol=1e-4,
            )
        for (scen, variable) in (
            ("ssp126", "Effective Radiative Forcing|Aerosols"),
            ("ssp370", "Effective Radiative Forcing|Aerosols"),
        ):
            res_scen_2015_emms = res.filter(variable=variable,
                                            year=2015,
                                            scenario=scen)
            if res_scen_2015_emms.empty:
                raise AssertionError(
                    "No CO2 emissions data for {}".format(scen))

            assert not np.equal(res_scen_2015_emms.values, 0).all()

        ssp245_ghg_erf_2015 = res.filter(
            variable="Effective Radiative Forcing|Greenhouse Gases",
            year=2015,
            scenario="ssp245",
            run_id=1,
        )
        ssp245_ghg_erf_2014 = res.filter(
            variable="Effective Radiative Forcing|Greenhouse Gases",
            year=2014,
            scenario="ssp245",
            run_id=1,
        )
        # check that jump in GHG ERF isn't there
        assert (ssp245_ghg_erf_2015.values.squeeze() -
                ssp245_ghg_erf_2014.values.squeeze()) < 0.1
        ssp245_ch4_conc_2015 = res.filter(
            variable="Atmospheric Concentrations|CH4",
            year=2015,
            scenario="ssp245",
            run_id=1,
        )
        ssp245_ch4_conc_2014 = res.filter(
            variable="Atmospheric Concentrations|CH4",
            year=2014,
            scenario="ssp245",
            run_id=1,
        )
        # ch
        # check that jump in GHG ERF isn't there
        assert (ssp245_ch4_conc_2014.values.squeeze() -
                ssp245_ch4_conc_2015.values.squeeze()) < 0.1

        self._check_output(res, expected_output_file, update_expected_values)
Exemple #25
0
def scmdf_to_emissions(scmdf, include_cfcs=True, startyear=1765, endyear=2100):
    """
    Opens an ScmDataFrame and extracts the data. Interpolates linearly
    between non-consecutive years in the SCEN file. Fills in chlorinated gases
    from a specified SSP scenario.

    Note this is a temporary fix for FaIR 1.6.

    Inputs:
        scmdf: ScmDataFrame

    Keywords:
        include_cfcs: bool
            MAGICC files do not come loaded with CFCs (indices 24-39).
            - if True, use the values from RCMIP for SSPs (all scenarios are
                the same).
            - Use False to ignore and create a 23-species emission file.
        startyear: First year of output file.
        endyear: Last year of output file.

    Returns:
        nt x 40 numpy emissions array (nt x 23 if ``include_cfcs`` is ``False``)
    """

    # We expect that aeneris and silicone are going to give us a nicely
    # formatted ScmDataFrame with all 23 species present and correct at
    # timesteps 2015, 2020 and ten-yearly to 2100.
    # We also implicitly assume that data up until 2014 will follow SSP
    # historical.
    # This adapter will not be tested on anything else!

    n_cols = 40
    nt = endyear - startyear + 1

    data_out = np.ones((nt, n_cols)) * np.nan
    data_out[:, 0] = np.arange(startyear, endyear + 1)

    if not has_scmdata:
        raise ImportError(
            "This is not going to work without having scmdata installed")

    if not isinstance(scmdf, ScmDataFrame):
        raise TypeError("scmdf must be an scmdata.ScmDataFrame instance")

    if not include_cfcs:
        raise NotImplementedError("include_cfcs equal to False")

    if scmdf[["model", "scenario"]].drop_duplicates().shape[0] != 1:
        raise AssertionError("Should only have one model-scenario pair")

    scen_start_year = 2015

    scmdf = ScmRun(scmdf.timeseries()).interpolate(
        [dt.datetime(y, 1, 1) for y in range(scen_start_year, endyear + 1)])

    years = scmdf["year"].values
    first_scenyear = years[0]
    first_scen_row = int(first_scenyear - startyear)

    # if correct units and interpolation were guaranteed we could do this for scenario too which is quicker
    hist_df = ssp245_world_emms_holder.values_fair_units.filter(
        year=range(startyear, 2015)).timeseries()

    future_ssp245_df = ssp245_world_emms_holder.values_fair_units.filter(
        year=range(2015, endyear + 1)).timeseries()

    for species in EMISSIONS_SPECIES_UNITS_CONTEXT["species"]:
        fair_col, _, _ = _get_fair_col_unit_context(species)

        hist_df_row = hist_df.index.get_level_values("variable").str.endswith(
            species)

        data_out[:first_scen_row,
                 fair_col] = hist_df[hist_df_row].values.squeeze()

        future_ssp245_df_row = future_ssp245_df.index.get_level_values(
            "variable").str.endswith(species)

        data_out[first_scen_row:, fair_col] = future_ssp245_df[
            future_ssp245_df_row].values.squeeze()

    for var_df in scmdf.groupby("variable"):
        variable = var_df.get_unique_meta("variable", no_duplicates=True)
        in_unit = var_df.get_unique_meta("unit", no_duplicates=True)
        fair_col, fair_unit, context = _get_fair_col_unit_context(variable)

        if in_unit != fair_unit:
            var_df_fair_unit = var_df.convert_unit(fair_unit, context=context)
        else:
            var_df_fair_unit = var_df

        data_out[first_scen_row:, fair_col] = var_df_fair_unit.values.squeeze()

    return data_out
def test_plumeplot_values(plumeplot_scmrun, quantiles_plumes, time_axis, linewidth):
    mock_ax = MagicMock()

    palette = {"a_model": "tab:blue", "a_model_2": "tab:red"}
    dashes = {"a_scenario": "-", "a_scenario_2": "--"}

    quantiles = [v for qv in quantiles_plumes for v in qv[0]]
    summary_stats = ScmRun(
        plumeplot_scmrun.quantiles_over("ensemble_member", quantiles=quantiles)
    )
    summary_stats.plumeplot(
        ax=mock_ax,
        quantiles_plumes=quantiles_plumes,
        pre_calculated=True,
        hue_var="climate_model",
        palette=palette,
        style_var="scenario",
        dashes=dashes,
        time_axis=time_axis,
        linewidth=linewidth,
    )

    xaxis = summary_stats.timeseries(time_axis=time_axis).columns.tolist()

    def _is_in_calls(call_to_check, call_args_list):
        pargs_to_check = call_to_check[1]
        kargs_to_check = call_to_check[2]
        in_call = False
        for ca in call_args_list:
            pargs = ca[0]
            pargs_match = True
            for i, p in enumerate(pargs):
                if isinstance(p, np.ndarray):
                    if not np.allclose(p, pargs_to_check[i]):
                        pargs_match = False
                else:
                    if not p == pargs_to_check[i]:
                        pargs_match = False

                if not pargs_match:
                    print(p)
                    print(pargs_to_check[i])

            kargs = ca[1]
            if pargs_match and kargs == kargs_to_check:
                in_call = True

        return in_call

    def _get_with_empty_check(idf_filtered):
        if idf_filtered.empty:
            raise ValueError("Empty")

        return idf_filtered.values.squeeze()

    def _make_fill_between_call(idf, cm, scen, quant_alpha):
        quantiles = quant_alpha[0]
        alpha = quant_alpha[1]

        return call(
            xaxis,
            _get_with_empty_check(
                idf.filter(climate_model=cm, scenario=scen, quantile=quantiles[0])
            ),
            _get_with_empty_check(
                idf.filter(climate_model=cm, scenario=scen, quantile=quantiles[1])
            ),
            alpha=alpha,
            color=palette[cm],
            label="{:.0f}th - {:.0f}th".format(quantiles[0] * 100, quantiles[1] * 100),
        )

    def _make_plot_call(idf, cm, scen, quant_alpha):
        quantiles = quant_alpha[0]
        alpha = quant_alpha[1]

        return call(
            xaxis,
            _get_with_empty_check(
                idf.filter(climate_model=cm, scenario=scen, quantile=quantiles[0])
            ),
            color=palette[cm],
            linestyle=dashes[scen],
            linewidth=linewidth,
            label="{:.0f}th".format(quantiles[0] * 100),
            alpha=alpha,
        )

    cm_scen_combos = summary_stats.meta[["climate_model", "scenario"]].drop_duplicates()
    cm_scen_combos = [v[1].values.tolist() for v in cm_scen_combos.iterrows()]

    plume_qa = [q for q in quantiles_plumes if len(q[0]) == 2]
    fill_between_calls = [
        _make_fill_between_call(summary_stats, cm, scen, qa)
        for cm, scen in cm_scen_combos
        for qa in plume_qa
    ]

    # debug by looking at mock_ax.fill_between.call_args_list
    assert all(
        [
            _is_in_calls(c, mock_ax.fill_between.call_args_list)
            for c in fill_between_calls
        ]
    )

    line_qa = [q for q in quantiles_plumes if len(q[0]) == 1]
    plot_calls = [
        _make_plot_call(summary_stats, cm, scen, qa)
        for cm, scen in cm_scen_combos
        for qa in line_qa
    ]

    # debug by looking at mock_ax.plot.call_args_list
    assert all([_is_in_calls(c, mock_ax.plot.call_args_list) for c in plot_calls])
Exemple #27
0
    def _make_full_cfgs(self, scenarios, cfgs):  # pylint: disable=R0201
        full_cfgs = []
        run_id_block = 0

        for (scenario, model), smdf in tqdm(
                scenarios.timeseries().groupby(["scenario", "model"]),
                desc="Creating FaIR emissions inputs",
        ):
            smdf_in = ScmRun(smdf)
            endyear = smdf_in.time_points.years()[-1]
            emissions = scmdf_to_emissions(smdf_in, endyear=endyear)

            emissions_pi = np.zeros(40)
            emissions_pi[5] = 1.2212429848636561
            emissions_pi[6] = 348.5273588
            emissions_pi[7] = 60.02182622
            emissions_pi[8] = 3.8773253867471933
            emissions_pi[9] = 2.097770755
            emissions_pi[10] = 15.44766815
            emissions_pi[11] = 6.92769009144426

            nt = emissions.shape[0]

            scenario_cfg = [{
                "scenario":
                scenario,
                "model":
                model,
                "run_id":
                run_id_block + i,
                "emissions":
                emissions,
                "natural":
                natural.Emissions.emissions[:nt, :],
                "F_volcanic":
                cmip6_volcanic.Forcing.volcanic[:nt],
                "F_solar":
                cmip6_solar.Forcing.solar[:nt],
                "efficacy":
                np.ones(45),
                "diagnostics":
                "AR6",
                "gir_carbon_cycle":
                True,
                "temperature_function":
                "Geoffroy",
                "aerosol_forcing":
                "aerocom+ghan2",
                "fixPre1850RCP":
                False,
                "E_pi":
                emissions_pi,
                "b_tro3":
                np.array([
                    1.77871043e-04, 5.80173377e-05, 1.94458719e-04,
                    2.09151270e-03
                ]),
                "tropO3_forcing":
                "cmip6",
                "aCO2land":
                0.0006394631886297174,
                "b_aero":
                np.array([-0.00503, 0.0, 0.0, 0.0, 0.0385, -0.0104, 0.0]),
                "ghan_params":
                np.array([1.232, 73.9, 63.0]),
                "gmst_factor":
                1 / 1.04,
                "ohu_factor":
                0.92,
                **cfg,
            } for i, cfg in enumerate(cfgs)]
            run_id_block += len(scenario_cfg)

            full_cfgs += scenario_cfg

        return full_cfgs
Exemple #28
0
import numpy as np
from scmdata import ScmRun

IDX = [2010, 2020, 2030]

start = ScmRun(
    data=np.arange(18).reshape(3, 6),
    index=IDX,
    columns={
        "variable": [
            "Emissions|CO2|Fossil",
            "Emissions|CO2|AFOLU",
            "Emissions|CO2|Fossil",
            "Emissions|CO2|AFOLU",
            "Cumulative Emissions|CO2",
            "Surface Air Temperature Change",
        ],
        "unit": ["GtC / yr", "GtC / yr", "GtC / yr", "GtC / yr", "GtC", "K"],
        "region":
        ["World|NH", "World|NH", "World|SH", "World|SH", "World", "World"],
        "model":
        "idealised",
        "scenario":
        "idealised",
    },
)

start.head()

fos = start.filter(variable="*Fossil")
fos.head()