Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Next Release

- [#952](https://github.com/IAMconsortium/pyam/pull/952) Add an `aggregate_kyoto_gases()` method
- [#946](https://github.com/IAMconsortium/pyam/pull/946) Handle plot-styling by meta indicators with `np.nan`
- [#944](https://github.com/IAMconsortium/pyam/pull/944) Refactor to a `format_n()` function for nice log messages
- [#943](https://github.com/IAMconsortium/pyam/pull/943) Improved handling for division by zero
Expand Down
21 changes: 21 additions & 0 deletions pyam/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import pandas as pd
from pandas.api.types import is_integer

from pyam.emissions import SPECIES_UNIT_MAPPING, aggregate_kyoto_gases
from pyam.netcdf import to_xarray

try:
Expand Down Expand Up @@ -1864,6 +1865,26 @@ def check_internal_consistency(self, components=False, **kwargs):
]
]

def aggregate_kyoto_gases(self, *, metric: str, append: bool = False):
"""Compute the aggregate Kyoto gases from a set of species using a GWP metric

metric: str
A global warming potential (GWP) metric supported by :mod:`iam_units`,
e.g. 'AR6GWP100'.
append : bool, optional
Append the aggregate emissions timeseries to `self` and return None,
else return aggregated emissions timeseries as new :class:`IamDataFrame`.

See Also
--------
pyam.IamDataFrame.convert_unit

"""
data = concat(aggregate_kyoto_gases(self, metric)).aggregate(
f"Emissions|Kyoto Gases [{metric}]", components=SPECIES_UNIT_MAPPING.keys()
)
return self._finalize(data, append=append)

def slice(self, *, keep=True, **kwargs):
"""Return a (filtered) slice object of the IamDataFrame timeseries data index

Expand Down
40 changes: 40 additions & 0 deletions pyam/emissions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
from pyam.exceptions import raise_data_error

REQUIRED_SPECIES = ["Emissions|CO2", "Emissions|CH4", "Emissions|N2O"]

SPECIES_UNIT_MAPPING = {
"Emissions|CO2": "Mt CO2/yr",
"Emissions|CH4": "Mt CH4/yr",
"Emissions|N2O": "kt N2O/yr",
"Emissions|SF6": "kt SF6/yr",
"Emissions|C2F6": "kt C2F6/yr",
"Emissions|C6F14": "kt C6F14/yr",
"Emissions|CF4": "kt CF4/yr",
"Emissions|HFC|HFC125": "kt HFC125/yr",
"Emissions|HFC|HFC134a": "kt HFC134a/yr",
"Emissions|HFC|HFC143a": "kt HFC143a/yr",
"Emissions|HFC|HFC227ea": "kt HFC227ea/yr",
"Emissions|HFC|HFC23": "kt HFC23/yr",
"Emissions|HFC|HFC32": "kt HFC32/yr",
# inconsistent notation between iam-units and common-definitions
# "Emissions|HFC|HFC43-10": "kt HFC43-10/yr",
}


def aggregate_kyoto_gases(df, metric: str):
"""Internal implementation of the `aggregate_kyoto_gases` function"""

missing = df.require_data(variable=REQUIRED_SPECIES)
if missing is not None:
raise_data_error("Missing species for aggregation", missing)

df_list = list()
for species, unit in SPECIES_UNIT_MAPPING.items():
if species in df.variable:
df_list.append(
df.filter(variable=species).convert_unit(
unit, "Mt CO2-equiv/yr", context=metric
)
)

return df_list
60 changes: 60 additions & 0 deletions tests/test_emissions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import pandas as pd
import pytest

from pyam import IamDataFrame
from pyam.testing import assert_iamframe_equal

EMISSIONS_SPECIES_DATA = pd.DataFrame(
[
["Emissions|CO2", "Mt CO2/yr", 42885.41, 33011.87, 24642.81],
["Emissions|CH4", "Mt CH4/yr", 413.63, 287.42, 233.97],
["Emissions|N2O", "kt N2O/yr", 11623.95, 9005.23, 8177.40],
["Emissions|SF6", "kt SF6/yr", 8.01, 5.26, 2.60],
["Emissions|HFC|HFC125", "kt HFC125/yr", 98.76, 57.44, 16.71],
["Emissions|HFC|HFC134a", "kt HFC134a/yr", 248.84, 144.53, 42.41],
["Emissions|HFC|HFC143a", "kt HFC143a/yr", 40.59, 23.61, 6.87],
["Emissions|HFC|HFC23", "kt HFC23/yr", 7.13, 4.24, 1.55],
["Emissions|HFC|HFC32", "kt HFC32/yr", 61.18, 35.55, 10.29],
],
columns=["variable", "unit", 2020, 2025, 2030],
)


EXP_GHG_DATA = pd.DataFrame(
[
[
"Emissions|Kyoto Gases [AR6GWP100]",
"Mt CO2-equiv/yr",
58938.34,
44284.49,
33666.64,
]
],
columns=["variable", "unit", 2020, 2025, 2030],
)


@pytest.mark.parametrize("append", ((False, True)))
def test_kyoto_ghg(append):
df_args = dict(model="model_a", scenario="scenario_a", region="World")
df = IamDataFrame(EMISSIONS_SPECIES_DATA, **df_args)
exp = IamDataFrame(EXP_GHG_DATA, **df_args)

if append:
obs = df.copy()
obs.aggregate_kyoto_gases(metric="AR6GWP100", append=append)
exp = df.append(exp)
else:
obs = df.aggregate_kyoto_gases(metric="AR6GWP100")

assert_iamframe_equal(exp, obs)


def test_kyoto_ghg_raises():
df_args = dict(model="model_a", scenario="scenario_a", region="World")
df = IamDataFrame(EMISSIONS_SPECIES_DATA, **df_args)
df.filter(variable="Emissions|CH4", keep=False, inplace=True)

match = "Missing species for aggregation:.* scenario_a Emissions|CH4"
with pytest.raises(ValueError, match=match):
df.aggregate_kyoto_gases(metric="AR6GWP100")
Loading