-
Notifications
You must be signed in to change notification settings - Fork 123
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
835065c
commit 0762055
Showing
6 changed files
with
94 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import ixmp4 | ||
from ixmp4.core.region import RegionModel | ||
from ixmp4.core.unit import UnitModel | ||
|
||
|
||
def write_to_ixmp4(platform: ixmp4.Platform | str, df): | ||
"""Save all scenarios as new default runs in an ixmp4 platform database instance | ||
Parameters | ||
---------- | ||
platform : :class:`ixmp4.Platform` or str | ||
The ixmp4 platform database instance to which the scenario data is saved | ||
df : pyam.IamDataFrame | ||
The IamDataFrame instance with scenario data | ||
""" | ||
if df.time_domain != "year": | ||
raise NotImplementedError("Only time_domain='year' is supported for now") | ||
|
||
if not isinstance(platform, ixmp4.Platform): | ||
platform = ixmp4.Platform(platform) | ||
|
||
# TODO: implement a try-except to roll back changes if any error writing to platform | ||
# depends on https://github.com/iiasa/ixmp4/issues/29 | ||
# quickfix: ensure that units and regions exist before writing | ||
for dimension, values, model in [ | ||
("regions", df.region, RegionModel), | ||
("units", df.unit, UnitModel), | ||
]: | ||
platform_values = getattr(platform, dimension).tabulate().name.values | ||
if missing := set(values).difference(platform_values): | ||
raise model.NotFound( | ||
", ".join(missing) | ||
+ f". Use `Platform.{dimension}.create()` to add the missing {dimension}." | ||
) | ||
|
||
for model, scenario in df.index: | ||
_df = df.filter(model=model, scenario=scenario) | ||
|
||
run = platform.runs.create(model=model, scenario=scenario) | ||
run.iamc.add(_df.data) | ||
run.meta = dict(_df.meta.iloc[0]) | ||
run.set_as_default() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import pytest | ||
from ixmp4.core import Platform | ||
from ixmp4.data.backend import SqliteTestBackend | ||
from ixmp4.core.region import RegionModel | ||
from ixmp4.core.unit import UnitModel | ||
|
||
|
||
def test_to_ixmp4_missing_region_raises(test_df_year): | ||
"""Writing to platform raises if region not defined""" | ||
platform = Platform(_backend=SqliteTestBackend()) | ||
with pytest.raises(RegionModel.NotFound, match="World. Use `Platform.regions."): | ||
test_df_year.to_ixmp4(platform=platform) | ||
|
||
|
||
def test_to_ixmp4_missing_unit_raises(test_df_year): | ||
"""Writing to platform raises if unit not defined""" | ||
platform = Platform(_backend=SqliteTestBackend()) | ||
platform.regions.create(name="World", hierarchy="common") | ||
with pytest.raises(UnitModel.NotFound, match="EJ/yr. Use `Platform.units."): | ||
test_df_year.to_ixmp4(platform=platform) | ||
|
||
|
||
def test_ixmp4_integration(test_df): | ||
"""Write an IamDataFrame to the platform""" | ||
platform = Platform(_backend=SqliteTestBackend()) | ||
platform.regions.create(name="World", hierarchy="common") | ||
platform.units.create(name="EJ/yr") | ||
|
||
if test_df.time_domain == "year": | ||
test_df.to_ixmp4(platform=platform) | ||
else: | ||
with pytest.raises(NotImplementedError): | ||
test_df.to_ixmp4(platform=platform) | ||
|
||
# TODO add test for reading data from ixmp4 platform |