NodeObservation

NodeObservation(
    data,
    *,
    at,
    item=None,
    name=None,
    weight=1.0,
    quantity=None,
    aux_items=None,
    attrs=None,
    position_tol=None,
)

Class for observations at network nodes.

Create a NodeObservation from a DataFrame or other data source. The at parameter accepts two forms:

  • str — the node’s name in the model (e.g. a Res1D node name).
  • tuple[str, float] — a breakpoint, as (reach_id, position) along a reach.

Both are resolved against the network when the observation is matched.

.. note:: “Node” in this API follows the broad graph sense: it covers both junctions (named connection points) and chainage points (breakpoints along a reach). MIKE 1D users who distinguish node (junction) from gridpoint sharply can use the (reach_id, position) tuple form to target a specific chainage point, or :class:ReachObservation when the quantity is uniform across the whole reach and any breakpoint will do.

To create multiple NodeObservation objects from a single data source, use :meth:from_multiple.

Parameters

Name Type Description Default
data (str, Path, mikeio.Dataset, mikeio.DataArray, pd.DataFrame, pd.Series, xr.Dataset or xr.DataArray) data source with time series for the node required
at str or tuple[str, float] Observation location. Accepted forms: * str — the node’s name in the model (e.g. a Res1D node name). * tuple[str, float] — a breakpoint, as (reach_id, position). required
item (int, str) index or name of the wanted item/column, by default None if data contains more than one item, item must be given None
name str user-defined name for easy identification in plots etc, by default derived from data None
weight float weighting factor for skill scores, by default 1.0 1.0
quantity Quantity The quantity of the observation, for validation with model results None
aux_items list list of names or indices of auxiliary items, by default None None
attrs dict additional attributes to be added to the data, by default None None
position_tol float How far the position in at may be from a model breakpoint and still match it. The nearest breakpoint inside it that carries the model result’s item is used. By default None, which absorbs only rounding (mikeio1d’s 1e-3). Ignored for a node name. None

Raises

Name Type Description
ValueError If position_tol is negative or not finite.

Examples

>>> import modelskill as ms
>>> o1 = ms.NodeObservation(data, at="123", name="123")
>>> o2 = ms.NodeObservation(df, item="Water Level", at="456")
>>>
>>> # String alias resolved at match time
>>> o3 = ms.NodeObservation(data, at="node_A")
>>>
>>> # Breakpoint as (reach_id, position) tuple
>>> o4 = ms.NodeObservation(data, at=("reach_1", 24.5))
>>>
>>> # A measured chainage, snapped onto the nearest breakpoint within 0.5
>>> o5 = ms.NodeObservation(data, at=("reach_1", 24.0), position_tol=0.5)
>>>
>>> # Multiple node observations from separate data sources
>>> obs = ms.NodeObservation.from_multiple(nodes={"123": df1, "456": df2})

Attributes

Name Description
at Observation location: a node name, or a (reach_id, position) breakpoint.
attrs Attributes of the observation
gtype Geometry type
n_points Number of data points
name Name of time series (value item name)
node Name of the node this observation sits at, or None for a break point.
plot Plot using the ComparerPlotter
quantity Quantity of time series
time Time index
values Values as numpy array
weight Weighting factor for skill scores
x x-coordinate
y y-coordinate

Methods

Name Description
copy Create a deep copy of the TimeSeries.
equals Check if two TimeSeries are equal
from_multiple Create multiple NodeObservation objects.
sel Select data by label
to_dataframe Convert matched data to pandas DataFrame
trim Trim observation data to a given time interval

copy

NodeObservation.copy()

Create a deep copy of the TimeSeries.

Returns

Name Type Description
TimeSeries Deep copy of the TimeSeries object

equals

NodeObservation.equals(other)

Check if two TimeSeries are equal

from_multiple

NodeObservation.from_multiple(
    data=None,
    nodes=None,
    quantity=None,
    aux_items=None,
    attrs=None,
    position_tol=None,
)

Create multiple NodeObservation objects.

Two calling conventions are supported:

  1. Separate data sources — pass only nodes as a dict mapping each node ID to its own data source (file path, DataFrame, etc.)::

    obs = NodeObservation.from_multiple(nodes={"123": df1, "456": "sensor.csv"})
  2. Shared data source — pass a single data object together with nodes as a dict mapping each node ID to the column name or index to select from data::

    obs = NodeObservation.from_multiple(data=df, nodes={"123": "col_a", "456": "col_b"})

Parameters

Name Type Description Default
data PointType Shared data source (required when nodes values are column selectors). None
nodes dict[str | tuple[str, float], PointType | str | int] Mapping of location -> data source or column selector. A location takes either of the forms accepted by at: a node name, or a (reach_id, position) breakpoint. Note that a location can appear only once, so this form cannot express several observations at the same node. None
quantity Quantity Physical quantity metadata, by default None. None
aux_items list[int | str] | None Auxiliary items, by default None. None
attrs dict | None Additional attributes, by default None. None
position_tol float Tolerance for every breakpoint position, as in NodeObservation, by default None. None

Returns

Name Type Description
list[NodeObservation] List of NodeObservation objects.

Raises

Name Type Description
ValueError If nodes is not given.

sel

NodeObservation.sel(**kwargs)

Select data by label

to_dataframe

NodeObservation.to_dataframe()

Convert matched data to pandas DataFrame

Include x, y coordinates only if gtype=track

Returns

Name Type Description
pd.DataFrame data as a pandas DataFrame

trim

NodeObservation.trim(
    start_time=None,
    end_time=None,
    buffer='1s',
    no_overlap='error',
)

Trim observation data to a given time interval

Parameters

Name Type Description Default
start_time pd.Timestamp start time None
end_time pd.Timestamp end time None
buffer str buffer time around start and end time, by default “1s” '1s'
no_overlap Literal['ignore', 'error', 'warn'] Empty data handling. 'error'