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

Remove dependency on ScenarioInfo objects #344

Merged
merged 2 commits into from
Apr 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 52 additions & 23 deletions postreise/plot/plot_sim_vs_hist.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import warnings

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

from postreise.analyze.generation.summarize import sum_generation_by_state


class PlotSettings:
Expand All @@ -10,41 +11,67 @@ class PlotSettings:
size_inches = (20, 10)


def plot_generation_sim_vs_hist(sim_gen, hist_gen, s_info, state, showmax=True):
"""
Plot simulated vs historical generation of each resource in the scenario
def plot_generation_sim_vs_hist(
scenario,
hist_gen,
state,
show_max=True,
plot_show=True,
):
"""Plot simulated vs historical generation of each resource in the scenario
for the given state. Optionally include max generation.

:param pandas.DataFrame sim_gen: simulated generation dataframe
:param pandas.DataFrame hist_gen: historical generation dataframe
:param powersimdata.design.ScenarioInfo s_info: scenario info instance.
:param powersimdata.scenario.scenario.Scenario scenario: scenario instance.
:param pandas.DataFrame hist_gen: historical generation data frame. Columns are
resources and indices are state names.
:param str state: the US state
:param bool showmax: determine whether to additionally plot max generation of each resource
:param bool show_max: determine whether to additionally plot max generation of each
resource.
:param plot_show: show the plot or not, defaults to True.
:return: (*matplotlib.axes.Axes*) -- axes object of the plot.
:raises TypeError:
if ``hist_gen`` is not a data frame.
if ``state`` is not a str.
:raises ValueError: if ``state`` is not in ``hist_gen`` or ``scenario``.
"""
labels = list(sim_gen.columns)
all_resources = s_info.get_available_resource("all")
if not isinstance(hist_gen, pd.DataFrame):
raise TypeError("hist_gen must be a pandas.DataFrame")
if not isinstance(state, str):
raise TypeError("state must be a str")

sim_gen = sum_generation_by_state(scenario)
if state not in sim_gen.index or state not in hist_gen.index:
raise ValueError("Invalid state")

all_resources = list(sim_gen.columns)

sim = [int(round(sim_gen.loc[state, res])) for res in all_resources]
hist = [int(round(hist_gen.loc[state, res])) for res in all_resources]

def calc_max(gen_type):
with warnings.catch_warnings():
warnings.simplefilter("ignore")
return int(
s_info.get_capacity(gen_type, state) * len(s_info.pg.index) / 1000
)
grid = scenario.get_grid()
pg = scenario.get_pg()

def calc_max(fuel):
loadzone = list(grid.model_immutables.area_to_loadzone(state, "state")) # noqa
capacity = grid.plant.query("type == @fuel & zone_name == @loadzone")[
"Pmax"
].sum()
if capacity == 0:
print(f"No {fuel} generator in {state}")

return int(capacity * pg.shape[0] / 1000)

max_gen = []
if showmax:
if show_max:
max_gen = [calc_max(res) for res in all_resources]

x = np.arange(len(labels)) # the label locations
x = np.arange(len(all_resources)) # the label locations
width = PlotSettings.width
fontsize = PlotSettings.fontsize
size_inches_x, size_inches_y = PlotSettings.size_inches

fig, ax = plt.subplots()
if showmax:
if show_max:
rects1 = ax.bar(x - width, hist, width, label="Historical")
rects2 = ax.bar(x, sim, width, label="Simulated")
rects3 = ax.bar(x + width, max_gen, width, label="Max Generation")
Expand All @@ -56,7 +83,7 @@ def calc_max(gen_type):
ax.set_ylabel("GWh", fontsize=fontsize)
ax.set_title(state, fontsize=fontsize)
ax.set_xticks(x)
ax.set_xticklabels(labels, fontsize=fontsize)
ax.set_xticklabels(all_resources, fontsize=fontsize)
ax.legend(fontsize=fontsize)

def autolabel(rects):
Expand All @@ -74,8 +101,10 @@ def autolabel(rects):

autolabel(rects1)
autolabel(rects2)
if showmax:
if show_max:
autolabel(rects3)
fig.tight_layout()
fig.set_size_inches(size_inches_x, size_inches_y)
plt.show()
if plot_show:
plt.show()
return ax
78 changes: 78 additions & 0 deletions postreise/plot/tests/test_plot_sim_vs_hist.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import pandas as pd
import pytest
from powersimdata.tests.mock_scenario import MockScenario

from postreise.plot.plot_sim_vs_hist import plot_generation_sim_vs_hist

mock_plant = {
"plant_id": ["A", "B", "C", "D", "E", "F", "G", "H"],
"zone_id": [301, 302, 303, 304, 305, 306, 307, 308],
"Pmax": [100, 75, 150, 30, 50, 300, 200, 80],
"Pmin": [0, 0, 0, 0, 0, 100, 10, 0],
"type": ["solar", "wind", "hydro", "hydro", "wind", "coal", "ng", "wind"],
"zone_name": [
"Far West",
"North",
"West",
"South",
"North Central",
"South Central",
"Coast",
"East",
],
}

mock_pg = pd.DataFrame(
{
"A": [80, 75, 72, 81],
"B": [22, 22, 25, 20],
"C": [130, 130, 130, 130],
"D": [25, 26, 27, 28],
"E": [10, 11, 9, 12],
"F": [290, 295, 295, 294],
"G": [190, 190, 191, 190],
"H": [61, 63, 65, 67],
},
index=pd.date_range(start="2016-01-01", periods=4, freq="H"),
)

grid_attrs = {"plant": mock_plant}
scenario = MockScenario(grid_attrs, pg=mock_pg)
scenario.info["interconnect"] = "Texas"
scenario.info["start_date"] = pd.Timestamp(2016, 1, 1)
scenario.info["end_date"] = pd.Timestamp(2016, 1, 1, 3)
scenario.state.grid.id2zone = {
k: v for k, v in zip(mock_plant["zone_id"], mock_plant["zone_name"])
}
scenario.state.grid.zone2id = {v: k for k, v in scenario.state.grid.id2zone.items()}
scenario.state.grid.model = "usa_tamu"

hist_gen = pd.DataFrame(
{
"solar": 100 * 4,
"wind": 205 * 4,
"hydro": 180 * 4,
"coal": 300 * 4,
"ng": 200 * 4,
},
index=["Texas"],
)


def test_plot_generation_sim_vs_hist_argument_type():
with pytest.raises(TypeError, match="hist_gen must be a pandas.DataFrame"):
plot_generation_sim_vs_hist(scenario, 3, "Texas")
with pytest.raises(TypeError, match="state must be a str"):
plot_generation_sim_vs_hist(scenario, pd.DataFrame(), ["Texas"])


def test_plot_generation_sim_vs_hist_argument_value():
with pytest.raises(ValueError, match="Invalid state"):
plot_generation_sim_vs_hist(scenario, hist_gen, "Washington")


def test_plot_generation_sim_vs_hist():
plot_generation_sim_vs_hist(
scenario, hist_gen, "Texas", show_max=False, plot_show=False
)
plot_generation_sim_vs_hist(scenario, hist_gen, "Texas", plot_show=False)