Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
21265dc
Record the decision to move the network topology layer to mikeio1d
jpalm3r Aug 13, 2026
9d3d1c6
Note the proposed move to mikeio1d in the network roadmap entry
jpalm3r Aug 13, 2026
4c8e92d
Accept ADR-013 now that the upstream module exists
jpalm3r Aug 25, 2026
c9dc5b1
Locate network observations with a MIKE+ database
jpalm3r Aug 25, 2026
34d3aad
Document locating observations from a MIKE+ database
jpalm3r Aug 11, 2026
62486c7
Identify a network timeseries by name, not by graph integer
jpalm3r Aug 25, 2026
72ec69d
Take the network topology layer from mikeio1d
jpalm3r Aug 25, 2026
f6765b6
Build the network model result on mikeio1d's topology layer
jpalm3r Aug 25, 2026
dfc9fe4
Drop the integer form of NodeObservation's at=
jpalm3r Aug 25, 2026
7f9efc6
Point the docs and the records at the upstream module
jpalm3r Aug 25, 2026
c81faf3
Keep a 1.4.0a3 comparer loading
jpalm3r Aug 25, 2026
c9ef75b
Say plainly what the ADRs now record
jpalm3r Aug 25, 2026
6999d61
Cut the flourishes from the network ADRs
jpalm3r Aug 25, 2026
181b2b5
merge latest changes from main
jpalm3r Sep 3, 2026
a178762
Potential fix for pull request finding 'Statement has no effect'
jpalm3r Sep 3, 2026
8294657
Potential fix for pull request finding 'Statement has no effect'
jpalm3r Sep 3, 2026
64bb87a
Potential fix for pull request finding 'Statement has no effect'
jpalm3r Sep 3, 2026
27babc8
Merge branch 'network-phase-2' of https://github.com/DHI/modelskill i…
jpalm3r Sep 3, 2026
62df504
Add reach branch to Comparer.to_dataframe
jpalm3r Sep 3, 2026
904e5f0
Guard node extraction against locations with no data
jpalm3r Sep 3, 2026
ec14d7b
Fix Option B breakpoint example in the network guide
jpalm3r Sep 3, 2026
38c120e
Match MIKE+ source on the file name, not a substring
jpalm3r Sep 3, 2026
1123857
Keep unclassifiable MIKE+ stations from aborting a resolve
jpalm3r Sep 3, 2026
04e93ad
Treat a Quantity passed with db= as metadata only
jpalm3r Sep 3, 2026
71be06c
Rewrite ADR-013 to the point
jpalm3r Sep 3, 2026
137dfaf
Move the network location reader next to NodeObservation
jpalm3r Sep 3, 2026
3fcea06
Read a NodeObservation's location through one function
jpalm3r Sep 3, 2026
f5d4711
State the network-coordinate rule once, on GeometryType
jpalm3r Sep 3, 2026
52f0711
Read a coordinate off a dataset through one function
jpalm3r Sep 3, 2026
525e876
Take the network vocabulary off the TimeSeries base
jpalm3r Sep 3, 2026
a5b0ae2
Give the network parsers a module of their own
jpalm3r Sep 3, 2026
4a50c0d
Name the network scope in from_network_coords
jpalm3r Sep 4, 2026
c6beb58
Keep the coordinate reader in the coordinate module
jpalm3r Sep 4, 2026
50fe132
Read a network location from the coordinate module
jpalm3r Sep 4, 2026
aac8db1
Test the network module through its public surface
jpalm3r Sep 4, 2026
a8ba234
Reach the network comparers through modelskill's own names
jpalm3r Sep 4, 2026
bc6e446
Match a reach observation end to end
jpalm3r Sep 4, 2026
dffb909
Run the doctests that state the network-coordinate rule
jpalm3r Sep 4, 2026
61babd0
Moving constant
jpalm3r Sep 4, 2026
9b5d164
Fix network plotting in example notebook
jpalm3r Sep 4, 2026
0be65c2
Include tests for network values passed to the comparer
jpalm3r Sep 4, 2026
d2995a1
Reusing existing fixtures
jpalm3r Sep 4, 2026
173fe46
Move function to network_helpers
jpalm3r Sep 4, 2026
77545a1
Assert the network values survive item selection and the file path
jpalm3r Sep 4, 2026
5f4d838
Remove NetworkModelResult.nodes
jpalm3r Sep 4, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ jobs:
version: "1.8.27"

- name: Install dependencies
run: uv sync --group dev --group docs --group networks
run: uv sync --group dev --group docs --group network

- name: Build documentation
run: just docs
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/full_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ jobs:
enable-cache: true

- name: Install dependencies
run: uv sync --group test --group networks --no-dev
run: uv sync --group test --group network --no-dev

- name: Install pandas 2.x
if: matrix.pandas-version == 'pandas2'
Expand All @@ -57,7 +57,7 @@ jobs:
- name: Test
run: just test

build-no-networks:
build-no-network:
runs-on: ubuntu-latest

steps:
Expand All @@ -71,7 +71,7 @@ jobs:
python-version: "3.12"
enable-cache: true

- name: Install dependencies (without networks)
- name: Install dependencies (without network)
run: uv sync --group test --no-dev

- name: Test
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/notebooks_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
python-version: "3.14"
enable-cache: true
- name: Install dependencies
run: uv sync --group test --group notebooks --group networks --no-dev
run: uv sync --group test --group notebooks --group network --no-dev
- name: Test notebooks
run: |
uv run pytest tests/notebooks/
5 changes: 4 additions & 1 deletion adr/010-optional-domain-dependencies.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,10 @@ Installation: `pip install modelskill modelskill-network`

**Open Questions:**
- Should `modelskill[all]` install all optional model types?
- How to handle version constraints for optional dependencies?
- How to handle version constraints for optional dependencies? Answered for network
support by [ADR-013](013-network-topology-in-mikeio1d.md): the `network` extra names a
minimum mikeio1d, because the topology layer ships there. Network support requires
whatever Python that release requires.
- Should optional dependencies be tested in CI for every commit or separately?

## Status Notes
Expand Down
12 changes: 11 additions & 1 deletion adr/012-network-format-constructors.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
# ADR-012: One Network Constructor per Modelling Product

**Status**: Draft
**Status**: Accepted, narrowed by [ADR-013](013-network-topology-in-mikeio1d.md)

**Date**: 2026-08

## Narrowed by ADR-013

The constructors, the companion arguments, the extension tables, the coverage test and the
`.inp` reader are mikeio1d's. It replaced `from_mike` and `from_epanet` with one
`Network.open` that reads the extension. Naming a constructor after the product that wrote
the file is still the rule, and mikeio1d applies it.

`NetworkModelResult` hands a path to mikeio1d. The refusal messages for `.out`, `.resx`
and the formats without a fixture are written there.

## Context

`Network` is built from result files read through mikeio1d, whose 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 — making the name promise one format while reading nine.
Expand Down
59 changes: 59 additions & 0 deletions adr/013-network-topology-in-mikeio1d.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# ADR-013: The Network Topology Layer Belongs to mikeio1d

**Status**: Accepted

**Date**: 2026-08

## Context

`modelskill.network` had grown to roughly 630 lines of topology: the abstract node/reach/breakpoint types, a `Res1D` adapter, one constructor per modelling product, the `.resx` and `.inp` companions,
tables of which extensions we refuse and why, a networkx graph carrying reach lengths and boundary edges, an alias map, and `find`/`recall`/`to_dataset` on top. `NetworkModelResult` uses five members
of `Network`, two of them private, and never traverses the graph. mikeio1d's `experimental.to_networkx` converts the same files in 25 lines and ignores gridpoints.

That leaves us on the far side of the line ADR-001 drew for mikeio, where we call `mikeio.read()` and stop, modelling no dfsu geometry and policing no format list. `Res1D` reads nine extensions across
five products. Our tables decide which of the nine we accept, and a test fails our CI when a mikeio1d release adds a tenth. The fixtures those tables are checked against are copies of mikeio1d's own:
`network.res1d`, `network_cali.res11`, `epanet.res/.resx/.inp`.

## Decision

mikeio1d gains an optional network module that builds and owns `Network`. modelskill requires it and consumes what it produces.

| Owner | Pieces |
|---|---|
| mikeio1d | abstract types and `BasicNode`/`BasicReach`, the `Res1D` adapter, `Network.open`, the `.resx` and `.inp` companions, the extension policy tables, graph construction with its length and boundary semantics, the alias map, `find`, `recall`, `to_dataframe`, `to_dataset` |
| modelskill | `NetworkModelResult`, `NodeModelResult`, `NodeObservation`, `ReachObservation`, matching, the MIKE+ station resolver |

`NetworkModelResult` takes a `Network` the upstream module built, or a path it hands to that module. The module is an extra there, carrying networkx and xarray, so `to_dataset()` ships with the class.
modelskill's `network` extra requires a mikeio1d release new enough to contain it.

Original IDs become the only identifier a user handles: `NodeObservation.at` takes a node name or a `(reach, distance)` pair, and no longer an integer. The alias integers stay an internal index,
because the ID space mixes names and break points and a tuple cannot be an xarray coordinate value. A saved comparer records the original ID with the integer beside it as `node_index`, so reloading
does not depend on the numbering the installed mikeio1d handed out.

The loader's output over six fixture loads was recorded before anything moved — graph edges with their lengths and boundary flags, the alias map, the dataframe, and every answer `find` and `recall`
give. Those snapshots are the upstream module's acceptance test. Phase 1 landed as mikeio1d [#247](https://github.com/DHI/mikeio1d/pull/247), merged 2026-08-19. The snapshots pass there unchanged
twice: against the code moved verbatim, and again after the two product constructors collapsed into `Network.open`.

modelskill 1.4.0 waits for the mikeio1d release carrying the module, which is not out yet.

## Alternatives Considered

**Keep the layer here.** Defensible while the API is private. Costs a format matrix, an EPANET `.inp` parser and a graph contract for traversals we never perform.

**Move only the constructors and companions**, leaving the graph and the abstract types here. Splits the format knowledge from the topology it produces, and leaves `Res1DReach` here as the single
adapter for a plug point with no second implementation.

**A separate `modelskill-network` package.** Rejected in ADR-010 for fragmenting the install. It would still own format knowledge that belongs with mikeio1d.

**Ask mikeio1d to guarantee stable node numbering** instead of dropping integers from our API. Puts a promise on someone else's release process, to protect a number users should not be handling.

## Consequences

- ADR-012 is narrowed: the constructors, the companion arguments, the extension tables and the coverage test become mikeio1d's. Naming a constructor after the product that wrote the file is still the
rule, and mikeio1d applies it.
- ADR-010's open question about version constraints for optional dependencies is answered for this feature: the `network` extra pins a minimum mikeio1d, and network support requires whatever Python
that release requires.
- A hand-built network needs mikeio1d installed, since `BasicNode`/`BasicReach` move too. That costs a .NET dependency for users who touch no MIKE file, which only matters for tests and for a backend
nobody has written.
- Dropping `at=<int>` breaks a signature that shipped in the 1.4.0a3 alpha only, while the network module is opt-in and absent from the API reference. Removing it after 1.4.0 would cost more.
- Releases become coupled in one direction: a fix to network file reading ships on mikeio1d's schedule. A format mikeio1d adds no longer breaks our CI.
3 changes: 2 additions & 1 deletion adr/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ 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)
- [ADR-012](012-network-format-constructors.md) - One Network constructor per modelling product (narrowed by ADR-013)
- [ADR-013](013-network-topology-in-mikeio1d.md) - The network topology layer belongs to mikeio1d

## Contributing

Expand Down
Binary file removed docs/images/res1d_network_mapping.png
Binary file not shown.
Loading
Loading