Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updates to result-summaries #245

Merged
merged 9 commits into from
Jan 14, 2025
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
Loading