Skip to content
Open
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ scratch.py
ispypsa_runs/**/*.csv
ispypsa_runs/**/*.parquet
ispypsa_runs/**/*.hdf5
ispypsa_runs/**/results/**

# ignore doit database
.doit*
32 changes: 31 additions & 1 deletion dodo.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@
add_lines_to_network,
initialise_network,
run,
save_results,
)
from ispypsa.results import load_results, save_results
from ispypsa.results.plotting import plot_map_of_energy_generation_by_carrier
from ispypsa.templater.dynamic_generator_properties import (
template_generator_dynamic_properties,
)
Expand Down Expand Up @@ -57,6 +58,7 @@
_PYPSA_FRIENDLY_DIRECTORY = Path(run_folder, "pypsa_friendly")
_PARSED_TRACE_DIRECTORY = Path(config.traces.path_to_parsed_traces)
_PYPSA_OUTPUTS_DIRECTORY = Path(run_folder, "outputs")
_RESULTS_DIRECTORY = Path(run_folder, "results")

configure_logging()

Expand Down Expand Up @@ -203,6 +205,19 @@ def create_and_run_pypsa_model(
save_results(network, pypsa_outputs_location)


def create_results(
config: ModelConfig, pypsa_outputs_location: Path, results_location: Path
) -> None:
create_or_clean_task_output_folder(results_location)
network = load_results(pypsa_outputs_location)
fig, ax = plot_map_of_energy_generation_by_carrier(
network, config, figure_size_inches=(6.5, 8), figure_kwargs=dict(dpi=600)
)
fig.savefig(
Path(results_location, "map_of_total_generation_by_carrier.png"), dpi=600
)


def task_cache_required_tables():
return {
"actions": [(build_parsed_workbook_cache, [_PARSED_WORKBOOK_CACHE])],
Expand Down Expand Up @@ -288,3 +303,18 @@ def task_create_and_run_pypsa_model():
],
"targets": [Path(_PYPSA_OUTPUTS_DIRECTORY, "network.hdf5")],
}


def task_produce_results():
return {
"actions": [
(
create_results,
[config, _PYPSA_OUTPUTS_DIRECTORY, _RESULTS_DIRECTORY],
)
],
"file_dep": [
Path(_PYPSA_OUTPUTS_DIRECTORY, "network.hdf5"),
],
"targets": [Path(_RESULTS_DIRECTORY, "map_of_total_generation_by_carrier.png")],
}
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ dependencies = [
"isp-trace-parser>=1.0.0",
"pyarrow>=18.0.0",
"tables>=3.10.1",
"cartopy>=0.24.1",
]
readme = "README.md"
requires-python = ">= 3.10"
Expand Down
2 changes: 0 additions & 2 deletions src/ispypsa/model/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
from ispypsa.model.initialise import initialise_network
from ispypsa.model.lines import add_lines_to_network
from ispypsa.model.run import run
from ispypsa.model.save_results import save_results

__all__ = [
"add_buses_to_network",
Expand All @@ -13,5 +12,4 @@
"add_carriers_to_network",
"add_lines_to_network",
"run",
"save_results",
]
12 changes: 7 additions & 5 deletions src/ispypsa/model/buses.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@


def _add_bus_to_network(
bus_name: str, network: pypsa.Network, path_to_demand_traces: Path
bus_definition: dict, network: pypsa.Network, path_to_demand_traces: Path
) -> None:
"""
Adds a Bus to the network and if a demand trace for the Bus exists, also adds the
Expand All @@ -19,8 +19,9 @@

Returns: None
"""
network.add(class_name="Bus", name=bus_name)

bus_definition["class_name"] = "Bus"
network.add(**bus_definition)
bus_name = bus_definition["name"]

Check warning on line 24 in src/ispypsa/model/buses.py

View check run for this annotation

Codecov / codecov/patch

src/ispypsa/model/buses.py#L22-L24

Added lines #L22 - L24 were not covered by tests
demand_trace_path = path_to_demand_traces / Path(f"{bus_name}.parquet")
if demand_trace_path.exists():
demand = pd.read_parquet(demand_trace_path)
Expand Down Expand Up @@ -48,6 +49,7 @@
"""
buses = pd.read_csv(path_pypsa_inputs / Path("buses.csv"))
path_to_demand_traces = path_pypsa_inputs / Path("demand_traces")
buses["name"].apply(
lambda x: _add_bus_to_network(x, network, path_to_demand_traces)
buses.apply(

Check warning on line 52 in src/ispypsa/model/buses.py

View check run for this annotation

Codecov / codecov/patch

src/ispypsa/model/buses.py#L52

Added line #L52 was not covered by tests
lambda row: _add_bus_to_network(row.to_dict(), network, path_to_demand_traces),
axis=1,
)
7 changes: 0 additions & 7 deletions src/ispypsa/model/save_results.py

This file was deleted.

3 changes: 3 additions & 0 deletions src/ispypsa/results/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from ispypsa.results.io import load_results, save_results

__all__ = ["load_results", "save_results"]
13 changes: 13 additions & 0 deletions src/ispypsa/results/io.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from pathlib import Path

import pypsa


def save_results(network: pypsa.Network, pypsa_outputs_location: Path) -> None:
network.export_to_hdf5(Path(pypsa_outputs_location, "network.hdf5"))

Check warning on line 7 in src/ispypsa/results/io.py

View check run for this annotation

Codecov / codecov/patch

src/ispypsa/results/io.py#L7

Added line #L7 was not covered by tests


def load_results(pypsa_outputs_location: str | Path) -> pypsa.Network:
network = pypsa.Network()
network.import_from_hdf5(Path(pypsa_outputs_location, "network.hdf5"))
return network

Check warning on line 13 in src/ispypsa/results/io.py

View check run for this annotation

Codecov / codecov/patch

src/ispypsa/results/io.py#L11-L13

Added lines #L11 - L13 were not covered by tests
86 changes: 86 additions & 0 deletions src/ispypsa/results/plot_helpers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import matplotlib.figure
from matplotlib.patches import Patch

from ispypsa.config.validators import ModelConfig

_DEFAULT_CARRIER_COLOUR_MAPPING = {
# corresponds to distillate in OpenElectricity
"Liquid Fuel": "#E46E56",
"Black Coal": "#251C00",
"Brown Coal": "#675B42",
"Gas": "#E78114",
"Water": "#ACE9FE",
"Solar": "#FECE00",
"Wind": "#2A7E3F",
# corresponds to gas_hydrogen in OpenElectricity
"Hyblend": "#C75338",
}
"""Colour mapping for carriers/fuel types. Same colour scheme as OpenElectricity"""

_DEFAULT_GEOMAP_COLOURS = dict(ocean="#dbdbdd", land="#fdfdfe")
"""Colour mapping for ocean and land in the map plot"""

_DEFAULT_FACECOLOR = "#faf9f6"
"""Facecolour to use in Figures (from OpenElectricity)"""


def _determine_title_year_range(config: ModelConfig) -> str:
"""
Determines the year range string for use in plot titles based on
ISPyPSA configuration options.
"""
(start, end) = (config.traces.start_year, config.traces.end_year)
year_type = config.traces.year_type

Check warning on line 33 in src/ispypsa/results/plot_helpers.py

View check run for this annotation

Codecov / codecov/patch

src/ispypsa/results/plot_helpers.py#L32-L33

Added lines #L32 - L33 were not covered by tests
if year_type == "fy" and start != end:
year_range = f"FY{str(start)[-2:]}-{str(end)[-2:]}"

Check warning on line 35 in src/ispypsa/results/plot_helpers.py

View check run for this annotation

Codecov / codecov/patch

src/ispypsa/results/plot_helpers.py#L35

Added line #L35 was not covered by tests
elif start == end:
year_range = f"{start}"

Check warning on line 37 in src/ispypsa/results/plot_helpers.py

View check run for this annotation

Codecov / codecov/patch

src/ispypsa/results/plot_helpers.py#L37

Added line #L37 was not covered by tests
else:
year_range = f"{start}-{end}"
return year_range

Check warning on line 40 in src/ispypsa/results/plot_helpers.py

View check run for this annotation

Codecov / codecov/patch

src/ispypsa/results/plot_helpers.py#L39-L40

Added lines #L39 - L40 were not covered by tests


def _add_figure_fuel_type_legend(
fig: matplotlib.figure.Figure,
carrier_colour_mapping: dict[str, str],
legend_kwargs=dict(),
) -> None:
"""Adds a legend that maps fuel types to their patch colours to a
`matplotlib.figure.Figure`.

Args:
fig: `matplotlib.figure.Figure`
carrier_colour_mapping: Dictionary that maps each carrier to a colour
legend_kwargs (optional): Keyword arguments for
`matplotlib.figure.Figure.legend()`. Anything specified in this dict will
overwrite ISPyPSA defaults. Defaults to dict().
"""
legend_patches = [

Check warning on line 58 in src/ispypsa/results/plot_helpers.py

View check run for this annotation

Codecov / codecov/patch

src/ispypsa/results/plot_helpers.py#L58

Added line #L58 was not covered by tests
Patch(color=color, label=carrier)
for carrier, color in carrier_colour_mapping.items()
]
fig.legend(

Check warning on line 62 in src/ispypsa/results/plot_helpers.py

View check run for this annotation

Codecov / codecov/patch

src/ispypsa/results/plot_helpers.py#L62

Added line #L62 was not covered by tests
handles=legend_patches,
**_consolidate_plot_kwargs(
dict(
title="Fuel Type",
loc="lower center",
fontsize=8,
title_fontsize=10,
ncol=4,
frameon=False,
),
legend_kwargs,
),
)


def _consolidate_plot_kwargs(
predefined_kwargs: dict, user_specified_kwargs: dict
) -> dict:
"""Adds to or replaces ISPyPSA's keyword arguments for plot functions using those
provided by the user in the function call.
"""
kwargs = predefined_kwargs
kwargs.update(user_specified_kwargs)
return kwargs

Check warning on line 86 in src/ispypsa/results/plot_helpers.py

View check run for this annotation

Codecov / codecov/patch

src/ispypsa/results/plot_helpers.py#L84-L86

Added lines #L84 - L86 were not covered by tests
Loading
Loading