-
Notifications
You must be signed in to change notification settings - Fork 127
Description
This feature would add methods to the IamDataFrame to compute Kaya identity factors according to the methodology described in Koomey et al 2019 and 2022.
KoomeyExploringBlackBox2022FINAL.pdf
SupplementalinformationKoomeyExploringBlackBox-FINAL.docx
InsidetheblackboxFINAL2019.pdf
AppendicesInsidetheBlackBox-v61.docx
Our idea is to add three methods to the public api of the compute module which return Kaya variables, Kaya factors, and an LMDI decomposition. Please let me know if the compute module is not the right place for this feature!
Kaya Variables
These are produced by simple transformations of the input data variables, mostly doing arithmetic with the emissions and CCS input variables to get the quantities we're interested in.
Kaya Factors
These are the terms of the Expanded Kaya identity, calculated from the Kaya variables.
LMDI Decomposition
The Log-Mean Divisia Index method attributes the a portion of the total change in emissions from the reference scenario to the intervention scenario to each Kaya Factor.
Below are example tests for the method to compute Kaya variables. I hope this is enough to get the discussion started. As I progress with the development I'll update this thread with questions that come up.
import pandas as pd
import input_variable_names
import kaya_variable_names
import pytest
from pyam import IamDataFrame
from pyam.testing import assert_iamframe_equal
from pyam.utils import IAMC_IDX
TEST_DF = IamDataFrame(
pd.DataFrame(
[
[input_variable_names.POPULATION, "million", 1000],
[input_variable_names.GDP_PPP, "billion USD_2005/yr", 6],
[input_variable_names.GDP_MER, "billion USD_2005/yr", 5],
[input_variable_names.FINAL_ENERGY, "EJ/yr", 8],
[input_variable_names.PRIMARY_ENERGY, "EJ/yr", 10],
[input_variable_names.PRIMARY_ENERGY_COAL, "EJ/yr", 5],
[input_variable_names.PRIMARY_ENERGY_GAS, "EJ/yr", 2],
[input_variable_names.PRIMARY_ENERGY_OIL, "EJ/yr", 2],
[input_variable_names.EMISSIONS_CO2_FOSSIL_FUELS_AND_INDUSTRY, "Mt CO2/yr", 10],
[input_variable_names.EMISSIONS_CO2_INDUSTRIAL_PROCESSES, "Mt CO2/yr", 1],
[input_variable_names.EMISSIONS_CO2_CARBON_CAPTURE_AND_STORAGE, "Mt CO2/yr", 4],
[input_variable_names.EMISSIONS_CO2_CARBON_CAPTURE_AND_STORAGE_BIOMASS, "Mt CO2/yr", 1],
[input_variable_names.CCS_FOSSIL_ENERGY, "Mt CO2/yr", 2],
[input_variable_names.CCS_FOSSIL_INDUSTRY, "Mt CO2/yr", 1],
[input_variable_names.CCS_BIOMASS_ENERGY, "Mt CO2/yr", 0.5],
[input_variable_names.CCS_BIOMASS_INDUSTRY, "Mt CO2/yr", 0.5],
],
columns=["variable", "unit", 2010],
),
model="model_a",
scenario="scen_a",
region="World",
)
EXP_DF = IamDataFrame(
pd.DataFrame(
[
[kaya_variable_names.POPULATION, "billion", 1.0],
[kaya_variable_names.GNP, "billion USD_2010/yr", 6.6],
[kaya_variable_names.FINAL_ENERGY, "EJ/yr", 8.0],
[kaya_variable_names.PRIMARY_ENERGY, "EJ/yr", 10.0],
[kaya_variable_names.PRIMARY_ENERGY_FF, "EJ/yr", 9.0],
[kaya_variable_names.TFC, "Mt CO2/yr", 12.0],
[kaya_variable_names.NFC, "Mt CO2/yr", 10.0],
],
columns=["variable", "unit", 2010],
),
model="model_a",
scenario="scen_a",
region="World",
)
@pytest.mark.parametrize("append", (False, True))
def test_kaya_variables(append):
"""Test computing kaya variables"""
if append:
obs = TEST_DF.copy()
obs.compute.kaya_variables(scenarios=['scen_a'], append=True)
assert_iamframe_equal(TEST_DF.append(EXP_DF), obs)
else:
obs = TEST_DF.compute.kaya_variables(scenarios=['scenario_a'])
assert_iamframe_equal(EXP_DF, obs)
@pytest.mark.parametrize("append", (False, True))
def test_kaya_variables_empty_when_input_variables_missing(append):
"""Assert that computing kaya variables with missing input variables returns empty"""
if append:
obs = TEST_DF.copy()
(obs.filter(variable=input_variable_names.POPULATION) # select subset of required input variables
.compute.kaya_variables(scenarios=['scen_a'], append=True)
)
assert_iamframe_equal(TEST_DF, obs) # assert that no data was added
else:
obs = TEST_DF.compute.kaya_variables(scenarios=['scen_a'])
assert obs.empty