Пример #1
0
def get_spec(context) -> Mapping[str, ScenarioInfo]:
    """Return the spec for the MESSAGE-GLOBIOM global model RES.

    Returns
    -------
    :class:`dict` of :class:`.ScenarioInfo` objects
    """
    context.use_defaults(SETTINGS)

    add = ScenarioInfo()

    # Add technologies
    add.set["technology"] = copy(get_codes("technology"))

    # Add regions

    # Load configuration for the specified region mapping
    nodes = get_codes(f"node/{context.regions}")

    # Top-level "World" node
    # FIXME typing ignored temporarily for PR#9
    world = nodes[nodes.index("World")]  # type: ignore [arg-type]

    # Set elements: World, followed by the direct children of World
    add.set["node"] = [world] + world.child

    # Initialize time periods
    add.year_from_codes(get_codes(f"year/{context.years}"))

    # Add levels
    add.set["level"] = get_codes("level")

    # Add commodities
    add.set["commodity"] = get_codes("commodity")

    # Add units, associated with commodities
    units = set(
        eval_anno(commodity, "unit") for commodity in add.set["commodity"])
    # Deduplicate by converting to a set and then back; not strictly necessary,
    # but reduces duplicate log entries
    add.set["unit"] = sorted(filter(None, units))

    if context.res_with_dummies:
        # Add dummy technologies
        add.set["technology"].extend(
            [Code(id="dummy"), Code(id="dummy source")])
        # Add a dummy commodity
        add.set["commodity"].append(Code(id="dummy"))

    # The RES is the base, so does not require/remove any elements
    return dict(add=add, remove=ScenarioInfo(), require=ScenarioInfo())
    def test_levels(self):
        data = get_codes("level")

        # Some expected commodities are present
        for check in "primary", "useful":
            assert check in data

        # Descriptions are parsed without new lines
        assert "\n" not in str(data[data.index("primary")].description)
    def test_year(self, codelist, length):
        """Year code lists can be loaded and contain the correct number of codes.

        :seealso: :meth:`.TestScenarioInfo.test_year_from_codes`.
        """
        # Year codelist can be loaded
        data = get_codes(f"year/{codelist}")

        # List contains the expected number of codes
        assert len(data) == length
    def test_hierarchy(self):
        """get_codes() returns objects with the expected hierarchical relationship."""
        codes = get_codes("node/R11")

        AUT = codes[codes.index("AUT")]
        R11_WEU = codes[codes.index("R11_WEU")]
        World = codes[codes.index("World")]

        assert R11_WEU is AUT.parent
        assert AUT in R11_WEU.child

        assert World is R11_WEU.parent
        assert R11_WEU in World.child
    def test_nodes(self, codelist, to_check, length, member):
        """Tests of node codelists."""
        # Node codelist can be loaded
        data = get_codes(f"node/{codelist}")

        # List contains a particular region
        assert to_check in data

        # Region contains the correct number of countries
        code = data[data.index(to_check)]
        assert len(code.child) == length

        # A specific country is present in the region
        assert member in code.child
    def test_commodities(self):
        data = get_codes("commodity")

        # Some expected commodities are present
        for check in "coal", "electr":
            assert check in data

        # Units for one commodity can be retrieved and parsed
        coal = data[data.index("coal")]
        registry(str(coal.get_annotation(id="unit").text))

        # Descriptions are parsed without new lines
        crudeoil = data[data.index("crudeoil")]
        assert "\n" not in str(crudeoil.description)
Пример #7
0
def input():
    """Fixture: test data for :func:`.adapt_R11_R14`."""
    R11_all = get_codes("node/R11")
    R11_reg = R11_all[R11_all.index("World")].child
    df = make_df(PAR,
                 technology="coal_ppl",
                 year_vtg=[2021, 2022],
                 value=[1.2, 3.4],
                 unit="year").pipe(broadcast, node_loc=R11_reg)

    # Set a specific value for the regions to be broadcast
    df["value"] = df["value"].where(df["node_loc"] != "R11_FSU", VALUE)

    return {PAR: df}
    def test_technologies(self):
        # Retrieve the tech info without calling technologies.cli
        data = get_codes("technology")

        # Check the length of the returned dataframe
        assert len(data) == 377

        # Get info on a certain technology
        h2_fc_trp = data[data.index("h2_fc_trp")]
        assert ["transport", "useful"
                ] == eval(str(h2_fc_trp.get_annotation(id="output").text))

        # Check that the default value for 'vintaged' is False when omitted from the
        # YAML file
        elec_exp = data[data.index("elec_exp")]
        assert False is eval(str(elec_exp.get_annotation(id="vintaged").text))
Пример #9
0
def identify_nodes(scenario: Scenario) -> str:
    """Return the ID of a node codelist given the contents of `scenario`.

    Returns
    -------
    str
        The ID of the :doc:`/pkg-data/node` containing the regions of `scenario`.

    Raises
    ------
    ValueError
        if no codelist can be identified, or the nodes in the scenario do not match the
        children of the “World” node in the codelist.
    """
    from message_ix_models.model.structure import get_codes

    nodes = sorted(scenario.set("node"))

    # Candidate ID: split e.g. "R14_AFR" to "R14"
    id = nodes[0].split("_")[0]

    try:
        # Get the corresponding codelist
        codes = get_codes(f"node/{id}")
    except FileNotFoundError:
        raise ValueError(f"Couldn't identify node codelist from {repr(nodes)}")

    glb_node = [n.endswith("_GLB") for n in nodes]
    if any(glb_node):
        omit = nodes.pop(glb_node.index(True))
        log.info(f"Omit known, non-standard node '{omit}' from set to match")

    # Expected list of nodes
    world = codes[codes.index("World")]  # type: ignore [arg-type]
    codes = [world] + world.child

    try:
        assert set(nodes) == set(map(str, codes))
    except AssertionError:
        raise ValueError("\n".join([
            f"Node IDs suggest codelist {repr(id)}, values do not match:",
            repr(nodes),
            repr(codes),
        ]))
    else:
        log.info(f"Identified node codelist {repr(id)}")
        return id
Пример #10
0
def test_adapt_R11_R14_0(input):
    """:func:`.adapt_R11_R14` handles :class:`pandas.DataFrame`."""
    # Function runs
    output = adapt_R11_R14(input)

    # Output is a dict containing 1 entry
    df_out = output.pop(PAR)
    assert 0 == len(output)

    # Output covers all R14 regions
    R14_all = get_codes("node/R14")
    R14_reg = R14_all[R14_all.index("World")].child
    assert set(R14_reg) == set(df_out["node_loc"])

    # Output has expected length
    assert 14 * 2 == len(df_out)

    # Output values for new regions match input value for R11_FSU
    target_nodes = ("R14_CAS", "R14_RUS", "R14_SCS", "R14_UBM")
    assert (
        VALUE == df_out[df_out["node_loc"].isin(target_nodes)]["value"]).all()
Пример #11
0
    def test_year_from_codes(self, caplog, codelist, y0, N_all, N_Y, y_m1,
                             dp_checks):
        caplog.set_level(logging.DEBUG, logger="message_ix_models")

        info = ScenarioInfo()
        codes = get_codes(f"year/{codelist}")
        info.year_from_codes(codes)

        # First model period
        assert y0 == info.y0
        assert ("firstmodelyear", y0) in info.set["cat_year"]

        # Total number of periods
        assert N_all == len(info.set["year"])

        # Number of model periods
        assert N_Y == len(info.Y)

        # Final period
        assert y_m1 == info.Y[-1]

        # Convert the data frame to a series
        dp = info.par["duration_period"].set_index("year")["value"]

        # duration_period entries are as expected
        for key, expected in dp_checks:
            assert expected == dp[key]

        # Test logging
        assert 0 == len(caplog.messages)

        info.year_from_codes(codes)

        assert 3 == len(caplog.messages)
        assert all(
            msg.startswith("Discard existing") for msg in caplog.messages)
 def test_node_historic_country(self):
     """get_codes() handles ISO 3166 alpha-3 codes for historic countries."""
     assert "SCG" in get_codes("node/R11")
 def test_get_codes(self, name):
     """The included code lists can be loaded."""
     get_codes(name)