Skip to content

Commit e79e1f3

Browse files
Add a function to initialize an IamDataFrame form an ixmp4 Run
1 parent db581d9 commit e79e1f3

File tree

3 files changed

+60
-2
lines changed

3 files changed

+60
-2
lines changed

pyam/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
read_datapackage,
1414
)
1515
from pyam.iiasa import lazy_read_iiasa, read_iiasa
16-
from pyam.ixmp4 import read_ixmp4
16+
from pyam.ixmp4 import read_ixmp4, read_ixmp4_run
1717
from pyam.netcdf import read_netcdf
1818
from pyam.run_control import run_control
1919
from pyam.statistics import Statistics

pyam/ixmp4.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,48 @@ def read_ixmp4(
7070
return IamDataFrame(data, meta=meta, index=index)
7171

7272

73+
def read_ixmp4_run(
74+
run: ixmp4.Run,
75+
region: str | list[str] | None = None,
76+
variable: str | list[str] | None = None,
77+
unit: str | list[str] | None = None,
78+
year: int | list[int] | None = None,
79+
):
80+
"""Return timeseries data and meta indicatos from an ixmp4 run as IamDataFrame
81+
82+
Parameters
83+
----------
84+
run : :class:`ixmp4.Run`
85+
An ixmp4 run instance from which to read timeseries data and meta indicators
86+
region, variable, unit : str or list of str, optional
87+
Filter timeseries data by these dimensions.
88+
year : int or list of int, optional
89+
Filter timeseries data by time domain.
90+
"""
91+
from pyam import IamDataFrame
92+
93+
if year is not None:
94+
raise NotImplementedError("Filter by 'year' not implemented in ixmp4.")
95+
96+
meta = pd.DataFrame.from_dict(run.meta, orient="index").T
97+
meta.index = pd.MultiIndex.from_tuples(
98+
[(run.model.name, run.scenario.name)],
99+
name=["model", "scenario"]
100+
)
101+
meta["version"] = run.version
102+
103+
return IamDataFrame(
104+
data=run.iamc.tabulate(
105+
region=region,
106+
variable=variable,
107+
unit=unit,
108+
),
109+
meta=meta,
110+
model=run.model.name,
111+
scenario=run.scenario.name,
112+
)
113+
114+
73115
def write_to_ixmp4(platform: ixmp4.Platform | str, df, checkpoint_message: str):
74116
"""Save all scenarios as new default runs in an ixmp4 platform database instance
75117

tests/test_ixmp4.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from ixmp4.core.unit import UnitModel
44

55
import pyam
6-
from pyam import read_ixmp4
6+
from pyam import read_ixmp4, read_ixmp4_run
77
from pyam.testing import assert_iamframe_equal
88

99

@@ -109,3 +109,19 @@ def test_ixmp4_reserved_columns(test_platform, test_df_year, drop_meta):
109109

110110
# version is included when reading again from the platform
111111
assert_iamframe_equal(test_df_year, pyam.read_ixmp4(test_platform))
112+
113+
114+
def test_ixmp4_read_run(test_platform, test_df):
115+
"""Initialize an IamDataFrame from an ixmp4 run"""
116+
117+
# write to platform
118+
test_df.to_ixmp4(platform=test_platform)
119+
120+
# get a run and cast to an IamDataFrame
121+
run = test_platform.runs.get("model_a", "scen_a")
122+
obs = read_ixmp4_run(run)
123+
124+
# assert that the returned object and the original IamDataFrame are equal
125+
exp = test_df.filter(scenario="scen_a")
126+
exp.set_meta(1, "version") # the IamDataFrame read from ixmp4 includes the version
127+
pyam.assert_iamframe_equal(exp, obs)

0 commit comments

Comments
 (0)