From bf7531d4accd911a2744f23e46142710b77ceda9 Mon Sep 17 00:00:00 2001 From: jpalm3r Date: Tue, 4 Aug 2026 15:06:58 +0200 Subject: [PATCH] Revert "Merge pull request #687 from DHI/modelskill: Per-product Network constructors, with EPANET companion files" This reverts commit 8651801de4cd9eb2299029d28bb6cc6c0592abea, reversing changes made to eb1cbc489486703b76bc196c4ade153af73d8930. --- .github/workflows/full_test.yml | 6 +- .gitignore | 4 +- adr/012-network-format-constructors.md | 77 --- adr/README.md | 1 - docs/user-guide/network.qmd | 106 +--- notebooks/Collection_systems_network.ipynb | 4 +- roadmap/features/network-models.md | 6 +- src/modelskill/model/adapters/_inp.py | 109 ---- src/modelskill/model/adapters/_res1d.py | 64 +-- src/modelskill/model/network.py | 2 +- src/modelskill/network.py | 423 ++------------ tests/notebooks/test_notebooks.py | 2 +- tests/test_network.py | 638 +-------------------- tests/testdata/README.md | 25 - tests/testdata/epanet.inp | 226 -------- tests/testdata/epanet.res | Bin 17066 -> 0 bytes tests/testdata/epanet.resx | Bin 1019 -> 0 bytes tests/testdata/network_cali.res11 | Bin 196339 -> 0 bytes tests/testdata/swmm.out | Bin 44166 -> 0 bytes 19 files changed, 80 insertions(+), 1613 deletions(-) delete mode 100644 adr/012-network-format-constructors.md delete mode 100644 src/modelskill/model/adapters/_inp.py delete mode 100644 tests/testdata/README.md delete mode 100644 tests/testdata/epanet.inp delete mode 100644 tests/testdata/epanet.res delete mode 100644 tests/testdata/epanet.resx delete mode 100644 tests/testdata/network_cali.res11 delete mode 100644 tests/testdata/swmm.out diff --git a/.github/workflows/full_test.yml b/.github/workflows/full_test.yml index bd62ad2b4..7881909ca 100644 --- a/.github/workflows/full_test.yml +++ b/.github/workflows/full_test.yml @@ -10,7 +10,7 @@ jobs: lint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v4 - uses: astral-sh/ruff-action@v2 with: version: 0.6.2 @@ -24,7 +24,7 @@ jobs: pandas-version: ["pandas2", "pandas3"] # TODO: drop pandas2 once 3.x is well-established steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v4 - uses: extractions/setup-just@v3 @@ -58,7 +58,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v4 - uses: extractions/setup-just@v3 diff --git a/.gitignore b/.gitignore index b38653822..318f22d3b 100644 --- a/.gitignore +++ b/.gitignore @@ -153,6 +153,4 @@ docs/_site/ docs/_extensions/ docs/api/*.qmd -uv.lock - -tests/testdata/confidential/* \ No newline at end of file +uv.lock \ No newline at end of file diff --git a/adr/012-network-format-constructors.md b/adr/012-network-format-constructors.md deleted file mode 100644 index 7e1785027..000000000 --- a/adr/012-network-format-constructors.md +++ /dev/null @@ -1,77 +0,0 @@ -# ADR-012: One Network Constructor per Modelling Product - -**Status**: Draft - -**Date**: 2026-08 - -## Context - -`Network` is built from result files read through mikeio1d. Its single `Res1D` class opens nine extensions across five products — MIKE 1D (`.res1d`), MIKE 11 (`.res11`), MOUSE (`.prf`, `.crf`, `.xrf`), EPANET (`.res`), SWMM (`.out`), Water Hammer (`.whr`), and `.resx`, which is shared by the last three. There is no per-format reader and no per-format constructor argument, so from mikeio1d's side all nine look alike. - -modelskill's constructor was named `from_res1d`, and its extension guard was briefly widened to accept everything mikeio1d could read. That made the name misleading: it promised one format and read nine. - -Loading each of mikeio1d's own fixtures showed the nine are not interchangeable: - -- `.res1d` and `.res11` produce a full network with real reach lengths and gridpoints. `.res11` initially failed because MIKE 11 keeps its timeseries on reach gridpoints, leaving nodes with no quantities at all — a bug in modelskill's adapter, now fixed. -- `.res` (EPANET) loads, but as a link-node model it reports no reach length and one synthetic gridpoint per reach. mikeio1d signals the missing length by returning `0`, which is indistinguishable from a genuine zero. -- `.out` (SWMM) and `.resx` expose no reach start/end nodes. Looking closer, this is not an upstream API gap: the raw `StartNodeIndex` is `-1` on every reach, node coordinates are `nan`, and there are no chainages, so the connectivity is absent from the files themselves. It lives in a *companion* file — SWMM's `.inp` input file, and, for `.resx`, the sibling `.res` that defines the network the `.resx` adds results to. -- MOUSE and `.whr` have no test fixture anywhere, including in mikeio1d's testdata, so nothing about them can be verified. - -## Decision - -Name constructors after the product that writes the file, and only ship one where a committed fixture backs it: - -| Constructor | Extensions | -|---|---| -| `Network.from_mike` | `.res1d`, `.res11` | -| `Network.from_epanet` | `.res`, plus optional `.resx` and `.inp` companions | - -`from_res1d` is removed. It only ever shipped in the 1.4.0a3 alpha, and the network module is opt-in and absent from the API reference, so a deprecation shim would have added a second name for the tested path without protecting a real caller. - -Every extension mikeio1d can read is accounted for in one of three module-level tables in `network.py` — readable by `from_mike`, readable by `from_epanet`, or refused with a specific reason. A test asserts the three cover exactly `Res1D.get_supported_file_extensions()`, so a mikeio1d release that adds a tenth format fails CI and forces a decision rather than leaving the format silently unreachable. - -Four supporting rules: - -- **A constructor takes its product's companion files as arguments, not as separate constructors.** A product may write several files for one run, and the result file is not always the whole picture. `from_epanet(res, resx=..., inp=...)` reflects that: the `.resx` adds node quantities and the `.inp` adds the reach lengths that no result file carries. The alternative — a `from_resx()` — would have been wrong, since a companion file describes a network defined elsewhere and cannot stand on its own. A companion is validated against the main file (same time axis, no unknown IDs) rather than merged on trust, because two runs would line up silently and produce a network that nothing downstream would flag. -- **A constructor requires a fixture.** Naming a product in the API is a support claim; it should be backed by a test that builds a `Network` from a real file of that product. MOUSE and Water Hammer are refused today for exactly this reason, and each becomes a six-line addition once a redistributable fixture exists. -- **A refusal names the file that would lift it.** "mikeio1d does not expose reach start/end nodes" was accurate about our code path but wrong about the cause, and it left users with nothing to do. The `.out` refusal now names the companion `.inp` and the issue tracking it; the `.resx` refusal names `from_epanet(res, resx=...)`, which is a next action rather than a dead end. -- **Degenerate results are documented, not warned about.** EPANET's undefined reach lengths and absent breakpoints are stated in the `from_epanet` docstring and the user guide, and asserted in tests. A runtime warning would fire on correct usage and teach users to filter our warnings, and both consequences already raise where they bite. -- **An unreadable reach length is undefined, not zero.** `NetworkReach.length` is optional and defaults to `None`, and the adapter maps mikeio1d's `0` sentinel onto it. Reporting `0` would assert that an EPANET pipe has no extent, which is false — the length exists, mikeio1d just cannot read it — and it makes a length-weighted graph algorithm treat the reach as free to traverse. With `None`, `networkx` fails instead: shortest-path treats the edge as unreachable and weight-summing calls raise `TypeError`. Omitting the edge attribute altogether was rejected for the opposite reason, since `networkx` then defaults the weight to `1`. Nothing inside modelskill reads the length, so this only affects `Network.graph`; matching and extraction work from break point distances. - -## Alternatives Considered - -**One constructor per extension** — `from_res`, `from_out`, `from_whr` say nothing about the product they belong to, and MOUSE would need three identical methods. - -**A generic catch-all (`from_file` or `from_mikeio1d`)** — a second way to do the same thing. With every extension either read or explicitly refused, the catch-all's only remaining job is forward compatibility with formats mikeio1d adds later, which the drift test handles more usefully by demanding a decision. - -**Keep `from_res1d` permissive** — preserves the misleading name, and a constructor that accepts everything cannot tell an EPANET user which method to reach for instead. - -**Ship all five product constructors regardless of coverage** — MOUSE and Water Hammer would be unverifiable, so the method list would stop being a reliable statement of what works. SWMM is a different case: its `.inp` does carry the missing topology and a fixture for it exists upstream, so it is deferred rather than impossible ([#689](https://github.com/DHI/modelskill/issues/689)). - -**A `from_resx()` constructor, or a caller-supplied edge list** — both were considered while working out what `.resx` and `.out` needed. A `from_resx()` cannot work, because a companion file describes a network defined elsewhere. An edge-list argument for supplying topology by hand was redundant: `NetworkReach` is already an abstract base class, so that path exists without new API. - -## Consequences - -Positive: - -- The method list is the format list; `Network.from_` answers "which formats does this read". -- Refusals name the file that would lift them, so a user has somewhere to go. -- Passing a file the other constructor handles raises a `ValueError` naming that constructor. -- One private implementation (`Network._from_mikeio1d`) does the version guard, extension validation, `Res1D` construction, node/reach filtering and companion-file handling, so a new product constructor is a docstring and one call. -- EPANET networks get real edge lengths and two more node quantities, and the `.inp` reader added for it (`model/adapters/_inp.py`) is the same one SWMM support will need, since the two products share the `.inp` layout. - -Negative: - -- MIKE 11 is covered by a fixture but has no field-tested usage behind it yet. -- MOUSE and Water Hammer are refused even though mikeio1d may well read them correctly. This is deliberate: refusing with a reason is recoverable, while a method that silently produces a wrong graph is not. -- The `.inp` reader is ours to maintain. mikeio1d does not read `.inp` at all, and pulling in `wntr` or `swmmio` for two sections each would weigh more than the parser does (ADR-010). The cost is that an unusual `.inp` dialect is our bug to fix. -- `.resx` merges node quantities only. Its reach-level quantities need a data location on single-gridpoint reaches, which is #680. - -## Relationship to ADR-009 - -[ADR-009](009-factory-pattern.md) argues for auto-detecting entry points such as `model_result()` and `observation()` so users need not know the class hierarchy. That is not in tension with this decision. Auto-detection resolves *which class* to build from the shape of the data; these constructors resolve *which product wrote the file*, which is information the call site should state rather than have guessed — particularly when the answer decides whether reach-based matching will work at all. - -## See Also - -- [ADR-010](010-optional-domain-dependencies.md) — why mikeio1d is an optional dependency -- `tests/testdata/README.md` — provenance of the result fixtures diff --git a/adr/README.md b/adr/README.md index 59b6d3bf2..eeff80d44 100644 --- a/adr/README.md +++ b/adr/README.md @@ -30,7 +30,6 @@ Each ADR follows this structure: - [ADR-009](009-factory-pattern.md) - Factory pattern for type detection - [ADR-010](010-optional-domain-dependencies.md) - Optional dependencies for domain-specific model types (Draft) - [ADR-011](011-vertical-pre-extracted-columns.md) - VerticalModelResult ingests pre-extracted columns -- [ADR-012](012-network-format-constructors.md) - One Network constructor per modelling product (Draft) ## Contributing diff --git a/docs/user-guide/network.qmd b/docs/user-guide/network.qmd index 56df21b1b..dd8ed055d 100644 --- a/docs/user-guide/network.qmd +++ b/docs/user-guide/network.qmd @@ -132,33 +132,18 @@ Network → NetworkModelResult → match() → Comparer ## Building a Network -You can build a `Network` object by loading it from a supported network result file. Reading these files relies on [mikeio1d](https://github.com/DHI/mikeio1d), so install the `networks` dependency group first. +You can build a `Network` object by loading it from a supported network format. -There is one constructor per product that writes the file: +Currently, the only supported format is `mikeio.Res1D`. -| Constructor | Extensions | Product | -|---|---|---| -| `Network.from_mike` | `.res1d`, `.res11` | MIKE 1D, MIKE 11 | -| `Network.from_epanet` | `.res`, plus optional `.resx` and `.inp` | EPANET | - -The remaining formats mikeio1d can open cannot be turned into a `Network`, and say so when you try: - -| Extension | Why not | -|---|---| -| `.out` (SWMM) | The reach connectivity is not in the `.out` at all — it lives in the companion `.inp` input file, which modelskill does not read yet ([#689](https://github.com/DHI/modelskill/issues/689)). | -| `.resx` | Not a network on its own. It holds extra results for the network defined in the sibling `.res`, so pass it as `from_epanet(res, resx=...)` instead. | -| `.prf`, `.crf`, `.xrf` (MOUSE), `.whr` (Water Hammer) | No test fixture exists for these formats, so support cannot be verified. [Open an issue](https://github.com/DHI/modelskill/issues) if you need one. | +### Res1D file -### From a network result file - -The quickest way to get a `Network` is from the path to a result file: +The quickest way to get a `Network` is from the path to a MIKE 1D result file: ```{python} # | echo: false path_to_res1d = "../../tests/testdata/network.res1d" -path_to_res11 = "../../tests/testdata/network_cali.res11" -path_to_epanet = "../../tests/testdata/epanet.res" path_to_sensor_data_1 = "../../tests/testdata/network_sensor_1.csv" path_to_sensor_data_2 = "../../tests/testdata/network_sensor_2.csv" ``` @@ -166,7 +151,7 @@ path_to_sensor_data_2 = "../../tests/testdata/network_sensor_2.csv" ```{python} from modelskill.network import Network -network = Network.from_mike(path_to_res1d) +network = Network.from_res1d(path_to_res1d) network ``` @@ -176,81 +161,18 @@ or a `mikeio1d.Res1D` that has already been opened: from mikeio1d import Res1D res = Res1D(path_to_res1d) -network = Network.from_mike(res) -``` - -MIKE 11 files work the same way. Note that MIKE 11 keeps its timeseries on reach gridpoints rather than on nodes, so the nodes of such a network carry no data of their own: - -```{python} -Network.from_mike(path_to_res11) -``` - -EPANET results use `from_epanet`: - -```{python} -Network.from_epanet(path_to_epanet) -``` - -#### EPANET companion files - -An EPANET run writes more than one file, and the `.res` is not the whole picture: - -| File | What it adds | -|---|---| -| `.res` | The network and its main timeseries. Required. | -| `.resx` | Extra results — tank volume and pump energy. Merged onto matching nodes. | -| `.inp` | The model input. The only one of the three carrying reach lengths. | - -Pass the companions alongside the result file to get a fuller network: - -```{python} -# | echo: false -path_to_epanet_resx = "../../tests/testdata/epanet.resx" -path_to_epanet_inp = "../../tests/testdata/epanet.inp" -``` - -```{python} -network_epanet = Network.from_epanet( - path_to_epanet, - resx=path_to_epanet_resx, - inp=path_to_epanet_inp, -) -network_epanet -``` - -`Volume` and `Volume Percentage` come from the `.resx`, and the reach lengths from the `.inp`: - -```{python} -sorted( - d["length"] - for *_, d in network_epanet.graph.edges(data=True) - if d["length"] is not None -) +network = Network.from_res1d(res) ``` -::: {.callout-warning} -## EPANET reach geometry is limited - -EPANET is a link-node model, and mikeio1d reports no length and a single synthetic gridpoint for each reach. So for an EPANET network: - -* without `inp=`, every edge of `network.graph` has `length=None`. A length-weighted `networkx` call then fails rather than returning a meaningless number — shortest-path treats the edge as unreachable, and anything that sums the weights raises `TypeError`. With `inp=`, only pumps and valves stay `None`, since `[PIPES]` is the one section carrying lengths -* reaches have no breakpoints, so a `ReachObservation` cannot be matched — use `NodeObservation` instead -* `find(reach=..., distance=)` never resolves; only `distance="start"` and `distance="end"` work - -For the same reason, `resx=` merges node quantities only. Its reach-level quantities — pump energy, efficiency and costs — have no breakpoint to live on, which is tracked in [#680](https://github.com/DHI/modelskill/issues/680). - -Node timeseries, `to_dataframe()`, `to_dataset()`, `find(node=...)` and `recall()` are unaffected. -::: - -A MIKE 1D network contains multiple levels that are unified into a generic network structure as depicted in the image below. The image introduces concepts like _find_, _recall_ and _boundary_ which are explained in the following sections. +A `Res1D` network contains multiple levels that are unified into a generic network structure as depicted in the image below. The image introduces concepts like _find_, _recall_ and _boundary_ which are explained in the following sections. ![How a Res1D file maps to a Network object. Reaches and nodes are re-indexed as integers; boundary nodes expose `find()`/`recall()` round-trip lookups.](../images/res1d_network_mapping.png) #### Selective loading -Large result files can contain thousands of nodes and gridpoints. Loading all of that data into memory is slow and may cause memory issues — especially when you only need the timeseries at a handful of nodes where observations exist. +Large Res1D files can contain thousands of nodes and gridpoints. Loading all of that data into memory is slow and may cause memory issues — especially when you only need the timeseries at a handful of nodes where observations exist. -Both constructors accept the same two optional arguments to restrict what gets loaded: +`from_res1d` accepts two optional arguments to restrict what gets loaded: | Argument | Type | Effect | |---|---|---| @@ -264,7 +186,7 @@ Selective loading only controls **which timeseries are held in memory**. The ful The most memory-efficient setup — useful when you only care about specific junction nodes — is to pass the node IDs you need and skip all intermediate gridpoints with `reaches=[]`: ```{python} -network_subset = Network.from_mike( +network_subset = Network.from_res1d( path_to_res1d, nodes=["78", "46"], reaches=[], @@ -275,7 +197,7 @@ network_subset If you also need gridpoint data along a particular reach, pass its name (or a list of names): ```{python} -network_subset = Network.from_mike( +network_subset = Network.from_res1d( path_to_res1d, nodes=["78", "46"], reaches=["94l1"], @@ -463,9 +385,7 @@ Use `ReachObservation` when your measured quantity is representative of the whol In case you have your network data in a format that is not included in [Building a Network](#building-a-network), you can assemble a `Network` object by subclassing the abstract base classes `NetworkNode` and `NetworkReach`. `NetworkNode` requires three properties: `id`, `data`, and `boundary`. -`NetworkReach` requires four: `id`, `start`, `end`, and `breakpoints`. - -`NetworkReach.length` is optional and defaults to `None`. Reach length matters in some domains (rivers, sewer networks) and not in others (link-node water distribution models), so override it only where a length exists. Where it is left undefined, the reach contributes an edge with `length=None` to `network.graph`, which keeps length-weighted graph algorithms from quietly treating the reach as free. Nothing else in modelskill reads the length — matching and extraction work from break point distances alone. +`NetworkReach` requires five: `id`, `start`, `end`, `length`, and `breakpoints`. The following is a simple implementation example: @@ -532,7 +452,7 @@ class ExampleReach(NetworkReach): ``` ::: {.callout-tip} -The three abstract properties that **every** `NetworkNode` subclass must implement are `id`, `data` and `boundary`. If `boundary` is not relevant for your use case, define the property to return an empty dictionary, as in the example above. Similarly, a `NetworkReach` with no intermediate points can return an empty `breakpoints` list, and one with no meaningful length can leave the `length` property out altogether. +The three abstract properties that **every** `NetworkNode` subclass must implement are `id`, `data` and `boundary`. If `boundary` is not relevant for your use case, define the property to return an empty dictionary, as in the example above. Similarly, a `NetworkReach` with no intermediate points can return an empty `breakpoints` list. ::: diff --git a/notebooks/Collection_systems_network.ipynb b/notebooks/Collection_systems_network.ipynb index 89e9962e0..a79d769fe 100644 --- a/notebooks/Collection_systems_network.ipynb +++ b/notebooks/Collection_systems_network.ipynb @@ -37,7 +37,7 @@ "```python\n", "from modelskill.network import Network\n", "\n", - "network = Network.from_mike(\"path/to/results.res1d\")\n", + "network = Network.from_res1d(\"path/to/results.res1d\")\n", "``` \n", "\n", "### Custom network format\n", @@ -89,7 +89,7 @@ } ], "source": [ - "network = Network.from_mike(\"../tests/testdata/network.res1d\")\n", + "network = Network.from_res1d(\"../tests/testdata/network.res1d\")\n", "network" ] }, diff --git a/roadmap/features/network-models.md b/roadmap/features/network-models.md index fc7a7f96c..b4b586662 100644 --- a/roadmap/features/network-models.md +++ b/roadmap/features/network-models.md @@ -13,7 +13,7 @@ This reduces the effort required to produce quality-assured model deliverables a ## What This Enables -- Load MIKE 1D, MIKE 11 and EPANET simulation results as model results +- Load MIKE 1D simulation results (Res1D files) as model results - Match network model outputs against point observations at specific nodes, reaches, or catchments - Apply the full suite of ModelSkill metrics and visualisations to network model validation - Compare multiple network model scenarios side by side @@ -21,6 +21,4 @@ This reduces the effort required to produce quality-assured model deliverables a ## Current Status -In active development. MIKE 1D, MIKE 11 and EPANET result files can be read today. Integration with ModelSkill's validation workflow is underway. - -MOUSE and Water Hammer results are not read yet: no shareable result file exists for either format, so support cannot be verified. SWMM results cannot be supported until mikeio1d exposes reach connectivity for them. +In active development. Reading of MIKE 1D result files is already supported. Integration with ModelSkill's validation workflow is underway. diff --git a/src/modelskill/model/adapters/_inp.py b/src/modelskill/model/adapters/_inp.py deleted file mode 100644 index 329b2c92a..000000000 --- a/src/modelskill/model/adapters/_inp.py +++ /dev/null @@ -1,109 +0,0 @@ -"""Minimal reader for EPANET and SWMM ``.inp`` input files. - -mikeio1d reads only the binary result formats, so the ``.inp`` that accompanies a -result file has to be parsed here. Both products use the same layout: bracketed -section headers, ``;``-prefixed comments (including the ``;;Name Node1 ...`` -column headers the products write), whitespace-delimited data rows, and blank -lines to ignore. - -Only the sections modelskill needs are interpreted; everything else is kept as -raw fields for a caller to use, or ignored. -""" - -from __future__ import annotations - -from pathlib import Path - - -def read_sections(path: str | Path) -> dict[str, list[list[str]]]: - """Parse an ``.inp`` file into its sections. - - Parameters - ---------- - path : str or Path - Path to an EPANET or SWMM ``.inp`` file. - - Returns - ------- - dict[str, list[list[str]]] - Section name (upper case, without brackets) mapped to its data rows, - each row split into whitespace-delimited fields. Comment-only and blank - lines are dropped, as is any trailing comment on a data row. - - Examples - -------- - >>> sections = read_sections("model.inp") # doctest: +SKIP - >>> sections["PIPES"][0] # doctest: +SKIP - ['10', '10', '11', '3209.544', '304.8', '100', '0', 'Open'] - """ - sections: dict[str, list[list[str]]] = {} - current: list[list[str]] | None = None - - with open(path, "r", encoding="utf-8", errors="replace") as f: - for line in f: - # A comment can trail a data row, so strip it before anything else. - line = line.split(";", 1)[0].strip() - if not line: - continue - - if line.startswith("["): - name = line.strip("[]").strip().upper() - current = sections.setdefault(name, []) - continue - - if current is not None: - current.append(line.split()) - - return sections - - -def read_pipe_lengths(path: str | Path) -> dict[str, float]: - """Read reach lengths from the ``[PIPES]`` section of an EPANET ``.inp``. - - Parameters - ---------- - path : str or Path - Path to an EPANET ``.inp`` file. - - Returns - ------- - dict[str, float] - Pipe ID mapped to its length. Pumps and valves are links too, but carry - no length, so they are absent from the result rather than present with a - placeholder. - - Raises - ------ - ValueError - If the file has no ``[PIPES]`` section, or a row there has too few - fields to read a length from. - - Notes - ----- - ``[PIPES]`` rows are ``ID Node1 Node2 Length Diameter Roughness ...``, so the - length is the fourth field. The units are whatever the model declares in - ``[OPTIONS]``; no conversion is applied. - """ - sections = read_sections(path) - - try: - rows = sections["PIPES"] - except KeyError: - raise ValueError( - f"'{path}' has no [PIPES] section, so it does not look like an " - "EPANET input file. Available sections: " - f"{sorted(sections)}." - ) - - _ID, _LENGTH = 0, 3 - lengths: dict[str, float] = {} - for row in rows: - if len(row) <= _LENGTH: - raise ValueError( - f"Cannot read a pipe length from [PIPES] row {' '.join(row)!r} " - f"in '{path}': expected at least {_LENGTH + 1} fields " - f"(ID, Node1, Node2, Length), got {len(row)}." - ) - lengths[row[_ID]] = float(row[_LENGTH]) - - return lengths diff --git a/src/modelskill/model/adapters/_res1d.py b/src/modelskill/model/adapters/_res1d.py index 567f0d498..d6d391da0 100644 --- a/src/modelskill/model/adapters/_res1d.py +++ b/src/modelskill/model/adapters/_res1d.py @@ -13,12 +13,6 @@ def _simplify_colnames(node: ResultNode | ResultGridPoint) -> pd.DataFrame: # We remove suffixes and indexes so the columns contain only the quantity names - # Some formats keep no timeseries at all on some locations - MIKE 11, for instance, - # stores everything on reach gridpoints, leaving the nodes empty. Asking mikeio1d - # for a dataframe there raises, so return an empty one instead. - if not node.quantities: - return pd.DataFrame() - # The columns in a Res1D dataframe follow the convention "Quantity:Location:Sublocation" # where Location refers to the node id or the reach id followed by the chainage. RES1D_NAME_SEP = ":" @@ -39,44 +33,6 @@ def _simplify_colnames(node: ResultNode | ResultGridPoint) -> pd.DataFrame: return df.rename(columns=renamer_dict).copy() -def _merge_extra_quantities( - base: pd.DataFrame, extra: pd.DataFrame, *, node_id: str -) -> pd.DataFrame: - """Append a companion file's quantities to a node's frame as extra columns. - - Parameters - ---------- - base : pd.DataFrame - The node's frame from the main result file. - extra : pd.DataFrame - The same node's frame from the companion file, sharing its time index. - node_id : str - Node ID, used in error messages. - - Returns - ------- - pd.DataFrame - - Raises - ------ - ValueError - If a quantity appears in both frames. Concatenating would give the node - two columns of the same name, which is the state ``_simplify_colnames`` - already refuses. - """ - if extra.empty: - return base - - overlapping = base.columns.intersection(extra.columns) - if len(overlapping) > 0: - raise ValueError( - f"Node {node_id!r} already has {sorted(overlapping)} in the main " - "result file, so the companion file's copy cannot be merged in." - ) - - return pd.concat([base, extra], axis=1) - - class Res1DNode(NetworkNode): def __init__( self, @@ -128,18 +84,9 @@ def __init__( end_node: Res1DNode, *, populate_gridpoints: bool = True, - length: float | None = None, ): self._id = reach.name - # Must be checked separately: some formats (.resx) report None for both the - # reach and the node, which the identity checks below would let through. - if reach.start_node is None or reach.end_node is None: - raise ValueError( - f"mikeio1d reported no start/end node for reach {reach.name!r}; " - "this result format's topology cannot be represented as a Network." - ) - if start_node.id != reach.start_node: raise ValueError("Incorrect starting node.") if end_node.id != reach.end_node: @@ -151,14 +98,7 @@ def __init__( self._start = start_node self._end = end_node - - # A length read from a companion input file wins, since mikeio1d has none - # to offer for the formats that need one. Otherwise: mikeio1d returns 0 - # when it cannot read a reach length - link-node models such as EPANET - # report this for every reach. Report it as undefined rather than as a - # zero-length reach, which would make length-weighted graph algorithms - # treat the reach as free. The two cases cannot be told apart upstream. - self._length = length if length is not None else (reach.length or None) + self._length = reach.length self._breakpoints: list[ReachBreakPoint] = [ GridPoint( gridpoint.reach_name, @@ -181,7 +121,7 @@ def end(self) -> Res1DNode: return self._end @property - def length(self) -> float | None: + def length(self) -> float: return self._length @property diff --git a/src/modelskill/model/network.py b/src/modelskill/model/network.py index 328c1cdea..17c62035c 100644 --- a/src/modelskill/model/network.py +++ b/src/modelskill/model/network.py @@ -197,7 +197,7 @@ def _extract_node(self, observation: NodeObservation) -> NodeModelResult: raise ValueError( f"Node {node_id} exists in the network topology but its timeseries was not loaded. " f"Re-create the NetworkModelResult with the relevant nodes populated, " - f"e.g. Network.from_mike(path, nodes=[...])." + f"e.g. Network.from_res1d(nodes=[...])." ) return NodeModelResult( diff --git a/src/modelskill/network.py b/src/modelskill/network.py index 3aff11f48..071bc01f6 100644 --- a/src/modelskill/network.py +++ b/src/modelskill/network.py @@ -30,62 +30,6 @@ from .model.adapters._res1d import Res1DReach -_MIKE_EXTENSIONS = frozenset({".res1d", ".res11"}) -_EPANET_EXTENSIONS = frozenset({".res"}) - -_NO_FIXTURE = ( - "{product} results are not supported yet: modelskill has no test fixture for " - "this format, so support cannot be verified. Please open an issue if you need it." -) -# A result file that holds timeseries but no topology of its own. The connectivity -# is in a companion file we do not parse yet. -_TOPOLOGY_IN_COMPANION_FILE = ( - "SWMM '.out' files carry no reach connectivity of their own - it lives in the " - "companion '.inp' input file, which modelskill does not read yet. Tracked in " - "https://github.com/DHI/modelskill/issues/689." -) -# A companion result file: readable, but it describes a network defined elsewhere. -_COMPANION_RESULT_FILE = ( - "'.resx' holds extra EPANET results (tank volume, pump energy) for a network " - "defined in the sibling '.res' file, so it has no topology of its own. Read the " - "'.res' file and pass this one alongside it: " - "Network.from_epanet(res, resx=...)." -) - -# extension -> why modelskill will not read it, even though mikeio1d can -_UNSUPPORTED_EXTENSIONS: dict[str, str] = { - ".out": _TOPOLOGY_IN_COMPANION_FILE, - ".resx": _COMPANION_RESULT_FILE, - ".prf": _NO_FIXTURE.format(product="MOUSE"), - ".crf": _NO_FIXTURE.format(product="MOUSE"), - ".xrf": _NO_FIXTURE.format(product="MOUSE"), - ".whr": _NO_FIXTURE.format(product="Water Hammer"), -} - -# extension -> the constructor that reads it, for "use X instead" errors -_EXTENSION_CONSTRUCTORS: dict[str, str] = { - **{extension: "from_mike" for extension in _MIKE_EXTENSIONS}, - **{extension: "from_epanet" for extension in _EPANET_EXTENSIONS}, -} - - -def _check_file_path_is_str(res: Res1D) -> None: - """Reject a Res1D opened with a path object rather than a string. - - mikeio1d resolves reach topology with ``str.endswith`` on - ``Res1D.file_path``, which raises ``AttributeError`` from deep inside the - load when that attribute is a ``Path``. Fail here instead, where the cause - can be named. - """ - file_path = getattr(res, "file_path", None) - if file_path is not None and not isinstance(file_path, str): - raise TypeError( - f"This Res1D was opened with a {type(file_path).__name__} file_path, " - "which mikeio1d cannot resolve reach topology from. Re-open it as " - "Res1D(str(path)), or pass the path to the constructor directly." - ) - - class NetworkNode(ABC): """Abstract base class for a node in a network. @@ -185,7 +129,7 @@ def data(self) -> pd.DataFrame: @property def distance(self) -> float: - """Along-reach distance of this break point, measured from the start node.""" + """Along-reach distance of this break point (same units as :attr:`NetworkReach.length`).""" return self.id[1] @property @@ -202,31 +146,30 @@ class NetworkReach(ABC): a list of :class:`ReachBreakPoint` objects for intermediate chainage locations. - Subclass this to integrate your own network topology. Four properties + Subclass this to integrate your own network topology. Five properties must be implemented: * :attr:`id` - a unique string identifier for the reach. * :attr:`start` - the upstream/start :class:`NetworkNode`. * :attr:`end` - the downstream/end :class:`NetworkNode`. + * :attr:`length` - total reach length (in the units of your coordinate + system). * :attr:`breakpoints` - list of :class:`ReachBreakPoint` instances ordered by increasing distance from the start node (empty list if none). - :attr:`length` is optional and defaults to ``None``. Reach length matters - in some domains (rivers, sewer networks) and not in others (link-node water - distribution models), so override it only where a length exists. - The concrete helper :class:`BasicReach` is provided for the common case where all data is already available in memory. Examples -------- - Minimal subclass, without a length: + Minimal subclass: >>> class MyReach(NetworkReach): - ... def __init__(self, rid, start_node, end_node): + ... def __init__(self, rid, start_node, end_node, length): ... self._id = rid ... self._start = start_node ... self._end = end_node + ... self._length = length ... @property ... def id(self): return self._id ... @property @@ -234,16 +177,9 @@ class NetworkReach(ABC): ... @property ... def end(self): return self._end ... @property - ... def breakpoints(self): return [] - - Add a :attr:`length` property on top of that when the domain has one: - - >>> class MyMeasuredReach(MyReach): - ... def __init__(self, rid, start_node, end_node, length): - ... super().__init__(rid, start_node, end_node) - ... self._length = length - ... @property ... def length(self): return self._length + ... @property + ... def breakpoints(self): return [] See Also -------- @@ -272,9 +208,10 @@ def end(self) -> NetworkNode: pass @property - def length(self) -> float | None: - """Total length of this reach in network units, or ``None`` if undefined.""" - return None + @abstractmethod + def length(self) -> float: + """Total length of this reach in network units.""" + pass @property @abstractmethod @@ -341,18 +278,14 @@ class BasicReach(NetworkReach): Start node. end : NetworkNode End node. - length : float, optional - Reach length, by default None (undefined). + length : float + Reach length. breakpoints : list[ReachBreakPoint], optional Intermediate break points, by default empty. Examples -------- >>> reach = BasicReach("reach_1", node_a, node_b, length=250.0) - - Where the domain has no reach length, leave it out: - - >>> reach = BasicReach("pipe_1", node_a, node_b) """ def __init__( @@ -360,7 +293,7 @@ def __init__( id: str, start: NetworkNode, end: NetworkNode, - length: float | None = None, + length: float, breakpoints: list[ReachBreakPoint] | None = None, ) -> None: self._id = id @@ -382,7 +315,7 @@ def end(self) -> NetworkNode: return self._end @property - def length(self) -> float | None: + def length(self) -> float: return self._length @property @@ -416,20 +349,19 @@ def __repr__(self) -> str: return "\n".join(out) @classmethod - def from_mike( + def from_res1d( cls, res: str | Path | Res1D, *, nodes: str | list[str] | None = None, reaches: str | list[str] | None = None, ) -> Network: - """Create a Network from a MIKE 1D or MIKE 11 result file. + """Create a Network from a Res1D file or object. Parameters ---------- res : str, Path or Res1D - Path to a ``.res1d`` or ``.res11`` file, or an already-opened - :class:`mikeio1d.Res1D` object. + Path to a .res1d file, or an already-opened :class:`mikeio1d.Res1D` object. nodes : str, list of str, or None, optional Controls which nodes have their timeseries data loaded into memory. @@ -453,24 +385,17 @@ def from_mike( ------- Network - Raises - ------ - NotImplementedError - If the file extension is not one modelskill can read. - ValueError - If the extension belongs to another constructor, such as EPANET. - Examples -------- Load everything (default behaviour): >>> from modelskill.network import Network - >>> network = Network.from_mike("model.res1d") + >>> network = Network.from_res1d("model.res1d") Load data only for the two nodes where observations exist, and skip all intermediate gridpoint data to keep memory usage low: - >>> network = Network.from_mike( + >>> network = Network.from_res1d( ... "model.res1d", ... nodes=["node_a", "node_b"], ... reaches=[], @@ -478,155 +403,13 @@ def from_mike( Load data for selected nodes and gridpoints for one specific reach: - >>> network = Network.from_mike( + >>> network = Network.from_res1d( ... "model.res1d", ... nodes=["node_a", "node_b"], ... reaches=["reach_1"], ... ) - - Notes - ----- - MIKE 11 keeps its timeseries on reach gridpoints rather than on nodes, - so the nodes of a ``.res11`` network carry no data of their own. Pass - ``reaches`` rather than ``nodes`` to control what gets loaded. - - See Also - -------- - from_epanet : Read an EPANET result file. - """ - return cls._from_mikeio1d( - res, - nodes=nodes, - reaches=reaches, - allowed=_MIKE_EXTENSIONS, - caller="from_mike", - ) - - @classmethod - def from_epanet( - cls, - res: str | Path | Res1D, - *, - resx: str | Path | Res1D | None = None, - inp: str | Path | None = None, - nodes: str | list[str] | None = None, - reaches: str | list[str] | None = None, - ) -> Network: - """Create a Network from an EPANET result file and its companions. - - An EPANET run writes up to three files that modelskill can use. The - ``.res`` holds the network and its main timeseries; the optional - ``.resx`` holds extra results; and the optional ``.inp`` is the input - file, which is the only one of the three carrying reach lengths. - - Parameters - ---------- - res : str, Path or Res1D - Path to a ``.res`` file, or an already-opened - :class:`mikeio1d.Res1D` object. - resx : str, Path, Res1D or None, optional - Companion ``.resx`` file from the same run. Its extra node - quantities (tank ``Volume`` and ``Volume Percentage``) are merged - onto the matching nodes. By default None, and those quantities are - simply absent. - inp : str, Path or None, optional - EPANET ``.inp`` input file for the same model, read for its - ``[PIPES]`` lengths. By default None, and reach lengths are - undefined. - nodes : str, list of str, or None, optional - Which nodes get their timeseries loaded. See :meth:`from_mike`. - reaches : str, list of str, or None, optional - Which reaches get their gridpoint data loaded. See - :meth:`from_mike`. EPANET results have no intermediate gridpoints, - so this argument has no effect. - - Returns - ------- - Network - - Raises - ------ - NotImplementedError - If the file extension is not one modelskill can read. - ValueError - If the extension belongs to another constructor, such as MIKE, if a - companion file has the wrong extension, or if ``resx`` does not come - from the same run as ``res``. - - Examples - -------- - >>> from modelskill.network import Network - >>> network = Network.from_epanet("model.res") - - With both companions, for real edge lengths and the extra quantities: - - >>> network = Network.from_epanet( - ... "model.res", - ... resx="model.resx", - ... inp="model.inp", - ... ) - - Notes - ----- - EPANET is a link-node model, and mikeio1d reports no length and a - single synthetic gridpoint for each of its reaches. As a result: - - * without ``inp``, every edge of :attr:`graph` has ``length=None``, so a - length-weighted graph algorithm fails rather than returning a - meaningless number. Pumps and valves keep ``length=None`` even with - ``inp``, since ``[PIPES]`` is the only section carrying lengths - * reaches have no breakpoints, so - :class:`~modelskill.obs.ReachObservation` cannot be matched against - an EPANET network — use :class:`~modelskill.obs.NodeObservation` - * ``find(reach=..., distance=)`` never resolves; only - ``distance="start"`` and ``distance="end"`` work - - For the same reason, ``resx`` merges node quantities only. Its - reach-level quantities (pump energy, efficiency and costs) have no - breakpoint to live on, which is tracked in issue #680. - - Node timeseries, :meth:`to_dataframe`, :meth:`to_dataset`, - ``find(node=...)`` and :meth:`recall` are unaffected. - - See Also - -------- - from_mike : Read a MIKE 1D or MIKE 11 result file. """ - return cls._from_mikeio1d( - res, - nodes=nodes, - reaches=reaches, - allowed=_EPANET_EXTENSIONS, - caller="from_epanet", - resx=resx, - inp=inp, - ) - @classmethod - def _from_mikeio1d( - cls, - res: str | Path | Res1D, - *, - nodes: str | list[str] | None, - reaches: str | list[str] | None, - allowed: frozenset[str], - caller: str, - resx: str | Path | Res1D | None = None, - inp: str | Path | None = None, - ) -> Network: - """Shared implementation behind the public ``from_*`` constructors. - - Parameters - ---------- - allowed : frozenset of str - Extensions this constructor accepts. - caller : str - Name of the public method, used in error messages. - resx : str, Path, Res1D or None, optional - Companion result file whose node quantities are merged in. - inp : str, Path or None, optional - Companion input file read for reach lengths. - """ if sys.version_info >= (3, 14): raise NotImplementedError( f"Current version of 'mikeio1d' requires python < 3.14 and {sys.version} is being used." @@ -636,13 +419,12 @@ def _from_mikeio1d( if isinstance(res, (str, Path)): path = Path(res) - cls._validate_extension(path.suffix, allowed=allowed, caller=caller) + if path.suffix.lower() != ".res1d": + raise NotImplementedError( + f"Unsupported file extension '{path.suffix}'. Only .res1d files are supported." + ) res = _Res1D(str(path)) - elif isinstance(res, _Res1D): - _check_file_path_is_str(res) - suffix = Path(res.file_path).suffix - cls._validate_extension(suffix, allowed=allowed, caller=caller) - else: + elif not isinstance(res, _Res1D): raise TypeError( f"Expected a str, Path or Res1D object, got {type(res).__name__!r}" ) @@ -661,144 +443,22 @@ def _from_mikeio1d( else: reaches_list = list(reaches) - extra = None if resx is None else cls._open_companion_result(res, resx) - lengths = None if inp is None else cls._read_companion_lengths(inp) - - list_of_reaches = cls._load_res1d_network( - res, nodes_list, reaches_list, extra=extra, lengths=lengths - ) + list_of_reaches = cls._load_res1d_network(res, nodes_list, reaches_list) return cls(list_of_reaches) - - @staticmethod - def _read_companion_lengths(inp: str | Path) -> dict[str, float]: - """Read reach lengths from a companion ``.inp`` input file.""" - from modelskill.model.adapters._inp import read_pipe_lengths - - path = Path(inp) - if path.suffix.lower() != ".inp": - raise ValueError( - f"Expected an EPANET '.inp' input file, got '{path.suffix}'. " - "This argument reads reach lengths from the model input, not " - "from a result file." - ) - return read_pipe_lengths(path) - - @staticmethod - def _open_companion_result(res: Res1D, resx: str | Path | Res1D) -> Res1D: - """Open and validate a companion ``.resx`` result file. - - Raises - ------ - ValueError - If the extension is not ``.resx``, or if the file does not come from - the same run as ``res``. - """ - from mikeio1d import Res1D as _Res1D - - if isinstance(resx, (str, Path)): - path = Path(resx) - if path.suffix.lower() != ".resx": - raise ValueError( - f"Expected an EPANET '.resx' companion file, got '{path.suffix}'." - ) - extra = _Res1D(str(path)) - elif isinstance(resx, _Res1D): - _check_file_path_is_str(resx) - if Path(resx.file_path).suffix.lower() != ".resx": - raise ValueError( - "Expected an EPANET '.resx' companion file, got " - f"'{Path(resx.file_path).suffix}'." - ) - extra = resx - else: - raise TypeError( - f"Expected a str, Path or Res1D object, got {type(resx).__name__!r}" - ) - - # Merging two different runs would line up silently and produce a network - # that is wrong in a way no later error would reveal. - if not res.time_index.equals(extra.time_index): - raise ValueError( - "The '.resx' companion does not share a time axis with the " - "'.res' file, so the two are not from the same run. Got " - f"{len(extra.time_index)} steps ending {extra.end_time} against " - f"{len(res.time_index)} ending {res.end_time}." - ) - - unknown = set(extra.nodes) - set(res.nodes) - if unknown: - raise ValueError( - f"The '.resx' companion holds nodes {sorted(unknown)} that are " - "absent from the '.res' network, so the two files do not describe " - "the same model." - ) - - return extra - - @staticmethod - def _validate_extension( - suffix: str, *, allowed: frozenset[str], caller: str - ) -> None: - """Check a file extension against mikeio1d and against one constructor. - - Raises - ------ - NotImplementedError - If modelskill cannot read the extension, either because mikeio1d - does not support it or because modelskill does not. - ValueError - If another constructor is the one that reads this extension. - """ - from mikeio1d import Res1D as _Res1D - - extension = suffix.lower() - - # Checked before the supported set below, since these all *are* readable - # by mikeio1d - it is modelskill that cannot use the result. - reason = _UNSUPPORTED_EXTENSIONS.get(extension) - if reason is not None: - raise NotImplementedError(f"Cannot read '{suffix}' files. {reason}") - - supported = _Res1D.get_supported_file_extensions() - if extension not in supported: - readable = sorted(supported - set(_UNSUPPORTED_EXTENSIONS)) - raise NotImplementedError( - f"Unsupported file extension '{suffix}'. " - f"Supported extensions are {readable}." - ) - - if extension not in allowed: - constructor = _EXTENSION_CONSTRUCTORS.get(extension) - if constructor is None: - raise NotImplementedError( - f"File extension '{suffix}' is supported by mikeio1d but is not mapped " - "to a Network constructor in this version of modelskill. " - "Please upgrade modelskill or open an issue." - ) - raise ValueError( - f"Network.{caller}() reads {sorted(allowed)} files, got '{suffix}'. " - f"Use Network.{constructor}() instead." - ) - @staticmethod def _load_res1d_network( res: Res1D, nodes: list[str], reaches: list[str], - *, - extra: Res1D | None = None, - lengths: dict[str, float] | None = None, ) -> list[Res1DReach]: from modelskill.model.adapters._res1d import ( Res1DReach, Res1DNode, - _merge_extra_quantities, _simplify_colnames, ) nodes_set = set(nodes) reaches_set = set(reaches) - lengths = lengths or {} # In order to work with bigger files, we might want to select a subset of nodes and avoid # potential memory issues. For this reason, we create this intermediate step that populates @@ -810,12 +470,6 @@ def _init_node(reach: ResultReach, is_end: bool) -> Res1DNode: if id in nodes_set: node = res.nodes[id] df = _simplify_colnames(node) - # Merged here rather than up front so selective loading still - # decides what is held in memory. - if extra is not None and id in extra.nodes: - df = _merge_extra_quantities( - df, _simplify_colnames(extra.nodes[id]), node_id=id - ) overlapping_gridpoint = reach.gridpoints[gpt_idx] boundary = _simplify_colnames(overlapping_gridpoint) return Res1DNode(id, data=df, boundary={reach.name: boundary}) @@ -828,7 +482,6 @@ def _init_node(reach: ResultReach, is_end: bool) -> Res1DNode: _init_node(reach, False), _init_node(reach, True), populate_gridpoints=reach.name in reaches_set, - length=lengths.get(reach.name), ) for reach in res.reaches.values() ] @@ -838,9 +491,7 @@ def _generate_alias_map(g: nx.Graph) -> dict[str | tuple[str, float], int]: return {g.nodes[id]["alias"]: id for id in g.nodes()} @staticmethod - def _generate_reaches_dict( - reaches: Sequence[NetworkReach], - ) -> dict[str, NetworkReach]: + def _generate_reaches_dict(reaches: Sequence[NetworkReach]) -> dict[str, NetworkReach]: return {r.id: r for r in reaches} @staticmethod @@ -934,17 +585,11 @@ def _generate_graph(reaches: Sequence[NetworkReach]) -> nx.Graph: g0.add_node(bp_key, data=bp.data) g0.add_edge(start_key, bp_keys[0], length=reach.breakpoints[0].distance) - - # Only the final segment needs the total length. Break point - # distances are known even when the total is not, so a reach - # without a length still gets real lengths on every edge but - # this one. - tail_length = ( - None - if reach.length is None - else reach.length - reach.breakpoints[-1].distance + g0.add_edge( + bp_keys[-1], + end_key, + length=reach.length - reach.breakpoints[-1].distance, ) - g0.add_edge(bp_keys[-1], end_key, length=tail_length) # 3) Connect consecutive intermediate breakpoints for i in range(reach.n_breakpoints - 1): diff --git a/tests/notebooks/test_notebooks.py b/tests/notebooks/test_notebooks.py index 8b6fd62dc..e44be8975 100644 --- a/tests/notebooks/test_notebooks.py +++ b/tests/notebooks/test_notebooks.py @@ -8,7 +8,7 @@ _TEST_DIR = os.path.dirname(os.path.abspath(__file__)) PARENT_DIR = os.path.join(_TEST_DIR, "../..") SKIP_LIST = ["Download", "Metocean_track_comparison_global", "Metrics_widget", "Collection_systems_network"] -# We skip Collection_systems_network.ipynb since it uses Network.from_mike() which uses pythonnet and, currently, it does not support python 3.14 +# We skip Collection_systems_network.ipynb since it uses Network.from_res1d() which uses pythonnet and, currently, it does not support python 3.14 def _process_notebook(notebook_filename, notebook_path="notebooks"): diff --git a/tests/test_network.py b/tests/test_network.py index 150f043ba..931860102 100644 --- a/tests/test_network.py +++ b/tests/test_network.py @@ -2,7 +2,6 @@ # ruff: noqa: E402 import sys -from pathlib import Path import pytest pytest.importorskip("networkx") @@ -15,21 +14,10 @@ NetworkModelResult, NodeModelResult, ) -from modelskill.model.adapters._inp import read_pipe_lengths, read_sections -from modelskill.model.adapters._res1d import ( - Res1DNode, - Res1DReach, - _simplify_colnames, -) from modelskill.network import ( Network, BasicNode, BasicReach, - NetworkReach, - ReachBreakPoint, - _EPANET_EXTENSIONS, - _MIKE_EXTENSIONS, - _UNSUPPORTED_EXTENSIONS, ) from modelskill.obs import NodeObservation from modelskill.quantity import Quantity @@ -212,8 +200,7 @@ def test_extract_wrong_observation_type(self, sample_network): obs = ms.PointObservation(df, x=0.0, y=0.0) with pytest.raises( - TypeError, - match="NetworkModelResult supports NodeObservation and ReachObservation", + TypeError, match="NetworkModelResult supports NodeObservation and ReachObservation" ): nmr.extract(obs) @@ -455,7 +442,7 @@ def test_matching_workflow_multiple_nodes(self, sample_network, sample_node_data ) def test_open_res1d(): path_to_file = "./tests/testdata/network.res1d" - network = Network.from_mike(path_to_file) + network = Network.from_res1d(path_to_file) assert network.graph.number_of_nodes() == 259 @@ -464,7 +451,7 @@ def test_open_res1d(): ) def test_extract_reach_observation_happy_path(sample_node_data): path_to_file = "./tests/testdata/network.res1d" - network = Network.from_mike(path_to_file) + network = Network.from_res1d(path_to_file) nmr = NetworkModelResult(network, item="Discharge", name="network_model") obs_data = sample_node_data.rename(columns={"WaterLevel": "Discharge"}) obs = ms.ReachObservation(obs_data, reach="100l1", item="Discharge") @@ -481,12 +468,14 @@ def test_extract_reach_observation_happy_path(sample_node_data): ) def test_extract_reach_observation_non_equivalent_breakpoints_raises(sample_node_data): path_to_file = "./tests/testdata/network.res1d" - network = Network.from_mike(path_to_file) + network = Network.from_res1d(path_to_file) nmr = NetworkModelResult(network, item="Discharge") obs_data = sample_node_data.rename(columns={"WaterLevel": "Discharge"}) obs = ms.ReachObservation(obs_data, reach="113l1", item="Discharge") - with pytest.raises(ValueError, match="Not all data in breakpoints are equivalent"): + with pytest.raises( + ValueError, match="Not all data in breakpoints are equivalent" + ): nmr.extract(obs) @@ -497,7 +486,7 @@ def test_extract_reach_observation_with_reaches_not_populated_raises_valueerror( sample_node_data, ): path_to_file = "./tests/testdata/network.res1d" - network = Network.from_mike(path_to_file, reaches=[]) + network = Network.from_res1d(path_to_file, reaches=[]) nmr = NetworkModelResult(network, item="WaterLevel") obs = ms.ReachObservation(sample_node_data, reach="100l1", item="WaterLevel") @@ -512,7 +501,7 @@ def test_extract_reach_observation_breakpoint_node_missing_raises_valueerror( sample_node_data, ): path_to_file = "./tests/testdata/network.res1d" - network = Network.from_mike(path_to_file) + network = Network.from_res1d(path_to_file) nmr = NetworkModelResult(network, item="Discharge") obs_data = sample_node_data.rename(columns={"WaterLevel": "Discharge"}) baseline_obs = ms.ReachObservation(obs_data, reach="100l1", item="Discharge") @@ -533,13 +522,13 @@ def test_extract_reach_observation_breakpoint_node_missing_raises_valueerror( @pytest.mark.skipif( sys.version_info >= (3, 14), reason="mikeio1d requires Python < 3.14" ) -def test_from_mike_nodes_filter_creates_full_network(): +def test_from_res1d_nodes_filter_creates_full_network(): """When nodes is specified, the full network topology is created.""" path_to_file = "./tests/testdata/network.res1d" - full_network = Network.from_mike(path_to_file) + full_network = Network.from_res1d(path_to_file) selected_nodes = ["1", "108"] - partial_network = Network.from_mike(path_to_file, nodes=selected_nodes) + partial_network = Network.from_res1d(path_to_file, nodes=selected_nodes) # Full topology is preserved assert ( @@ -550,12 +539,12 @@ def test_from_mike_nodes_filter_creates_full_network(): @pytest.mark.skipif( sys.version_info >= (3, 14), reason="mikeio1d requires Python < 3.14" ) -def test_from_mike_nodes_filter_only_selected_have_data(): +def test_from_res1d_nodes_filter_only_selected_have_data(): """When nodes is specified, only selected nodes contain non-empty data.""" path_to_file = "./tests/testdata/network.res1d" selected_nodes = ["1", "108"] - network = Network.from_mike(path_to_file, nodes=selected_nodes, reaches=[]) + network = Network.from_res1d(path_to_file, nodes=selected_nodes, reaches=[]) g = network.graph.copy() n_nodes = network.graph.number_of_nodes() @@ -567,12 +556,12 @@ def test_from_mike_nodes_filter_only_selected_have_data(): @pytest.mark.skipif( sys.version_info >= (3, 14), reason="mikeio1d requires Python < 3.14" ) -def test_from_mike_nodes_single_string(): +def test_from_res1d_nodes_single_string(): """nodes argument accepts a single string (not just a list).""" path_to_file = "./tests/testdata/network.res1d" - full_network = Network.from_mike(path_to_file) + full_network = Network.from_res1d(path_to_file) - network = Network.from_mike(path_to_file, nodes="108", reaches=[]) + network = Network.from_res1d(path_to_file, nodes="108", reaches=[]) g = network.graph.copy() assert g.number_of_nodes() == full_network.graph.number_of_nodes() @@ -589,7 +578,7 @@ def test_dataframe_from_partial_network(): """nodes argument accepts a single string (not just a list).""" path_to_file = "./tests/testdata/network.res1d" selected_nodes = ["108", "101"] - network = Network.from_mike(path_to_file, nodes=selected_nodes, reaches=[]) + network = Network.from_res1d(path_to_file, nodes=selected_nodes, reaches=[]) nodes_in_df = network.to_dataframe().droplevel(axis=1, level=1).columns assert set(nodes_in_df) == set([network.find(n) for n in selected_nodes]) @@ -598,10 +587,10 @@ def test_dataframe_from_partial_network(): @pytest.mark.skipif( sys.version_info >= (3, 14), reason="mikeio1d requires Python < 3.14" ) -def test_from_mike_empty_nodes_and_reaches_keeps_topology_and_empty_outputs(): +def test_from_res1d_empty_nodes_and_reaches_keeps_topology_and_empty_outputs(): path_to_file = "./tests/testdata/network.res1d" - full_network = Network.from_mike(path_to_file) - network = Network.from_mike(path_to_file, nodes=[], reaches=[]) + full_network = Network.from_res1d(path_to_file) + network = Network.from_res1d(path_to_file, nodes=[], reaches=[]) assert network.graph.number_of_nodes() == full_network.graph.number_of_nodes() @@ -616,181 +605,6 @@ def test_from_mike_empty_nodes_and_reaches_keeps_topology_and_empty_outputs(): assert len(ds.data_vars) == 0 -# --------------------------------------------------------------------------- -# Optional reach length -# --------------------------------------------------------------------------- - - -class _StubBreakPoint(ReachBreakPoint): - """Minimal concrete ReachBreakPoint for building reaches by hand.""" - - def __init__(self, reach_id, distance, data=None): - self._id = (reach_id, distance) - self._data = pd.DataFrame() if data is None else data - - @property - def id(self): - return self._id - - @property - def data(self): - return self._data - - -def _two_node_pair(): - time = pd.date_range("2020", periods=3, freq="h") - df = pd.DataFrame({"WaterLevel": [1.0, 1.1, 1.2]}, index=time) - return BasicNode("a", df), BasicNode("b", df.copy()) - - -class TestOptionalReachLength: - """Reach length is undefined in some domains, so it must be omittable.""" - - def test_subclass_may_omit_length(self): - class LengthlessReach(NetworkReach): - def __init__(self, id, start, end): - self._id, self._start, self._end = id, start, end - - @property - def id(self): - return self._id - - @property - def start(self): - return self._start - - @property - def end(self): - return self._end - - @property - def breakpoints(self): - return [] - - a, b = _two_node_pair() - reach = LengthlessReach("r1", a, b) - - assert reach.length is None - assert Network([reach]).graph.number_of_nodes() == 2 - - def test_basic_reach_length_defaults_to_none(self): - a, b = _two_node_pair() - - assert BasicReach("r1", a, b).length is None - - def test_edge_length_is_none_when_undefined(self): - a, b = _two_node_pair() - - network = Network([BasicReach("r1", a, b)]) - - assert [d["length"] for *_, d in network.graph.edges(data=True)] == [None] - - def test_breakpoint_distances_survive_an_undefined_length(self): - """Only the final segment needs the total, so the rest keep real lengths.""" - a, b = _two_node_pair() - breakpoints = [_StubBreakPoint("r1", d) for d in (30.0, 70.0)] - - network = Network([BasicReach("r1", a, b, breakpoints=breakpoints)]) - - lengths = sorted( - (d["length"] for *_, d in network.graph.edges(data=True)), - key=lambda v: (v is None, v), - ) - assert lengths == [30.0, 40.0, None] - - def test_length_weighted_algorithms_fail_loudly(self): - """Storing None keeps networkx honest. - - Omitting the attribute instead would let networkx default the weight to - 1, so every call below would return a plausible but meaningless number. - With None, shortest-path treats the edge as hidden and the arithmetic - consumers raise. - """ - import networkx as nx - - a, b = _two_node_pair() - g = Network([BasicReach("r1", a, b)]).graph - - with pytest.raises(nx.NetworkXNoPath): - nx.shortest_path_length(g, 0, 1, weight="length") - - with pytest.raises(TypeError): - g.size(weight="length") - - def test_known_length_is_unchanged(self): - a, b = _two_node_pair() - breakpoints = [_StubBreakPoint("r1", 40.0)] - - network = Network([BasicReach("r1", a, b, 100.0, breakpoints)]) - - assert sorted(d["length"] for *_, d in network.graph.edges(data=True)) == [ - 40.0, - 60.0, - ] - - -# --------------------------------------------------------------------------- -# Which extensions each constructor accepts, and why the rest are refused -# --------------------------------------------------------------------------- - - -@pytest.mark.skipif( - sys.version_info >= (3, 14), reason="mikeio1d requires Python < 3.14" -) -class TestExtensionPolicy: - @pytest.mark.parametrize("suffix", [".res1d", ".res11", ".RES1D"]) - def test_from_mike_accepts_mike_extensions(self, tmp_path, suffix): - """The file does not exist, so mikeio1d - not the guard - is what complains.""" - with pytest.raises((FileExistsError, FileNotFoundError)): - Network.from_mike(tmp_path / f"network{suffix}") - - def test_error_lists_only_readable_extensions(self): - with pytest.raises(NotImplementedError) as excinfo: - Network.from_mike("network.nc") - - message = str(excinfo.value) - for extension in _MIKE_EXTENSIONS | _EPANET_EXTENSIONS: - assert extension in message - for extension in _UNSUPPORTED_EXTENSIONS: - assert extension not in message - - def test_swmm_refusal_names_the_companion_inp(self): - """A real file, so this fails the day SWMM support lands.""" - with pytest.raises(NotImplementedError, match=r"companion '\.inp'"): - Network.from_mike("./tests/testdata/swmm.out") - - def test_resx_refusal_points_at_the_resx_argument(self): - """'.resx' is a companion, so the message must name what to do instead.""" - with pytest.raises( - NotImplementedError, match=r"from_epanet\(res, resx=\.\.\.\)" - ): - Network.from_mike("./tests/testdata/epanet.resx") - - @pytest.mark.parametrize("suffix", [".prf", ".crf", ".xrf", ".whr"]) - def test_formats_without_a_fixture_are_refused(self, tmp_path, suffix): - with pytest.raises(NotImplementedError, match="no test fixture"): - Network.from_mike(tmp_path / f"network{suffix}") - - def test_every_mikeio1d_extension_is_accounted_for(self): - """A new mikeio1d format must be read or explicitly refused, never ignored.""" - from mikeio1d import Res1D - - accounted_for = ( - _MIKE_EXTENSIONS | _EPANET_EXTENSIONS | set(_UNSUPPORTED_EXTENSIONS) - ) - - assert accounted_for == Res1D.get_supported_file_extensions() - - def test_res1d_opened_with_a_path_is_refused(self): - """mikeio1d calls str.endswith on file_path, so a Path breaks it later on.""" - from mikeio1d import Res1D - - res = Res1D(Path("./tests/testdata/network.res1d")) - - with pytest.raises(TypeError, match="file_path"): - Network.from_mike(res) - - # --------------------------------------------------------------------------- # NodeObservation — alias / breakpoint node forms # --------------------------------------------------------------------------- @@ -971,413 +785,3 @@ def test_match_with_string_alias(self, sample_network, sample_node_data): comparer = ms.match(obs, nmr) assert comparer.n_points > 0 assert "Network_Model" in comparer.mod_names - - -# --------------------------------------------------------------------------- -# Res1D adapter — no mikeio1d required, the adapter is duck-typed -# --------------------------------------------------------------------------- - - -class _StubLocation: - """Stands in for a mikeio1d ResultNode / ResultGridPoint.""" - - def __init__(self, quantities, df=None): - self.quantities = quantities - self._df = df - - def to_dataframe(self): - if self._df is None: - raise AssertionError("to_dataframe() should not be called") - return self._df - - -class TestSimplifyColnames: - def test_location_without_quantities_gives_empty_frame(self): - """MIKE 11 keeps its data on gridpoints, leaving nodes with no quantities.""" - df = _simplify_colnames(_StubLocation(quantities=[])) - - assert df.empty - assert list(df.columns) == [] - - def test_quantity_columns_are_stripped_of_location_suffix(self): - time = pd.date_range("2020", periods=2, freq="h") - raw = pd.DataFrame({"WaterLevel:node_1": [1.0, 2.0]}, index=time) - - df = _simplify_colnames(_StubLocation(quantities=["WaterLevel"], df=raw)) - - assert list(df.columns) == ["WaterLevel"] - - -class _StubReach: - """Stands in for a mikeio1d ResultReach.""" - - def __init__(self, name="r1", start_node="a", end_node="b", length=100.0): - self.name = name - self.start_node = start_node - self.end_node = end_node - self.length = length - self.gridpoints = [] - - -class TestRes1DReachConnectivity: - """Formats that expose no reach connectivity must fail with a clear message.""" - - @pytest.mark.parametrize("missing", ["start_node", "end_node"]) - def test_missing_node_raises(self, missing): - reach = _StubReach(**{missing: None}) - - with pytest.raises(ValueError, match="no start/end node for reach 'r1'"): - Res1DReach(reach, Res1DNode("a"), Res1DNode("b")) - - def test_both_nodes_missing_raises(self): - """.resx reports None for both, which the identity checks alone would allow.""" - reach = _StubReach(start_node=None, end_node=None) - - with pytest.raises(ValueError, match="no start/end node"): - Res1DReach(reach, Res1DNode(None), Res1DNode(None)) # type: ignore[arg-type] - - def test_mismatched_start_node_still_raises(self): - with pytest.raises(ValueError, match="Incorrect starting node"): - Res1DReach(_StubReach(), Res1DNode("wrong"), Res1DNode("b")) - - -class TestRes1DReachLength: - """mikeio1d returns 0 when it cannot read a length; that is not a real zero.""" - - @pytest.mark.parametrize("reported", [0, 0.0]) - def test_zero_becomes_undefined(self, reported): - reach = Res1DReach(_StubReach(length=reported), Res1DNode("a"), Res1DNode("b")) - - assert reach.length is None - - def test_real_length_passes_through(self): - reach = Res1DReach(_StubReach(length=47.5), Res1DNode("a"), Res1DNode("b")) - - assert reach.length == 47.5 - - -# --------------------------------------------------------------------------- -# from_mike / from_epanet -# --------------------------------------------------------------------------- - -requires_mikeio1d = pytest.mark.skipif( - sys.version_info >= (3, 14), reason="mikeio1d requires Python < 3.14" -) - - -@requires_mikeio1d -class TestFromMike: - def test_res1d(self): - network = Network.from_mike("./tests/testdata/network.res1d") - - assert network.graph.number_of_nodes() == 259 - - def test_res11(self): - """MIKE 11 keeps its data on gridpoints, so its nodes are empty.""" - network = Network.from_mike("./tests/testdata/network_cali.res11") - - assert len(network._reaches) == 3 - assert network.graph.number_of_nodes() == 71 - assert set(network.quantities) == {"Discharge", "Water Level"} - assert [r.n_breakpoints for r in network._reaches.values()] == [23, 21, 23] - - def test_res11_reaches_have_real_lengths(self): - network = Network.from_mike("./tests/testdata/network_cali.res11") - - lengths = [d["length"] for *_, d in network.graph.edges(data=True)] - assert all(length > 0 for length in lengths) - - def test_open_res1d_object(self): - from mikeio1d import Res1D - - res = Res1D("./tests/testdata/network.res1d") - - network = Network.from_mike(res, nodes=[], reaches=[]) - - assert network.graph.number_of_nodes() == 259 - - def test_epanet_file_is_redirected(self): - with pytest.raises(ValueError, match=r"Use Network\.from_epanet\(\)"): - Network.from_mike("./tests/testdata/epanet.res") - - def test_unknown_extension(self): - with pytest.raises(NotImplementedError, match="Unsupported file extension"): - Network.from_mike("./tests/testdata/obs.dfs0") - - def test_unsupported_type(self): - with pytest.raises(TypeError, match="Expected a str, Path or Res1D object"): - Network.from_mike(42) # type: ignore[arg-type] - - -@requires_mikeio1d -class TestFromEpanet: - def test_epanet(self): - network = Network.from_epanet("./tests/testdata/epanet.res") - - assert network.graph.number_of_nodes() == 11 - assert len(network._reaches) == 13 - assert set(network.quantities) == { - "Demand", - "Head", - "Pressure", - "WaterQuality", - } - assert not network.to_dataframe().empty - - def test_link_node_reaches_have_no_length_or_breakpoints(self): - """Without inp=, mikeio1d reports neither - documented in the docstring.""" - network = Network.from_epanet("./tests/testdata/epanet.res") - - lengths = [d["length"] for *_, d in network.graph.edges(data=True)] - assert lengths and all(length is None for length in lengths) - assert all(r.n_breakpoints == 0 for r in network._reaches.values()) - - def test_reach_observation_cannot_be_matched(self, sample_node_data): - """Follows from having no breakpoints; also documented in the docstring.""" - network = Network.from_epanet("./tests/testdata/epanet.res") - nmr = NetworkModelResult(network, item="Pressure") - obs = ms.ReachObservation(sample_node_data, reach="10", item="WaterLevel") - - with pytest.raises(ValueError, match="breakpoints"): - nmr.extract(obs) - - def test_mike_file_is_redirected(self): - with pytest.raises(ValueError, match=r"Use Network\.from_mike\(\)"): - Network.from_epanet("./tests/testdata/network.res1d") - - def test_open_res1d_object_is_validated(self): - from mikeio1d import Res1D - - res = Res1D("./tests/testdata/network.res1d") - - with pytest.raises(ValueError, match=r"Use Network\.from_mike\(\)"): - Network.from_epanet(res) - - @pytest.mark.parametrize("suffix", [".res", ".RES"]) - def test_extension_is_case_insensitive(self, tmp_path, suffix): - with pytest.raises((FileExistsError, FileNotFoundError)): - Network.from_epanet(tmp_path / f"network{suffix}") - - -# --------------------------------------------------------------------------- -# EPANET companion files: .inp for reach lengths, .resx for extra quantities -# --------------------------------------------------------------------------- - -_EPANET_RES = "./tests/testdata/epanet.res" -_EPANET_RESX = "./tests/testdata/epanet.resx" -_EPANET_INP = "./tests/testdata/epanet.inp" - -# The 12 [PIPES] entries; reach "9" is the pump, which carries no length. -_PUMP_REACH = "9" - - -@requires_mikeio1d -class TestEpanetCompanionInp: - """`.inp` is the only one of the three files carrying reach lengths.""" - - def test_pipe_reaches_get_real_lengths(self): - network = Network.from_epanet(_EPANET_RES, inp=_EPANET_INP) - - lengths = {r.id: r.length for r in network._reaches.values()} - assert lengths["10"] == pytest.approx(3209.544) - assert lengths["110"] == pytest.approx(60.96) - - def test_pump_reach_stays_undefined(self): - """[PIPES] is the only section with lengths, so pumps keep None.""" - network = Network.from_epanet(_EPANET_RES, inp=_EPANET_INP) - - lengths = {r.id: r.length for r in network._reaches.values()} - assert lengths[_PUMP_REACH] is None - assert sum(v is None for v in lengths.values()) == 1 - - def test_graph_edges_carry_the_lengths(self): - network = Network.from_epanet(_EPANET_RES, inp=_EPANET_INP) - - lengths = [d["length"] for *_, d in network.graph.edges(data=True)] - assert sum(v is not None for v in lengths) == 12 - - def test_node_ids_overlapping_reach_ids_are_not_confused(self): - """Most IDs here name both a node and a reach, e.g. '9', '10', '21'.""" - network = Network.from_epanet(_EPANET_RES, inp=_EPANET_INP) - - assert set(network._reaches) & set(network._alias_map) # they do overlap - # Reach "10" is 3209.544 long; node "10" is untouched by the length map. - assert network._reaches["10"].length == pytest.approx(3209.544) - node_10 = network.find(node="10") - assert "Head" in network.to_dataframe()[node_10].columns - - def test_wrong_suffix_is_refused(self): - with pytest.raises(ValueError, match=r"Expected an EPANET '\.inp'"): - Network.from_epanet(_EPANET_RES, inp=_EPANET_RESX) - - def test_file_without_a_pipes_section_is_refused(self, tmp_path): - other = tmp_path / "not-epanet.inp" - other.write_text("[JUNCTIONS]\n;;Name\n9 1000\n") - - with pytest.raises(ValueError, match=r"no \[PIPES\] section"): - Network.from_epanet(_EPANET_RES, inp=other) - - -@requires_mikeio1d -class TestEpanetCompanionResx: - """`.resx` holds extra results for the network defined in the sibling `.res`.""" - - def test_extra_node_quantities_are_merged(self): - network = Network.from_epanet(_EPANET_RES, resx=_EPANET_RESX) - - assert set(network.quantities) == { - "Demand", - "Head", - "Pressure", - "WaterQuality", - "Volume", - "Volume Percentage", - } - - def test_only_the_nodes_present_in_the_resx_gain_them(self): - """The .resx covers the tank and the reservoir, not all eleven nodes.""" - network = Network.from_epanet(_EPANET_RES, resx=_EPANET_RESX) - df = network.to_dataframe() - - with_volume = { - node - for node in df.columns.get_level_values("node").unique() - if "Volume" in df[node].columns - } - # Node IDs are re-indexed to integers, so recall the original labels. - assert {network.recall(node)["node"] for node in with_volume} == {"2", "9"} - - def test_values_come_through(self): - network = Network.from_epanet(_EPANET_RES, resx=_EPANET_RESX) - - reservoir = network.find(node="9") - volume = network.to_dataframe()[(reservoir, "Volume Percentage")] - assert len(volume) == 25 - assert volume.notna().all() - - def test_selective_loading_still_governs_what_is_read(self): - network = Network.from_epanet(_EPANET_RES, resx=_EPANET_RESX, nodes=["2"]) - - df = network.to_dataframe() - tank = network.find(node="2") - assert set(df.columns.get_level_values("node").unique()) == {tank} - assert "Volume" in df[tank].columns - - def test_both_companions_together(self): - network = Network.from_epanet(_EPANET_RES, resx=_EPANET_RESX, inp=_EPANET_INP) - - assert "Volume" in network.quantities - assert network._reaches["10"].length == pytest.approx(3209.544) - - def test_an_open_res1d_object_is_accepted(self): - from mikeio1d import Res1D - - network = Network.from_epanet(_EPANET_RES, resx=Res1D(_EPANET_RESX)) - - assert "Volume" in network.quantities - - def test_wrong_suffix_is_refused(self): - with pytest.raises(ValueError, match=r"Expected an EPANET '\.resx'"): - Network.from_epanet(_EPANET_RES, resx=_EPANET_RES) - - def test_a_result_file_of_another_format_is_refused(self): - from mikeio1d import Res1D - - other = Res1D("./tests/testdata/network.res1d") - - with pytest.raises(ValueError, match=r"Expected an EPANET '\.resx'"): - Network.from_epanet(_EPANET_RES, resx=other) - - def test_a_companion_from_another_run_is_refused(self, monkeypatch): - """Merging two runs would line up silently and give a wrong network.""" - from mikeio1d import Res1D - - res = Res1D(_EPANET_RES) - resx = Res1D(_EPANET_RESX) - shifted = resx.time_index + pd.Timedelta("1D") - - # Both objects share the Res1D class, so shift only this one instance. - original = type(resx).time_index.fget - monkeypatch.setattr( - type(resx), - "time_index", - property(lambda self: shifted if self is resx else original(self)), - ) - - with pytest.raises(ValueError, match="does not share a time axis"): - Network.from_epanet(res, resx=resx) - - def test_a_companion_naming_an_unknown_node_is_refused(self, monkeypatch): - """A node the .res has never heard of means these are different models.""" - from mikeio1d import Res1D - - res = Res1D(_EPANET_RES) - resx = Res1D(_EPANET_RESX) - strangers = dict(resx.nodes) | {"not_in_the_res": None} - - original = type(resx).nodes.fget - monkeypatch.setattr( - type(resx), - "nodes", - property(lambda self: strangers if self is resx else original(self)), - ) - - with pytest.raises(ValueError, match="not_in_the_res"): - Network.from_epanet(res, resx=resx) - - def test_unsupported_type_is_refused(self): - with pytest.raises(TypeError, match="Expected a str, Path or Res1D object"): - Network.from_epanet(_EPANET_RES, resx=42) # type: ignore[arg-type] - - -class TestReadInp: - """Minimal .inp reader - see modelskill/model/adapters/_inp.py.""" - - def _write(self, tmp_path, text): - path = tmp_path / "model.inp" - path.write_text(text) - return path - - def test_sections_are_keyed_without_brackets_and_upper_cased(self, tmp_path): - path = self._write(tmp_path, "[Pipes]\n1 a b 10\n[TANKS]\n2 5\n") - - assert set(read_sections(path)) == {"PIPES", "TANKS"} - - def test_comment_and_blank_lines_are_dropped(self, tmp_path): - path = self._write( - tmp_path, - ";a leading banner\n\n[PIPES]\n" - ";;ID Node1 Node2 Length\n" - ";;-- ----- ----- ------\n" - "1 a b 10\n\n", - ) - - assert read_sections(path) == {"PIPES": [["1", "a", "b", "10"]]} - - def test_trailing_comment_is_stripped_from_a_data_row(self, tmp_path): - path = self._write(tmp_path, "[PIPES]\n1 a b 10 ; the short one\n") - - assert read_sections(path)["PIPES"] == [["1", "a", "b", "10"]] - - def test_rows_before_any_section_are_ignored(self, tmp_path): - path = self._write(tmp_path, "stray row\n[PIPES]\n1 a b 10\n") - - assert read_sections(path) == {"PIPES": [["1", "a", "b", "10"]]} - - def test_lengths_are_read_from_the_fourth_field(self, tmp_path): - path = self._write(tmp_path, "[PIPES]\n1 a b 10.5 300 100\n") - - assert read_pipe_lengths(path) == {"1": 10.5} - - def test_a_short_row_raises_rather_than_dropping_a_length(self, tmp_path): - path = self._write(tmp_path, "[PIPES]\n1 a b\n") - - with pytest.raises(ValueError, match="Cannot read a pipe length"): - read_pipe_lengths(path) - - def test_a_repeated_section_header_accumulates(self, tmp_path): - path = self._write( - tmp_path, "[PIPES]\n1 a b 10\n[TANKS]\n2 5\n[PIPES]\n3 c d 20\n" - ) - - assert read_pipe_lengths(path) == {"1": 10.0, "3": 20.0} diff --git a/tests/testdata/README.md b/tests/testdata/README.md deleted file mode 100644 index a6f4a71c6..000000000 --- a/tests/testdata/README.md +++ /dev/null @@ -1,25 +0,0 @@ -# Test data provenance - -Most files here were produced for modelskill. The exceptions are listed below. - -## From DHI/mikeio1d - -These network files come from -[DHI/mikeio1d](https://github.com/DHI/mikeio1d/tree/main/tests/testdata) -(commit `d937466`), copied unchanged. mikeio1d is MIT-licensed, as is modelskill. - -| File | Format | Used for | -|---|---|---| -| `network_cali.res11` | MIKE 11 | `Network.from_mike` coverage for `.res11` | -| `epanet.res` | EPANET | `Network.from_epanet` coverage | -| `epanet.resx` | EPANET (MIKE+) | the `resx=` companion — extra node quantities merged onto the `.res` network | -| `epanet.inp` | EPANET input | the `inp=` companion — real pipe lengths, which the `.res` does not carry | -| `swmm.out` | SWMM | asserting `.out` is refused — its reach connectivity lives in a companion `.inp` we do not read yet (#689) | - -`epanet.resx` and `epanet.inp` pair with `epanet.res`: same run, same IDs. The -`.resx` node and reach IDs are a strict subset of the `.res` ones, and the `.inp` -`[PIPES]` IDs cover every `.res` reach except the pump. - -`swmm.out` is kept without its `.inp` on purpose. It pins the refusal, so the test -fails the day we add SWMM support or a future mikeio1d starts reporting reach -connectivity for it. diff --git a/tests/testdata/epanet.inp b/tests/testdata/epanet.inp deleted file mode 100644 index 2b42e3a37..000000000 --- a/tests/testdata/epanet.inp +++ /dev/null @@ -1,226 +0,0 @@ -;***************************************************** -;* Generated from MIKE+ * -;***************************************************** - -[TITLE] - -[JUNCTIONS] -;------------------------------------------------------ -;ID Elevation Demand Pattern -;------------------------------------------------------ -10 216.408000 -11 216.408000 -12 213.360000 -13 211.836000 -21 213.360000 -22 211.836000 -23 210.312000 -31 213.360000 -32 216.408000 - -[RESERVOIRS] -;------------------------------------------------------ -;ID Head Pattern -;------------------------------------------------------ -9 243.840000 - -[TANKS] -;--------------------------------------------------------------------------------------------------------- -;ID Elev. Init. Min. Max. Diam. MinVol VolCurve Overflow -; Level Level Level -;--------------------------------------------------------------------------------------------------------- -2 259.080000 36.576000 30.480000 45.720000 15.392400 0.000000 * No - -[PIPES] -;----------------------------------------------------------------- -;ID Head Tail Length Diam Rough. Minor CV -; Node Node -;----------------------------------------------------------------- -10 10 11 3209.544000 457.200000 100.000000 0.000000 -11 11 12 1609.344000 355.600000 100.000000 0.000000 -110 2 12 60.960000 457.200000 100.000000 0.000000 -111 11 21 1609.344000 254.000000 100.000000 0.000000 -112 12 22 1609.344000 304.800000 100.000000 0.000000 -113 13 23 1609.344000 203.200000 100.000000 0.000000 -12 12 13 1609.344000 254.000000 100.000000 0.000000 -121 21 31 1609.344000 203.200000 100.000000 0.000000 -122 22 32 1609.344000 152.400000 100.000000 0.000000 -21 21 22 1609.344000 254.000000 100.000000 0.000000 -22 22 23 1609.344000 304.800000 100.000000 0.000000 -31 31 32 1609.344000 152.400000 100.000000 0.000000 - -[VALVES] -;------------------------------------------------------ -; ID Head Tail Diam Type Setting (Losscoef) -; Node Node -;------------------------------------------------------ - -[PUMPS] -;------------------------------------------------------------------ -;ID Head Tail Properties -; Node Node -;------------------------------------------------------------------ -9 9 10 HEAD 1 - -[VSD_PUMPS] -;------------------------------------------------------------------------------------- -;Pump Node Setpoint Setpoint SetpointType Speed Speed ControlType -;ID ID Value Curve 0/1(pressure/HGL) min max 0/1(downstream node, any node) -;------------------------------------------------------------------------------------- - -[EMITTERS] -;------------------------------------------------------ -; Node Flow Coeff. -; ID -;------------------------------------------------------ - -[DEMANDS] -;------------------------------------------------------------------ -; NodeID Demand Pattern -;------------------------------------------------------------------ -10 0.000000 ;BASE -11 9.463530 ;BASE -12 9.463530 ;BASE -13 6.309020 ;BASE -21 9.463530 ;BASE -22 12.618039 ;BASE -23 9.463530 ;BASE -31 6.309020 ;BASE -32 6.309020 ;BASE - -[PATTERNS] -;ID Multipliers -1 1.000000 -1 1.200000 -1 1.400000 -1 1.600000 -1 1.400000 -1 1.200000 -1 1.000000 -1 0.800000 -1 0.600000 -1 0.400000 -1 0.600000 -1 0.800000 - -[STATUS] -;ID Status/Setting - -[CURVES] -;ID X-Value Y-Value -1 94.635295 76.200000 - -[CONTROLS] -LINK 9 OPEN IF NODE 2 BELOW 33.528000 -LINK 9 CLOSED IF NODE 2 ABOVE 42.672000 - -[RULES] - -[MIXING] -;Tank Model -2 MIXED -9 MIXED - -[QUALITY] -;------------------------------------------------------------------ -;Nodes Initial -;ID quality -;------------------------------------------------------------------ -10 0.500000 -11 0.500000 -12 0.500000 -13 0.500000 -21 0.500000 -22 0.500000 -23 0.500000 -31 0.500000 -32 0.500000 -2 1.000000 -9 1.000000 - -[SOURCES] -;----------------------------------------------- -;NODEID SRCTYPE STRENGTH PATTERN -;----------------------------------------------- - -[REACTIONS] -GLOBAL BULK -0.500000 -GLOBAL WALL -1.000000 -GLOBAL NewBulk 0.000000 0.000000 -ORDER BULK 1.000000 -ORDER WALL 1 -ROUGHNESS CORRELATION 0.000000 - -[ENERGY] -GLOBAL PRICE 0 -GLOBAL EFFIC 75 -DEMAND CHARGE 0 - -[TIMES] -Duration 24:0:0 -Hydraulic Timestep 1:0:0 -Quality Timestep 0:5:0 -Pattern Timestep 2:0:0 -Pattern Start 0:0:0 -Report Timestep 1:0:0 -Report Start 0:0:0 -Start Date 2022:10:13 -Start ClockTime 0:00:00 -STATISTIC NONE - -[REPORT] -;------------------------------------------------------ -STATUS FULL -SUMMARY YES -MESSAGES YES -ENERGY YES -NODES NONE -LINKS NONE - -[OPTIONS] -UNITS LPS -DIFFUSIVITY 1.000000 -HEADLOSS H-W -SPECIFIC GRAVITY 1.000000 -VISCOSITY 1.000000 -TRIALS 40 -TOLERANCE 0.010000 -ACCURACY 0.001000 -Quality NONE -PATTERN 1 -EMITTER EXPONENT 0.500000 -CHECKFREQ 2 -MAXCHECK 10.000000 -DAMPLIMIT 0.000000 -DEMAND MULTIPLIER 1.000000 -UNBALANCED CONTINUE 10 - -[TURBINES] -;------------------------------------------------------ -; ID -;------------------------------------------------------ - -[COORDINATES] -;------------------------------------------------------ -;Node X-coord Y-coord -;ID -;------------------------------------------------------ -10 6.096000 21.336000 -11 9.144000 21.336000 -12 15.240000 21.336000 -13 21.336000 21.336000 -21 9.144000 12.192000 -22 15.240000 12.192000 -23 21.336000 12.192000 -31 9.144000 3.048000 -32 15.240000 3.048000 -2 15.240000 27.432000 -9 3.048000 21.336000 - -[VERTICES] -;------------------------------------------------------ -;Link X-coord Y-coord -;ID -;------------------------------------------------------ - -[END] diff --git a/tests/testdata/epanet.res b/tests/testdata/epanet.res deleted file mode 100644 index dbc080f9abe104854cf7a3fd86d0c1c3a17d65b5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17066 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 diff --git a/tests/testdata/epanet.resx b/tests/testdata/epanet.resx deleted file mode 100644 index 327373e021b5a7d5c4b9a4c206bfaa676c0ab531..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1019 zcmdmNc36&yfq?;pL4Xm6S)nwDFTlsZ&=APTU<6+L82%~T0?RpxFM-SDDINgJX%^lG%aw_(fXg)}K;)8SAA{u%-CPBi zTRj&dw{r6{uv~A?TDY9tcBq*fUV!CacNDzI{W0M_?!D<~dN0n4=8V7dGHOEKimKD!2%+q-fhhFtLR%V4?SfcY45 zHXvq$ z0n5$12Qm{Pr}=81lM2wQW$XK#CiFdV+@z=Av{+o*$?sym(;tr%r+0r5?zRuR?NGBr z(h)|(LI|b~Cf+Ka;$(cZ(<$WsdZ*cEJDiNJMLF(zR^eD?BJSkax!h@k)e5J@_YCd+ d%rmg#(3NyhKjmYucld}c$UG1qL~jOWdjMlf!-@a^ diff --git a/tests/testdata/network_cali.res11 b/tests/testdata/network_cali.res11 deleted file mode 100644 index ce51c1db39e5ac9d870da363418940a37a7c7e14..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 196339 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 `R8}~ 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 If&EkQe-X@BasU7T diff --git a/tests/testdata/swmm.out b/tests/testdata/swmm.out deleted file mode 100644 index 9801df1b2ea44915606afd4d386fdb39dd1202f1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 44166 zcmeFaXH*o+_Wun^5|Auea?W|^Ts?pR5J5pPColqLR6r#oAW=ZY8~`z)U`7Q+jG!P2 z2E?3m&iYK%4A5N9^`3Kn|Mk4G*V;2R{jJ(nyTXUAp=V}zzZ$*1r^L`9BY0F0SWkg< z6PUQb9N~i#d~k*jF7Uw>KDfaL9(-_z4;U=q=zt!b(W47`bVZMD=#hsWQBEh6)5#H@ zadJYBsFahi6mp5G{>uuHA7Nd{gCp|b_!sqd7x)hxJXk{T7f-Qz7CT742 zZ9NbZgEm9(8VD>_kTzgpad^NA+tXrVQJ#W40G=1Cp8wbB*m<1uk)3J4NsGHp@3dtOZF6U9?KTToUENTSAxiAe~ap~1GdpA$)fr)ow_?6gPcYnX}^oa^^L z&cQs;+RL`T76W2p1^-d@znyC@+g^J$$KO9a$8Ae{Sy=CBe#a|e0-p1b6`h3r)lFcq zZ(tw6{*e-xw7}p>=plL*JfXSr-}1uz@c3{36ovAC)w%V-w#f-hUSMz)!qo_m*r?k; zN$_Inh@hZ2L0WKzM#BGm_>=FycM)92zd6v_{y*qwjsC7YT(`eD5G#J8BYylwM@;#R zjyUt*bitach79{}2V8T%(*@=JSNw=u|INSPypUzT$?!+||EC9*3OM?AInuR7w|8yb z8jpA-CYUcB2ffjC9rv}^v<1=ZOWXcHkb`^vmwZ{zCHeRJHUE+?*v^n!PRt*RW=p>G z`=9xmM@aIIjJfI%DXcx_oR-)C5o;QFC64w$bh z`aC5#*KruEEangB`)j^F-Qv3V+r6!rZ$2c6rLQfcqg8~w>c4$00}VP0Pl{&Kc>TdQ zCrM_&ZFnsrCI+=HVR`_j!!&ByA=}pg&ryMNpL(JGP|c8m2KCrJ(X6v%e^8!2gYJ>l zxt=6F zeWm?=Hfm`uI2x+MTs4E&JHn$n`Y_V5a}DfQnG!HcWede7!D}Efu^2&LL4)bswZ;4` zK1r+()V<(!k?u>DJT4Qx|x zF(@xkVT$jeYcH`D!5B&zoIw6>5cgQ`f_-3{?OMk3@G^RwX)%bIa+E*lX%D)4el*+N zvp;~b1PbDNpfea~71n_6lk_Ro&Bc60|0LE%poMOXqb4mW1h@Jnf!gC&$v!&-F%K2A zsk%3am6l{Q`&0pi7bYIrQ>2(C&sw&$VGWpn*BIpc*3koB><9aHOM38m$~3EZg%!WL z9hlzo0Vi6&(y`}CfsLk%$G$QTdT`_&Hqv@8xT<&<9NDhIoPPKXEZ>~xv2W}wy0TXz zo9|fy;G9qn3ZzGSF9EkFhVjp6Z=+mCM6)M)^#=>C8ZdifXV4+$6TqgN41TO-J=H%h zn#EoE1I@GAz}2EV)5|mml+r;SN{b5V{K{yyZG3;QOwiBng1)C0&jqTc-`K#EdMfm2 zF<&ntOvK>Vy#{3BrtX;*STn^TYr;QZ;mP>0bt@EA0CZtw_?NT4q* zY+#kn6$|YzTq!|7%3GZL>vBC0P{7Iz5^QEu&vs0L6`n0x?SBW}i02*vp1QE#wfAbWi0T7E_ zfckyKH)BxrZ8O-sPLgSTvW?xfBo(aBUrxWhDCE_TjA8~FEdTb-TsC{JCn#&&Mn~m$ zuJ?%XLR~^Xl3jh@6HKY=!&JN$u2+ZfIbikiO@cbb#4-~j*(+{dAV*~+BRQ{gJ)g>R zfy@?5yT6eo0^&j1m+?%Mdnd2-F40IoTey#n=p~qc@js|{DMDV&c{87e2Fo{hTgcx& z*_)lL^@Dodx06=`4Tbue`wRJ+dOpw>5EB!|2g|9yTP1icCZ=`wFsr7!9271*$uP#k z_+ab_IkiZ?zodpu3||dC%$-6n&lKwTIa3B2EZ^TQfxqQ$02?elfjREp8K2KXVf#l3 z+OHvK{}<07Cg8o0SJU3fF~d^&qWE5A)UsxBYr*bsrhsy7rU#0j2WJcoJ)CAwp&t#2 zWCyEw0T_##-w!JPQ!1$c;>^xknoA80UC3Xs-WzEm+s=MO9iZ z;ui$^u%Wy>K@72s^!~$Og4!CvJ~5VAFSnh2xG@!Uf3XUz_$JTbt8Rb!$N81 z#bH*=bUCm|tOa}-M@H{<9eA6Q?V+u=hL+E-VX1kmfy!x`-QO>W33{u=mhbuK@#@1F zdd|9itd&+SfOBGC`f|E#*%sh9s+J%1Re@e05y_5g@C1qu#mu!6+vw!lrQo3DGyZZ( zYkG3uNcNee7no4A2{at*!$h&W0kQso$Izpa%+Sq|Y#)Cw;4#^hc{XSY{d3VuV4gmd zueQ#fz8svuKWsjTJ(cakx+;%kPBzQ2vFhR;b7owm4?f(;ei;-G;QVe0>7zu;9_J${it8Vfj{?FT#u*9RP@FQ@Ii+RwxNU=re0UB`Mg z789eF{e*qpdFa=Nu@7cY0v>eclUuDtE7oRr$#=t`lD$`v|4Y8aqq<%4QTAc%@;BuF z%oi|yKRc%?_m_MZzBP97XB{8T9u}v&kXkfcyGf#=nP9A6eQ6#P=$qIdC8)oVAgnfumb4qm$aXp7;1BBRyhe9_xKP z98_P=VP5p>7IU_ zy!ztR2kA!w?D-+AJoE*)yz2dUyWq8$*v1Ka**IOn-}S*~87os^`(f%0=xTJ*1TNnV$kum6k9v z5_8bs3&V|Dn4#9Ik$!C70d{ijGEg`@53FUCnHfQEK*0Ms9vbs^)1*N-JE4LCFcx{Q zarCr>$AE12diJfDIo(=e$JeNlV{0?Kn9HxMXtN%Q>?_MOwp8Obbs@u^KYOP9U-PPR z1v_cX91wbDJ22X*#$^1s3wAh9@Hi|vk1mPa%O14O0V(^x0HXo@8R`6M;Jny&4~LhB z=rKe0v5Rl!0M`vU?3G?i7?(BH?7Q8To}s?7%;^QC?E1VE0Ov$=-UYhc_$;{Kr0wx4 zW(<9KX&5_?qJUqV4wydr8Ql+T0f~+79)s^C(aYb5v0gb8D54Zumub1oEaQ`4Y=M%e z%G>~^d0#l&W=(^~l1G^A1?BYP2giWdqvQNTH`mg~M)&6zY8tYmy^>kAwP{TM4cct; zMq7`d#GXv^nml&MnQ#E-PtBJcX7lXc><9(SGq6FOxjDL&)moe)7+1(E;re?g=0R&p z9YgDV*1{y4{ogTuLU3LQt7ww{zMC%ovACe{1f1C(imv4Jh?lV zzkIkYyJy){rU>uk)i%Dc{kuj~uo*E~plsksM(v~U`YP{x6qER67>e(3w_5h>sx<&} zvjzv&UZuxgx&Wf~nRwWjMbMLzL)k-Xc>u-|8s$Yd+^qoqt)=Y1sj{@!Egrv7OO;*L zpves1s!m^NkYLyMoyeX`sH9R}@c5Xi>R<9I;`tg@y(|Wd8C(KF?NykAs&_!$%TXR- z^i2AZ{66;irW|n6tqBy);W3UC4M4tnxrfH9&Gd`S2ieyNd0?xzH=FD?k{LHsmwn-S1j3KRnu&P59!@?h?$aiW+$~d}4PG+NzmevS<}M`|NxG=Z{+cRAz;~ z5<7E*yl1z=_vrJJDp)2tOE9j8S7`m&{NU5;s>h?TfaBSIz;keYz;U{(?$*I8xF1|1 zeE+IFD}1J}It}TvF5MoEV?P~m0o+W50$xS#b?TDONLG^H{l=wV@{OT)c3i(fA0GU1 zY&X|m{rzXY`wu1fMDefw&JRfJQm<3$1a_pfTbFug3OJPOcA-nX8@vCv{p=uZK z)vAt85?w#Zskks&g(s2zz-=F!Sepa%t@P--XN0`k@t}-`2Fq{r9>*RgT)=Tx7uq9T zxL)D;GV5}rmy8?7>if9>6T4cv_=<47YWpWK%NLd-|8IIsU^6$kg5jTE&^JeQuIKnq zV*&J2S5?7os>=d_)OUJ|ekZRSb7GKQGq{!Q=CKP%?zus|NEY&H*)oiV2FttLiRB-1 z^JCW&H>oduI(eo0jzId8XN&liuY6clUInxIYG?ZgFTRP|H^%S^yZGUD&^%x(W8O=s z!`N5aOQHJn^l!2Ad@I1gw-~)n6u-oxMj9Hd-&HY-Z*)I|)sg#7Z_w|I@420@{fE+8 z*>4fMz_j33v|O8zSJ%T1)5WjTkpKGpPb}Sb5||qeW8_rl(#O2=!On~v{^WxfsaZe9 zv03L_0F340yf&(>av{h%sLC#!HIurA#qvj54q)#LrRW|0+bP=b5O6+z7SwJqrABBh z;@|P|VTW8g#cWEbqqpX61)gV{UB+Kfg(VnJ4P#v)z`1N5)bf$9F2zIzMi*WsVhKSI{DG{qals!J|9ihs9VA z&FyZqu}LfYSa%nIbE0UM9(`=^M9_3gn}0%oEVXCYIJTy*3wXbG5B;Ftg}!Odf@KuJ zAGsuj+B<6;dt!tOkos7`?9Q*Hk1Iw2a8uFadxAeLt1*F<+3pG^iC?0}#^ChNv=pEj zqsxzc{DaCEp2_cZVgg&ea~v?Xeo3Fl&w^F$jK-F`q`&4@Gal5f(X6h31m{M*%@FY0D6HTk4I+5Q?nJC~1T zk00ym@2~O&DHQSN$t8B-2CTQ}YD1TL8*0Y0v!}QMZXJ+AX33IW^7%j4@EFkRZ5Mwq zAGh3pOT&C#Syf%)2wkA((Ie|STe$K7RVyjv73R`LL4$tU-i&1zy>|w4K8n-&r-eL< z`shSCk|wCm@T@z6zhHYoQR6%E$uXhsdeDr72FsTT`pN9LGibF^r3S=zuJ_(z0O`Sd z$FhA+I0Lh)S5)#T;d(vT|2kFo^aHA2CVf0BMY@7?4Q+Y@XTPKny&ctW#yiU%sNDbt zOIpyevYouTXDsA=(PlM1dFeTrP2MABiT*#BHdq3O2HRJDPt0RKexBWQ!;Rd}`Tt<6 z-+rVUZnO5-6V!wM{9-mU<#cEJ-&H%J`e#3Q##$yF0i&j5GOp4>9mc-0)D!7_1H19B zBsYNOr<17l2||5nlrjYk*1uU=)gzpF%4!}lrb*dOUUfG{T6qv)<9aO{%ks5?gp;1%FcsdCdXI4YEMt^D?xu= z>JGdY9A#C#S5aFY++q(stpHLqPG45PM=8EE2jQcOSmmR8$W1mcSlzUv;Ozi^8o$$> zPP?oD!ZqvJjRiN!em>p!v*$N}8q=%v9XmrhesCB_e8}T(tLjCGr>XH*l|Bb>PFU%F zCuP2DW6}?d19g=fi1&NOvL9=l!D^*ZWVD$k<Iw5iHsJ5*T~cki4fd9&ePdv-RaW z>06oF^vSaRAnckAyTz&}bx7|lYhS(r!1?2L+mz;+1_P@b4By*cm-64B#(!}BIpFf@ z%nuiOm`o8G3pk$bNBcQAPDV4Q3Euk?9&kUH_8+{`a89B2n9^tr+VcfAjb%MryYdBU z|C#Su|0@0~>6Kl0(C*{^<#XlNyItC6w|zXDKBOzJ{$JMjzkF%-?@smXCghdkb(Vw% z%ft)%ZL*->wp$OOhSdmp1hp%Xr;(oZI*@;LxE1?kZ7eA+;+1TG83B!3r|g^+q+?v? zdawA1A>BG_F`YWgmkMTLsct8P>y>Bvh)gsWN9$Q`pdZ^q-V_Xz%%o;`cCP0U28l=y zGr!5cN-77%R4$b((aEcXT}zRE!oHcEGHe^T@UA;yDB{%^KP7i)-1gCR3WN!VS9NaI zU39zFWG14fv;B?Rno#_bY6JOeN=@15$4SilZbBW#E)n$_=@PX(es>8~cC+0lB1UvS z!$0pk4pCoAeJ6oO{QIO zWj-!$Wt@+i5w?j(nAfY9)2=IeQ1&+Q6h5(t$r@_PHc8DSM?W9PE*feEHV#q2w+s?T zW07NCMK1~5i|0Sm1c4>*=nd&flzzNb0d?f7S`PnzHixieKlo>CV4<90F4EAJloH~aY{@}=C^BbKe+Tic-5}` zdH(x7@Nj2287eO1)g|px0vflpypl5Id0faVsBLz&Lvujp<2E8ZHx(aUX+>@m-JeC7 zrsB}J6>L7Ad$t2`ISMC-*hpfQb zz5`0aqjNpi4}XC4BAz9)e~dJJ{)!i+(Y=#bsp4;uzUrd_7+rOb?lX1^-b=)*Lz=^R z(75fJkiG}k;P7hYj)h%x)s2Zv!0}FAc{REr|AtDk)anPV#PJ^q%ujKl4r33z>?hRw zU8Ve*c98F;Y#;(e@ynfIF=*WS>*Dy7Z1>Lij(9vlV#PnivE77a%F?7!evf3j~Pq88{~f9JM1ij_bjQUE(pf_pQSV(gJYhjpo?b zms{{1 zfcCpP4tqGH1kGg$&AxQCYA~*797-_*dF02%kI2}`EcI;05r(?^o>?k!nvkyS&xDOP zq~ZJ-VCzX;syxOVu=)zp!|I6VK|h%zp74G4PF``x@UPNvoVra@@8A{O4`%$~)n9eh zKRQ?YIf;}P@v3s8D*=t`AmQ^BvRrii1hta#LrBMKM!1c?VDEY$^&7EB#H$UL6mV$V z^6xy<$UF|O78K|rUGPpiuX^GqS20^js+WjY9##(tjka&d|ExV)?g`J|yG3qNqCEJW z>sf8dJhWZ|CVs=_JU!#iS5l+=yLIv^#yTG91zRPFBR4K%+uzT|6-B(N`gp|+8n=Dn zTJg9NhgVKk)x^8sQTy-2TH}wLdti+_6evQ(EB8$c-Pg1x zBmF@4y~N22*?8V@hPb~Yg`B0-pElxmkW#;R<8%P>VtR9q-ePobj$_ z2a{kM?lqi2ub-^OiRW8KceD$}NI6_5?M5dsTOHKE?fb6@se*jo%pud=v~Hgv#*I8e z&W#?+1TX*26lSXs(x!{u*Z212k+bd*-+H!^;!FLR-PL*^E!m0S-&u@x+w1FoZd5WU zzNsfwqq&p0A5sX`XGarymp2lcp7A)G6I;3ouZ7MJdrUu5AA|cmSK_JMdFZ-ntu21{ zu5jP#BGHSX)lzU@stIfPzQz56pCmc)vJ^GWIhZ*mJ0ILBDksF(>EM%od~% zn}fz;pZ6!~)dzLlr5+=!Hml(Ydlr!8FO;a0J61E>&aPt$+v12(-PQ5&lCRw1{ONZ` zg#tnAnJmdoAlW~WSikcn{@`epps)Tuui!ZOOVxDj*Wi9I^AE4MQ~zJ3)vpJVm(k}` z#KcmcwBpdXj)GLTlffchL9KEBcr*vv`RB zb+lg3F-C41>%?78ynI47i+A!$Ls}2%gRZFX_Pu@LI;V`nmceWg=%oJ+TUaugdC&)A801!JFmED`Au^Ikev&3Ets`R8L-K-nXMAh#YNGZJH(lZOA!4@cH1-ZzdrWwJwR@wQd;J1qq_<63#w%!@ z=BAnS2sfHMlq_eAnROA-Oz@ENc+paKr~R8$9br9l%8sD^-Xdp3Jk<&4Qa869+%$|) zAYi~5%>wdNx*Ky%y@Hu0a}6iNpE;kYKkP)- zrxIfwc9P|rteETPZZca|cPDDIpSi37N1Uzh8<7q>ZjnQZvYEcahl8M09${yf%2QuB z!VS)e;32Ox83F=6?7k(=Q=AJ?daM0cm%G%B}e*fuIQ^FFqJ^K8uK3EzGB zH4QS*@d0U)7SH5N9nT!hrwBJOo?FgD6<0WaR+>E~XQU-DHtj> z>}5aX->PbhbI{LZC$jJe8O`C<$`2=z{w(dR^AVYiPPzw=kqI1L*-dLex_ra~7unzg z&OZid1{9+H zZdvjfzq8A-OWoXdaMLhG9fvG3zn~AJ`C>I=GjTD|_*}{U(Vd63m0JynL80@=%sHCO zG5KWXX!SOnJpa<(;YyWV>1!9_%;YSx%|ekW=~KcOf3L?gzCL$o8GqD%cVRP8<$jR# z$(qYJW*Gye2nAx(Lqk{HWN{ZbC%%mAN_dI%+dA49G;aA%Z`Tw49A2GzV}|sv-e>I3 z$ZW6^FUTjYMZDVYD@8m%qKxL|gjp9I<40_9ARE?`d=9S;O-e_4cF|kMYfp|lY;)R7 z_T%ts*u@;A-<>?rIsUn+lXQwWE+gVqqeH7JG;aG)`Zv5<`#6qyU){MM9I)alivPs1 zZ0qpVldS0CIHpO&D;T@){0n#<)vz@CKOmqsKJOp2{Pk7CF&qI~z(~^X{ zH&s~Kwq{wvdZbh0P=8xJt-_U^75)~lV2pRR%_67bc1)nuTxL+357BTd$vW0$h*iVv zTlk$d0c6}4afYxCV2J%o@tBPxY#jF5TZ@hUhA+D`i|qFH9bGdrp85W$1TXgpwte5t z)<#jHfXMr>n#`39WU2=JWE9pv!1E8MI~(PVae{LqYUWZDmw!4zYs%cl?y6PW58S%a zZmcQ~E1a_#Y1V7Q>7+Z7_=*qfo%__rI?Y|LNmM&8CmW^YnE1O5%#I%VL{&FRXcFy7PTFL5TEs+PB=Ham)8RoOcgKqbXC2O_wqepDUIj#~b%n-lA4>m*SBp#Hm`fa9 z9o1Tg+P6w~ki}hf3v;LNIA*_yS1|TdUw0$D`^nyx5;MM;+tgjdbwu&6d6UP3#;spl ze<`WS;nhx=fvEj4EftOhH?tgMN|%tzB3@nZPxCB$j70jR+cr+m2FN-dxvY!(E$D{! zh@*U;(}6PM@rUyg&E?(>HiPw?O%-16o;$w+A1d~)OWoXdaMLix?b+JQmH}SO zv18`M%n}cacS*YDnqM~IEVVsH^AHOr1P{j#&C<90*!!n>x&8sX_C)|G*LH~x z-5kJN`M4CHuc2#YUiI1HruPU!<6H{qwhm+ZEvaV`QmgUCi55;J2c#U~oVe{XOBk1z zIz4rH6?VK=ldWsp7Mr}85?I7;A;Vh~Xu1Nsi}`-&=A@R^=ukx5!XN4-kiMnw>4@4b z%tKs)c;j8_U@<+#KI>x%&q4M!8Vmkd9m-ob9^0hFbA248;!<^B0FgE?ootM;V1gcB zrnA1E#5d#(a(EbNVGrkzp;iX@!p(*;+c9zyf5Iy`PA`6lckl}C z2lM{$iaX8zRXWh+E-_2Qs|xlm294`zh6<0|FX9o@Y$i=cbKr`Ywn^2b4@R{u{)CH2 zzw=^?J2Y;2GGI1Aad`FBVjt2^FVnE;nf%7;=Z+BaezoxZo4I=n@aaaIkpF8^o9ymP zi??-tGlzW7`F@5G$FW8xkBT%52b&@tA2Chm_r<1x!s?E+9zc&%5>TT2NQ8Nj@cmM6^woAs$`^3#!bx* z+DVw6E2_dZMe$!R7{i0ct-t@GNb&>c`xz$Q) z{APS$iJHTrE6?rVoTyFSQH-6dR<@b%^4MzKg_G{CLGzIo`%H&^b>akO zIy%ll`n#Wf+W4)wxcDUU0(G7Kl%LMLu)2+ByfwC`EW6uH_K)T{emH@~qGaw5@`K9w zj(M&AK!>OuIhV8x>&5I|vWq^`V=JC|`kdV*sZF+U{`9h*PoCeU$!yK3U|J?^#~pS~ zv9ErO+x-(>!EqWr4}E_E>RPxT%>TnH?lk*X=^n9XiBJ)*u9@z}pm80s8ph-%5s#qO ztl)~~fc)f9hO!2Z1`dR zrR_Am0vj@IJ0>aO)$3e0S7_Y!q4aNfmFN@46mxiWDS<%#8y(jg#py0Iywp36$rAAj z#{On(0MaYxPBXS2O&UqqZWY{5A>2>aU$fyshX~vG8MMvl zr$J=1h*!C>t!~XJ;%MzkOjNZCZ+>cX@#6t(eOetlr*L>PE%U|-zxeo^;atN_2CyD7 z%?6F9e6c?sbM0`Ky1DJ(reTbQVJ2k6gb2Ex z{L@I6HkfG>_5fHP*<0Abt23@juF$ycL+Rh}YPeM#lh5JR{z1b1^0j;wgHfqZ^jyW` zm^cxyVC+V#%~1U#XI(W=f4@Wj?YR}Wswn<`cVu|bxb+{e@FGugc-7%in*(UAkFH%x_kEy&+ojX`!P7PM zU_D3n3g1ukc5}qn5T#w}=C*^IhA~bO6W$ju+whnUC!6s_b7T$dQ*P*GtklAZw4bOx z4dN8NzC{nee4@=jnOClF`NqrQ6B zu!pSCcIuedA5xFuy)Sx_N0MICJx(s9x2%ZA18!>AJo@p*3eKP2-}{iycYmNIzQ;1( zd=l~FHdAfHhZ5HRgjaB!?#UN|_I`!?!4-da)!rTd`g!v1B4V(JSLN}c7&NZ4X~QJR zBoU9G)-vJ=(x*R<&>d#N=w!rb5N0BMPqu|SG;aASbqB(R!>fv$E=X6Mw8T7#9&VSU;k#Q+(HwiMxyR~-YPMzf1x{o+hgTz&g>$fcS)J90(oL3gTU^O~9A4GM zZ$#z6SO@ERt)5mXic2vG(e>4t#gAN|aodN|zv0zwg*YaK!>gn*Z&3W(B1?N4<)-My zK8|JPig*QMKWZS2>Mz?GrMGlRzup>=X}Gc|{y~;E+@NvmAG6e%+{59OrtVr)epI)6 zRz8#WS*9MgBg;g*y7+Xd+hDQ;>Ce~1TkrhlZ}rV(I#%s1yf4!A*lgN!whSJ2^M-Ef z;@vv1o)krS)ZWG-O+3PI<=^5Jj8QyP3UNng%vt)5=285}>h--t7RKs^+JD9tbbln| z)wu0+VU_}J-W031Sd>Gjo{R91|)?YAY**Sw;! zs6oulE#vSLKNndy{PeMcbK=Q&E#z~&{|d^`F%0`?kZAs9(qOX}V?5ovEp|rQ!);ZR z%)K=1l1!e>^J`(&YmVCBqZ%woi=a)kUaB3_?6wj=*6eI8epAtkzxRV%v|J|YE9dL0 z$a~uiP(Q#vnP9pGzkJMz+@5ir=IdszJwUcqr%F*pgp`rrZggDd~=O4u3yhsUc$%L!i*uLjSfFlbzNk0ss_ zQ6e5eEiU93(u-@&wGZ&5v{uZQC5%P7d5x?)G;aCoRs+Ig4QYDiy`Wo346mW=6C zGc9tZh*v54KQO|$2byDX`*ST_tEO6H`3m-<9A3Gdj77TXpkm8Jg(M4~ATzRiNc z!uOB9UsbUBmUYjfcGY66omb*pj=DhOwhyI$!>f}YW0@EZulC(Jh2nocAYA8l3#FZP zIhL6w;uVa2LUkL`OI7W4D;4E+u*WgDk|_SrU3=Z2aqAE9G9fo}cty;J7sju0(6U}3 z&myH>pIk5E6+3&9+ng5R=Lb&c54Pexu&^u(@WN*GT8Y+k^n@V#{+N$gX25D~4c#a$ zSWoS$pQyim6(sT6ZRvlDS1`uS_unI*PQ7>2Y74jGoASo#Jc@MD{xPW@E5I%xO`@@Y zo@^kF>n?E7y*pM(XKu-Ttjbkb&c9zJ{j696zx~~|cbub~ZsmkjoOf4vZ=AT1I}^0T z2Y)cx&+34IsU@5fH}}gUpJNn~D4nJuSWAMb*@7t&rgM0P?paTbk+!IB2^H!agMIHm z+j{v1zE$}F1w4M4HsUJzPLoM|l8S3HDpuJ)9$P%(pLOe78i)FF&GQt}(pCkH3+$86 zMR9odOyPZO^Lzm9JYx_(V(wncGOHX5IDdu?FeM#i>gnL|9!zeJAe?rUvnr@;v-l^x zg5y**dt9#ew^8W^nLy1 zG>5ddsjJrs{$DTBAMJX`gT^iY^NA{9%HdVykB>;7r}WI^^VP$~5k@`93=yv+lrCew zSMDSK%CYel59|ERsZr`=0f$%DBZi_mn6Q1B1=csr{LpSqawUgXO$SCJeZa^c7IF*E znS;iuSUazlZeHsGjoUty{td4*?!_{*IK0v`EJ5w7N%GXX!0WBK>_jXxUc@UHd%f8q zq<`6=qp+E4mH5iTw)k#sP%Z^_E_mN4IUmCXW){4>gjPM28=K zik(U9rQM3Z)a>0(w8t^dt&i3@0)bX+;7bCrQD^;)R9l+8Otc|s}nKjp2Mv^ z%&@auDf<#r4p%@v3w@;-`KeL3+--5o`R6Z~!+0*mK0;&RU-f`kxg@sZ?9BmWjxqs$NP z=x656lOxkPyhEN>!>eoIB+^Us-7}X_L-Va-`TYkuN>y0ai*`5dbx8B_N93b()@kGX>!dKEMk|UruxJC z>a~^|v7s%(`*p?eW%Q*z-?5SEvRcbtwQB5>WAW$Tg?q&kT#2z2x5R7T*jw<9%bUYF zVKDP0itAL1KecL#D^`1dhcQnt-DvE@JG=-#IaHsLQUYb19f*~EA7uIFtcAsZ^t0H8 z*WD4X)cjx5i++aSV+VdVub6cT-OKU#V>23y`KI+mZAf?ruV5ed36~R=o1j6r`q|^U z`Gw|R0_T~*`Qx%s9%;|?v>59q2mJK+=jQ7}jtYGKeO|$FTKw1zwD&LE53c#ctM=~r z*U#fCXAq=_SFg|AcZbGxb~61KF;2uIsLcwTispdbAXT+p`<|+_*k8wWMEVA-ga?gV z{t?}Iza%_Ad|f%xLnCsH2=A$e^!&Gi{ig7Kh8x!lG3IG8^6z3CXLe|)*jEymo>MG;aG)`Zv6q z0I#1oygGMDcz=G7*uY+GD^1mSrLjzqh*vQ7ip*rx{xR1z)K`3Zqh?v%SMYft;q{gO z+hK0dxb-(Z5X8sf)uzw7sQrDSH=4PBi!%+6hM&(AUSAOvvTm;uh41faUFVta=%s4* zruBt;kB7p0m%J~k(|vWTG2@YGYVKo4sls}i;?AJ)oauQ8+tO`hm$BitgPVpi27Ek@ z7~$>`MNc%1!&@x-^tzRzr{?4~A4_uCg0%8mfpn6?X)I-RZ}no^Z)#&w(=fiPu$*;| zMB2jT3HHWILnE=rn_kox6I@#BD=K$+j5s5ER0rQY)y3RDNXZP&iEhi2~=Xzy3JA6)x~SMA;Lub)4@A4|B4cojS2 zq&qaOv$jinh~Xk0L2aV1H(HM+u5K#HCzO?`9d)?2NO!W%=0W3@clLjd>xtGYJip|c z@IBx7yRn81?tTWzg@XIPM7&bJpM-7j%0~XzPt7oO_8f0ATkH+7fWs@Xby8?v4;a4A z^v;JxCJrm!6VV)Az5gnUbd&xvX6qELnfQDmI(T*NxrYlhZu?OBH@up?Kb9HE;nlD* zf7HIj{Kcwk=J~29tc_&`ig*QM4>z8S^n7j(P<@o{(+ z6)k+f{z~$0(5_aUE)-j1UqA|vq4hI3UP zYkR6l=?%ej^w%IQ!U@n9Ume7hxAWDm9oA8O`X~bXJZ3M_EQdwV)BLYuOE==Zn*DmI zo%T_{SEM{aT4w%Zn(eQIzd!G3HhNZXQ#dEG&Rsy`w&{um)o-aTX1zGtaEViYgMBi^ zykl9ydsvpNA52YE=V6IOGt8$Z0<)!O@-gWZ!h6pq-m0M=e&ge+n7moQh+8Hwo|)mo zy}5Z=5m7OJK*zj>eSCGq8`PHCQSYg`9lh{D4LeK~dZwGe`E$Vh9nyAaeWD*dRmXE9 zB+d3Mye#nf_jv`!Dcng7wD&9A53c{itM=~r*Uu-r4<=kiygGS&yE`1m&58bsu=`lGWi z6VpVzIu$wvvzr`^{Cn-&WWxItZ@l%*9bzVjSF3!5|DRO#I$#nxb(!(#J`af59A4?w zy+-A)@_U^IQQo10SBJh?xatvs|2Lb#3p2oT>ur-FD%h+(+!A-*$W9qjepVqDe=qS%o_~@!F%8P#{D}~`W<}r8~ z(#9s((W~e0z-C@bQrT-TL>b#V5L50UEax#Ym`=|;iygI%RsG&;fXeikkJza@*HO7| zN|)&MzEb!B*$Jk$8(mG{oKUY8-p8@RS&P~@Rt38s5M~gdKv_B4E3J)8qYsNCURiD5iTdi9M*-1$B+rQ5% zI8IES6lm{PxF6i`hga?0@vooDR`wyBM7)xYTkZ~x>uhtuI>KMXBd8r8BfOud+4HD^ z3U5WvPf>#Jj}qxGlSlBNam%ALhgbipUGX_C*l!BgYtbEF3>r7jxBQF56b`Q@dI+!a zx4MTIS1xli%I|%J2;=Z-Sj|OLepy;?lP5~wjHX4JcJONQYBd*VT>mKj8(y_+h-Cse zyn3szkNjf_l1iC(FDXn(k7fFZcm-p>ct^h%qpSKq72R|1oxIyFA z|30yan9AXmnVs-EUIw1cG`=4hV)RM5k(eUl)%%dWu5~?HQT=Pv5=kQP(gbEQsUf|W6LeN`ILB0TizQ42O=xlL!4TKO9luRjsI@APIJ(soSpq7$-? zV2?G9D+l&jr8Fty9HXt~e#KnQ#+nRP@v2}$TAb(w>I z(L{9W^{QYjyXge-nUb)IPTFCNS6ZAkwm-DN2xd5lZx;5|k0r#$L&E!L;Ca}`3wk!8 zazn#TQMp6J@B<@Kjo;ReFoN^PtMM|@{6?OmUpRHcM_tx5$zSqL;PdbE3XYT7qNnJ) zvtgZZKe+J^uV7dFpN_531Ys}Y)x5(=?$EdnzicQVd_+8g8lYs*9GFwtyQjgJZ*rym z1@~`@bUK6OLF1N3>EH0Ga^Zerq=;7&BwaCR-0~+{Yl#UQUitSH{>?n6dd!fFEHwCe z^fVE|;nmiX3RK?zL#Yw?lwznMu8VaOz2Dxuv6~Atu78yN4X+Nbh-G{^yy`w)ct2BA z;7Emh4~L$a39$@c#48xPl%PK7Gq%w{v9Lr;;mtkx{SYEvF<)Ij3yfR;)d<1&@o;!$ z?ox)zk7QpNdb?B`SRJh<#)^0)Uc1h9MaBW78>$h;drEs5^*Ea59;!~E^|jjd0@b%Z z7gGcIJ)hM@z@Hix(-2>c#&hP0h1fYqt6#^4+Za(A##py=Ir5oXV@+TG4DfuvK!y2N zEPFaVQpBd87rwu*++Bqpv3CXL`^{W&#sn#a2NMji3r~fg$M%2aLO+x#$HX@nDAmV` zDK-hdA7N)j74rGGcsqUU?gMOiqpNYhIm(DFrTwiCuaXm@$bGM)y3E19Xd*gwsF}b< zs~ki=2h?TIF^4qqtI0M-QIfKTFvFXBg~GY;F^VV+w(9T+`}l&X@OwUKx{@M}!PbhFWQ{{(^0zt1Z;PAR#UJ9q{6gPZ^G>c0); z-#+iXz>%;K@ya|t+#MRXuzPMM(O1MHs5v}*jr7G=GvrpjA1}LHZv(C-(iO|BdC<7! zQTjK$T6Sy)F;v8>lQ#`8Xx#FoXC*P3!>bjU!Z}!U$I;-apMrkS+atsn4zDso)}iu} zD&~d~TO-_t_@n_8ENG{;mkdR0{k=1*oTJUBVA=Q)Ka1YdT~6xYlk9kAivI_ ze!(JrnE6s{F6yh)YZHl)QidJ#8uszxC6%b$+@2-W?U378O-PVIxBXW7aQ^hXbr@-x zSGUm4mUpq)!wn5Bdx;zT6JEh_n!n*h2e06Mut>nG_TK}8?fc#FC*NQ9&ey3Hgq4U_ z%Vh)Ip>cCg>YGA%ig*My^=BEG}wmQ|m!z+W-SjLOPtJdH)6n|C`BgX`2$!bK#GK7d%F!rTyKOp_u zS~>abkejlO&tyAzwI}MND>QEX6YR^0VH{rNo=HRPzb}4WZ@)`f@BCNWi6J6heHk9( zy76@m(!K8uH<0OVuU}9-l}cO}V+VbFdR~+mTjRpG(iPtjAuC4>YKH zWQo{v_mU>MzLFLXB8^+eqBj3U)4H6x+r1YyJy7_)S&K_%(sZ6QZhoP+{^mvBdc%y4 z&xC#X$U2C4uv)XjC+y=sFL$H1cug#%$ISD?Z2GwUMQcRd&|QSiF}??k`9 z2hYd#6za#nMX;+J7*L)h_}-4ELSD_*0N|EiEP(k2R!wJ_ItKha@5#8#6zcFi7=?Zl zP;Bmj4eaQ#abUNA-p>#u7{h&{?^N1x@+3P{avktIDh|qCAEu{BR|7viX^$1hJm{jM z5$uy6G=Q<}7Q}BcdoJ+1BE?GcM^JY!X7bl1hOoZ6rnL024OG~La!_&o0QeT8PAzE7 z}gwae;o-!NJaLJ>4 z^bR`v(LT0#a4vvz;zeo_eR0QXU|6}CKdR^j<@+dtr3@IbN?&9`oX4b{^qbrtk^JBc2>P76C5VNHpjH_Hx1oO_d2qHRSt;*aQ>_t;w|`1NGaC% z*#i#;>@dCdz&_T;w&VAm(fHNA@};v{I=|lvjww9a&%tqO&{XU4`-58qyh52o4;LlH z=pw=Qr*Y5e&Ys4qk0iU~gTFayKB8+r$zwm*we{zI$v0Xok&ul@$8*L3l>dTSW#9Yl4h_gR2DozylD^-Fs!yEg9PzxB&NYq9+t%(sy$>hc>M zyzrg;+_dyx@{KC=>*DXB$1c8p_Y8Lb{UrK`l8{%IE8`ew(Erqh)7YR861=P*NB>mq&p|**%z$@ty1W-G)2>{r9`Sos|km z19#nfGJeLLypo-}8tFkJPO+Xb>%gr(%c(<&!rvd9E9fg|u)M~so%{uv>FhdW2M1xILP5RQA#69$SjSTlqo7ij-%oTkp?mqQAegDC+gdK zKTmAlcYW)u_gmll*V$`b>)Fr#?R&WPb?x8U!@cjHo{zl$3z+^-W%}RfuZBDy%K2(I z6T`#phq?NRg?03fkfZoO}B(z=6~%?Xnw6h+kq zW4ec1v7DM{}nQ?zDMDX=Ye!)5y1X^Rj{wlOKSS2 zD7@x8X}3`&f||EuG3{gzvF3vys+KwS`uVZS+Vqhv;^D~*Bg<0 zYO#OYX4$h8FUqVbn?A|p6PrJjP!q*A+{5ELW9;;5e5mi4SWIGK!M`8;OSu=dFF_s) zCEn7#jg6DN(+T@-h`k>?@(o|H7@0DK%g65hw4ws&)Fcvj|L^|&cE8M#;j-1~ZeN|} z?7lklAve~wyWE-P0D9~n|61R-`<2L2Wxm3%^#|EH)OJ7ps(-`M1L=Y=fV=DeZ~u;| z41or!a=yydo(WlF``{EEK&Kog@w$*|SbSN|M=W+dLatBfvdl#0+}MFt&!|FOg?^6H z%JG0Tw)~vu0rWBEIJLYog&TPKgYPqZI6SB|fVOx=V(Tp*;S+`apo)1LlpSC+<(MTu zK9KfY1+cR~i+Viq%lW)MD2~HDPuI~$FCWFDjdUqN?=O7i=e&=@rI)Mdv64)@d+IiF zqT+e`LU(&9Yi#}9OT}zv{!`xlU|IHR4xf^(3m=YeA@$zHqK?a7_-g;+Ke*#Fq{~pY zsNyaDvo#vMSCiwc?=d&!{V%^cTy{7^l{Tyo1-&-P@x~vGN!GgCW`7SI)22Fleeo~* zTmskszWwjgur3=%FVUi&UXkDs1X4vQHY2F(mjiId*H z!AqeB0eIL78~y8G%e|qvvuPWBWXEEdZK}HM9yHsajyvZZk<^hTRx>TG9U%1Pjk1+DtB6V~s6 z^U<3$j>*7mPOO>V8(KU$!SH=B7Pb_ST`d9h)ix5VxorZ+e22rnn)}gRrwr^c^ey?J zEr9;(4TQV`7lqhvw6};5r5$#|$3=Z1G%y_>B;P~I|NPUB7kT)O%mHX{Pg6XTs z0SQ-8=8zgvs?^o+votBvRij}9=#ypE2XeiXC$)99l^<*7PgtJfy7_9@CR z_tI_pT#qcw=PNdL7t5D(v0&G`m+ozBoGx`iyYB7m{b1(5;j8r?v%cb&n4kdqPW->} z%eVWr+Lp*(mHz+h5AHYlS_gGTR3Lq1DZt%+{kMPZf75{D6#9eP?s);$*gpKq95>bN zB>t1|hH(o0K^Du2Z{+Y}O>VLaFUHUXJHvryw;shZF&W7i-v>JFAV7-qmEErSgA<3p zTYm*z@;*dG9E^lc3jINkqMoozpfBgk2rs%?YK=RN?Skic`h&x*5;@#O{{>yAQ;Zkg z-wPXf`h(QuBo04e^o$;rdj?}0b>@2@`Sq1$ww{DFe*bPw)FJu$gAMg)%KW13K$n7r8<4{BEU74}vv* z`&yq8;T4|#pvQ+jTzR#b&*%g9&S0CLcfu12{lUY+Old`PI){tjJfkhXFT~{&mVgzV zn(&vM`Kah)7+%WgWSv_RKvyuaV}0p!PW~;+CcSE4)+B#c&$h4e)L!zTyou{e(Cj4O zpB(m?$5)xX29bjo!Tj&JDWk>MIkX?V|IQC)(D^89*&Ey(t_oBUAro~Cpm(5jD3$Jjp+9NiCFcX^!P5|k zT+vMTyjY0YobVGxfw~#fQE2)pv@2MX9F=+;xfX1t0@p4g-;YZHv&@8z z&KX#c7LF!^@8E&rXee5hjnq$z>7d==!2aVry2mFQJWFg$RJy8hu~Ig?LY+p%#QB#k z?CS2)6`GL#vh~xGkFY`HFQdET5{3%?r2bvyM!3X*T(f6g3fVTNF z`tIp7_*=fJFI&#Vf*;TBZET#H8n(;2G4}mn_P^n)Zv3C$zjp+VR~CZR3O%pl;e{k? z{F3cO25_$8`iaG~s}Yw2RdXES>c$~}7FvNk#q;(vx8n)c_~rMUbOx1*^OfCRI7L3+ z%YwoCNKyGu#NA9Oe5%m%dRq_(WR@Gb`ZM=MAX$PZWw*)^j^^nPKJ@J3@RMVX;4yBS z5r}n$6iQQsWtnvGIJ@pj9*B{)c9r6|a{_ZBU z_~MuAtM&eqxb~CNGpNv(aM&_-6EaYdnLT7 z-~MXVDbR|iKNxULt`{5Se;xPwBNZLAoCt@M%CE1^MXN}Csx&zNlGnS^#+{?^!iZnV z=YeOz;;~_9tV@4<@xB}B4zpmxrwG9MQv6dM7ms=M?qKR_`B+xA{q^s*i1QddFm}B- z@H=4KGW2u5RLmv;za>WSR8R`)o4FG2n>qn(E{&&_-wc2ov|YfkL{(_uk$^5$yWnRz zKIAXus6A_y~HCLSA`}E(?@&elnnXISM2>@&Ody`rrZB%G0u$wdJ4W8mv2Y1#;>p@{Q(PKD|dtntflZ8HFgJiam;DF6OVJ+y=*^w)jhFgMld7JJ1!nqimh8*@Qn_h3hfC6Dl4Dy&6O;3d;3A&> zpiaM74nIF^0T4X5C1d-o{;WSZM&q7{HGcmF!cc;*KiJc*^DEqRM<}Y`>EkT6y~!P) zHj5F`k~URImVPLTR+jS>>$~B`77l+gxd+i-_on2!I`e&|!v99Ss}k1u?W;-+pqI)Q z|C)#huK&HWVo6!n0^*@DqpzsYA8e=(k+h76=kSTN0i(;!e9LouDtUTU3@E_PXzzd` zq_eIcd2c=`dGb_G%=$9l;TJ9*L0vrnO@96Eb@Gl1j-#@5AlWbV%R4#N$Ex>_fSY$X zN*QR3XEk?{)v5!e(N!(tq`Vq(^ngp?yz3&Qx>F51dKrSlUcMt+^B;rs za5uDB#~e?*Ly)N+p9q(na;bJo9O$dA3o}O?N9S=e4qd;ARJz?0UURJ>*_k<(r6iFThC5_jPmE*2wwJK@G6BckBCir8by4dDjo&EUZg`Y?HH66$)B zf#PpOkbQ3cLXvfp2{wN+RvNaV?yiKVUUFf2i@Au@_ zSDWTC^CK|E?;p3$dw%sTR(~S|`SbYdh}AmI|ClwKZ6B0)*sNO`g2W2GVtt>XnA_#y zaTnphQgd6Cam;vJh5t zSUHA_*gpNMw)y?wud_b(J%0>Ti5DTAUA1VcW}|fQ-$+hdvIiWRNg}(4 zg(%|nL*iF*qctM+-FHgdqkj;yIg!xyJ9k`{6sA+}9L5rw4nGQ0_RDO)v%VuOvw6c|soQQ- zFI}e*N40|`F@2|quel#3XPe#!TdzY@lOn}EZ-tSbA>rcpB6rah_XtU(4b7E%b~YCd zZg?h@>^B$AGf=m6vo!rsDiIptSrog%Yh$qMvp6r>SZ~onVFwd!BYc?}4lkIk zY2#t>$hx!k1PD;@RjIopnHoKttABdpZrjk3RW|$ME`l%~UoBZEzrN{OSZI6Ic!y1E z#bvOC$5+!A)N|$MofQb1K55zhEEx1zfAG*FGZAb2{&DO73twqZ3qd1!eAV-@eC{|? zdYx61(xh>_Iya&&CHeIg>wE1X`SZI6Z;*Aow0S<~JP20sRmql8@xasa@7``m5`-tsm)QR0okV2z5P>xw8YpkB z9eP=oPCVU_I8I~eN=6?+N$F>SeEjL1;~hk8?w2v%{62iU&iYuE84uznIHKw!htb78 zn@9&eUn^A|$v8-jB9;Bu1I<4Np-b*mMdEe`1C-?)Je$ z8mEvs_e_O)WnDI-hgeF+%H+A)?zREum=sDal6KlWP+l(ZHmD+h{o^9=HeQJIw^$($ zfgu^O;Hs^9NU{x^KU!|Tf*9n7{BGG`QQANfwvQ5)f9T147xDM`ijC9RJzw7688Zj@ TPsVb4C@Bq79B|KxrGx(myYz30