Skip to content

Commit 749e14e

Browse files
committed
Add .tests.report.legacy.test_pp_utils
Copied from iiasa/message_data branch `dev`.
1 parent 40476d8 commit 749e14e

File tree

1 file changed

+109
-0
lines changed

1 file changed

+109
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
from itertools import product
2+
3+
import pandas as pd
4+
import pytest
5+
from message_ix_models.model.structure import get_codes
6+
from message_ix_models.util import nodes_ex_world
7+
8+
from message_data.tools.post_processing import pp_utils
9+
from message_data.tools.post_processing.pp_utils import fil
10+
11+
#: These format strings appear in .default_tables.retr_hfc() in calls to :func:`.fil`.
12+
FACTOR_EXPR = "refAC foam Fire ANMDI mVac Solv".split()
13+
14+
#: These values appear in default_run_config.yaml. The commented lines are those for
15+
#: which :func:`.fil` is *not* called.
16+
FACTOR_VAL_UNIT = (
17+
# (0, "kt HFC134a-equiv/yr"), # Total # Not called because hfc: "Total"
18+
(125, "kt HFC125/yr"), # HFC125
19+
(134, "kt HFC134a/yr"), # HFC134a
20+
(143, "kt HFC143a/yr"), # HFC143a
21+
(227, "kt HFC227ea/yr"), # HFC227ea
22+
# (0, "kt HFC23/yr"), # HFC23 # Not called because run: "empty"
23+
(245, "kt HFC245fa/yr"), # HFC245fa
24+
(32, "kt HFC32/yr"), # HFC32
25+
(431, "kt HFC43-10/yr"), # HFC430
26+
(365, "kt HFC365mfc/yr"), # HFC365mfc # Not called because run: False
27+
(152, "kt HFC152a/yr"), # HFC152a
28+
(236, "kt HFC236fa/yr"), # HFC236fa # Not called because run: False
29+
)
30+
31+
32+
#: Input data expected by :func:`.fil`.
33+
#:
34+
#: - Axis named "Region" with short labels, e.g. "ABC" rather than "R##_ABC"
35+
#: - Some columns with period labels, as integers.
36+
#: - Float or NaN values.
37+
FIL_DF = pd.DataFrame(
38+
[[1.0, None, 1.0]], columns=[2000, 2050, 2100], index=["AFR"]
39+
).rename_axis("Region")
40+
41+
42+
def pp_utils_globals(monkeypatch, regions):
43+
"""Set :mod:`.pp_utils` global module variables.
44+
45+
This utility function uses pytest's `monkeypatch` fixture to set the variables; the
46+
pre-existing values are restored after the end of each test.
47+
48+
This only sets the globals that are used by :func:`.fil()`.
49+
"""
50+
# region_id: the ID of the node code list; i.e. Context.regions
51+
monkeypatch.setattr(pp_utils, "region_id", regions)
52+
53+
# regions: a mapping from model's native "R##_ABC" to "ABC", *plus* e.g. "R##_GLB"
54+
# mapped to # "World". This normally set by .iamc_report_hackathon.report().
55+
nodes = get_codes(f"node/{regions}")
56+
nodes = nodes[nodes.index("World")].child
57+
regions_map = {n.id: n.id.split("_")[1] for n in nodes_ex_world(nodes)}
58+
regions_map[f"{regions}_GLB"] = "World"
59+
monkeypatch.setattr(pp_utils, "regions", regions_map)
60+
61+
# unit_conversion: a mapping of mappings. fil() directly sets "???" on its data and
62+
# then looks up mappings from "???" to `units_out`
63+
monkeypatch.setattr(
64+
pp_utils,
65+
"unit_conversion",
66+
{"???": {units: 1.0 for _, units in FACTOR_VAL_UNIT}},
67+
)
68+
69+
# Expected index of data frame returned by fil()
70+
return set(regions_map.values())
71+
72+
73+
@pytest.mark.parametrize("regions", ["R11", "R12"])
74+
@pytest.mark.parametrize(
75+
"fil_arg, min_filled_values",
76+
[
77+
("HFC_fac", 1), # The only supported value
78+
("foo", 0), # Other values are essentially a no-op
79+
],
80+
)
81+
def test_fil(monkeypatch, regions, fil_arg, min_filled_values):
82+
"""Test :func:`.pp_utils.fil`.
83+
84+
The test is parametrized for `regions` and each argument to :func:`.fil`.
85+
86+
`min_filled_values` checks that at least N values in the resulting data frame are
87+
populated from the file(s).
88+
"""
89+
# Monkey-patch the global variables in the pp_utils module used by fil() and
90+
# retrieve the expected index of the result
91+
expected_regions = pp_utils_globals(monkeypatch, regions)
92+
93+
# Iterate over all values for the `factor` and `units` arguments that fil() is
94+
# expected to support
95+
for factor_expr, (factor_val, units) in product(FACTOR_EXPR, FACTOR_VAL_UNIT):
96+
# Mirror how values for the `factor` argument are constructed in
97+
# .default_tables.retr_hfc(), e.g. "Fire134"
98+
factor = f"{factor_expr}{factor_val}"
99+
100+
# Function executes without error
101+
result = fil(FIL_DF, fil_arg, factor, units)
102+
103+
# Returned data are a pd.DataFrame with the expected index
104+
assert expected_regions == set(result.index)
105+
106+
# Number of NaN values in results is as expected
107+
assert min_filled_values <= (
108+
result.notnull().sum().sum() - FIL_DF.notnull().sum().sum()
109+
)

0 commit comments

Comments
 (0)