pypsa-eur/scripts/plot_summary.py
2022-09-28 20:33:50 +02:00

217 lines
4.7 KiB
Python

# -*- coding: utf-8 -*-
# SPDX-FileCopyrightText: : 2017-2022 The PyPSA-Eur Authors
#
# SPDX-License-Identifier: MIT
"""
Plots energy and cost summaries for solved networks.
Relevant Settings
-----------------
Inputs
------
Outputs
-------
Description
-----------
"""
import logging
import os
import matplotlib.pyplot as plt
import pandas as pd
from _helpers import configure_logging
logger = logging.getLogger(__name__)
def rename_techs(label):
if "H2" in label:
label = "hydrogen storage"
elif label == "solar":
label = "solar PV"
elif label == "offwind-ac":
label = "offshore wind ac"
elif label == "offwind-dc":
label = "offshore wind dc"
elif label == "onwind":
label = "onshore wind"
elif label == "ror":
label = "hydroelectricity"
elif label == "hydro":
label = "hydroelectricity"
elif label == "PHS":
label = "hydroelectricity"
elif "battery" in label:
label = "battery storage"
return label
preferred_order = pd.Index(
[
"transmission lines",
"hydroelectricity",
"hydro reservoir",
"run of river",
"pumped hydro storage",
"onshore wind",
"offshore wind ac",
"offshore wind dc",
"solar PV",
"solar thermal",
"OCGT",
"hydrogen storage",
"battery storage",
]
)
def plot_costs(infn, config, fn=None):
## For now ignore the simpl header
cost_df = pd.read_csv(infn, index_col=list(range(3)), header=[1, 2, 3])
df = cost_df.groupby(cost_df.index.get_level_values(2)).sum()
# convert to billions
df = df / 1e9
df = df.groupby(df.index.map(rename_techs)).sum()
to_drop = df.index[df.max(axis=1) < config["plotting"]["costs_threshold"]]
print("dropping")
print(df.loc[to_drop])
df = df.drop(to_drop)
print(df.sum())
new_index = (preferred_order.intersection(df.index)).append(
df.index.difference(preferred_order)
)
new_columns = df.sum().sort_values().index
fig, ax = plt.subplots()
fig.set_size_inches((12, 8))
df.loc[new_index, new_columns].T.plot(
kind="bar",
ax=ax,
stacked=True,
color=[config["plotting"]["tech_colors"][i] for i in new_index],
)
handles, labels = ax.get_legend_handles_labels()
handles.reverse()
labels.reverse()
ax.set_ylim([0, config["plotting"]["costs_max"]])
ax.set_ylabel("System Cost [EUR billion per year]")
ax.set_xlabel("")
ax.grid(axis="y")
ax.legend(handles, labels, ncol=4, loc="upper left")
fig.tight_layout()
if fn is not None:
fig.savefig(fn, transparent=True)
def plot_energy(infn, config, fn=None):
energy_df = pd.read_csv(infn, index_col=list(range(2)), header=[1, 2, 3])
df = energy_df.groupby(energy_df.index.get_level_values(1)).sum()
# convert MWh to TWh
df = df / 1e6
df = df.groupby(df.index.map(rename_techs)).sum()
to_drop = df.index[df.abs().max(axis=1) < config["plotting"]["energy_threshold"]]
print("dropping")
print(df.loc[to_drop])
df = df.drop(to_drop)
print(df.sum())
new_index = (preferred_order.intersection(df.index)).append(
df.index.difference(preferred_order)
)
new_columns = df.columns.sort_values()
fig, ax = plt.subplots()
fig.set_size_inches((12, 8))
df.loc[new_index, new_columns].T.plot(
kind="bar",
ax=ax,
stacked=True,
color=[config["plotting"]["tech_colors"][i] for i in new_index],
)
handles, labels = ax.get_legend_handles_labels()
handles.reverse()
labels.reverse()
ax.set_ylim([config["plotting"]["energy_min"], config["plotting"]["energy_max"]])
ax.set_ylabel("Energy [TWh/a]")
ax.set_xlabel("")
ax.grid(axis="y")
ax.legend(handles, labels, ncol=4, loc="upper left")
fig.tight_layout()
if fn is not None:
fig.savefig(fn, transparent=True)
if __name__ == "__main__":
if "snakemake" not in globals():
from _helpers import mock_snakemake
snakemake = mock_snakemake(
"plot_summary",
summary="energy",
simpl="",
clusters=5,
ll="copt",
opts="Co2L-24H",
attr="",
ext="png",
country="all",
)
configure_logging(snakemake)
config = snakemake.config
summary = snakemake.wildcards.summary
try:
func = globals()[f"plot_{summary}"]
except KeyError:
raise RuntimeError(f"plotting function for {summary} has not been defined")
func(
os.path.join(snakemake.input[0], f"{summary}.csv"), config, snakemake.output[0]
)