Ejemplo n.º 1
0
 def test_w_out_config(self, test_scenarios):
     with pytest.raises(NotImplementedError):
         run(
             scenarios=test_scenarios.filter(scenario=["ssp126"]),
             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,
                     },
                 ]
             },
             output_variables=("Surface Air Temperature Change", ),
             out_config={"CiceroSCM": ("With ECS", )},
         )
Ejemplo n.º 2
0
def test_return_config_clash_error(test_scenarios, cfgs):
    with pytest.raises(ValueError):
        run(
            climate_models_cfgs={"MAGICC7": cfgs},
            scenarios=test_scenarios.filter(scenario=["ssp126"]),
            output_variables=("Surface Air Temperature Change", ),
            out_config={"MAGICC7": ("pf_apply", )},
        )
Ejemplo n.º 3
0
def test_run_out_config_type_error():
    error_msg = re.escape(
        "`out_config` values must be tuples, this isn't the case for "
        "climate_model: 'model_a'")
    with pytest.raises(TypeError, match=error_msg):
        run(
            climate_models_cfgs={"model_a": ["config list"]},
            scenarios="not used",
            out_config={"model_a": "hi"},
        )
Ejemplo n.º 4
0
def test_run_out_config_conflict_error():
    error_msg = re.escape("Found model(s) in `out_config` which are not in "
                          "`climate_models_cfgs`: {'another model'}")
    with pytest.raises(NotImplementedError):
        with pytest.warns(UserWarning, match=error_msg):
            run(
                climate_models_cfgs={"model_a": ["config list"]},
                scenarios="not used",
                out_config={"another model": ("hi", )},
            )
Ejemplo n.º 5
0
    def test_variable_naming(self, test_scenarios):
        missing_from_fair = (
            "Effective Radiative Forcing|Aerosols|Direct Effect|BC|MAGICC AFOLU",
            "Effective Radiative Forcing|Aerosols|Direct Effect|BC|MAGICC Fossil and Industrial",
            "Effective Radiative Forcing|Aerosols|Direct Effect|OC|MAGICC AFOLU",
            "Effective Radiative Forcing|Aerosols|Direct Effect|OC|MAGICC Fossil and Industrial",
            "Effective Radiative Forcing|Aerosols|Direct Effect|SOx|MAGICC AFOLU",
            "Effective Radiative Forcing|Aerosols|Direct Effect|SOx|MAGICC Fossil and Industrial",
            "Net Atmosphere to Ocean Flux|CO2",
            "Net Atmosphere to Land Flux|CO2",
        )
        common_variables = [
            c for c in self._common_variables if c not in missing_from_fair
        ]
        res = run(
            climate_models_cfgs={"FaIR": ({
                "startyear": 1750
            }, )},
            scenarios=test_scenarios.filter(scenario="ssp126"),
            output_variables=common_variables,
        )

        missing_vars = set(common_variables) - set(res["variable"])
        if missing_vars:
            raise AssertionError(missing_vars)
Ejemplo n.º 6
0
    def test_variable_naming(self, test_scenarios):
        """
        Test that variable naming is implemented as expecteds
        """
        # pseudo-code

        # a model might not report all outputs
        missing_variables = (
            "Net Atmosphere to Ocean Flux|CO2",
            "Net Atmosphere to Land Flux|CO2",
        )
        common_variables = [
            c for c in self._common_variables if c not in missing_variables
        ]

        # run the model and request all common variables the model reportss
        res = run(
            climate_models_cfgs={"climate_model": ({"para1": 3.43},)},
            scenarios=test_scenarios.filter(scenario="ssp126"),
            output_variables=common_variables,
        )

        # check that all expected outputs were returned
        missing_vars = set(common_variables) - set(res["variable"])
        if missing_vars:
            raise AssertionError(missing_vars)
Ejemplo n.º 7
0
def test_fair_ocean_factors(test_scenarios):
    res_default_factors = run(
        climate_models_cfgs={"FaIR": [{}]},
        scenarios=test_scenarios.filter(scenario=["ssp585"]),
        output_variables=(
            "Surface Air Ocean Blended Temperature Change",
            "Heat Uptake|Ocean",
            "Heat Content|Ocean",
        ),
    )

    res_custom_factors = run(
        climate_models_cfgs={
            "FaIR": [
                {
                    "gmst_factor": np.linspace(0.90, 1.00, 351),  # test with array
                    "ohu_factor": 0.93,
                }
            ]
        },
        scenarios=test_scenarios.filter(scenario=["ssp585"]),
        output_variables=(
            "Surface Air Ocean Blended Temperature Change",
            "Heat Uptake|Ocean",
            "Heat Content|Ocean",
        ),
    )

    assert (
        res_default_factors.filter(
            variable="Surface Air Ocean Blended Temperature Change",
            region="World",
            year=2100,
            scenario="ssp585",
        ).values
        != res_custom_factors.filter(
            variable="Surface Air Ocean Blended Temperature Change",
            region="World",
            year=2100,
            scenario="ssp585",
        ).values
    )
Ejemplo n.º 8
0
    def test_run(self, test_scenarios):
        """
        Test that the model can be run, ideally with more than one configuration
        """
        # pseudo-code
        res = run(
            climate_models_cfgs={
                "climate_model": [
                    {
                        "para1": "value1",
                        "para2": 1.1
                    },
                    {
                        "para1": "value3",
                        "para2": 1.2
                    },
                    {
                        "para1": "value5",
                        "para2": 1.3
                    },
                ],
            },
            scenarios=test_scenarios.filter(
                scenario=["ssp126", "ssp245", "ssp370"]),
            output_variables=(
                "output",
                "var",
                "list",
            ),
            out_config=None,
        )

        assert isinstance(res, ScmRun)
        assert res["run_id"].min() == 0
        assert res["run_id"].max() == 8

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

        assert set(res.get_unique_meta("variable")) == set(
            ["expected", "output", "variables"])

        # output value checks e.g.
        npt.assert_allclose(
            2.31,
            res.filter(
                variable="Surface Air Temperature Change",
                region="World",
                year=2100,
                scenario="ssp126",
            ).values.max(),
            rtol=self._rtol,
        )
Ejemplo n.º 9
0
    def test_variable_naming(self, test_scenarios):
        common_variables = self._common_variables
        res = run(
            climate_models_cfgs={
                "MAGICC7": ({
                    "core_climatesensitivity": 3
                }, )
            },
            scenarios=test_scenarios.filter(scenario="ssp126"),
            output_variables=common_variables,
        )

        missing_vars = set(common_variables) - set(res["variable"])
        if missing_vars:
            raise AssertionError(missing_vars)
Ejemplo n.º 10
0
def test_return_config(test_scenarios, out_config):
    core_climatesensitivities = [2, 3]
    rf_total_runmoduses = ["ALL", "CO2"]

    cfgs = []
    for cs in core_climatesensitivities:
        for runmodus in rf_total_runmoduses:
            cfgs.append({
                "out_dynamic_vars": [
                    "DAT_TOTAL_INCLVOLCANIC_ERF",
                    "DAT_SURFACE_TEMP",
                ],
                "core_climatesensitivity":
                cs,
                "rf_total_runmodus":
                runmodus,
            })

    res = run(
        climate_models_cfgs={"MAGICC7": cfgs},
        scenarios=test_scenarios.filter(
            scenario=["ssp126", "ssp245", "ssp370"]),
        output_variables=(
            "Surface Air Temperature Change",
            "Effective Radiative Forcing",
        ),
        out_config={"MAGICC7": out_config},
    )

    for k in out_config:
        assert k in res.meta.columns
        ssp126 = res.filter(scenario="ssp126")

        # check all the configs were used and check that each scenario
        # has all the configs included in the metadata too
        if k == "core_climatesensitivity":
            assert set(
                res.get_unique_meta(k)) == set(core_climatesensitivities)
            assert set(
                ssp126.get_unique_meta(k)) == set(core_climatesensitivities)
        elif k == "rf_total_runmodus":
            assert set(res.get_unique_meta(k)) == set(rf_total_runmoduses)
            assert set(ssp126.get_unique_meta(k)) == set(rf_total_runmoduses)
        else:
            raise NotImplementedError(k)
Ejemplo n.º 11
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)
Ejemplo n.º 12
0
scenarios = pyam.IamDataFrame(data_file_scenarios)

assert MAGICC7.get_version() == EXPECTED_MAGICC_VERSION, MAGICC7.get_version()

res = run(
    climate_models_cfgs={
        "MAGICC7": [
            {
                "core_climatesensitivity": 3,
                "rf_soxi_dir_wm2": -0.2,
                "out_temperature": 1,
            },
            {
                "core_climatesensitivity": 2,
                "rf_soxi_dir_wm2": -0.1,
                "out_temperature": 1,
            },
            {
                "core_climatesensitivity": 5,
                "rf_soxi_dir_wm2": -0.35,
                "out_temperature": 1,
            },
        ],
    },
    scenarios=scenarios,
)

if UPDATE:
    res.to_csv(data_file_regression)
else:
    expected_res = pyam.IamDataFrame(data_file_regression)
Ejemplo n.º 13
0
def test_magicc7_run(test_scenarios, magicc7_is_available):
    debug_run = False

    res = run(
        climate_models_cfgs={
            "MAGICC7": [
                {
                    "core_climatesensitivity":
                    3,
                    "rf_soxi_dir_wm2":
                    -0.2,
                    "out_temperature":
                    1,
                    "out_forcing":
                    1,
                    "out_dynamic_vars": [
                        "DAT_AEROSOL_ERF",
                        "DAT_HEATCONTENT_AGGREG_TOTAL",
                        "DAT_CO2_AIR2LAND_FLUX",
                    ],
                    "out_ascii_binary":
                    "BINARY",
                    "out_binary_format":
                    2,
                },
                {
                    "core_climatesensitivity": 2,
                    "rf_soxi_dir_wm2": -0.1,
                    "out_temperature": 1,
                    "out_forcing": 1,
                    "out_ascii_binary": "BINARY",
                    "out_binary_format": 2,
                },
                {
                    "core_climatesensitivity": 5,
                    "rf_soxi_dir_wm2": -0.35,
                    "out_temperature": 1,
                    "out_forcing": 1,
                    "out_ascii_binary": "BINARY",
                    "out_binary_format": 2,
                },
            ],
        },
        scenarios=test_scenarios.filter(
            scenario=["ssp126", "ssp245", "ssp370"]),
        output_variables=(
            "Surface Temperature",
            "Effective Radiative Forcing",
            "Effective Radiative Forcing|Aerosols",
            "Effective Radiative Forcing|CO2",
            "Heat Content|Ocean",
            "Net Atmosphere to Land Flux|CO2",
        ),
    )

    assert isinstance(res, ScmRun)
    assert res["run_id"].min() == 0
    assert res["run_id"].max() == 8
    assert res.get_unique_meta("climate_model",
                               no_duplicates=True) == "MAGICC{}".format(
                                   MAGICC7.get_version())
    assert set(res.get_unique_meta("variable")) == set([
        "Surface Temperature",
        "Effective Radiative Forcing",
        "Effective Radiative Forcing|Aerosols",
        "Effective Radiative Forcing|CO2",
        "Heat Content|Ocean",
        "Net Atmosphere to Land Flux|CO2",
    ])

    # check ocean heat content unit conversion comes through correctly
    _check_res(
        1824.05,
        res.filter(
            unit="ZJ",
            variable="Heat Content|Ocean",
            region="World",
            year=2100,
            scenario="ssp126",
        ).values.max(),
        not debug_run,
        rtol=RTOL,
    )

    _check_res(
        0.472378,
        res.filter(
            unit="GtC / yr",
            variable="Net Atmosphere to Land Flux|CO2",
            region="World",
            year=2100,
            scenario="ssp126",
        ).values.max(),
        not debug_run,
        rtol=RTOL,
    )

    _check_res(
        2.756034,
        res.filter(variable="Surface Temperature",
                   region="World",
                   year=2100,
                   scenario="ssp126").values.max(),
        not debug_run,
        rtol=RTOL,
    )
    _check_res(
        1.2195495,
        res.filter(variable="Surface Temperature",
                   region="World",
                   year=2100,
                   scenario="ssp126").values.min(),
        not debug_run,
        rtol=RTOL,
    )

    _check_res(
        5.5226571,
        res.filter(variable="Surface Temperature",
                   region="World",
                   year=2100,
                   scenario="ssp370").values.max(),
        not debug_run,
        rtol=RTOL,
    )
    _check_res(
        2.733369581,
        res.filter(variable="Surface Temperature",
                   region="World",
                   year=2100,
                   scenario="ssp370").values.min(),
        not debug_run,
        rtol=RTOL,
    )

    # check we can also calcluate quantiles
    quantiles = calculate_quantiles(res, [0.05, 0.17, 0.5, 0.83, 0.95])

    _check_res(
        1.27586919,
        quantiles.filter(
            variable="Surface Temperature",
            region="World",
            year=2100,
            scenario="ssp126",
            quantile=0.05,
        ).values,
        not debug_run,
        rtol=RTOL,
    )
    _check_res(
        2.6587052,
        quantiles.filter(
            variable="Surface Temperature",
            region="World",
            year=2100,
            scenario="ssp126",
            quantile=0.95,
        ).values,
        not debug_run,
        rtol=RTOL,
    )

    _check_res(
        2.83627686,
        quantiles.filter(
            variable="Surface Temperature",
            region="World",
            year=2100,
            scenario="ssp370",
            quantile=0.05,
        ).values,
        not debug_run,
        rtol=RTOL,
    )
    _check_res(
        5.34663565,
        quantiles.filter(
            variable="Surface Temperature",
            region="World",
            year=2100,
            scenario="ssp370",
            quantile=0.95,
        ).values,
        not debug_run,
        rtol=RTOL,
    )

    if debug_run:
        assert False, "Turn off debug"
Ejemplo n.º 14
0
def test_forcing_categories(test_scenarios):
    forcing_categories = [
        "Effective Radiative Forcing|CO2",
        "Effective Radiative Forcing|CH4",
        "Effective Radiative Forcing|N2O",
        "Effective Radiative Forcing|CF4",
        "Effective Radiative Forcing|C2F6",
        "Effective Radiative Forcing|C6F14",
        "Effective Radiative Forcing|HFC23",
        "Effective Radiative Forcing|HFC32",
        "Effective Radiative Forcing|HFC125",
        "Effective Radiative Forcing|HFC134a",
        "Effective Radiative Forcing|HFC143a",
        "Effective Radiative Forcing|HFC227ea",
        "Effective Radiative Forcing|HFC245fa",
        "Effective Radiative Forcing|HFC4310mee",
        "Effective Radiative Forcing|SF6",
        "Effective Radiative Forcing|CFC11",
        "Effective Radiative Forcing|CFC12",
        "Effective Radiative Forcing|CFC113",
        "Effective Radiative Forcing|CFC114",
        "Effective Radiative Forcing|CFC115",
        "Effective Radiative Forcing|CCl4",
        "Effective Radiative Forcing|CH3CCl3",
        "Effective Radiative Forcing|HCFC22",
        "Effective Radiative Forcing|HCFC141b",
        "Effective Radiative Forcing|HCFC142b",
        "Effective Radiative Forcing|Halon1211",
        "Effective Radiative Forcing|Halon1202",
        "Effective Radiative Forcing|Halon1301",
        "Effective Radiative Forcing|Halon2402",
        "Effective Radiative Forcing|CH3Br",
        "Effective Radiative Forcing|CH3Cl",
        "Effective Radiative Forcing|Tropospheric Ozone",
        "Effective Radiative Forcing|Stratospheric Ozone",
        "Effective Radiative Forcing|CH4 Oxidation Stratospheric H2O",
        "Effective Radiative Forcing|Contrails",
        "Effective Radiative Forcing|Aerosols|Direct Effect|SOx",
        "Effective Radiative Forcing|Aerosols|Direct Effect|Secondary Organic Aerosol",
        "Effective Radiative Forcing|Aerosols|Direct Effect|Nitrate",
        "Effective Radiative Forcing|Aerosols|Direct Effect|BC",
        "Effective Radiative Forcing|Aerosols|Direct Effect|OC",
        "Effective Radiative Forcing|Aerosols|Indirect Effect",
        "Effective Radiative Forcing|Black Carbon on Snow",
        "Effective Radiative Forcing|Land-use Change",
        "Effective Radiative Forcing|Volcanic",
        "Effective Radiative Forcing|Solar",
        "Effective Radiative Forcing",
        "Effective Radiative Forcing|Anthropogenic",
        "Effective Radiative Forcing|Greenhouse Gases",
        "Effective Radiative Forcing|Kyoto Gases",
        "Effective Radiative Forcing|CO2, CH4 and N2O",
        "Effective Radiative Forcing|F-Gases",
        "Effective Radiative Forcing|Montreal Protocol Halogen Gases",
        "Effective Radiative Forcing|Aerosols|Direct Effect",
        "Effective Radiative Forcing|Aerosols",
        "Effective Radiative Forcing|Ozone",
        "Effective Radiative Forcing",
    ]

    res = run(
        climate_models_cfgs={"FaIR": [{}]},
        scenarios=test_scenarios.filter(scenario=["ssp245"]),
        output_variables=tuple(forcing_categories),
        out_config=None,
    )

    # storing results in a dict makes this a bit more compact
    forcing = {}
    for variable in forcing_categories:
        forcing[variable] = res.filter(variable=variable,
                                       region="World").values

    npt.assert_allclose(
        forcing["Effective Radiative Forcing|CO2"] +
        forcing["Effective Radiative Forcing|CH4"] +
        forcing["Effective Radiative Forcing|N2O"] +
        forcing["Effective Radiative Forcing|CF4"] +
        forcing["Effective Radiative Forcing|C2F6"] +
        forcing["Effective Radiative Forcing|C6F14"] +
        forcing["Effective Radiative Forcing|HFC23"] +
        forcing["Effective Radiative Forcing|HFC32"] +
        forcing["Effective Radiative Forcing|HFC125"] +
        forcing["Effective Radiative Forcing|HFC134a"] +
        forcing["Effective Radiative Forcing|HFC143a"] +
        forcing["Effective Radiative Forcing|HFC227ea"] +
        forcing["Effective Radiative Forcing|HFC245fa"] +
        forcing["Effective Radiative Forcing|HFC4310mee"] +
        forcing["Effective Radiative Forcing|SF6"] +
        forcing["Effective Radiative Forcing|CFC11"] +
        forcing["Effective Radiative Forcing|CFC12"] +
        forcing["Effective Radiative Forcing|CFC113"] +
        forcing["Effective Radiative Forcing|CFC114"] +
        forcing["Effective Radiative Forcing|CFC115"] +
        forcing["Effective Radiative Forcing|CCl4"] +
        forcing["Effective Radiative Forcing|CH3CCl3"] +
        forcing["Effective Radiative Forcing|HCFC22"] +
        forcing["Effective Radiative Forcing|HCFC141b"] +
        forcing["Effective Radiative Forcing|HCFC142b"] +
        forcing["Effective Radiative Forcing|Halon1211"] +
        forcing["Effective Radiative Forcing|Halon1202"] +
        forcing["Effective Radiative Forcing|Halon1301"] +
        forcing["Effective Radiative Forcing|Halon2402"] +
        forcing["Effective Radiative Forcing|CH3Br"] +
        forcing["Effective Radiative Forcing|CH3Cl"],
        forcing[
            "Effective Radiative Forcing|Greenhouse Gases"],  # should this be "well mixed" greenhouse gases?
    )

    npt.assert_allclose(
        forcing["Effective Radiative Forcing|CO2"] +
        forcing["Effective Radiative Forcing|CH4"] +
        forcing["Effective Radiative Forcing|N2O"] +
        forcing["Effective Radiative Forcing|CF4"] +
        forcing["Effective Radiative Forcing|C2F6"] +
        forcing["Effective Radiative Forcing|C6F14"] +
        forcing["Effective Radiative Forcing|HFC23"] +
        forcing["Effective Radiative Forcing|HFC32"] +
        forcing["Effective Radiative Forcing|HFC125"] +
        forcing["Effective Radiative Forcing|HFC134a"] +
        forcing["Effective Radiative Forcing|HFC143a"] +
        forcing["Effective Radiative Forcing|HFC227ea"] +
        forcing["Effective Radiative Forcing|HFC245fa"] +
        forcing["Effective Radiative Forcing|HFC4310mee"] +
        forcing["Effective Radiative Forcing|SF6"],
        forcing["Effective Radiative Forcing|Kyoto Gases"],
    )

    npt.assert_allclose(
        forcing["Effective Radiative Forcing|CO2"] +
        forcing["Effective Radiative Forcing|CH4"] +
        forcing["Effective Radiative Forcing|N2O"],
        forcing["Effective Radiative Forcing|CO2, CH4 and N2O"],
    )

    npt.assert_allclose(
        forcing["Effective Radiative Forcing|CF4"] +
        forcing["Effective Radiative Forcing|C2F6"] +
        forcing["Effective Radiative Forcing|C6F14"] +
        forcing["Effective Radiative Forcing|HFC23"] +
        forcing["Effective Radiative Forcing|HFC32"] +
        forcing["Effective Radiative Forcing|HFC125"] +
        forcing["Effective Radiative Forcing|HFC134a"] +
        forcing["Effective Radiative Forcing|HFC143a"] +
        forcing["Effective Radiative Forcing|HFC227ea"] +
        forcing["Effective Radiative Forcing|HFC245fa"] +
        forcing["Effective Radiative Forcing|HFC4310mee"] +
        forcing["Effective Radiative Forcing|SF6"],
        forcing["Effective Radiative Forcing|F-Gases"],
    )

    npt.assert_allclose(
        forcing["Effective Radiative Forcing|CFC11"] +
        forcing["Effective Radiative Forcing|CFC12"] +
        forcing["Effective Radiative Forcing|CFC113"] +
        forcing["Effective Radiative Forcing|CFC114"] +
        forcing["Effective Radiative Forcing|CFC115"] +
        forcing["Effective Radiative Forcing|CCl4"] +
        forcing["Effective Radiative Forcing|CH3CCl3"] +
        forcing["Effective Radiative Forcing|HCFC22"] +
        forcing["Effective Radiative Forcing|HCFC141b"] +
        forcing["Effective Radiative Forcing|HCFC142b"] +
        forcing["Effective Radiative Forcing|Halon1211"] +
        forcing["Effective Radiative Forcing|Halon1202"] +
        forcing["Effective Radiative Forcing|Halon1301"] +
        forcing["Effective Radiative Forcing|Halon2402"] +
        forcing["Effective Radiative Forcing|CH3Br"] +
        forcing["Effective Radiative Forcing|CH3Cl"],
        forcing["Effective Radiative Forcing|Montreal Protocol Halogen Gases"],
    )

    npt.assert_allclose(
        forcing["Effective Radiative Forcing|Tropospheric Ozone"] +
        forcing["Effective Radiative Forcing|Stratospheric Ozone"],
        forcing["Effective Radiative Forcing|Ozone"],
    )

    npt.assert_allclose(
        forcing["Effective Radiative Forcing|Aerosols|Direct Effect|SOx"] +
        forcing[
            "Effective Radiative Forcing|Aerosols|Direct Effect|Secondary Organic Aerosol"]
        +
        forcing["Effective Radiative Forcing|Aerosols|Direct Effect|Nitrate"] +
        forcing["Effective Radiative Forcing|Aerosols|Direct Effect|BC"] +
        forcing["Effective Radiative Forcing|Aerosols|Direct Effect|OC"],
        forcing["Effective Radiative Forcing|Aerosols|Direct Effect"],
    )

    # If up to here is fine, then we only need to check previouly defined aggregates against "super-aggregates"
    npt.assert_allclose(
        forcing["Effective Radiative Forcing|Aerosols|Direct Effect"] +
        forcing["Effective Radiative Forcing|Aerosols|Indirect Effect"],
        forcing["Effective Radiative Forcing|Aerosols"],
    )

    npt.assert_allclose(
        forcing["Effective Radiative Forcing|Greenhouse Gases"] +
        forcing["Effective Radiative Forcing|Ozone"] +
        forcing["Effective Radiative Forcing|CH4 Oxidation Stratospheric H2O"]
        + forcing["Effective Radiative Forcing|Contrails"] +
        forcing["Effective Radiative Forcing|Aerosols"] +
        forcing["Effective Radiative Forcing|Black Carbon on Snow"] +
        forcing["Effective Radiative Forcing|Land-use Change"],
        forcing["Effective Radiative Forcing|Anthropogenic"],
    )

    npt.assert_allclose(
        forcing["Effective Radiative Forcing|Anthropogenic"] +
        forcing["Effective Radiative Forcing|Volcanic"] +
        forcing["Effective Radiative Forcing|Solar"],
        forcing["Effective Radiative Forcing"],
    )
Ejemplo n.º 15
0
def test_startyear(test_scenarios, test_scenarios_2600):
    # we can't run different start years in the same ensemble as output files will differ in shape.
    # There is a separate test to ensure this does raise an error.
    res_1850 = run(
        climate_models_cfgs={"FaIR": [{
            "startyear": 1850
        }]},
        scenarios=test_scenarios.filter(scenario=["ssp245"]),
        output_variables=("Surface Air Temperature Change", ),
        out_config=None,
    )

    res_1750 = run(
        climate_models_cfgs={"FaIR": [{
            "startyear": 1750
        }]},
        scenarios=test_scenarios.filter(scenario=["ssp245"]),
        output_variables=("Surface Air Temperature Change", ),
        out_config=None,
    )

    res_default = run(
        climate_models_cfgs={"FaIR": [{}]},
        scenarios=test_scenarios.filter(scenario=["ssp245"]),
        output_variables=("Surface Air Temperature Change", ),
        out_config=None,
    )

    gsat2100_start1850 = res_1850.filter(
        variable="Surface Air Temperature Change",
        region="World",
        year=2100,
    ).values

    gsat2100_start1750 = res_1750.filter(
        variable="Surface Air Temperature Change",
        region="World",
        year=2100,
    ).values

    gsat2100_startdefault = res_default.filter(
        variable="Surface Air Temperature Change",
        region="World",
        year=2100,
    ).values

    assert gsat2100_start1850 != gsat2100_start1750
    assert gsat2100_start1750 == gsat2100_startdefault

    with pytest.raises(ValueError):
        run(
            climate_models_cfgs={"FaIR": [{
                "startyear": 1650
            }]},
            scenarios=test_scenarios.filter(scenario=["ssp245"]),
            output_variables=("Surface Air Temperature Change", ),
            out_config=None,
        )

    with pytest.raises(ValueError):
        run(
            climate_models_cfgs={"FaIR": [{}]},
            scenarios=test_scenarios_2600.filter(scenario=["ssp245"]),
            output_variables=("Surface Air Temperature Change", ),
            out_config=None,
        )

    with pytest.raises(ValueError):
        run(
            climate_models_cfgs={
                "FaIR": [{
                    "startyear": 1750
                }, {
                    "startyear": 1850
                }]
            },
            scenarios=test_scenarios.filter(scenario=["ssp245"]),
            output_variables=("Surface Air Temperature Change", ),
            out_config=None,
        )
Ejemplo n.º 16
0
    def test_run(
        self,
        test_scenarios,
        monkeypatch,
        nworkers,
        test_data_dir,
        update_expected_values,
    ):
        expected_output_file = os.path.join(
            test_data_dir,
            "expected-integration-output",
            "expected_fair1X_test_run_output.json",
        )

        monkeypatch.setenv("FAIR_WORKER_NUMBER", "{}".format(nworkers))
        res = run(
            climate_models_cfgs={
                "FaIR": [
                    {},
                    {
                        "q": np.array([0.3, 0.45]),
                        "r0": 30.0,
                        "lambda_global": 0.9
                    },
                    {
                        "q": np.array([0.35, 0.4]),
                        "r0": 25.0,
                        "lambda_global": 1.1
                    },
                ],
            },
            scenarios=test_scenarios.filter(
                scenario=["ssp126", "ssp245", "ssp370"]),
            output_variables=(
                "Surface Air Temperature Change",
                "Atmospheric Concentrations|CO2",
                "Heat Content",
                "Effective Radiative Forcing",
                "Effective Radiative Forcing|Aerosols",
                "Effective Radiative Forcing|CO2",
                "CO2 Air to Land Flux",  # should be ignored
            ),
            out_config=None,
        )

        assert isinstance(res, ScmRun)
        assert res["run_id"].min() == 0
        assert res["run_id"].max() == 8
        assert res.get_unique_meta("climate_model",
                                   no_duplicates=True) == "FaIRv{}".format(
                                       FAIR.get_version())

        assert set(res.get_unique_meta("variable")) == set([
            "Surface Air Temperature Change",
            "Atmospheric Concentrations|CO2",
            "Heat Content",
            "Effective Radiative Forcing",
            "Effective Radiative Forcing|Aerosols",
            "Effective Radiative Forcing|CO2",
        ])

        # 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

        self._check_output(res, expected_output_file, update_expected_values)
Ejemplo n.º 17
0
def test_multimodel_run(test_scenarios, magicc7_is_available):
    debug_run = False

    res = run(
        climate_models_cfgs={
            "FaIR": [
                {},
                {
                    "q": np.array([0.3, 0.45]),
                    "r0": 30.0,
                    "lambda_global": 0.9
                },
                {
                    "q": np.array([0.35, 0.4]),
                    "r0": 25.0,
                    "lambda_global": 1.1
                },
            ],
            "MAGICC7": [
                {
                    "core_climatesensitivity":
                    3,
                    "rf_soxi_dir_wm2":
                    -0.2,
                    "out_temperature":
                    1,
                    "out_forcing":
                    1,
                    "out_dynamic_vars": [
                        "DAT_CO2_CONC",
                        "DAT_AEROSOL_ERF",
                        "DAT_HEATCONTENT_AGGREG_TOTAL",
                        "DAT_HEATUPTK_AGGREG",
                    ],
                    "out_ascii_binary":
                    "BINARY",
                    "out_binary_format":
                    2,
                },
                {
                    "core_climatesensitivity":
                    2,
                    "rf_soxi_dir_wm2":
                    -0.1,
                    "out_temperature":
                    1,
                    "out_forcing":
                    1,
                    "out_dynamic_vars": [
                        "DAT_CO2_CONC",
                        "DAT_AEROSOL_ERF",
                        "DAT_HEATCONTENT_AGGREG_TOTAL",
                        "DAT_HEATUPTK_AGGREG",
                    ],
                    "out_ascii_binary":
                    "BINARY",
                    "out_binary_format":
                    2,
                },
                {
                    "core_climatesensitivity":
                    5,
                    "rf_soxi_dir_wm2":
                    -0.35,
                    "out_temperature":
                    1,
                    "out_forcing":
                    1,
                    "out_dynamic_vars": [
                        "DAT_CO2_CONC",
                        "DAT_AEROSOL_ERF",
                        "DAT_HEATCONTENT_AGGREG_TOTAL",
                        "DAT_HEATUPTK_AGGREG",
                    ],
                    "out_ascii_binary":
                    "BINARY",
                    "out_binary_format":
                    2,
                },
            ],
        },
        scenarios=test_scenarios.filter(
            scenario=["ssp126", "ssp245", "ssp370"]),
        output_variables=(
            "Surface Temperature",
            "Atmospheric Concentrations|CO2",
            "Heat Content|Ocean",
            "Heat Uptake|Ocean",
            "Effective Radiative Forcing",
            "Effective Radiative Forcing|Aerosols",
            "Effective Radiative Forcing|CO2",
        ),
        out_config=None,
    )

    assert isinstance(res, ScmRun)

    climate_models = res.get_unique_meta("climate_model")
    assert any(["MAGICC" in m for m in climate_models])
    assert any(["FaIR" in m for m in climate_models])

    for climate_model in climate_models:
        res_cm = res.filter(climate_model=climate_model)
        assert set(res_cm.get_unique_meta("variable")) == set([
            "Surface Temperature",
            "Effective Radiative Forcing",
            "Effective Radiative Forcing|Aerosols",
            "Effective Radiative Forcing|CO2",
            "Heat Content|Ocean",
            "Heat Uptake|Ocean",
            "Atmospheric Concentrations|CO2",
        ])

    quantiles = calculate_quantiles(res, [0.05, 0.17, 0.5, 0.83, 0.95])

    _check_res(
        1.3603486,
        quantiles.filter(
            variable="Surface Temperature",
            region="World",
            year=2100,
            scenario="ssp126",
            quantile=0.05,
        ).values,
        not debug_run,
        rtol=RTOL,
    )
    _check_res(
        2.61950384,
        quantiles.filter(
            variable="Surface Temperature",
            region="World",
            year=2100,
            scenario="ssp126",
            quantile=0.95,
        ).values,
        not debug_run,
        rtol=RTOL,
    )

    _check_res(
        2.99063777,
        quantiles.filter(
            variable="Surface Temperature",
            region="World",
            year=2100,
            scenario="ssp370",
            quantile=0.05,
        ).values,
        not debug_run,
        rtol=RTOL,
    )
    _check_res(
        5.34821243,
        quantiles.filter(
            variable="Surface Temperature",
            region="World",
            year=2100,
            scenario="ssp370",
            quantile=0.95,
        ).values,
        not debug_run,
        rtol=RTOL,
    )

    quantiles_cm = calculate_quantiles(
        res,
        [0.05, 0.17, 0.5, 0.83, 0.95],
        process_over_columns=("run_id", "ensemble_member"),
    )

    _check_res(
        1.27586919,
        quantiles_cm.filter(
            variable="Surface Temperature",
            region="World",
            year=2100,
            scenario="ssp126",
            quantile=0.05,
            climate_model="MAGICC*",
        ).values,
        not debug_run,
        rtol=RTOL,
    )
    _check_res(
        5.34663565,
        quantiles_cm.filter(
            variable="Surface Temperature",
            region="World",
            year=2100,
            scenario="ssp370",
            quantile=0.95,
            climate_model="MAGICC*",
        ).values,
        not debug_run,
        rtol=RTOL,
    )

    _check_res(
        1.80924238,
        quantiles_cm.filter(
            variable="Surface Temperature",
            region="World",
            year=2100,
            scenario="ssp126",
            quantile=0.05,
            climate_model="FaIR*",
        ).values,
        not debug_run,
        rtol=RTOL,
    )
    _check_res(
        4.76399179,
        quantiles_cm.filter(
            variable="Surface Temperature",
            region="World",
            year=2100,
            scenario="ssp370",
            quantile=0.95,
            climate_model="FaIR*",
        ).values,
        not debug_run,
        rtol=RTOL,
    )

    if debug_run:
        assert False, "Turn off debug"
Ejemplo n.º 18
0
    def test_run(
        self,
        test_scenarios,
        test_data_dir,
        update_expected_values,
    ):
        expected_output_file = os.path.join(
            test_data_dir,
            "expected-integration-output",
            "expected_magicc7_test_run_output.json",
        )

        res = run(
            climate_models_cfgs={
                "MAGICC7": [
                    {
                        "core_climatesensitivity":
                        3,
                        "rf_soxi_dir_wm2":
                        -0.2,
                        "out_temperature":
                        1,
                        "out_forcing":
                        1,
                        "out_dynamic_vars": [
                            "DAT_AEROSOL_ERF",
                            "DAT_HEATCONTENT_AGGREG_TOTAL",
                            "DAT_CO2_AIR2LAND_FLUX",
                        ],
                        "out_ascii_binary":
                        "BINARY",
                        "out_binary_format":
                        2,
                    },
                    {
                        "core_climatesensitivity": 2,
                        "rf_soxi_dir_wm2": -0.1,
                        "out_temperature": 1,
                        "out_forcing": 1,
                        "out_ascii_binary": "BINARY",
                        "out_binary_format": 2,
                    },
                    {
                        "core_climatesensitivity": 5,
                        "rf_soxi_dir_wm2": -0.35,
                        "out_temperature": 1,
                        "out_forcing": 1,
                        "out_ascii_binary": "BINARY",
                        "out_binary_format": 2,
                    },
                ],
            },
            scenarios=test_scenarios.filter(
                scenario=["ssp126", "ssp245", "ssp370"]),
            output_variables=(
                "Surface Air Temperature Change",
                "Effective Radiative Forcing",
                "Effective Radiative Forcing|Aerosols",
                "Effective Radiative Forcing|CO2",
                "Heat Content|Ocean",
                "Net Atmosphere to Land Flux|CO2",
            ),
        )

        assert isinstance(res, ScmRun)
        assert res["run_id"].min() == 0
        assert res["run_id"].max() == 8
        assert res.get_unique_meta("climate_model",
                                   no_duplicates=True) == "MAGICC{}".format(
                                       MAGICC7.get_version())
        assert set(res.get_unique_meta("variable")) == set([
            "Surface Air Temperature Change",
            "Effective Radiative Forcing",
            "Effective Radiative Forcing|Aerosols",
            "Effective Radiative Forcing|CO2",
            "Heat Content|Ocean",
            "Net Atmosphere to Land Flux|CO2",
        ])

        # 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

        self._check_output(res, expected_output_file, update_expected_values)
Ejemplo n.º 19
0
def test_multimodel_run(test_scenarios, test_data_dir, update_expected_values):
    expected_output_file = os.path.join(
        test_data_dir,
        "expected-integration-output",
        "expected_run_multimodel_output.json",
    )

    res = run(
        climate_models_cfgs={
            "FaIR": [
                {},
                {"q": np.array([0.3, 0.45]), "r0": 30.0, "lambda_global": 0.9},
                {"q": np.array([0.35, 0.4]), "r0": 25.0, "lambda_global": 1.1},
            ],
            "MAGICC7": [
                {
                    "core_climatesensitivity": 3,
                    "rf_soxi_dir_wm2": -0.2,
                    "out_temperature": 1,
                    "out_forcing": 1,
                    "out_dynamic_vars": [
                        "DAT_CO2_CONC",
                        "DAT_AEROSOL_ERF",
                        "DAT_HEATCONTENT_AGGREG_TOTAL",
                        "DAT_HEATUPTK_AGGREG",
                    ],
                    "out_ascii_binary": "BINARY",
                    "out_binary_format": 2,
                },
                {
                    "core_climatesensitivity": 2,
                    "rf_soxi_dir_wm2": -0.1,
                    "out_temperature": 1,
                    "out_forcing": 1,
                    "out_dynamic_vars": [
                        "DAT_CO2_CONC",
                        "DAT_AEROSOL_ERF",
                        "DAT_HEATCONTENT_AGGREG_TOTAL",
                        "DAT_HEATUPTK_AGGREG",
                    ],
                    "out_ascii_binary": "BINARY",
                    "out_binary_format": 2,
                },
                {
                    "core_climatesensitivity": 5,
                    "rf_soxi_dir_wm2": -0.35,
                    "out_temperature": 1,
                    "out_forcing": 1,
                    "out_dynamic_vars": [
                        "DAT_CO2_CONC",
                        "DAT_AEROSOL_ERF",
                        "DAT_HEATCONTENT_AGGREG_TOTAL",
                        "DAT_HEATUPTK_AGGREG",
                    ],
                    "out_ascii_binary": "BINARY",
                    "out_binary_format": 2,
                },
            ],
        },
        scenarios=test_scenarios.filter(scenario=["ssp126", "ssp245", "ssp370"]),
        output_variables=(
            "Surface Air Temperature Change",
            "Atmospheric Concentrations|CO2",
            "Heat Content|Ocean",
            "Heat Uptake|Ocean",
            "Effective Radiative Forcing",
            "Effective Radiative Forcing|Aerosols",
            "Effective Radiative Forcing|CO2",
        ),
        out_config=None,
    )

    assert isinstance(res, ScmRun)

    climate_models = res.get_unique_meta("climate_model")
    assert any(["MAGICC" in m for m in climate_models])
    assert any(["FaIR" in m for m in climate_models])

    for climate_model in climate_models:
        res_cm = res.filter(climate_model=climate_model)
        assert set(res_cm.get_unique_meta("variable")) == set(
            [
                "Surface Air Temperature Change",
                "Effective Radiative Forcing",
                "Effective Radiative Forcing|Aerosols",
                "Effective Radiative Forcing|CO2",
                "Heat Content|Ocean",
                "Heat Uptake|Ocean",
                "Atmospheric Concentrations|CO2",
            ]
        )

    # 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

    openscm_runner.testing._check_output(
        res, expected_output_file, rtol=RTOL, update=update_expected_values
    )
Ejemplo n.º 20
0
def test_fair_run(test_scenarios):
    res = run(
        climate_models_cfgs={
            "FaIR": [
                {},
                {
                    "q": np.array([0.3, 0.45]),
                    "r0": 30.0,
                    "lambda_global": 0.9
                },
                {
                    "q": np.array([0.35, 0.4]),
                    "r0": 25.0,
                    "lambda_global": 1.1
                },
            ],
        },
        scenarios=test_scenarios.filter(
            scenario=["ssp126", "ssp245", "ssp370"]),
        output_variables=(
            "Surface Temperature",
            "Atmospheric Concentrations|CO2",
            "Heat Content",
            "Effective Radiative Forcing",
            "Effective Radiative Forcing|Aerosols",
            "Effective Radiative Forcing|CO2",
            "CO2 Air to Land Flux",  # should be ignored
        ),
        out_config=None,
    )

    assert isinstance(res, ScmRun)
    assert res["run_id"].min() == 0
    assert res["run_id"].max() == 8
    assert res.get_unique_meta("climate_model",
                               no_duplicates=True) == "FaIRv{}".format(
                                   FAIR.get_version())

    assert set(res.get_unique_meta("variable")) == set([
        "Surface Temperature",
        "Atmospheric Concentrations|CO2",
        "Heat Content",
        "Effective Radiative Forcing",
        "Effective Radiative Forcing|Aerosols",
        "Effective Radiative Forcing|CO2",
    ])

    npt.assert_allclose(
        2.2099132544445927,
        res.filter(
            variable="Surface Temperature",
            region="World",
            year=2100,
            scenario="ssp126",
        ).values.max(),
        rtol=RTOL,
    )
    npt.assert_allclose(
        1.7945341435607594,
        res.filter(
            variable="Surface Temperature",
            region="World",
            year=2100,
            scenario="ssp126",
        ).values.min(),
        rtol=RTOL,
    )

    npt.assert_allclose(
        4.824878345585957,
        res.filter(
            variable="Surface Temperature",
            region="World",
            year=2100,
            scenario="ssp370",
        ).values.max(),
        rtol=RTOL,
    )
    npt.assert_allclose(
        4.07184261082167,
        res.filter(
            variable="Surface Temperature",
            region="World",
            year=2100,
            scenario="ssp370",
        ).values.min(),
        rtol=RTOL,
    )

    # check we can also calcluate quantiles
    quantiles = calculate_quantiles(res, [0.05, 0.17, 0.5, 0.83, 0.95])

    npt.assert_allclose(
        1.80924238,
        quantiles.filter(
            variable="Surface Temperature",
            region="World",
            year=2100,
            scenario="ssp126",
            quantile=0.05,
        ).values,
        rtol=RTOL,
    )
    npt.assert_allclose(
        2.18308358,
        quantiles.filter(
            variable="Surface Temperature",
            region="World",
            year=2100,
            scenario="ssp126",
            quantile=0.95,
        ).values,
        rtol=RTOL,
    )

    npt.assert_allclose(
        4.08625963,
        quantiles.filter(
            variable="Surface Temperature",
            region="World",
            year=2100,
            scenario="ssp370",
            quantile=0.05,
        ).values,
        rtol=RTOL,
    )
    npt.assert_allclose(
        4.76399179,
        quantiles.filter(
            variable="Surface Temperature",
            region="World",
            year=2100,
            scenario="ssp370",
            quantile=0.95,
        ).values,
        rtol=RTOL,
    )