Skip to content

Commit

Permalink
Merge pull request #5 from pmslavin/scenario_combinations
Browse files Browse the repository at this point in the history
Add Scenario combinations support and tests
  • Loading branch information
pmslavin authored Jul 3, 2023
2 parents 76125ed + 0fa4bbf commit 2c30b60
Show file tree
Hide file tree
Showing 7 changed files with 65 additions and 3 deletions.
10 changes: 9 additions & 1 deletion pywrparser/parsers/pywrjsonparser.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
PywrTimestepper,
PywrMetadata,
PywrScenario,
PywrScenarioCombination,
PywrTable,
PywrNode,
PywrEdge,
Expand Down Expand Up @@ -54,6 +55,7 @@ def __init__(self, json_src, ruleset=None):
self.parameters = {}
self.recorders = {}
self.scenarios = []
self.scenario_combinations = []
self.tables = {}


Expand Down Expand Up @@ -147,9 +149,15 @@ def parse(self, raise_on_error=False, raise_on_warning=False,
for scenario in self.src.get("scenarios", []):
with component_exc_capture("scenarios") as cc:
scen = PywrScenario(scenario)
cc.capture_warnings(self.scen)
cc.capture_warnings(scen)
self.scenarios.append(scen)

for combination in self.src.get("scenario_combinations", []):
with component_exc_capture("scenario_combinations") as cc:
comb = PywrScenarioCombination(combination)
cc.capture_warnings(comb)
self.scenario_combinations.append(comb)

for table_name, table_data in self.src.get("tables", {}).items():
with component_exc_capture("tables") as cc:
t = PywrTable(table_name, table_data)
Expand Down
5 changes: 3 additions & 2 deletions pywrparser/rules.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,15 +53,16 @@ def identify_types(module):
from pywrparser.types.node import PywrNode
from pywrparser.types.timestepper import PywrTimestepper
from pywrparser.types.metadata import PywrMetadata
from pywrparser.types.scenario import PywrScenario
from pywrparser.types.scenario import PywrScenario, PywrScenarioCombination
from pywrparser.types.table import PywrTable
from pywrparser.types.parameter import PywrParameter
from pywrparser.types.recorder import PywrRecorder
from pywrparser.types.edge import PywrEdge

base_types = (
PywrNode, PywrTimestepper, PywrMetadata, PywrScenario,
PywrTable, PywrParameter, PywrRecorder, PywrEdge
PywrTable, PywrParameter, PywrRecorder, PywrEdge,
PywrScenarioCombination
)

typemap = {t.__qualname__: t for t in base_types}
Expand Down
1 change: 1 addition & 0 deletions pywrparser/types/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
PywrTimestepper = rs.typemap["PywrTimestepper"]
PywrMetadata = rs.typemap["PywrMetadata"]
PywrScenario = rs.typemap["PywrScenario"]
PywrScenarioCombination = rs.typemap["PywrScenarioCombination"]
PywrTable = rs.typemap["PywrTable"]
PywrParameter = rs.typemap["PywrParameter"]
PywrRecorder = rs.typemap["PywrRecorder"]
Expand Down
4 changes: 4 additions & 0 deletions pywrparser/types/network.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ def __init__(self, parser):
self.metadata = parser.metadata
self.timestepper = parser.timestepper
self.scenarios = parser.scenarios
self.scenario_combinations = parser.scenario_combinations
self.tables = parser.tables
self.nodes = parser.nodes
self.edges = parser.edges
Expand Down Expand Up @@ -159,6 +160,9 @@ def as_dict(self):
if len(self.scenarios) > 0:
network["scenarios"] = [s.as_dict() for s in self.scenarios]

if len(self.scenario_combinations) > 0:
network["scenario_combinations"] = [s.as_dict() for s in self.scenario_combinations]

if len(self.tables) > 0:
network["tables"] = {n: t.as_dict() for n, t in self.tables.items()}

Expand Down
12 changes: 12 additions & 0 deletions pywrparser/types/scenario.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,15 @@ def name(self):

def rule_name_required(self):
assert isinstance(self.name, str), "Scenario has invalid name"



class PywrScenarioCombination(PywrType):
def __init__(self, data):
self.data = data


""" Validation rules """

def rule_name_required(self):
assert isinstance(self.data, list), "Scenario combination must be a list of scenario numbers"
10 changes: 10 additions & 0 deletions tests/data/valid_network.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@
"timestep": "h"
},
"scenarios": [
{
"name": "scenario0",
"size": 1,
"ensemble_names": [
"scn0"
]
},
{
"name": "scenario1",
"size": 1,
Expand All @@ -18,6 +25,9 @@
]
}
],
"scenario_combinations": [
[0, 1]
],
"nodes": [
{
"name": "Node_1",
Expand Down
26 changes: 26 additions & 0 deletions tests/test_scenarios.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import json
import pytest

from pywrparser.types.network import PywrNetwork
from pywrparser.types.scenario import PywrScenario, PywrScenarioCombination

def test_scenarios(valid_network_file):
"""
Two scenarios are defined
"""
network, errors, warnings = PywrNetwork.from_file(valid_network_file)
assert network is not None
assert errors is None
assert len(network.scenarios) == 2
assert isinstance(network.scenarios[0], PywrScenario)


def test_scenario_combinations(valid_network_file):
"""
One scenario combination is defined
"""
network, errors, warnings = PywrNetwork.from_file(valid_network_file)
assert network is not None
assert errors is None
assert len(network.scenario_combinations) == 1
assert isinstance(network.scenario_combinations[0], PywrScenarioCombination)

0 comments on commit 2c30b60

Please sign in to comment.