Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
82 commits
Select commit Hold shift + click to select a range
a76005c
Add NetworkModelResult and supporting classes for network data handling
jpalm3r Feb 18, 2026
e4d9362
Simplify parsing logic
jpalm3r Feb 18, 2026
d0c0f92
feat: Add NetworkModelResult for handling network data in model skill
jpalm3r Feb 19, 2026
91d4513
small fixes
jpalm3r Feb 19, 2026
3d7df6c
feat: Add NodeModelResult and NodeObservation for network node handling
jpalm3r Feb 19, 2026
1fc1ecf
feat: Add extract_multiple method for batch extraction of NodeModelRe…
jpalm3r Feb 19, 2026
35882ab
feat: Enhance matching functionality to support NodeModelResult and N…
jpalm3r Feb 19, 2026
5a692ef
feat: Update matching logic to extract observations from NetworkModel…
jpalm3r Feb 19, 2026
e15ae63
feat: Add NetworkObservation class for handling collections of node o…
jpalm3r Feb 19, 2026
1219a51
Fix test
jpalm3r Feb 19, 2026
98f8a80
Importing network test data
jpalm3r Feb 19, 2026
91daa72
feat: Update observation handling to include NodeObservation and adju…
jpalm3r Feb 20, 2026
26a6d45
feat: Simplify node retrieval in NodeModelResult and enhance coordina…
jpalm3r Feb 20, 2026
89d4925
feat: Enhance time coordinate handling in NetworkModelResult and impr…
jpalm3r Feb 20, 2026
caeee13
feat: Refactor observation handling to support network geometry and s…
jpalm3r Feb 20, 2026
c8c3ebd
refactor: Simplify node retrieval in NodeObservation by removing unne…
jpalm3r Feb 20, 2026
f826ea5
Update src/modelskill/matching.py
jpalm3r Feb 20, 2026
87e1335
commit with errors
jpalm3r Feb 20, 2026
a4476ad
Fix mypy issues. Introduce Nework1D protocol
jpalm3r Feb 20, 2026
0966458
Removing NetworkObservation
jpalm3r Feb 20, 2026
4e5cd78
refactor: streamline NetworkModelResult extraction method by removing…
jpalm3r Feb 20, 2026
0f5af4d
refactor: simplify observation matching logic in _match_single_obs fu…
jpalm3r Feb 20, 2026
d32e337
fix: add assertion message for non-empty datetime indices in _get_glo…
jpalm3r Feb 20, 2026
636bc0f
test: add unit tests for NetworkModelResult and NodeObservation classes
jpalm3r Feb 20, 2026
6bfa6bc
refactor: update notebook to use new network dataset and remove obsol…
jpalm3r Feb 20, 2026
f91a4df
Rename notebook
jpalm3r Feb 20, 2026
e42c69e
Enhance NodeObservation to support multiple nodes and auto-assign items
jpalm3r Feb 20, 2026
4cc16bf
Create MultiNodeObservation
jpalm3r Feb 23, 2026
dd91c65
refactor: streamline MultiNodeObservation initialization and enhance …
jpalm3r Feb 23, 2026
6298695
Add basic tests
jpalm3r Feb 23, 2026
902551b
feat: add validation function for network data and enhance NetworkTyp…
jpalm3r Feb 23, 2026
c77e86c
Add aux_item in NetworkModelResult
jpalm3r Feb 23, 2026
197e01f
merge latest changes
jpalm3r Feb 23, 2026
3cd7404
Removing obsolete tests
jpalm3r Feb 23, 2026
eb57ed2
feat: enhance NodeObservation and TimeSeries classes with Self type h…
jpalm3r Feb 24, 2026
6e4fc6b
Improting Self from typing_extension
jpalm3r Feb 24, 2026
4bded79
fix: correct typo in FieldTypes definition in matching.py
jpalm3r Feb 24, 2026
4fd5888
feat: add Self type hint and instance creation method to NodeModelResult
jpalm3r Feb 24, 2026
45e21fa
fix: remove NodeModelResult from Timeseries documentation
jpalm3r Feb 24, 2026
8d7c66d
Improving ValueError message
jpalm3r Feb 24, 2026
75a5db8
fix test valueerror message
jpalm3r Feb 24, 2026
2606a27
refactor: replace NETWORK geometry type with NODE in relevant modules
jpalm3r Feb 24, 2026
7b55d95
feat: handle NODE geometry type in TimeSeries class for data conversion
jpalm3r Feb 24, 2026
c1b505c
typo
jpalm3r Feb 24, 2026
ac09177
Removing some Optional statements
jpalm3r Feb 24, 2026
ad757a5
Replacing All Optional[...] statements
jpalm3r Feb 24, 2026
c023fb1
unused import
jpalm3r Feb 24, 2026
b124569
Replace assert by if... raise ValueError()
jpalm3r Feb 24, 2026
3deeeac
Updating obsolete tests
jpalm3r Feb 24, 2026
ac0da42
Refactor time series alignment: move align_data and helper functions …
jpalm3r Feb 24, 2026
1a98701
Simplifying tests.
jpalm3r Feb 24, 2026
8c48d5d
Refactor type hints: replace Optional with union types for improved c…
jpalm3r Feb 24, 2026
8ec880d
leftovers
jpalm3r Feb 24, 2026
769f1e2
Fix mypy error
jpalm3r Feb 24, 2026
8f47b36
Remove obsolete test
jpalm3r Feb 24, 2026
a01c696
Remove redundant check
jpalm3r Feb 24, 2026
3a4deca
Correct type.
jpalm3r Feb 24, 2026
3090bf1
Remove legacy Geometry.Network instances
jpalm3r Feb 25, 2026
f49d955
Newer tests for matching network results
jpalm3r Feb 25, 2026
82e50f2
Adding test for wrong matching
jpalm3r Feb 25, 2026
f65c833
Typo
jpalm3r Feb 25, 2026
1ae8fdc
Merge changes after round of review
jpalm3r Feb 25, 2026
5e82a12
Fix network validation
jpalm3r Feb 25, 2026
1455362
remove empty step in notebook
jpalm3r Feb 25, 2026
ca0b332
Remove empty cell
jpalm3r Feb 25, 2026
82a619b
Fix tests
jpalm3r Feb 25, 2026
467989e
remove detailed docstring
jpalm3r Feb 26, 2026
80f50b8
Including mapping as nodes argument
jpalm3r Feb 26, 2026
140ae33
Make MultiNodeObservation a Collection
jpalm3r Feb 26, 2026
eb49cc9
fix contains from MultiNodeObservation
jpalm3r Feb 26, 2026
3a64c37
improve notebook
jpalm3r Feb 26, 2026
e366942
Replace MultiNodeObservation by classmethod
jpalm3r Feb 26, 2026
3070b07
Remove unused import
jpalm3r Feb 27, 2026
4d130a5
Replace MultiNodeObservation for class method in NodeObservation
jpalm3r Feb 27, 2026
bf0296a
Save new nb
jpalm3r Feb 27, 2026
ceac146
Include csv to read a point
jpalm3r Feb 27, 2026
f11fb31
Refactor NodeObservation.from_multiple to handle optional data and im…
jpalm3r Feb 27, 2026
8f0dc68
Improving notebook and comitting test sensor data
jpalm3r Feb 27, 2026
369ba44
Including overload
jpalm3r Feb 27, 2026
aba3c59
comment out script for saving test data
jpalm3r Feb 27, 2026
9c054f2
Including new tests
jpalm3r Feb 27, 2026
6104e77
Merge pull request #588 from DHI/japr/multinodeobs
jpalm3r Feb 27, 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
1,386 changes: 1,386 additions & 0 deletions notebooks/Collection_systems_network.ipynb

Large diffs are not rendered by default.

9 changes: 4 additions & 5 deletions src/modelskill/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,10 @@
TrackModelResult,
GridModelResult,
DfsuModelResult,
NetworkModelResult,
DummyModelResult,
)
from .obs import (
observation,
PointObservation,
TrackObservation,
)
from .obs import observation, PointObservation, TrackObservation, NodeObservation
from .matching import from_matched, match
from .configuration import from_config
from .settings import options, get_option, set_option, reset_option, load_style
Expand Down Expand Up @@ -94,9 +91,11 @@ def load(filename: Union[str, Path]) -> Comparer | ComparerCollection:
"GridModelResult",
"DfsuModelResult",
"DummyModelResult",
"NetworkModelResult",
"observation",
"PointObservation",
"TrackObservation",
"NodeObservation",
"TimeSeries",
"match",
"from_matched",
Expand Down
17 changes: 8 additions & 9 deletions src/modelskill/comparison/_collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
Iterator,
List,
Union,
Optional,
Mapping,
Iterable,
overload,
Expand Down Expand Up @@ -286,13 +285,13 @@ def merge(

def sel(
self,
model: Optional[IdxOrNameTypes] = None,
observation: Optional[IdxOrNameTypes] = None,
quantity: Optional[IdxOrNameTypes] = None,
start: Optional[TimeTypes] = None,
end: Optional[TimeTypes] = None,
time: Optional[TimeTypes] = None,
area: Optional[List[float]] = None,
model: IdxOrNameTypes | None = None,
observation: IdxOrNameTypes | None = None,
quantity: IdxOrNameTypes | None = None,
start: TimeTypes | None = None,
end: TimeTypes | None = None,
time: TimeTypes | None = None,
area: List[float] | None = None,
**kwargs: Any,
) -> "ComparerCollection":
"""Select data based on model, time and/or area.
Expand Down Expand Up @@ -572,7 +571,7 @@ def gridded_skill(
binsize: float | None = None,
by: str | Iterable[str] | None = None,
metrics: Iterable[str] | Iterable[Callable] | str | Callable | None = None,
n_min: Optional[int] = None,
n_min: int | None = None,
**kwargs: Any,
) -> SkillGrid:
"""Skill assessment of model(s) on a regular spatial grid.
Expand Down
51 changes: 25 additions & 26 deletions src/modelskill/comparison/_collection_plotter.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
List,
Literal,
Mapping,
Optional,
Sequence,
Tuple,
Union,
Expand Down Expand Up @@ -60,19 +59,19 @@ def scatter(
quantiles: int | Sequence[float] | None = None,
fit_to_quantiles: bool = False,
show_points: bool | int | float | None = None,
show_hist: Optional[bool] = None,
show_density: Optional[bool] = None,
norm: Optional[colors.Normalize] = None,
show_hist: bool | None = None,
show_density: bool | None = None,
norm: colors.Normalize | None = None,
backend: Literal["matplotlib", "plotly"] = "matplotlib",
figsize: Tuple[float, float] = (8, 8),
xlim: Optional[Tuple[float, float]] = None,
ylim: Optional[Tuple[float, float]] = None,
xlim: Tuple[float, float] | None = None,
ylim: Tuple[float, float] | None = None,
reg_method: str | bool = "ols",
title: Optional[str] = None,
xlabel: Optional[str] = None,
ylabel: Optional[str] = None,
skill_table: Optional[Union[str, List[str], Mapping[str, str], bool]] = None,
ax: Optional[Axes] = None,
title: str | None = None,
xlabel: str | None = None,
ylabel: str | None = None,
skill_table: Union[str, List[str], Mapping[str, str], bool] | None = None,
ax: Axes | None = None,
**kwargs,
) -> Axes | list[Axes]:
"""Scatter plot tailored for comparing model output with observations.
Expand Down Expand Up @@ -190,17 +189,17 @@ def _scatter_one_model(
quantiles: int | Sequence[float] | None,
fit_to_quantiles: bool,
show_points: bool | int | float | None,
show_hist: Optional[bool],
show_density: Optional[bool],
show_hist: bool | None,
show_density: bool | None,
backend: Literal["matplotlib", "plotly"],
figsize: Tuple[float, float],
xlim: Optional[Tuple[float, float]],
ylim: Optional[Tuple[float, float]],
xlim: Tuple[float, float] | None,
ylim: Tuple[float, float] | None,
reg_method: str | bool,
title: Optional[str],
xlabel: Optional[str],
ylabel: Optional[str],
skill_table: Optional[Union[str, List[str], Mapping[str, str], bool]],
title: str | None,
xlabel: str | None,
ylabel: str | None,
skill_table: Union[str, List[str], Mapping[str, str], bool] | None,
ax,
**kwargs,
):
Expand Down Expand Up @@ -344,11 +343,11 @@ def hist(
bins: int | Sequence = 100,
*,
model: str | int | None = None,
title: Optional[str] = None,
title: str | None = None,
density: bool = True,
alpha: float = 0.5,
ax=None,
figsize: Optional[Tuple[float, float]] = None,
figsize: Tuple[float, float] | None = None,
**kwargs,
):
"""Plot histogram of specific model and all observations.
Expand Down Expand Up @@ -409,11 +408,11 @@ def _hist_one_model(
*,
mod_name: str,
bins: int | Sequence,
title: Optional[str],
title: str | None,
density: bool,
alpha: float,
ax,
figsize: Optional[Tuple[float, float]],
figsize: Tuple[float, float] | None,
**kwargs,
):
from ._comparison import MOD_COLORS
Expand Down Expand Up @@ -464,7 +463,7 @@ def taylor(
marker: str = "o",
marker_size: float = 6.0,
title: str = "Taylor diagram",
) -> Optional[Figure]:
) -> Figure | None:
"""Taylor diagram for model skill comparison.

Taylor diagram showing model std and correlation to observation
Expand Down Expand Up @@ -783,8 +782,8 @@ def _residual_hist_one_model(
def spatial_overview(
self,
ax=None,
figsize: Optional[Tuple] = None,
title: Optional[str] = None,
figsize: Tuple | None = None,
title: str | None = None,
) -> Axes:
"""Plot observation points on a map showing the model domain

Expand Down
48 changes: 27 additions & 21 deletions src/modelskill/comparison/_comparer_plotter.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
Literal,
Union,
List,
Optional,
Tuple,
Sequence,
TYPE_CHECKING,
Expand Down Expand Up @@ -464,19 +463,19 @@ def scatter(
quantiles: int | Sequence[float] | None = None,
fit_to_quantiles: bool = False,
show_points: bool | int | float | None = None,
show_hist: Optional[bool] = None,
show_density: Optional[bool] = None,
norm: Optional[colors.Normalize] = None,
show_hist: bool | None = None,
show_density: bool | None = None,
norm: colors.Normalize | None = None,
backend: Literal["matplotlib", "plotly"] = "matplotlib",
figsize: Tuple[float, float] = (8, 8),
xlim: Optional[Tuple[float, float]] = None,
ylim: Optional[Tuple[float, float]] = None,
xlim: Tuple[float, float] | None = None,
ylim: Tuple[float, float] | None = None,
reg_method: str | bool = "ols",
title: Optional[str] = None,
xlabel: Optional[str] = None,
ylabel: Optional[str] = None,
skill_table: Optional[Union[str, List[str], Mapping[str, str], bool]] = None,
ax: Optional[matplotlib.axes.Axes] = None,
title: str | None = None,
xlabel: str | None = None,
ylabel: str | None = None,
skill_table: Union[str, List[str], Mapping[str, str], bool] | None = None,
ax: matplotlib.axes.Axes | None = None,
**kwargs,
) -> matplotlib.axes.Axes | list[matplotlib.axes.Axes]:
"""Scatter plot tailored for model-observation comparison.
Expand Down Expand Up @@ -594,18 +593,18 @@ def _scatter_one_model(
quantiles: int | Sequence[float] | None,
fit_to_quantiles: bool,
show_points: bool | int | float | None,
show_hist: Optional[bool],
show_density: Optional[bool],
norm: Optional[colors.Normalize],
show_hist: bool | None,
show_density: bool | None,
norm: colors.Normalize | None,
backend: Literal["matplotlib", "plotly"],
figsize: Tuple[float, float],
xlim: Optional[Tuple[float, float]],
ylim: Optional[Tuple[float, float]],
xlim: Tuple[float, float] | None,
ylim: Tuple[float, float] | None,
reg_method: str | bool,
title: Optional[str],
xlabel: Optional[str],
ylabel: Optional[str],
skill_table: Optional[Union[str, List[str], Mapping[str, str], bool]],
title: str | None,
xlabel: str | None,
ylabel: str | None,
skill_table: Union[str, List[str], Mapping[str, str], bool] | None,
**kwargs,
):
"""Scatter plot for one model only"""
Expand Down Expand Up @@ -746,7 +745,14 @@ def taylor(
df = df.rename(columns={"_std_obs": "obs_std", "_std_mod": "std"})

pts = [
TaylorPoint(name=r.model, obs_std=r.obs_std, std=r.std, cc=r.cc, marker=marker, marker_size=marker_size)
TaylorPoint(
name=r.model,
obs_std=r.obs_std,
std=r.std,
cc=r.cc,
marker=marker,
marker_size=marker_size,
)
for r in df.itertuples()
]

Expand Down
Loading
Loading