Skip to content

Commit

Permalink
Implement using Config
Browse files Browse the repository at this point in the history
  • Loading branch information
measrainsey committed Nov 3, 2023
1 parent 99f32c2 commit b97bf23
Show file tree
Hide file tree
Showing 7 changed files with 292 additions and 222 deletions.
2 changes: 2 additions & 0 deletions message_ix_models/tools/costs/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
class Config:
"""Configuration for :mod:`.costs`."""

test_val: int = 2

#: Base year for projections.
base_year: int = BASE_YEAR

Expand Down
99 changes: 72 additions & 27 deletions message_ix_models/tools/costs/demo.py
Original file line number Diff line number Diff line change
@@ -1,43 +1,88 @@
from message_ix_models.tools.costs.config import Config
from message_ix_models.tools.costs.projections import create_cost_projections

# By default, the create_cost_projections() function will run for R12
# Example 1: By default, the Config fill will run for:
# R12
# for the base suite of technologies,
# with NAM as reference region,
# using GDP as the cost driver,
# and the updated data version.
# and the updated data version
# and outputs in MESSAGE format.
# The function will also run for all SSP scenarios,
# for all years from 2021 to 2100.
inv, fix = create_cost_projections()
default = Config()
out_default = create_cost_projections(
node=default.node,
ref_region=default.ref_region,
base_year=default.base_year,
module=default.module,
method=default.method,
scenario_version=default.scenario_version,
scenario=default.scenario,
convergence_year=default.convergence_year,
fom_rate=default.fom_rate,
format=default.format,
)

# Example 1: Get cost projections for SSP2 scenario in R12,
# Example 2: Get cost projections for SSP2 scenario in R12,
# using WEU as the reference region,
# with convergence as the method,
# for materials technologies,
# using GDP (updated data)
inv2, fix2 = create_cost_projections(
sel_node="r12",
sel_ref_region="R12_NAM",
sel_base_year=2021,
sel_module="materials",
sel_scenario_version="updated",
sel_scenario="ssp2",
sel_method="gdp",
# You can either put the inputs directly into the create_cost_projections function,
# or you can create a Config object and pass that in.
default = Config()

# Option 1: Directly input the parameters
out_materials_ssp2 = create_cost_projections(
node=default.node,
ref_region="R12_WEU",
base_year=default.base_year,
module="materials",
method="convergence",
scenario_version=default.scenario_version,
scenario="SSP2",
convergence_year=default.convergence_year,
fom_rate=default.fom_rate,
format=default.format,
)

# Example 2: Get cost projections in R11 (with WEU as reference region), using learning
# (this will run for all SSP scenarios)
inv, fix = create_cost_projections(
sel_node="r11",
sel_ref_region="R11_WEU",
sel_base_year=2021,
sel_method="learning",
sel_scenario_version="updated",
# Option 2: Create a Config object and pass that in
config = Config(
module="materials", scenario="SSP2", ref_region="R12_WEU", method="convergence"
)

# Example 3: Get cost projections in R12, using convergence
inv, fix = create_cost_projections(
sel_node="r12",
sel_base_year=2021,
sel_method="convergence",
out_materials_ssp2 = create_cost_projections(
node=config.node,
ref_region=config.ref_region,
base_year=config.base_year,
module=config.module,
method=config.method,
scenario_version=config.scenario_version,
scenario=config.scenario,
convergence_year=config.convergence_year,
fom_rate=config.fom_rate,
format=config.format,
)

# Example 4: Get cost projections in R11 using previous/original SSP scenarios
inv, fix = create_cost_projections(sel_node="r11", sel_scenario_version="original")
# Example 3: Get cost projections for SSP5 scenario in R12,
# using LAM as the reference region,
# with learning as the method,
# for materials technologies,

config = Config(
module="materials", scenario="SSP5", ref_region="R12_LAM", method="learning"
)

out_materials_ssp5 = create_cost_projections(
node=config.node,
ref_region=config.ref_region,
base_year=config.base_year,
module=config.module,
method=config.method,
scenario_version=config.scenario_version,
scenario=config.scenario,
convergence_year=config.convergence_year,
fom_rate=config.fom_rate,
format=config.format,
)
40 changes: 20 additions & 20 deletions message_ix_models/tools/costs/gdp.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@


# Function to read in (under-review) SSP data
def process_raw_ssp_data(input_node, input_ref_region) -> pd.DataFrame:
def process_raw_ssp_data(node, ref_region) -> pd.DataFrame:
"""Read in raw SSP data and process it
This function takes in the raw SSP data (in IAMC format), aggregates \
Expand Down Expand Up @@ -38,22 +38,22 @@ def process_raw_ssp_data(input_node, input_ref_region) -> pd.DataFrame:
(in units of billion US$2005/yr / million)
"""
# Change node selection to upper case
node_up = input_node.upper()
node_up = node.upper()

# Check if node selection is valid
if node_up not in ["R11", "R12", "R20"]:
print("Please select a valid region: R11, R12, or R20")

# Set default reference region
if input_ref_region is None:
if input_node.upper() == "R11":
input_ref_region = "R11_NAM"
if input_node.upper() == "R12":
input_ref_region = "R12_NAM"
if input_node.upper() == "R20":
input_ref_region = "R20_NAM"
if ref_region is None:
if node.upper() == "R11":
ref_region = "R11_NAM"
if node.upper() == "R12":
ref_region = "R12_NAM"
if node.upper() == "R20":
ref_region = "R20_NAM"
else:
input_ref_region = input_ref_region
ref_region = ref_region

# Set data path for node file
node_file = package_data_path("node", node_up + ".yaml")
Expand Down Expand Up @@ -162,7 +162,7 @@ def process_raw_ssp_data(input_node, input_ref_region) -> pd.DataFrame:
)

# If reference region is not in the list of regions, print error message
reference_region = input_ref_region.upper()
reference_region = ref_region.upper()
if reference_region not in df.region.unique():
print("Please select a valid reference region: " + str(df.region.unique()))
# If reference region is in the list of regions, calculate GDP ratios
Expand Down Expand Up @@ -212,22 +212,22 @@ def process_raw_ssp_data(input_node, input_ref_region) -> pd.DataFrame:

# Function to calculate adjusted region-differentiated cost ratios
def calculate_indiv_adjusted_region_cost_ratios(
region_diff_df, input_node, input_ref_region, input_base_year
region_diff_df, node, ref_region, base_year
):
df_gdp = (
process_raw_ssp_data(input_node=input_node, input_ref_region=input_ref_region)
process_raw_ssp_data(node=node, ref_region=ref_region)
.query("year >= 2020")
.drop(columns=["total_gdp", "total_population"])
)
df_cost_ratios = region_diff_df.copy()

# If base year does not exist in GDP data, then use earliest year in GDP data
# and give warning
base_year = int(input_base_year)
base_year = int(base_year)
if int(base_year) not in df_gdp.year.unique():
base_year = int(min(df_gdp.year.unique()))
print(
f"Base year {input_base_year} not found in GDP data. \
f"Base year {base_year} not found in GDP data. \
Using {base_year} for GDP data instead."
)

Expand All @@ -236,15 +236,15 @@ def calculate_indiv_adjusted_region_cost_ratios(
# If specified node is R12, then use R12_NAM as the reference region
# If specified node is R20, then use R20_NAM as the reference region
# However, if a reference region is specified, then use that instead
if input_ref_region is None:
if input_node.upper() == "R11":
if ref_region is None:
if node.upper() == "R11":
reference_region = "R11_NAM"
if input_node.upper() == "R12":
if node.upper() == "R12":
reference_region = "R12_NAM"
if input_node.upper() == "R20":
if node.upper() == "R20":
reference_region = "R20_NAM"
else:
reference_region = input_ref_region
reference_region = ref_region

gdp_base_year = df_gdp.query("year == @base_year").reindex(
["scenario_version", "scenario", "region", "gdp_ratio_reg_to_reference"], axis=1
Expand Down
50 changes: 24 additions & 26 deletions message_ix_models/tools/costs/learning.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@


# Function to get GEA based cost reduction data
def get_cost_reduction_data(input_module) -> pd.DataFrame:
def get_cost_reduction_data(module) -> pd.DataFrame:
"""Get cost reduction data
Raw data on cost reduction in 2100 for technologies are read from \
Expand Down Expand Up @@ -45,10 +45,10 @@ def get_cost_reduction_data(input_module) -> pd.DataFrame:
.reset_index(drop=1)
)

if input_module == "base":
if module == "base":
return base_rates

elif input_module == "materials":
elif module == "materials":
# Read in materials technology mapping file
materials_file_path = package_data_path("costs", "technology_materials_map.csv")
df_materials_tech = pd.read_csv(materials_file_path)
Expand Down Expand Up @@ -78,9 +78,7 @@ def get_cost_reduction_data(input_module) -> pd.DataFrame:


# Function to get technology learning scenarios data
def get_technology_learning_scenarios_data(
input_base_year, input_module
) -> pd.DataFrame:
def get_technology_learning_scenarios_data(base_year, module) -> pd.DataFrame:
"""Read in technology first year and learning scenarios data
Raw data on technology first year and learning scenarios are read from \
Expand All @@ -90,7 +88,7 @@ def get_technology_learning_scenarios_data(
Parameters
----------
input_base_year : int, optional
base_year : int, optional
The base year, by default set to global BASE_YEAR
Returns
Expand All @@ -109,9 +107,9 @@ def get_technology_learning_scenarios_data(
pd.read_csv(file)
.assign(
first_technology_year=lambda x: np.where(
x.first_year_original > input_base_year,
x.first_year_original > base_year,
x.first_year_original,
input_base_year,
base_year,
),
)
.drop(columns=["first_year_original"])
Expand All @@ -122,10 +120,10 @@ def get_technology_learning_scenarios_data(
)
)

if input_module == "base":
if module == "base":
return base_learn

elif input_module == "materials":
elif module == "materials":
# Read in materials technology mapping file
materials_file_path = package_data_path("costs", "technology_materials_map.csv")
df_materials_tech = pd.read_csv(materials_file_path)
Expand Down Expand Up @@ -157,10 +155,10 @@ def get_technology_learning_scenarios_data(
# Function to project reference region investment cost using learning rates
def project_ref_region_inv_costs_using_learning_rates(
regional_diff_df: pd.DataFrame,
input_node,
input_ref_region,
input_base_year,
input_module,
node,
ref_region,
base_year,
module,
) -> pd.DataFrame:
"""Project investment costs using learning rates for reference region
Expand All @@ -172,11 +170,11 @@ def project_ref_region_inv_costs_using_learning_rates(
----------
regional_diff_df : pandas.DataFrame
Dataframe output from :func:`get_weo_region_differentiated_costs`
input_node : str, optional
node : str, optional
The reference node, by default "r12"
input_ref_region : str, optional
ref_region : str, optional
The reference region, by default None (defaults set in function)
input_base_year : int, optional
base_year : int, optional
The base year, by default set to global BASE_YEAR
Returns
Expand All @@ -191,21 +189,21 @@ def project_ref_region_inv_costs_using_learning_rates(
"""

# Set default reference region
if input_ref_region is None:
if input_node.upper() == "R11":
if ref_region is None:
if node.upper() == "R11":
reference_region = "R11_NAM"
if input_node.upper() == "R12":
if node.upper() == "R12":
reference_region = "R12_NAM"
if input_node.upper() == "R20":
if node.upper() == "R20":
reference_region = "R20_NAM"
else:
reference_region = input_ref_region
reference_region = ref_region

# Get cost reduction data
df_cost_reduction = get_cost_reduction_data(input_module)
df_cost_reduction = get_cost_reduction_data(module)

# Get learning rates data
df_learning = get_technology_learning_scenarios_data(input_base_year, input_module)
df_learning = get_technology_learning_scenarios_data(base_year, module)

# Merge cost reduction data with learning rates data
df_learning_reduction = df_learning.merge(
Expand All @@ -221,7 +219,7 @@ def project_ref_region_inv_costs_using_learning_rates(
cost_region_2100=lambda x: x.reg_cost_base_year
- (x.reg_cost_base_year * x.cost_reduction),
b=lambda x: (1 - PRE_LAST_YEAR_RATE) * x.cost_region_2100,
r=lambda x: (1 / (LAST_MODEL_YEAR - input_base_year))
r=lambda x: (1 / (LAST_MODEL_YEAR - base_year))
* np.log((x.cost_region_2100 - x.b) / (x.reg_cost_base_year - x.b)),
reference_region=reference_region,
)
Expand Down
Loading

0 comments on commit b97bf23

Please sign in to comment.