Skip to content

Commit

Permalink
Merge pull request #245 from OSeMOSYS/summaries-updates
Browse files Browse the repository at this point in the history
Updates to result-summaries
  • Loading branch information
maartenbrinkerink authored Jan 14, 2025
2 parents 8503d50 + c20c3e2 commit e24b6ba
Show file tree
Hide file tree
Showing 6 changed files with 198 additions and 28 deletions.
8 changes: 8 additions & 0 deletions workflow/rules/postprocess.smk
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,20 @@ RESULT_SUMMARIES = [
"AnnualTotalTradeFlowsNode",
"AnnualTotalTradeFlowsCountry",
"AnnualEmissionIntensity",
"AnnualEmissionIntensityGlobal",
"PowerCapacityNode",
"TransmissionCapacityNode",
"PowerCapacityCountry",
"TransmissionCapacityCountry",
"GenerationSharesNode",
"GenerationSharesCountry",
"GenerationSharesGlobal",
"PowerCostNode",
"TotalCostNode",
"PowerCostCountry",
"TotalCostCountry",
"PowerCostGlobal",
"TotalCostGlobal",
"Metrics"
]

Expand Down Expand Up @@ -113,6 +117,7 @@ rule calculate_carbon_intensity:
annual_emissions = "results/{scenario}/results/AnnualEmissions.csv",
output:
emission_intensity = "results/{scenario}/result_summaries/AnnualEmissionIntensity.csv",
emission_intensity_global = "results/{scenario}/result_summaries/AnnualEmissionIntensityGlobal.csv",
log:
log = 'results/{scenario}/logs/carbon_intensity.log'
script:
Expand All @@ -127,8 +132,10 @@ rule calculate_costs:
output:
node_pwr_cost = "results/{scenario}/result_summaries/PowerCostNode.csv",
country_pwr_cost = "results/{scenario}/result_summaries/PowerCostCountry.csv",
global_pwr_cost = "results/{scenario}/result_summaries/PowerCostGlobal.csv",
node_cost = "results/{scenario}/result_summaries/TotalCostNode.csv",
country_cost = "results/{scenario}/result_summaries/TotalCostCountry.csv",
global_cost = "results/{scenario}/result_summaries/TotalCostGlobal.csv",
log:
log = 'results/{scenario}/logs/node_cost.log'
script:
Expand All @@ -144,6 +151,7 @@ rule calculate_generation_shares:
output:
generation_shares_node = "results/{scenario}/result_summaries/GenerationSharesNode.csv",
generation_shares_country = "results/{scenario}/result_summaries/GenerationSharesCountry.csv",
generation_shares_global = "results/{scenario}/result_summaries/GenerationSharesGlobal.csv",
log:
log = 'results/{scenario}/logs/generation_shares.log'
script:
Expand Down
29 changes: 25 additions & 4 deletions workflow/scripts/osemosys_global/summary/carbon_intensity.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ def format_production(
) -> pd.DataFrame:

df = production.copy()
df = df.loc[df.index.get_level_values("FUEL").str.startswith('ELC')]

df = df[
(df.index.get_level_values("TECHNOLOGY").str.startswith("PWR"))
Expand All @@ -40,24 +41,35 @@ def format_emissions(annual_emissions: pd.DataFrame) -> pd.DataFrame:
df["COUNTRY"] = df.EMISSION.str[3:6]
return df.groupby(["REGION", "EMISSION", "COUNTRY", "YEAR"]).sum()

def format_global_values(production: pd.DataFrame, emissions: pd.DataFrame) -> tuple[pd.DataFrame, pd.DataFrame]:
p_global = production.reset_index()[["YEAR", "VALUE"]
].groupby(["YEAR"]).sum()

e_global = emissions.reset_index()[["YEAR", "VALUE"]
].groupby(["YEAR"]).sum()

return p_global, e_global

def calculate_emission_intensity(
production: pd.DataFrame, emissions: pd.DataFrame
production: pd.DataFrame,
emissions: pd.DataFrame,
country: bool
) -> pd.DataFrame:

p = production.copy().rename(columns={"VALUE": "PROD_PJ"})
e = emissions.copy().rename(columns={"VALUE": "EMISSIONS_MT"})

df = p.join(e).fillna(0)
df = df.droplevel("COUNTRY") # emission retains country
if country:
df = df.droplevel("COUNTRY") # emission retains country

# 1 PJ (1000 TJ / PJ) (1000 GJ / TJ) (1000 MJ / GJ) (1000 kJ / MJ) (hr / 3600sec)
df["PROD_kwh"] = df.PROD_PJ.mul(1000).mul(1000).mul(1000).mul(1000).div(3600)

# 1 MT (1,000,000 T / MT) (1000 kg / T) (1000g / kg)
df["EMISSIONS_g"] = df.EMISSIONS_MT.mul(1000000).mul(1000).mul(1000)

# intensity in g/kwh
# intensity in g/kwh - kg/MWh
df["VALUE"] = df.EMISSIONS_g.div(df.PROD_kwh)

return df["VALUE"].to_frame()
Expand All @@ -68,11 +80,13 @@ def calculate_emission_intensity(
production_csv = snakemake.input.production_by_technology
annual_emissions_csv = snakemake.input.annual_emissions
save = snakemake.output.emission_intensity
save_global = snakemake.output.emission_intensity_global
storage = snakemake.params.storage
else:
production_csv = "results/India/results/ProductionByTechnology.csv"
annual_emissions_csv = "results/India/results/AnnualEmissions.csv"
save = "results/India/results/AnnualEmissionIntensity.csv"
save_global = "results/India/results/AnnualEmissionIntensityGlobal.csv"
storage = {"SDS": [], "LDS": []}

if storage:
Expand All @@ -85,7 +99,14 @@ def calculate_emission_intensity(

production = format_production(production, exclusions)
emissions = format_emissions(annual_emissions)

production_global, emissions_global = format_global_values(production, emissions)

emission_intensity = calculate_emission_intensity(production, emissions).round(2)
emission_intensity = calculate_emission_intensity(
production, emissions, country = True).round(2)

emission_intensity_global = calculate_emission_intensity(
production_global, emissions_global, country = False).round(2)

emission_intensity.to_csv(save, index=True)
emission_intensity_global.to_csv(save_global, index=True)
2 changes: 1 addition & 1 deletion workflow/scripts/osemosys_global/summary/constants.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""Constants for summary statistics"""

RENEWABLES = ["BIO", "GEO", "HYD", "SPV", "CSP", "WAS", "WAV", "WON", "WOF"]
CLEAN = ["BIO", "GEO", "HYD", "SPV", "CSP", "WAS", "WAV", "WON", "WOF", "URN"]
CLEAN = ["BIO", "CCS", "GEO", "HYD", "SPV", "CSP", "WAS", "WAV", "WON", "WOF", "URN"]
FOSSIL = ["CCG", "COA", "COG", "OCG", "OIL", "OTH", "PET"]

MONTH_NAMES = {
Expand Down
91 changes: 78 additions & 13 deletions workflow/scripts/osemosys_global/summary/costs.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,42 @@ def get_storage_cost(
.sum()
)

def get_transmission_cost(discounted_cost_tech: pd.DataFrame, country: bool) -> pd.DataFrame:

df = discounted_cost_tech.copy()

df1 = df[
(df.index.get_level_values("TECHNOLOGY").str.startswith("TRN"))
].copy()

if country:
r = "COUNTRY"
df1[r] = df1.index.get_level_values("TECHNOLOGY").str[3:6]
else:
r = "NODE"
df1[r] = df1.index.get_level_values("TECHNOLOGY").str[3:8]

df2 = df.copy()[
(df.index.get_level_values("TECHNOLOGY").str.startswith("TRN"))
]

if country:
r = "COUNTRY"
df2[r] = df2.index.get_level_values("TECHNOLOGY").str[8:11]
else:
r = "NODE"
df2[r] = df2.index.get_level_values("TECHNOLOGY").str[8:13]

for df in [df1, df2]:
df['VALUE'] = df['VALUE'] / 2

df = pd.concat([df1, df2])

return (
df.reset_index()[["REGION", r, "YEAR", "VALUE"]]
.groupby(["REGION", r, "YEAR"])
.sum()
)

def get_demand(demand: pd.DataFrame, country: bool) -> pd.DataFrame:

Expand Down Expand Up @@ -84,17 +120,22 @@ def get_pwr_cost(demand: pd.DataFrame, cost: pd.DataFrame) -> pd.DataFrame:
demand_csv = snakemake.input.demand
power_cost_node_csv = snakemake.output.node_pwr_cost
power_cost_country_csv = snakemake.output.country_pwr_cost
power_cost_global_csv = snakemake.output.global_pwr_cost
total_cost_node_csv = snakemake.output.node_cost
total_cost_country_csv = snakemake.output.country_cost
total_cost_global_csv = snakemake.output.global_cost

else:
discounted_cost_by_technology_csv = (
"results/India/results/DiscountedCostByTechnology.csv"
)
demand_csv = "results/India/results/Demand.csv"
power_cost_node_csv = "results/India/result_summaries/NodePowerCost.csv"
power_cost_country_csv = "results/India/result_summaries/CountryPowerCost.csv"
total_cost_node_csv = "results/India/result_summaries/NodeCost.csv"
total_cost_country_csv = "results/India/result_summaries/CountryCost.csv"
power_cost_node_csv = "results/India/result_summaries/PowerCostNode.csv"
power_cost_country_csv = "results/India/result_summaries/PowerCostCountry.csv"
power_cost_global_csv = "results/India/result_summaries/PowerCostGlobal.csv"
total_cost_node_csv = "results/India/result_summaries/TotalCostNode.csv"
total_cost_country_csv = "results/India/result_summaries/TotalCostCountry.csv"
total_cost_global_csv = "results/India/result_summaries/TotalCostGlobal.csv"

discounted_cost_by_technology = pd.read_csv(
discounted_cost_by_technology_csv, index_col=[0, 1, 2]
Expand All @@ -119,7 +160,11 @@ def get_pwr_cost(demand: pd.DataFrame, cost: pd.DataFrame) -> pd.DataFrame:

tech_cost = get_tech_cost(discounted_cost_by_technology, country=False)
storage_cost = get_storage_cost(discounted_cost_by_storage, country=False)
cost = tech_cost.add(storage_cost, fill_value=0)
transmission_cost = get_transmission_cost(discounted_cost_by_technology, country=False)

cost = tech_cost.add(storage_cost, fill_value = 0
).add(transmission_cost, fill_value = 0)

demand = get_demand(demand_raw, country=False)
pwr_cost = get_pwr_cost(demand, cost)

Expand All @@ -128,11 +173,31 @@ def get_pwr_cost(demand: pd.DataFrame, cost: pd.DataFrame) -> pd.DataFrame:

# country level metrics

tech_cost = get_tech_cost(discounted_cost_by_technology, country=True)
storage_cost = get_storage_cost(discounted_cost_by_storage, country=True)
cost = tech_cost.add(storage_cost, fill_value=0)
demand = get_demand(demand_raw, country=True)
pwr_cost = get_pwr_cost(demand, cost)

pwr_cost.to_csv(power_cost_country_csv, index=True)
cost.to_csv(total_cost_country_csv, index=True)
tech_cost_country = get_tech_cost(discounted_cost_by_technology, country=True)
storage_cost_country = get_storage_cost(discounted_cost_by_storage, country=True)
transmission_cost_country = get_transmission_cost(discounted_cost_by_technology, country=True)

cost_country = tech_cost_country.add(storage_cost_country, fill_value = 0
).add(transmission_cost_country, fill_value = 0)

demand_country = get_demand(demand_raw, country=True)
pwr_cost_country = get_pwr_cost(demand_country, cost_country)

pwr_cost_country.to_csv(power_cost_country_csv, index=True)
cost_country.to_csv(total_cost_country_csv, index=True)

# global level metrics

cost_global = tech_cost_country.add(storage_cost_country,
fill_value = 0
).add(transmission_cost_country, fill_value = 0
).groupby(["YEAR"]).sum()

demand_global = get_demand(demand_raw, country=True)
demand_global = demand_global.groupby([
demand_global.index.get_level_values("YEAR")]).sum()

pwr_cost_global = get_pwr_cost(demand_global, cost_global)

pwr_cost_global.to_csv(power_cost_global_csv, index=True)
cost_global.to_csv(total_cost_global_csv, index=True)
77 changes: 74 additions & 3 deletions workflow/scripts/osemosys_global/summary/gen_shares.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ def _get_gen_by_node(
) -> pd.DataFrame:

df = production.copy()
df = df.loc[df.index.get_level_values("FUEL").str.startswith('ELC')]

assert "TECHNOLOGY" in df.index.names

Expand All @@ -38,6 +39,7 @@ def _get_gen_by_country(
) -> pd.DataFrame:

df = production.copy()
df = df.loc[df.index.get_level_values("FUEL").str.startswith('ELC')]

assert "TECHNOLOGY" in df.index.names

Expand All @@ -56,6 +58,31 @@ def _get_gen_by_country(
.sum()
)

def _get_gen_global(
production: pd.DataFrame,
include: Optional[list[str]] = None,
exclude: Optional[list[str]] = None,
) -> pd.DataFrame:

df = production.copy()
df = df.loc[df.index.get_level_values("FUEL").str.startswith('ELC')]

assert "TECHNOLOGY" in df.index.names

df["TECH"] = df.index.get_level_values("TECHNOLOGY").str[3:6]
#df["COUNTRY"] = df.index.get_level_values("TECHNOLOGY").str[6:9]

if exclude:
df = df[~df.TECH.isin(exclude)].copy()

if include:
df = df[df.TECH.isin(include)].copy()

return (
df.reset_index()[["REGION", "YEAR", "VALUE"]]
.groupby(["REGION", "YEAR"])
.sum()
)

def calc_generation_shares_node(
production_by_technology: pd.DataFrame, exclusions: Optional[list[str]] = None
Expand All @@ -72,10 +99,13 @@ def calc_generation_shares_node(
]

total = _get_gen_by_node(df, exclude=exclusions).rename(columns={"VALUE": "TOTAL"})

clean = _get_gen_by_node(df, include=CLEAN).rename(columns={"VALUE": "CLEAN"})

renewable = _get_gen_by_node(df, include=RENEWABLES).rename(
columns={"VALUE": "RENEWABLE"}
)

fossil = _get_gen_by_node(df, include=FOSSIL).rename(columns={"VALUE": "FOSSIL"})

shares = (
Expand Down Expand Up @@ -128,13 +158,50 @@ def calc_generation_shares_country(

return shares[["CLEAN", "RENEWABLE", "FOSSIL"]].round(1)

def calc_generation_shares_global(
production_by_technology: pd.DataFrame, exclusions: Optional[list[str]] = None
) -> pd.DataFrame:

if not exclusions:
exclusions = []

df = production_by_technology.copy()

df = df[
(df.index.get_level_values("TECHNOLOGY").str.startswith("PWR"))
& ~(df.index.get_level_values("TECHNOLOGY").str.contains("TRN"))
]

total = _get_gen_global(df, exclude=exclusions).rename(
columns={"VALUE": "TOTAL"}
)
clean = _get_gen_global(df, include=CLEAN).rename(columns={"VALUE": "CLEAN"})
renewable = _get_gen_global(df, include=RENEWABLES).rename(
columns={"VALUE": "RENEWABLE"}
)
fossil = _get_gen_global(df, include=FOSSIL).rename(columns={"VALUE": "FOSSIL"})

shares = (
total.join(clean, how="outer")
.join(renewable, how="outer")
.join(fossil, how="outer")
.fillna(0)
)

shares["CLEAN"] = shares.CLEAN.div(shares.TOTAL).mul(100)
shares["RENEWABLE"] = shares.RENEWABLE.div(shares.TOTAL).mul(100)
shares["FOSSIL"] = shares.FOSSIL.div(shares.TOTAL).mul(100)

return shares[["CLEAN", "RENEWABLE", "FOSSIL"]].round(1)


if __name__ == "__main__":
if "snakemake" in globals():
production_by_technology_annual_csv = snakemake.input.production_by_technology
storage = snakemake.params.storage
gen_shares_node = snakemake.output.generation_shares_node
gen_shares_country = snakemake.output.generation_shares_country
gen_shares_global = snakemake.output.generation_shares_global
else:
production_by_technology_annual_csv = (
"results/India/results/ProductionByTechnologyAnnual.csv"
Expand All @@ -144,6 +211,10 @@ def calc_generation_shares_country(
gen_shares_country = (
"results/India/result_summaries/GenerationSharesCountry.csv"
)
gen_shares_global = (
"results/India/result_summaries/GenerationSharesGlobal.csv"
)


production_by_technology_annual = pd.read_csv(
production_by_technology_annual_csv, index_col=[0, 1, 2, 3]
Expand All @@ -155,9 +226,9 @@ def calc_generation_shares_country(
exclusions = []

nodes = calc_generation_shares_node(production_by_technology_annual, exclusions)
country = calc_generation_shares_country(
production_by_technology_annual, exclusions
)
country = calc_generation_shares_country(production_by_technology_annual, exclusions)
glob = calc_generation_shares_global(production_by_technology_annual, exclusions)

nodes.to_csv(gen_shares_node, index=True)
country.to_csv(gen_shares_country, index=True)
glob.to_csv(gen_shares_global, index=True)
Loading

0 comments on commit e24b6ba

Please sign in to comment.