sequencetools¶
This module implements tools for defining and handling different kinds of hydrological model sequences (time series).
Module sequencetools
implements the following members:
TypeFastAccessIOSequence_co
Type variable.
TypeIOSequence_co
Type variable.
TypeLinkSequence_co
Type variable.
TypeModelIOSequence_co
Type variable.
TypeModelSequence_co
Type variable.
TypeModelSequences
Type variable.
TypeOutputSequence_co
Type variable.
TypeSequence_co
Type variable.
TypeSequences
Type variable.
FastAccessIOSequence
Provides fast access to the values of theIOSequence
objects of a specific subgroup and supports handling time series data during simulations.
FastAccessInputSequence
FastAccessIOSequence
subclass specialised for input sequences.
FastAccessOutputSequence
FastAccessIOSequence
subclass specialised for output sequences.
FastAccessLinkSequence
FastAccessIOSequence
subclass specialised for link sequences.
FastAccessNodeSequence
FastAccessIOSequence
subclass specialised forNode
objects.
InfoArray
numpy
ndarray
subclass with an additional attribute describing the (potential) aggregation of the handled data.
StandardInputNames
Standard names for theInputSequence
subclasses of the various models.
Sequences
Base class for handling all sequences of a specific model.
SubSequences
Base class for handling subgroups of sequences.
ModelSequences
Base class for handling model-related subgroups of sequences.
SeriesMode
The type of propertyseriesmode
of classIOSequence
.
IOSequences
Subclass ofSubSequences
, specialised for handlingIOSequence
objects.
ModelIOSequences
Base class for handling model-related subgroups ofIOSequence
objects.
InputSequences
Base class for handlingInputSequence
objects.
OutputSequences
Base class for handlingOutputSequence
objects.
FactorSequences
Base class for handlingFactorSequence
objects.
FluxSequences
Base class for handlingFluxSequence
objects.
StateSequences
Base class for handlingStateSequence
objects.
LogSequences
Base class for handlingLogSequence
objects.
AideSequences
Base class for handlingAideSequence
objects.
LinkSequences
Base class for handlingLinkSequence
objects.
InletSequences
Base class for handling “inlet”LinkSequence
objects.
OutletSequences
Base class for handling “outlet”LinkSequence
objects.
ReceiverSequences
Base class for handling “receiver”LinkSequence
objects.
SenderSequences
Base class for handling “sender”LinkSequence
objects.
Sequence_
Base class for defining different kinds of sequences.
IOSequence
Base class for sequences with input/output functionalities.
ModelSequence
Base class for sequences to be handled byModel
objects.
ModelIOSequence
Base class for sequences with time series functionalities to be handled byModel
objects.
InputSequence
Base class for input sequences ofModel
objects.
OutputSequence
Base class forFactorSequence
,FluxSequence
andStateSequence
.
DependentSequence
Base class forFactorSequence
andFluxSequence
.
FactorSequence
Base class for factor sequences ofModel
objects.
FluxSequence
Base class for flux sequences ofModel
objects.
ConditionSequence
Base class forStateSequence
andLogSequence
.
StateSequence
Base class for state sequences ofModel
objects.
LogSequence
Base class for logging values required for later calculations.
LogSequenceFixed
Base class for log sequences with a fixed shape.
AideSequence
Base class for aide sequences ofModel
objects.
LinkSequence
Base class for link sequences ofModel
objects.
InletSequence
Base class for inlet link sequences ofModel
objects.
OutletSequence
Base class for outlet link sequences ofModel
objects.
ReceiverSequence
Base class for receiver link sequences ofModel
objects.
SenderSequence
Base class for sender link sequences ofModel
objects.
NodeSequence
Base class for all sequences to be handled byNode
objects.
Sim
Class for handling those values ofNode
objects that are “simulated”, meaning calculated by hydrological models.
Obs
Class for handling those values ofNode
objects that are observed, meaning read from data files.
NodeSequences
Base class for handlingSim
andObs
sequence objects.
- class hydpy.core.sequencetools.FastAccessIOSequence[source]¶
Bases:
FastAccess
Provides fast access to the values of the
IOSequence
objects of a specific subgroup and supports handling time series data during simulations.The following details are of relevance for HydPy developers only.
FastAccessIOSequence
is applied in Python mode only. When working in Cython mode, it is replaced by model-specific Cython extension classes, which are computationally more efficient. For compatibility with these extension classes,FastAccessIOSequence
objects work with dynamically set instance members. For example, suppose there is a sequence named seq1, which is 2-dimensional, then its associated attributes are:seq1 (
NDArrayFloat
): The actual sequence value(s)._seq1_ndim (
int
): The number of dimensions._seq1_length_0 (
int
): Length in the first dimension._seq1_length_1 (
int
): Length in the second dimension._seq1_ramflag (
bool
): Handle time series data in RAM?_seq1_array (
NDArrayFloat
): Time-series data (when handled in RAM)._seq1_diskflag_reading (
bool
): Read data from a NetCDF file during simulation?_seq1_diskflag_writing (
bool
): Write data to a NetCDF file during simulation?_seq1_ncarray (
NDArrayFloat
): An array connected with the data slice of the NetCDF file relevant for seq1.
Note that the respective
IOSequences
andIOSequence
objects initialise, change, and apply these dynamical attributes. To handle them directly is error-prone and thus not recommended.- load_data(idx: int) None [source]¶
Load the data of certain sequences from the defined sources.
The following flags specify the data source (listed in the order of their priority):
inputflag (
bool
): Take the data from an “input node”.diskflag_reading (
bool
): Read the data “on the fly” from a NetCDF file during a simulation run.ramflag (
bool
): Take the data from the time series handled by theseries
attribute of the respectiveIOSequence
object.
If, for example, diskflag_reading and ramflag are both activated,
load_data()
prefers the data available within the NetCDF file.
- save_data(idx: int) None [source]¶
Save the data of certain sequences to the defined sources.
The following flags the data targets:
diskflag_writing (
bool
): Write the data “on the fly” to a NetCDF file during a simulation run.ramflag (
bool
): Give the data to the time series handled by theseries
attribute of the respectiveIOSequence
object.
It is possible to write data to a NetCDF file and pass it to
series
simultaneously.
- class hydpy.core.sequencetools.FastAccessInputSequence[source]¶
Bases:
FastAccessIOSequence
FastAccessIOSequence
subclass specialised for input sequences.- set_pointerinput(name: str, pdouble: PDouble) None [source]¶
Use the given
PDouble
object as the pointer for the 0-dimensionalInputSequence
object with the given name.
- class hydpy.core.sequencetools.FastAccessOutputSequence[source]¶
Bases:
FastAccessIOSequence
FastAccessIOSequence
subclass specialised for output sequences.- set_pointeroutput(name: str, pdouble: PDouble) None [source]¶
Use the given
PDouble
object as the pointer for the 0-dimensionalOutputSequence
object with the given name.
- class hydpy.core.sequencetools.FastAccessLinkSequence[source]¶
Bases:
FastAccess
FastAccessIOSequence
subclass specialised for link sequences.- alloc(name: str, length: int) None [source]¶
Allocate enough memory for the given vector length of the
LinkSequence
object with the given name.Cython extension classes need to define
alloc()
if the model handles at least one 1-dimensionalLinkSequence
subclass.
- dealloc(name: str) None [source]¶
Free the previously allocated memory of the
LinkSequence
object with the given name.Cython extension classes need to define
dealloc()
if the model handles at least one 1-dimensionalLinkSequence
subclass.
- set_pointer0d(name: str, value: Double) None [source]¶
Define a pointer referencing the given
Double
object for the 0-dimensionalLinkSequence
object with the given name.Cython extension classes need to define
set_pointer0d()
if the model handles at least one 0-dimensionalLinkSequence
subclasses.
- set_pointer1d(name: str, value: Double, idx: int) None [source]¶
Define a pointer referencing the given
Double
object for the 1-dimensionalLinkSequence
object with the given name.The given index defines the vector position of the defined pointer.
Cython extension classes need to define
set_pointer1d()
if the model handles at least one 1-dimensionalLinkSequence
subclasses.
- class hydpy.core.sequencetools.FastAccessNodeSequence[source]¶
Bases:
FastAccessIOSequence
FastAccessIOSequence
subclass specialised forNode
objects.In contrast to other
FastAccessIOSequence
subclasses,FastAccessNodeSequence
only needs to handle a fixed number of sequences,Sim
andObs
. It thus can define the related attributes explicitly.- sim: Double¶
- obs: Double¶
- load_simdata(idx: int) None [source]¶
Load the next sim sequence value from a NetCDF file or, with second priority, from the
series
attribute of the currentSim
object.
- save_simdata(idx: int) None [source]¶
Save the next sim sequence value to a NetCDF file and/or to the
series
attribute of theSim
object.
- load_obsdata(idx: int) None [source]¶
Load the next sim sequence value from a NetCDF file or, with second priority, from the
series
attribute of theObs
object.
- save_obsdata(idx: int) None [source]¶
Save the next sim sequence value to a NetCDF file and/or to the
series
attribute of theObs
object.
- load_data(idx: int) None [source]¶
Call both method
load_simdata()
and methodload_obsdata()
.
- save_data(idx: int) None [source]¶
Call both method
save_simdata()
and methodsave_obsdata()
.
- fill_obsdata(idx: int = 0) None [source]¶
Use the current sim value for the current obs value if obs is
nan
.
- reset_obsdata(idx: int = 0) None [source]¶
Reset the current obs value to
nan
if modified beforehand by methodfill_obsdata()
.
- class hydpy.core.sequencetools.InfoArray(array: ndarray[Any, dtype[float64]], aggregation: Literal['unmodified', 'mean'] | None = None)[source]¶
Bases:
ndarray
[Any
,dtype
[float64
]]numpy
ndarray
subclass with an additional attribute describing the (potential) aggregation of the handled data.>>> from hydpy.core.sequencetools import InfoArray >>> array = InfoArray([1.0, 2.0], aggregation="mean") >>> array InfoArray([1., 2.]) >>> array.aggregation 'mean' >>> subarray = array[:1] >>> subarray InfoArray([1.]) >>> subarray.aggregation 'mean'
- class hydpy.core.sequencetools.StandardInputNames(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)[source]¶
Bases:
StrEnum
Standard names for the
InputSequence
subclasses of the various models.One can use these names instead of the model-specific sequence names for reading input time series from or to files. For further information, see the introductory documentation on class
HydPy
.The suffix “_HRU” refers to 1-dimensional sequences for which the different entries correspond to different spatial units (typically hydrological response units).
- AIR_TEMPERATURE = 'air_temperature'¶
Air temperature 2 m above the ground [°C].
- ALBEDO_HRU = 'albedo_hru'¶
Surface albedo [-].
- ARTIFICIAL_GROUNDWATER_RECHARGE = 'artificial_groundwater_recharge'¶
Artificial/additional groundwater recharge [mm/T].
- ARTIFICIAL_SURFACE_WATER_SUPPLY = 'artificial_surface_water_supply'¶
Artificial/additional surface water supply [mm/T].
- ATMOSPHERIC_PRESSURE = 'atmospheric_pressure'¶
Atmospheric pressure [hPa].
- CAPILLARY_RISE = 'capillary_rise'¶
Capillary rise [mm/T].
- CLEAR_SKY_SOLAR_RADIATION = 'clear_sky_solar_radiation'¶
Clear sky solar radiation [W/m²].
- EVAPOTRANSPIRATION = 'evapotranspiration'¶
Actual evapotranspiration [mm/T].
- GLOBAL_RADIATION = 'global_radiation'¶
Global radiation [W/m²].
- INTERCEPTED_WATER_HRU = 'intercepted_water_hru'¶
Amount of intercepted water [mm].
- NORMAL_AIR_TEMPERATURE = 'normal_air_temperature'¶
Normal air temperature 2 m above the ground [°C].
- NORMAL_EVAPOTRANSPIRATION = 'normal_evapotranspiration'¶
Normal evapotranspiration [mm/T].
- POSSIBLE_SUNSHINE_DURATION = 'possible_sunshine_duration'¶
Possible sunshine duration [h].
- POTENTIAL_EVAPOTRANSPIRATION = 'potential_evapotranspiration'¶
Potential evapotranspiration [mm/T].
- PRECIPITATION = 'precipitation'¶
Precipitation [mm/T].
- RELATIVE_HUMIDITY = 'relative_humidity'¶
Relative humidity [%].
- SNOW_COVER_DEGREE_CANOPY_HRU = 'snow_cover_degree_canopy_hru'¶
Snow cover degree in the canopies of tree-like vegetation [-].
- SNOW_COVER_DEGREE_HRU = 'snow_cover_degree_hru'¶
Snow cover degree [-].
- SOIL_WATER_HRU = 'soil_water_hru'¶
Amount of soil water [mm].
- SUNSHINE_DURATION = 'sunshine_duration'¶
Sunshine duration [h].
- WIND_SPEED = 'wind_speed'¶
Wind speed [m/s].
- class hydpy.core.sequencetools.Sequences(model: modeltools.Model, *, cls_inlets: type[InletSequences] | None = None, cls_receivers: type[ReceiverSequences] | None = None, cls_inputs: type[InputSequences] | None = None, cls_factors: type[FactorSequences] | None = None, cls_fluxes: type[FluxSequences] | None = None, cls_states: type[StateSequences] | None = None, cls_logs: type[LogSequences] | None = None, cls_aides: type[AideSequences] | None = None, cls_outlets: type[OutletSequences] | None = None, cls_senders: type[SenderSequences] | None = None, cymodel: CyModelProtocol | None = None, cythonmodule: types.ModuleType | None = None)[source]¶
Bases:
object
Base class for handling all sequences of a specific model.
Sequences
objects handle nine sequence subgroups as attributes such as the inlets and the receivers subsequences:>>> from hydpy.core.testtools import prepare_full_example_2 >>> hp, pub, TestIO = prepare_full_example_2() >>> sequences = hp.elements.land_dill_assl.model.sequences >>> bool(sequences.inlets) False >>> bool(sequences.fluxes) True
Iteration makes only the non-empty subgroups available that handle
Sequence_
objects:>>> for subseqs in sequences: ... print(subseqs.name) inputs factors fluxes states aides outlets >>> len(sequences) 6
Keyword access provides a type-safe way to query a subgroup via a string:
>>> type(sequences["inputs"]).__name__ 'InputSequences' >>> type(sequences["wrong"]) Traceback (most recent call last): ... TypeError: There is no sequence subgroup named `wrong`. >>> sequences["model"] Traceback (most recent call last): ... TypeError: Attribute `model` is of type `Model`, which is not a subtype of class `SubSequences`.
Class
Sequences
provides some methods related to reading and writing time series data, which (directly or indirectly) call the corresponding methods of the handledIOSequence
objects. In most cases, users should prefer to use the related methods of classHydPy
, but using the ones of classSequences
can be more convenient when analysing a specific model in-depth.To introduce these methods, we first change two IO-related settings:
>>> from hydpy import round_ >>> pub.options.checkseries = False >>> pub.sequencemanager.overwrite = True
Method
prepare_series()
can both enable and disable the handling of time series in rapid access memory (RAM), and both enable and disable the reading of input data from NetCDF files and the writing of NetCDF files “on the fly” during simulation runs:>>> from hydpy import attrready >>> sequences.prepare_series(allocate_ram=False, jit=False) >>> sequences.inputs.t.ramflag False >>> attrready(sequences.inputs.t, "series") False >>> sequences.inputs.t.diskflag False >>> sequences.inputs.t.diskflag_reading False >>> sequences.states.sm.diskflag_writing False
>>> sequences.prepare_series() >>> sequences.inputs.t.ramflag True >>> attrready(sequences.inputs.t, "series") True >>> sequences.inputs.t.diskflag False >>> sequences.inputs.t.diskflag_reading False >>> sequences.states.sm.diskflag_writing False
>>> sequences.prepare_series(allocate_ram=False, jit=True) >>> sequences.inputs.t.ramflag False >>> attrready(sequences.inputs.t, "series") False >>> sequences.inputs.t.diskflag True >>> sequences.inputs.t.diskflag_reading True >>> sequences.states.sm.diskflag_writing True
After applying
prepare_series()
, you can use the methodsload_series()
andsave_series()
to read or write the time series of the relevantInputSequence
,FactorSequence
,FluxSequence
, andStateSequence
object, as the following technical test suggests. The documentation on classIOSequence
explains the underlying functionalities of in more detail.>>> from unittest.mock import patch >>> template = "hydpy.core.sequencetools.%s.load_series" >>> with patch(template % "InputSequences") as inputs, patch(template % "FactorSequences") as factors, patch(template % "FluxSequences") as fluxes, patch(template % "StateSequences") as states: ... sequences.load_series() ... inputs.assert_called_with() ... factors.assert_called_with() ... fluxes.assert_called_with() ... states.assert_called_with()
>>> template = "hydpy.core.sequencetools.%s.save_series" >>> with patch(template % "InputSequences") as inputs, patch(template % "FactorSequences") as factors, patch(template % "FluxSequences") as fluxes, patch(template % "StateSequences") as states: ... sequences.save_series() ... inputs.assert_called_with() ... factors.assert_called_with() ... fluxes.assert_called_with() ... states.assert_called_with()
- model: modeltools.Model¶
- inlets: InletSequences¶
- receivers: ReceiverSequences¶
- inputs: InputSequences¶
- factors: FactorSequences¶
- fluxes: FluxSequences¶
- states: StateSequences¶
- logs: LogSequences¶
- aides: AideSequences¶
- outlets: OutletSequences¶
- senders: SenderSequences¶
- property iosubsequences: Iterator[InputSequences | FactorSequences | FluxSequences | StateSequences]¶
Yield all relevant
IOSequences
objects handled by the currentSequences
object.The currently available IO-subgroups are inputs, factors, fluxes, and states.
>>> from hydpy import prepare_model >>> model = prepare_model("hland_96") >>> for subseqs in model.sequences.iosubsequences: ... print(subseqs.name) inputs factors fluxes states
However, not all models implement sequences for all these subgroups. Therefore, the
iosubsequences
property only yields those subgroups which are non-empty:>>> model = prepare_model("musk_classic") >>> for subseqs in model.sequences.iosubsequences: ... print(subseqs.name) fluxes states
- prepare_series(allocate_ram: bool = True, jit: bool = False) None [source]¶
Call method
prepare_series()
of attributeinputs
with read_jit=jit and of attributesfactors
,fluxes
, andstates
with write_jit=jit.
- load_series()[source]¶
Call method
load_series()
of all handledIOSequences
objects.
- save_series()[source]¶
Call method
save_series()
of all handledIOSequences
objects.
- load_data(idx: int) None [source]¶
Call method
load_data()
of the handledInputSequences
object.
- save_data(idx: int) None [source]¶
Call method
save_data()
of the handledInputSequences
,FactorSequences
,FluxSequences
, andStateSequences
objects.
- update_outputs() None [source]¶
Call the method
update_outputs()
of the subattributesfactors
,fluxes
, andstates
.When working in Cython mode, the standard model import overrides this generic Python version with a model-specific Cython version.
- reset() None [source]¶
Call method
reset()
of all handledConditionSequence
objects.
- property conditionsequences: Iterator[ConditionSequence]¶
Generator object yielding all conditions (
StateSequence
andLogSequence
objects).
- property conditions: dict[str, dict[str, float | ndarray[Any, dtype[float64]]]]¶
A nested dictionary that contains the values of all condition sequences of a single model instance.
See the documentation on property
conditions
for further information.
- trim_conditions() None [source]¶
Call method
trim()
of each handledConditionSequence
.trim_conditions()
is just a convenience function for calling methodtrim()
of allStateSequence
andLogSequence
objects returned by propertyconditionsequences
. We demonstrate its functionality by preparing an instance of application modellland_dd
, using its available default values, and defining out-of-bound values of the soil moisture state sequenceBoWa
:>>> from hydpy import prepare_model, pub >>> pub.timegrids = "2000-01-01", "2000-01-10", "1d" >>> with pub.options.usedefaultvalues(True): ... model = prepare_model("lland_dd") ... model.parameters.control.nhru(2) >>> model.sequences.states.bowa = -100.0 >>> model.sequences.trim_conditions() >>> model.sequences.states.bowa bowa(0.0, 0.0)
- class hydpy.core.sequencetools.SubSequences(master: TypeGroup_co, cls_fastaccess: type[TypeFastAccess_co] | None = None)[source]¶
Bases:
SubVariables
[TypeSequences
,TypeSequence_co
,TypeFastAccess_co
]Base class for handling subgroups of sequences.
Each
SubSequences
object has a fastaccess attribute, which is an instance of (a subclass of) classFastAccess
when working in pure Python mode:>>> from hydpy import classname, Node, prepare_model, pub >>> with pub.options.usecython(False): ... model = prepare_model("lland_dd") >>> classname(model.sequences.logs.fastaccess) 'FastAccess' >>> classname(model.sequences.inputs.fastaccess) 'FastAccessInputSequence' >>> from hydpy.core.sequencetools import FastAccessNodeSequence >>> with pub.options.usecython(False): ... node = Node("test1") >>> isinstance(node.sequences.fastaccess, FastAccessNodeSequence) True
When working in Cython mode (the default and much faster than the pure Python mode), fastaccess is an object of the Cython extension class FastAccessNodeSequence of module sequenceutils or a Cython extension class specialised for the respective model and sequence group:
>>> with pub.options.usecython(True): ... model = prepare_model("lland_dd") >>> classname(model.sequences.inputs.fastaccess) 'InputSequences' >>> from hydpy.cythons.sequenceutils import FastAccessNodeSequence >>> with pub.options.usecython(True): ... node = Node("test2") >>> isinstance(Node("test2").sequences.fastaccess, FastAccessNodeSequence) True
See the documentation of similar class
SubParameters
for further information. However, note the difference that model developers should not subclassSubSequences
directly but specialised subclasses likeFluxSequences
orStateSequences
instead.
- class hydpy.core.sequencetools.ModelSequences(master: Sequences, cls_fastaccess: type[TypeFastAccess_co] | None = None, cymodel: CyModelProtocol | None = None)[source]¶
Bases:
SubSequences
[Sequences
,TypeModelSequence_co
,TypeFastAccess_co
]Base class for handling model-related subgroups of sequences.
- class hydpy.core.sequencetools.SeriesMode(ramflag: bool, diskflag_reading: bool, diskflag_writing: bool)[source]¶
Bases:
object
The type of property
seriesmode
of classIOSequence
.- ramflag: bool¶
Corresponds to property
ramflag
of classIOSequence
.
- diskflag_reading: bool¶
Corresponds to property
diskflag_reading
of classIOSequence
.
- diskflag_writing: bool¶
Corresponds to property
diskflag_writing
of classIOSequence
.
- class hydpy.core.sequencetools.IOSequences(master: TypeGroup_co, cls_fastaccess: type[TypeFastAccess_co] | None = None)[source]¶
Bases:
SubSequences
[TypeSequences
,TypeIOSequence_co
,TypeFastAccessIOSequence_co
]Subclass of
SubSequences
, specialised for handlingIOSequence
objects.- prepare_series(allocate_ram: bool = True, read_jit: bool = False, write_jit: bool = False) None [source]¶
Call method
prepare_series()
of all handledIOSequence
objects.
- load_series() None [source]¶
Call method
load_series()
of all handledIOSequence
objects with an activatedramflag
.
- save_series() None [source]¶
Call method
save_series()
of all handledIOSequence
objects with an activatedramflag
.
- class hydpy.core.sequencetools.ModelIOSequences(master: Sequences, cls_fastaccess: type[TypeFastAccess_co] | None = None, cymodel: CyModelProtocol | None = None)[source]¶
Bases:
IOSequences
[Sequences
,TypeModelIOSequence_co
,TypeFastAccessIOSequence_co
],ModelSequences
[TypeModelIOSequence_co
,TypeFastAccessIOSequence_co
]Base class for handling model-related subgroups of
IOSequence
objects.- load_data(idx: int) None [source]¶
Call method
load_data()
of theFastAccessIOSequence
object handled as attribute fastaccess.
- save_data(idx: int) None [source]¶
Call method
save_data()
of theFastAccessIOSequence
object handled as attribute fastaccess.
- class hydpy.core.sequencetools.InputSequences(master: Sequences, cls_fastaccess: type[TypeFastAccess_co] | None = None, cymodel: CyModelProtocol | None = None)[source]¶
Bases:
ModelIOSequences
[InputSequence
,FastAccessInputSequence
]Base class for handling
InputSequence
objects.
- class hydpy.core.sequencetools.OutputSequences(master: Sequences, cls_fastaccess: type[TypeFastAccess_co] | None = None, cymodel: CyModelProtocol | None = None)[source]¶
Bases:
ModelIOSequences
[TypeOutputSequence_co
,FastAccessOutputSequence
]Base class for handling
OutputSequence
objects.- update_outputs() None [source]¶
Call method
update_outputs()
of theFastAccessOutputSequence
object handled as attribute fastaccess.
- property numericsequences: Iterator[TypeOutputSequence_co]¶
Iterator for “numerical” sequences.
“numerical” means that the
NUMERIC
class attribute of the actual sequence isTrue
:>>> from hydpy import prepare_model >>> model = prepare_model("dam_v001") >>> len(model.sequences.fluxes) 16 >>> for seq in model.sequences.fluxes.numericsequences: ... print(seq) adjustedprecipitation(nan) actualevaporation(nan) inflow(nan) actualrelease(nan) flooddischarge(nan) outflow(nan)
- class hydpy.core.sequencetools.FactorSequences(master: Sequences, cls_fastaccess: type[TypeFastAccess_co] | None = None, cymodel: CyModelProtocol | None = None)[source]¶
Bases:
OutputSequences
[FactorSequence
]Base class for handling
FactorSequence
objects.
- class hydpy.core.sequencetools.FluxSequences(master: Sequences, cls_fastaccess: type[TypeFastAccess_co] | None = None, cymodel: CyModelProtocol | None = None)[source]¶
Bases:
OutputSequences
[FluxSequence
]Base class for handling
FluxSequence
objects.
- class hydpy.core.sequencetools.StateSequences(master: Sequences, cls_fastaccess: type[TypeFastAccess_co] | None = None, cymodel: CyModelProtocol | None = None)[source]¶
Bases:
OutputSequences
[StateSequence
]Base class for handling
StateSequence
objects.- new2old() None [source]¶
Call method
new2old()
of all handledStateSequence
objects.
- reset() None [source]¶
Call method
reset()
of all handledStateSequence
objects.
- class hydpy.core.sequencetools.LogSequences(master: Sequences, cls_fastaccess: type[TypeFastAccess_co] | None = None, cymodel: CyModelProtocol | None = None)[source]¶
Bases:
ModelSequences
[LogSequence
,FastAccess
]Base class for handling
LogSequence
objects.- reset() None [source]¶
Call method
reset()
of all handledLogSequence
objects.
- class hydpy.core.sequencetools.AideSequences(master: Sequences, cls_fastaccess: type[TypeFastAccess_co] | None = None, cymodel: CyModelProtocol | None = None)[source]¶
Bases:
ModelSequences
[AideSequence
,FastAccess
]Base class for handling
AideSequence
objects.
- class hydpy.core.sequencetools.LinkSequences(master: Sequences, cls_fastaccess: type[TypeFastAccess_co] | None = None, cymodel: CyModelProtocol | None = None)[source]¶
Bases:
ModelSequences
[TypeLinkSequence_co
,FastAccessLinkSequence
]Base class for handling
LinkSequence
objects.
- class hydpy.core.sequencetools.InletSequences(master: Sequences, cls_fastaccess: type[TypeFastAccess_co] | None = None, cymodel: CyModelProtocol | None = None)[source]¶
Bases:
LinkSequences
[InletSequence
]Base class for handling “inlet”
LinkSequence
objects.
- class hydpy.core.sequencetools.OutletSequences(master: Sequences, cls_fastaccess: type[TypeFastAccess_co] | None = None, cymodel: CyModelProtocol | None = None)[source]¶
Bases:
LinkSequences
[OutletSequence
]Base class for handling “outlet”
LinkSequence
objects.
- class hydpy.core.sequencetools.ReceiverSequences(master: Sequences, cls_fastaccess: type[TypeFastAccess_co] | None = None, cymodel: CyModelProtocol | None = None)[source]¶
Bases:
LinkSequences
[ReceiverSequence
]Base class for handling “receiver”
LinkSequence
objects.
- class hydpy.core.sequencetools.SenderSequences(master: Sequences, cls_fastaccess: type[TypeFastAccess_co] | None = None, cymodel: CyModelProtocol | None = None)[source]¶
Bases:
LinkSequences
[SenderSequence
]Base class for handling “sender”
LinkSequence
objects.
- class hydpy.core.sequencetools.Sequence_(subvars: SubVariables)[source]¶
Bases:
Variable
Base class for defining different kinds of sequences.
Note that model developers should not derive their model-specific sequence classes from
Sequence_
directly but from the “final” subclasses provided in modulesequencetools
(e.g.FluxSequence
).From the model developer perspective and especially from the user perspective,
Sequence_
is only a small extension of its base classVariable
. One relevant extension is that (only the) 0-dimensional sequence objects come with a predefined shape:>>> from hydpy import prepare_model >>> model = prepare_model("lland_dd") >>> model.sequences.fluxes.qa.shape () >>> nkor = model.sequences.fluxes.nkor >>> nkor.shape Traceback (most recent call last): ... hydpy.core.exceptiontools.AttributeNotReady: Shape information for variable `nkor` can only be retrieved after it has been defined.
For consistency with the usage of
Parameter
subclasses,Sequence_
objects are also “callable” for setting their values (but in a much less and flexible manner):>>> nkor.shape = 3 >>> nkor(2.0) >>> nkor nkor(2.0, 2.0, 2.0)
Under the hood, class
Sequence_
also prepares some attributes of itsFastAccess
object, used for performing the actual simulation calculations. Framework developers should note that the respective fastaccess attributes contain both the name of the sequence and the name of the original attribute in lowercase letters. We take NDIM as an example:>>> nkor.fastaccess._nkor_ndim 1
Some of these attributes require updating in some situations. For example, other sequences than
AideSequence
objects require a “length” attribute, which needs updating each time the sequence’s shape changes:>>> nkor.fastaccess._nkor_length 3
- property initinfo: tuple[float | Double, bool]¶
A
tuple
containing the initial value andTrue
or a missing value andFalse
, depending on the actualSequence_
subclass and the actual value of optionusedefaultvalues
.In the following, we do not explain property
initinfo
itself but show how it affects initialising newSequence_
objects. Therefore, let us define a sequence test class and prepare a function for initialising it and connecting the resulting instance to aModelSequences
object:>>> from hydpy.core.sequencetools import Sequence_, ModelSequences >>> from hydpy.core.variabletools import FastAccess >>> class Test(Sequence_): ... NDIM = 0 ... _CLS_FASTACCESS_PYTHON = FastAccess >>> class SubGroup(ModelSequences): ... CLASSES = (Test,) ... _CLS_FASTACCESS_PYTHON = FastAccess >>> def prepare(): ... subseqs = SubGroup(None) ... test = Test(subseqs) ... test.__hydpy__connect_variable2subgroup__() ... return test
By default, making use of the INIT attribute is disabled:
>>> prepare() test(nan)
Enable it by setting
usedefaultvalues
toTrue
:>>> from hydpy import pub >>> with pub.options.usedefaultvalues(True): ... prepare() test(0.0)
Attribute INIT of class
Sequence_
comes with the value 0.0 by default, which should be reasonable for mostSequence_
subclasses. However, subclasses can define other values. Most importantly, note the possibility to set INIT to None for sequences that do not allow specifying a reasonabe initial value for all possible situations:>>> Test.INIT = None >>> prepare() test(nan) >>> with pub.options.usedefaultvalues(True): ... prepare() test(nan)
- class hydpy.core.sequencetools.IOSequence(subvars: SubVariables)[source]¶
Bases:
Sequence_
Base class for sequences with input/output functionalities.
The documentation on modules
filetools
andnetcdftools
in some detail explains how to read and write time series files. However, due to efficiency, reading and writing time series files are disabled by default. Therefore, you must first prepare theseries
attribute of the relevantIOSequence
objects. Typically, you call methods likeprepare_inputseries()
of classHydPy
. Here, we instead use the related features of theIOSequence
class itself.We use the HydPy-H-Lahn example project and focus on the input, factor, fluxes, and state sequences:
>>> from hydpy.core.testtools import prepare_full_example_2 >>> hp, pub, TestIO = prepare_full_example_2() >>> inputs = hp.elements.land_lahn_marb.model.sequences.inputs >>> factors = hp.elements.land_lahn_marb.model.sequences.factors >>> fluxes = hp.elements.land_lahn_marb.model.sequences.fluxes >>> states = hp.elements.land_lahn_marb.model.sequences.states
Each
IOSequence
object comes four flags, answering the following questions:ramflag
: can its time series can be available in RAM?diskflag_reading
: read its values “on the fly” from a NetCDF file during simulation runs?diskflag_writing
:write its values “on the fly” to a NetCDF file during simulation runs?diskflag
: isdiskflag_reading
and/ordiskflag_writing
activated?
For input sequences as
T
, it is common to store their time series data (required for any simulation run) in RAM, which is much faster than (repeatedly) reading data “on the fly” and should be preferred, as long as limited available RAM is not an issue. For convenience, functionprepare_full_example_2()
preparedT
(and the other input sequences) accordingly:>>> inputs.t.ramflag True >>> inputs.t.diskflag_reading False >>> inputs.t.diskflag_writing False >>> inputs.t.diskflag False >>> from hydpy import round_ >>> round_(inputs.t.series) -0.7, -1.5, -4.6, -8.2
prepare_full_example_2()
also activated theramflag
of all factor, flux, and state sequences, which is unnecessary to perform a successful simulation. However, it is required to directly access the complete time series of simulated values afterwards (otherwise, only the last computed value(s) were available in RAM after a simulation run):>>> factors.tc.ramflag True >>> factors.tc.diskflag False >>> round_(factors.tc.series[:, 0]) nan, nan, nan, nan
Use
prepare_series()
to force a sequence to handle time series data in RAM or to read or write it on the fly. We now activate the reading functionality of input sequenceT
(while still keeping its time series in RAM, which we set to zero beforehand) and the writing feature of the factor sequencesContriArea
andTC
(without handling their data in RAM) and the writing feature of the state sequencesSM
andSP
(while handling their data in RAM simultaneously):>>> inputs.t.series = 0.0 >>> inputs.t.prepare_series(allocate_ram=True, read_jit=True) >>> factors.contriarea.prepare_series(allocate_ram=False, write_jit=True) >>> factors.tc.prepare_series(allocate_ram=False, write_jit=True) >>> states.sm.prepare_series(allocate_ram=True, write_jit=True) >>> states.sp.prepare_series(allocate_ram=True, write_jit=True)
Use the properties
ramflag
,diskflag_reading
,diskflag_writing
, anddiskflag
for querying the current configuration of individualIOSequence
objects:>>> inputs.t.ramflag True >>> inputs.t.diskflag_reading True >>> inputs.t.diskflag_writing False >>> inputs.t.diskflag True >>> round_(inputs.t.series) 0.0, 0.0, 0.0, 0.0
>>> factors.contriarea.ramflag False >>> factors.contriarea.diskflag_reading False >>> factors.contriarea.diskflag_writing True >>> factors.contriarea.diskflag True >>> factors.contriarea.series Traceback (most recent call last): ... hydpy.core.exceptiontools.AttributeNotReady: Sequence `contriarea` of element `land_lahn_marb` is not requested to make any time series data available.
>>> states.sm.ramflag True >>> states.sm.diskflag_reading False >>> states.sm.diskflag_writing True >>> states.sm.diskflag True >>> round_(states.sm.series[:, 0]) nan, nan, nan, nan
Now we perform a simulation run. Note that we need to change the current working directory to the iotesting directory temporarily (by using class
TestIO
) because the relevant NetCDF files are now read and written on the fly:>>> with TestIO(): ... hp.simulate()
After the simulation run, the read (
T
) and calculated (SM
andSP
) time series of the sequences with an activatedramflag
are directly available:>>> round_(inputs.t.series) -0.7, -1.5, -4.6, -8.2 >>> round_(states.sm.series[:, 0]) 99.1369, 99.01204, 98.93674, 98.91913 >>> round_(states.sp.series[:, 0, 0]) 0.0, 0.0, 0.0, 0.0
To inspect the time series of
ContriArea
andTC
, you must first activate theirramflag
and then load their data manually with methodload_series()
. The latter requires some additional configuration effort (see the documentation on modulenetcdftools
for further information):>>> factors.contriarea.prepare_series() >>> factors.tc.prepare_series() >>> pub.sequencemanager.filetype = "nc" >>> with TestIO(): ... pub.sequencemanager.open_netcdfreader() ... factors.contriarea.load_series() ... factors.tc.load_series() ... pub.sequencemanager.close_netcdfreader() >>> round_(factors.contriarea.series) 0.431311, 0.430524, 0.430049, 0.429938 >>> round_(factors.tc.series[:, 0]) 0.453086, -0.346914, -3.446914, -7.046914
We also load time series of
SM
andSP
to demonstrate that the data written to the respective NetCDF files are identical with the data directly stored in RAM:>>> with TestIO(): ... pub.sequencemanager.open_netcdfreader() ... states.sm.load_series() ... states.sp.load_series() ... pub.sequencemanager.close_netcdfreader() >>> round_(states.sm.series[:, 0]) 99.1369, 99.01204, 98.93674, 98.91913 >>> round_(states.sp.series[:, 0, 0]) 0.0, 0.0, 0.0, 0.0
Writing the time series of input sequences on the fly is supported but not simultaneously with reading them (at best, one would overwrite the same file with the same data; at worst, one could corrupt it):
>>> inputs.t.prepare_series(read_jit=True, write_jit=True) Traceback (most recent call last): ... ValueError: Reading from and writing into the same NetCDF file "just in time" during a simulation run is not supported but tried for sequence `t` of element `land_lahn_marb`.
For simplifying the following examples, we now handle all model time series in RAM:
>>> pub.sequencemanager.filetype = "asc" >>> hp.prepare_modelseries() >>> with TestIO(): ... hp.load_inputseries()
You cannot only access the time series data of individual
IOSequence
objects, but you can also modify it. See, for example, the simulated time series for flux sequencePC
(adjusted precipitation), which is zero because the values of input sequenceP
(given precipitation) are also zero:>>> round_(fluxes.pc.series[:, 0]) 0.0, 0.105611, 0.0, 0.0
We can assign different values to attribute
series
of sequenceP
, perform a new simulation run, and see that the newly calculated time series of sequencePC
reflects our data modification:>>> inputs.p.series = 10.0 >>> hp.simulate() >>> round_(fluxes.pc.series[:, 0]) 9.154557, 10.561131, 10.665633, 10.665633
Another convenience property is
seriesshape
, which combines the length of the simulation period with the shape of the individualIOSequence
object:>>> inputs.p.seriesshape (4,) >>> fluxes.pc.seriesshape (4, 13)
Note that resetting the
shape
of anIOSequence
object does not change how it handles its internal time series data but results in a loss of current information:>>> factors.tc.seriesshape (4, 13) >>> factors.fastaccess._tc_length 13 >>> round_(factors.tc.series[:, 0], 1) 0.5, -0.3, -3.4, -7.0
>>> factors.tc.shape = 2, >>> factors.tc.seriesshape (4, 2) >>> factors.fastaccess._tc_length 2 >>> round_(factors.tc.series[:, 0]) nan, nan, nan, nan
Resetting the
shape
ofIOSequence
objects with a deactivatedramflag
data works likewise:>>> fluxes.pc.prepare_series(allocate_ram=False)
>>> fluxes.pc.seriesshape (4, 13) >>> fluxes.fastaccess._pc_length 13 >>> fluxes.pc.series Traceback (most recent call last): ... hydpy.core.exceptiontools.AttributeNotReady: Sequence `pc` of element `land_lahn_marb` is not requested to make any time series data available.
>>> fluxes.pc.shape = (2,) >>> fluxes.pc.seriesshape (4, 2) >>> fluxes.fastaccess._pc_length 2 >>> fluxes.pc.series = 1.0 Traceback (most recent call last): ... hydpy.core.exceptiontools.AttributeNotReady: Sequence `pc` of element `land_lahn_marb` is not requested to make any time series data available.
- filetype¶
“Ending of the time series data file.
Usually,
IOSequence
objects query the current file type from theSequenceManager
object available in the globalpub
module:>>> from hydpy import pub >>> from hydpy.core.filetools import SequenceManager >>> pub.sequencemanager = SequenceManager()
>>> from hydpy.core.sequencetools import InputSequence >>> inputsequence = InputSequence(None) >>> inputsequence.filetype 'asc'
Alternatively, you can specify the file type for each
IOSequence
object individually:>>> inputsequence.filetype = "npy" >>> inputsequence.filetype 'npy' >>> inputsequence.filetype = "nc" >>> inputsequence.filetype 'nc'
Use the del statement to reset the object-specific setting:
>>> del inputsequence.filetype >>> inputsequence.filetype 'asc'
If neither a specific definition nor a
SequenceManager
object is available, propertyfiletype
raises the following error:>>> del pub.sequencemanager >>> inputsequence.filetype Traceback (most recent call last): ... hydpy.core.exceptiontools.AttributeNotReady: Sequence `inputsequence` does not know its file type. Either set it manually or prepare `pub.sequencemanager` correctly.
- aggregation¶
Type of aggregation for writing the time series to a data file.
Usually,
IOSequence
objects query the current aggregation mode from theSequenceManager
object available in the globalpub
module:>>> from hydpy import pub >>> from hydpy.core.filetools import SequenceManager >>> pub.sequencemanager = SequenceManager()
>>> from hydpy.core.sequencetools import FluxSequence >>> fluxsequence = FluxSequence(None) >>> fluxsequence.aggregation 'none'
Alternatively, you can specify the aggregation for each
IOSequence
object individually:>>> fluxsequence.aggregation = "mean" >>> fluxsequence.aggregation 'mean'
Use the del statement to reset the object-specific setting:
>>> del fluxsequence.aggregation >>> fluxsequence.aggregation 'none'
If neither a specific definition nor a
SequenceManager
object is available, propertyaggregation
raises the following error:>>> del pub.sequencemanager >>> fluxsequence.aggregation Traceback (most recent call last): ... hydpy.core.exceptiontools.AttributeNotReady: Sequence `fluxsequence` does not know its aggregation mode. Either set it manually or prepare `pub.sequencemanager` correctly.
- overwrite¶
True/False flag indicating if overwriting an existing data file is allowed or not.
Usually,
IOSequence
objects query the current overwrite flag from theSequenceManager
object available in the globalpub
module:>>> from hydpy import pub >>> from hydpy.core.filetools import SequenceManager >>> pub.sequencemanager = SequenceManager()
>>> from hydpy.core.sequencetools import FluxSequence >>> fluxsequence = FluxSequence(None) >>> fluxsequence.overwrite 0
Alternatively, you can specify the overwrite flag for each
IOSequence
object individually:>>> fluxsequence.overwrite = True >>> fluxsequence.overwrite 1
Use the del statement to reset the object-specific setting:
>>> del fluxsequence.overwrite >>> fluxsequence.overwrite 0
If neither a specific definition nor a
SequenceManager
object is available, propertyoverwrite
raises the following error:>>> del pub.sequencemanager >>> fluxsequence.overwrite Traceback (most recent call last): ... hydpy.core.exceptiontools.AttributeNotReady: Sequence `fluxsequence` does not know its overwrite flag. Either set it manually or prepare `pub.sequencemanager` correctly.
- filename¶
The filename of the relevant time series file.
By default, the filenames of file types that store time series of single sequence instance consists of
descr_device
,descr_sequence
, andfiletype
:>>> from hydpy.core.sequencetools import StateSequence >>> class S(StateSequence): ... descr_device = "device" ... descr_sequence = "group_sequence" ... filetype = "npy" ... aggregation = "none" >>> s = S(None) >>> s.filename 'device_group_sequence.npy'
For file types that store time series of multiple sequence instances,
descr_device
is omitted:>>> s.filetype = "nc" >>> s.filename 'group_sequence.nc'
When dealing with aggregated time series, the aggregation mode is suffixed:
>>> s.aggregation = "mean" >>> s.filename 'group_sequence_mean.nc' >>> s.filetype = "asc" >>> s.filename 'device_group_sequence_mean.asc'
- dirpath¶
The absolute path to the time series directory.
As long as it is not overwritten,
dirpath
is identical to the attributecurrentpath
of theSequenceManager
object available in modulepub
:>>> from hydpy import pub, repr_ >>> from hydpy.core.filetools import SequenceManager >>> class SM(SequenceManager): ... currentpath = "temp" >>> pub.sequencemanager = SM() >>> from hydpy.core.sequencetools import StateSequence >>> repr_(StateSequence(None).dirpath) 'temp'
- filepath¶
The absolute path to the time series file.
The path pointing to the file consists of
dirpath
andfilename
:>>> from hydpy.core.sequencetools import StateSequence >>> seq = StateSequence(None) >>> seq.dirpath = "path" >>> seq.filename = "file.npy" >>> from hydpy import repr_ >>> repr_(seq.filepath) 'path/file.npy'
- update_fastaccess() None [source]¶
Update the
FastAccessIOSequence
object handled by the actualIOSequence
object.Users do not need to apply the method
update_fastaccess()
directly. The following information should be relevant for framework developers only.The main documentation on class
Sequence_
mentions that theFastAccessIOSequence
attribute handles some information about its sequences, but it needs to be kept up-to-date by the sequences themselves. This updating is the task of methodupdate_fastaccess()
, being called by some other methods classIOSequence
call. We show this via the hidden attribute length, which is 0 after initialisation, and automatically set to another value when assigning it to propertyshape
ofIOSequence
subclasses asNKor
:>>> from hydpy import prepare_model >>> model = prepare_model("lland_dd") >>> nkor = model.sequences.fluxes.nkor >>> nkor.fastaccess._nkor_length 0 >>> nkor.shape = (3,) >>> nkor.fastaccess._nkor_length 3
- connect_netcdf(ncarray: ndarray[Any, dtype[float64]]) None [source]¶
Connect the current
IOSequence
object to the given buffer array for reading from or writing to a NetCDF file on the fly during a simulation run.
- prepare_series(allocate_ram: bool | None = True, read_jit: bool | None = False, write_jit: bool | None = False) None [source]¶
Define how to handle the time series data of the current
IOSequence
object.See the main documentation on class
IOSequence
for general information on methodprepare_series()
. Here, we only discuss the special case of passingNone
to it to preserve predefined settings.When leaving out certain arguments,
prepare_series()
takes their boolean defaults. That means subsequent calls overwrite previous ones:>>> from hydpy.core.testtools import prepare_full_example_2 >>> hp, pub, TestIO = prepare_full_example_2() >>> t = hp.elements.land_lahn_marb.model.sequences.inputs.t >>> t.prepare_series(allocate_ram=False, read_jit=True) >>> t.ramflag, t.diskflag_reading, t.diskflag_writing (False, True, False) >>> t.prepare_series(write_jit=True) >>> t.ramflag, t.diskflag_reading, t.diskflag_writing (True, False, True)
If you want to change one setting without modifying the others, pass
None
to the latter:>>> t.prepare_series(allocate_ram=False, read_jit=None, write_jit=None) >>> t.ramflag, t.diskflag_reading, t.diskflag_writing (False, False, True) >>> t.prepare_series(allocate_ram=None, read_jit=True, write_jit=False) >>> t.ramflag, t.diskflag_reading, t.diskflag_writing (False, True, False) >>> t.prepare_series(allocate_ram=None, read_jit=None, write_jit=None) >>> t.ramflag, t.diskflag_reading, t.diskflag_writing (False, True, False)
The check for configurations attempting to both read and write “just in time” takes predefined flags into account:
>>> t.prepare_series(read_jit=None, write_jit=True) Traceback (most recent call last): ... ValueError: Reading from and writing into the same NetCDF file "just in time" during a simulation run is not supported but tried for sequence `t` of element `land_lahn_marb`.
>>> t.prepare_series(read_jit=False, write_jit=True) >>> t.prepare_series(read_jit=True, write_jit=None) Traceback (most recent call last): ... ValueError: Reading from and writing into the same NetCDF file "just in time" during a simulation run is not supported but tried for sequence `t` of element `land_lahn_marb`.
- property ramflag: bool¶
A flag telling if the actual
IOSequence
object makes its time series data directly available in RAM.See the main documentation on class
IOSequence
for further information.
- property diskflag_reading: bool¶
A flag telling if the actual
IOSequence
reads its time series data on the fly from a NetCDF file during a simulation run.See the main documentation on class
IOSequence
for further information.
- property diskflag_writing: bool¶
A flag telling if the actual
IOSequence
writes its time series data on the fly to a NetCDF file during a simulation run.See the main documentation on class
IOSequence
for further information.
- property diskflag: bool¶
A flag telling if
diskflag_reading
and/ordiskflag_writing
of the currentIOSequence
object isTrue
:>>> from hydpy.core.sequencetools import StateSequence >>> for reading in (False, True): ... for writing in (False, True): ... class S(StateSequence): ... diskflag_reading = reading ... diskflag_writing = writing ... print(reading, writing, S(None).diskflag) False False False False True True True False True True True True
- property memoryflag: bool¶
A flag telling if either
ramflag
and/ordiskflag
of the currentIOSequence
object isTrue
:>>> from hydpy.core.sequencetools import StateSequence >>> for ram in (False, True): ... for disk in (False, True): ... class S(StateSequence): ... ramflag = ram ... diskflag = disk ... print(ram, disk, S(None).memoryflag) False False False False True True True False True True True True
- property seriesmode: SeriesMode¶
A combination of property
ramflag
,diskflag_reading
, anddiskflag_writing
.seriesmode
allows querying and changing all mentioned properties in one step:>>> from hydpy.core.testtools import prepare_full_example_2 >>> hp, pub, TestIO = prepare_full_example_2() >>> t = hp.elements.land_lahn_marb.model.sequences.inputs.t >>> t.prepare_series(read_jit=True) >>> sm_t = t.seriesmode >>> sm_t SeriesMode(ramflag=True, diskflag_reading=True, diskflag_writing=False) >>> p = hp.elements.land_lahn_marb.model.sequences.inputs.p >>> p.prepare_series(allocate_ram=False, write_jit=True) >>> sm_p = p.seriesmode >>> sm_p SeriesMode(ramflag=False, diskflag_reading=False, diskflag_writing=True)
>>> t.seriesmode = sm_p >>> t.seriesmode SeriesMode(ramflag=False, diskflag_reading=False, diskflag_writing=True) >>> p.seriesmode = sm_t >>> p.seriesmode SeriesMode(ramflag=True, diskflag_reading=True, diskflag_writing=False)
- shape¶
A tuple containing the actual lengths of all dimensions.
When setting a new
shape
of anIOSequence
object, one automatically calls methodupdate_fastaccess()
and, if necessary, prepares the new internalseries
array.See the main documentation on class
IOSequence
for further information.
- property seriesshape: tuple[int, ...]¶
The shape of the whole time series (time being the first dimension).
- property series: InfoArray¶
The complete time series data of the current
IOSequence
object within anInfoArray
covering the whole initialisation period (defined by theinit
Timegrid
of the globalTimegrids
object available in modulepub
).
- property simseries: InfoArray¶
Read and write access to the subset of the data of property
series
covering the actual simulation period (defined by thesim
Timegrid
of the globalTimegrids
object available in modulepub
).>>> from hydpy.core.testtools import prepare_full_example_2 >>> hp, pub, TestIO = prepare_full_example_2() >>> t = hp.elements.land_lahn_marb.model.sequences.inputs.t >>> pub.timegrids.sim.dates = "1996-01-02", "1996-01-04" >>> from hydpy import print_vector >>> print_vector(t.series) -0.7, -1.5, -4.6, -8.2 >>> print_vector(t.simseries) -1.5, -4.6 >>> t.simseries = 1.0, 2.0 >>> print_vector(t.series) -0.7, 1.0, 2.0, -8.2
- property evalseries: InfoArray¶
Read and write access to the subset of the data of property | IOSequence.series| covering the actual evaluation period (defined by the
eval_
Timegrid
of the globalTimegrids
object available in modulepub
).>>> from hydpy.core.testtools import prepare_full_example_2 >>> hp, pub, TestIO = prepare_full_example_2() >>> t = hp.elements.land_lahn_marb.model.sequences.inputs.t >>> pub.timegrids.eval_.dates = "1996-01-02", "1996-01-04" >>> from hydpy import print_vector >>> print_vector(t.series) -0.7, -1.5, -4.6, -8.2 >>> print_vector(t.evalseries) -1.5, -4.6 >>> t.evalseries = 1.0, 2.0 >>> print_vector(t.series) -0.7, 1.0, 2.0, -8.2
- load_series() None [source]¶
Read time series data from a file.
Method
load_series()
only calls methodload_file()
of classSequenceManager
passing itself as the only argument. Hence, see the documentation on the classSequenceManager
for further information. The following example only shows the error messages whenload_file()
is missing due to incomplete project configurations:>>> from hydpy.core.sequencetools import StateSequence >>> StateSequence(None).load_series() Traceback (most recent call last): ... hydpy.core.exceptiontools.AttributeNotReady: While trying to load the time series data of `statesequence`, the following error occurred: Attribute sequencemanager of module `pub` is not defined at the moment.
- adjust_series(timegrid_data: timetools.Timegrid, values: NDArrayFloat) NDArrayFloat [source]¶
Adjust a time series to the current initialisation period.
Note that, in most HydPy applications, method
adjust_series()
is called by other methods related to reading data from files and does not need to be called by the user directly. However, if you want to call it directly for some reason, you need to make sure that the shape of the givennumpy
ndarray
fits the givenTimegrid
object.Often, time series data available in data files cover a longer period than required for an actual simulation run. Method
adjust_series()
selects the relevant data by comparing the initialisationTimegrid
available in modulepub
and the given “data”Timegrid
object. We explain this behaviour by using the HydPy-H-Lahn example project and focussing on theObs
sequence ofNode
dill_assl:>>> from hydpy.core.testtools import prepare_full_example_2 >>> hp, pub, TestIO = prepare_full_example_2() >>> obs = hp.nodes.dill_assl.sequences.obs
With identical initialisation and data time grids, method
adjust_series()
returns the given data completely:>>> from hydpy import print_vector, Timegrid >>> import numpy >>> with TestIO(), pub.options.checkseries(False): ... print_vector(obs.adjust_series( ... Timegrid("1996-01-01", "1996-01-05", "1d"), ... numpy.arange(4, dtype=float))) 0.0, 1.0, 2.0, 3.0
For “too long” data, it only returns the relevant one:
>>> with TestIO(), pub.options.checkseries(False): ... print_vector(obs.adjust_series( ... Timegrid("1995-12-31", "1996-01-07", "1d"), ... numpy.arange(7, dtype=float))) 1.0, 2.0, 3.0, 4.0
For “too short” data, the behaviour differs depending on option
checkseries
. Withcheckseries
being enabled, methodadjust_series()
raises aRuntimeError
. Withcheckseries
being disabled, it extends the given array withnan
values (using methodadjust_short_series()
):>>> with TestIO(), pub.options.checkseries(True): ... obs.adjust_series(Timegrid("1996-01-02", "1996-01-04", "1d"), ... numpy.zeros((3,))) Traceback (most recent call last): ... RuntimeError: For sequence `obs` of node `dill_assl` the initialisation time grid (Timegrid("1996-01-01 00:00:00", "1996-01-05 00:00:00", "1d")) does not define a subset of the time grid of the data file `...dill_assl_obs_q.asc` (Timegrid("1996-01-02 00:00:00", "1996-01-04 00:00:00", "1d")).
>>> with TestIO(), pub.options.checkseries(False): ... print_vector(obs.adjust_series( ... Timegrid("1996-01-02", "1996-01-04", "1d"), numpy.zeros((2,)))) nan, 0.0, 0.0, nan
Additional checks raise errors in case of non-matching shapes or time information:
>>> with TestIO(): ... obs.adjust_series(Timegrid("1996-01-01", "1996-01-05", "1d"), ... numpy.zeros((5, 2))) Traceback (most recent call last): ... RuntimeError: The shape of sequence `obs` of node `dill_assl` is `()` but according to the data file `...dill_assl_obs_q.asc` it should be `(2,)`.
>>> with TestIO(): ... obs.adjust_series(Timegrid("1996-01-01", "1996-01-05", "1h"), ... numpy.zeros((24*5,))) Traceback (most recent call last): ... RuntimeError: According to data file `...dill_assl_obs_q.asc`, the date time step of sequence `obs` of node `dill_assl` is `1h` but the actual simulation time step is `1d`.
- adjust_short_series(timegrid: timetools.Timegrid, values: NDArrayFloat) NDArrayFloat [source]¶
Adjust a short time series to a longer time grid.
Mostly, time series data to be read from files should span (at least) the whole initialisation period of a HydPy project. However, incomplete time series might also be helpful for some variables used only for comparison (e.g. observed runoff used for calibration). Method
adjust_short_series()
adjusts such incomplete series to the public initialisation time grid stored in modulepub
. It is automatically called in methodadjust_series()
when necessary, provided that the optioncheckseries
is disabled.Assume the initialisation period of a HydPy project spans five days:
>>> from hydpy import pub >>> pub.timegrids = "2000.01.10", "2000.01.15", "1d"
Prepare a node series object for observational data:
>>> from hydpy.core.sequencetools import Obs >>> obs = Obs(None)
Prepare a test function that expects the time grid of the data and the data itself, which returns the adjusted array through invoking the method
adjust_short_series()
:>>> import numpy >>> def test(timegrid): ... values = numpy.ones(len(timegrid)) ... return obs.adjust_short_series(timegrid, values)
The following calls to the test function show the arrays returned for different kinds of misalignments:
>>> from hydpy import print_vector, Timegrid >>> print_vector(test(Timegrid("2000.01.05", "2000.01.20", "1d"))) 1.0, 1.0, 1.0, 1.0, 1.0 >>> print_vector(test(Timegrid("2000.01.12", "2000.01.15", "1d"))) nan, nan, 1.0, 1.0, 1.0 >>> print_vector(test(Timegrid("2000.01.12", "2000.01.17", "1d"))) nan, nan, 1.0, 1.0, 1.0 >>> print_vector(test(Timegrid("2000.01.10", "2000.01.13", "1d"))) 1.0, 1.0, 1.0, nan, nan >>> print_vector(test(Timegrid("2000.01.08", "2000.01.13", "1d"))) 1.0, 1.0, 1.0, nan, nan >>> print_vector(test(Timegrid("2000.01.12", "2000.01.13", "1d"))) nan, nan, 1.0, nan, nan >>> print_vector(test(Timegrid("2000.01.05", "2000.01.10", "1d"))) nan, nan, nan, nan, nan >>> print_vector(test(Timegrid("2000.01.05", "2000.01.08", "1d"))) nan, nan, nan, nan, nan >>> print_vector(test(Timegrid("2000.01.15", "2000.01.18", "1d"))) nan, nan, nan, nan, nan >>> print_vector(test(Timegrid("2000.01.16", "2000.01.18", "1d"))) nan, nan, nan, nan, nan
After enabling option
usedefaultvalues
, the missing values are initialised with zero instead of nan:>>> with pub.options.usedefaultvalues(True): ... print_vector(test(Timegrid("2000.01.12", "2000.01.17", "1d"))) 0.0, 0.0, 1.0, 1.0, 1.0
- apply_adjusted_series(timegrid_data: timetools.Timegrid, series: NDArrayFloat) None [source]¶
Take the values of the given “adjusted series”.
The “adjusted series” is usually returned by method
adjust_series()
. The behaviour of methodapply_adjusted_series()
depends on optionreset
. By default, “resetting” is enabled, meaning thatnan
values due to incomplete time series files overwrite previously available data. We demonstrate this using the NetCDF data provided by functionprepare_full_example_2()
but changing the initialisation period (only advised for testing purposes):>>> from hydpy.core.testtools import prepare_full_example_2 >>> hp, pub, TestIO = prepare_full_example_2() >>> pub.timegrids.init.firstdate = "1989-10-30" >>> pub.timegrids.init.lastdate = "1989-11-03" >>> t = hp.elements.land_dill_assl.model.sequences.inputs.t >>> t.series = -99.9 >>> opt = pub.options >>> sm = pub.sequencemanager >>> with TestIO(), sm.filetype("nc"), opt.checkseries(False): ... with sm.netcdfreading(): ... t.load_series() >>> from hydpy import round_ >>> round_(t.series) nan, nan, 10.1, 10.0
With option
reset
disabled, methodapply_adjusted_series()
keeps the already available data:>>> t.series = 99.9 >>> with TestIO(), sm.reset(False), sm.filetype("nc"), opt.checkseries(False): ... with sm.netcdfreading(): ... t.load_series() >>> from hydpy import round_ >>> round_(t.series) 99.9, 99.9, 10.1, 10.0
- check_completeness() None [source]¶
Raise a
RuntimeError
if theseries
contains at least onenan
value and if the optioncheckseries
is enabled.>>> from hydpy import pub >>> pub.timegrids = "2000-01-01", "2000-01-11", "1d" >>> from hydpy.core.sequencetools import StateSequence, StateSequences >>> class Seq(StateSequence): ... NDIM = 0 ... NUMERIC = False >>> class StateSequences(StateSequences): ... CLASSES = (Seq,) >>> seq = Seq(StateSequences(None)) >>> seq.__hydpy__connect_variable2subgroup__() >>> seq.prepare_series() >>> seq.check_completeness() Traceback (most recent call last): ... RuntimeError: The series array of sequence `seq` contains 10 nan values.
>>> seq.series = 1.0 >>> seq.check_completeness()
>>> seq.series[3] = numpy.nan >>> seq.check_completeness() Traceback (most recent call last): ... RuntimeError: The series array of sequence `seq` contains 1 nan value.
>>> with pub.options.checkseries(False): ... seq.check_completeness()
- save_series() None [source]¶
Write the time series data of the current
IOSequence
object to a file.Method
save_series()
only calls methodsave_file()
of classSequenceManager
, passing itself as the only argument. Hence, see the documentation on class theSequenceManager
for further information. The following example only shows the error messages whensave_file()
is missing due to incomplete project configurations:>>> from hydpy.core.sequencetools import StateSequence >>> StateSequence(None).save_series() Traceback (most recent call last): ... hydpy.core.exceptiontools.AttributeNotReady: While trying to save the time series data of `statesequence`, the following error occurred: Attribute sequencemanager of module `pub` is not defined at the moment.
- save_mean(*args, **kwargs) None [source]¶
Average the time series data with method
average_series()
of classIOSequence
and write the result to file using methodsave_file()
of classSequenceManager
.The main documentation on class
SequenceManager
provides some examples.
- property seriesmatrix: ndarray[Any, dtype[float64]]¶
The actual
IOSequence
object’s time series, arranged in a 2-dimensional matrix.For a 1-dimensional sequence object, property
seriesmatrix
returns the original values without modification:>>> from hydpy import pub >>> pub.timegrids = "2000-01-01", "2000-01-04", "1d" >>> from hydpy.models.hland import * >>> parameterstep("1d") >>> nmbzones(2) >>> fluxes.pc.prepare_series() >>> fluxes.pc.series = [[1.0, 2.0], [3.0, 4.0], [5.0, 6.0]] >>> from hydpy import print_vector >>> for values in fluxes.pc.seriesmatrix: ... print_vector(values) 1.0, 2.0 3.0, 4.0 5.0, 6.0
For all other sequences,
seriesmatrix
raises the following error by default:>>> inputs.p.seriesmatrix Traceback (most recent call last): ... NotImplementedError: Sequence `p` does not implement a method for converting its series to a 2-dimensional matrix.
- average_series(*args, **kwargs) InfoArray [source]¶
Average the actual time series of the
IOSequence
object for all time points.Method
average_series()
works similarly to methodaverage_values()
of classVariable
, from which we borrow some examples. However, we must first prepare aTimegrids
object to define theseries
length:>>> from hydpy import pub >>> pub.timegrids = "2000-01-01", "2000-01-04", "1d"
As shown for method
average_values()
, for 0-dimensionalIOSequence
objects, the result of methodaverage_series()
equalsseries
itself:>>> from hydpy.core.sequencetools import StateSequence, StateSequences >>> class SoilMoisture(StateSequence): ... NDIM = 0 ... NUMERIC = False >>> class StateSequences(StateSequences): ... CLASSES = (SoilMoisture,) >>> sm = SoilMoisture(StateSequences(None)) >>> sm.__hydpy__connect_variable2subgroup__() >>> sm.prepare_series() >>> import numpy >>> sm.series = numpy.array([190.0, 200.0, 210.0]) >>> sm.average_series() InfoArray([190., 200., 210.])
We require a weighting parameter for
IOSequence
objects with an increased dimensionality:>>> SoilMoisture.NDIM = 1 >>> sm.shape = 3 >>> sm.prepare_series() >>> sm.series = ([190.0, 390.0, 490.0], ... [200.0, 400.0, 500.0], ... [210.0, 410.0, 510.0]) >>> from hydpy.core.parametertools import Parameter >>> class Area(Parameter): ... NDIM = 1 ... shape = (3,) ... value = numpy.array([1.0, 1.0, 2.0]) >>> area = Area(None) >>> SoilMoisture.refweights = property(lambda self: area) >>> sm.average_series() InfoArray([390., 400., 410.])
The documentation on method
average_values()
provides many examples of using different masks in different ways. Here, we only show the results of methodaverage_series()
for a mask selecting the first two entries, for a mask selecting no entry at all, and for an ill-defined mask:>>> from hydpy.core.masktools import DefaultMask >>> class Soil(DefaultMask): ... @classmethod ... def new(cls, variable, **kwargs): ... return cls.array2mask(maskvalues) >>> SoilMoisture.mask = Soil()
>>> maskvalues = [True, True, False] >>> sm.average_series() InfoArray([290., 300., 310.])
>>> maskvalues = [False, False, False] >>> sm.average_series() InfoArray([nan, nan, nan])
>>> maskvalues = [True, True] >>> sm.average_series() Traceback (most recent call last): ... IndexError: While trying to calculate the mean value of the internal time series of sequence `soilmoisture`, the following error occurred: While trying to access the value(s) of variable `area` with key `[ True True]`, the following error occurred: boolean index did not match indexed array ...
- aggregate_series(*args, **kwargs) InfoArray [source]¶
Aggregate the time series data based on the actual
aggregation
attribute of the currentIOSequence
object.We prepare some nodes and elements with the help of method
prepare_io_example_1()
and select a 1-dimensional flux sequence of typeNKor
:>>> from hydpy.core.testtools import prepare_io_example_1 >>> nodes, elements = prepare_io_example_1() >>> seq = elements.element3.model.sequences.fluxes.nkor
If
aggregation
is none, the original time series values are returned:>>> seq.aggregation 'none' >>> seq.aggregate_series() InfoArray([[24., 25., 26.], [27., 28., 29.], [30., 31., 32.], [33., 34., 35.]])
If
aggregation
is mean, methodaggregate_series()
is called:>>> seq.aggregation = "mean" >>> seq.aggregate_series() InfoArray([25., 28., 31., 34.])
In case the state of the sequence is invalid:
>>> seq.aggregation = "nonexistent" >>> seq.aggregate_series() Traceback (most recent call last): ... RuntimeError: Unknown aggregation mode `nonexistent` for sequence `nkor` of element `element3`.
The following technical test confirms the propr passing of all potential positional and keyword arguments:
>>> seq.aggregation = "mean" >>> from unittest import mock >>> seq.average_series = mock.MagicMock() >>> _ = seq.aggregate_series(1, x=2) >>> seq.average_series.assert_called_with(1, x=2)
- abstract property descr_sequence: str¶
Description of the
IOSequence
object and its context.
- abstract property descr_device: str¶
Description of the
Device
object theIOSequence
object belongs to.
- class hydpy.core.sequencetools.ModelSequence(subvars: ModelSequences[ModelSequence, FastAccess])[source]¶
Bases:
Sequence_
Base class for sequences to be handled by
Model
objects.- property descr_sequence: str¶
Description of the
ModelSequence
object itself and theModel
type andSubSequences
group it belongs to.>>> from hydpy import prepare_model >>> from hydpy.models import test_stiff0d >>> model = prepare_model(test_stiff0d) >>> model.sequences.fluxes.q.descr_sequence 'test_stiff0d_flux_q'
- property descr_model: str¶
Description of the
Model
theModelSequence
object belongs to.>>> from hydpy import prepare_model >>> from hydpy.models import test, test_stiff0d >>> model = prepare_model(test) >>> model.sequences.fluxes.q.descr_model 'test' >>> model = prepare_model(test_stiff0d) >>> model.sequences.fluxes.q.descr_model 'test_stiff0d'
- property descr_device: str¶
Description of the
Element
object theModelSequence
object belongs to.>>> from hydpy import prepare_model, pub, Element >>> element = Element("my_element", outlets="outlet") >>> from hydpy.models.lland_knauf import * >>> parameterstep() >>> model.sequences.inputs.windspeed.descr_device '?' >>> element.model = model >>> model.sequences.inputs.windspeed.descr_device 'my_element'
>>> from hydpy import pub >>> pub.timegrids = "2000-01-01", "2001-01-02", "1d" >>> nhru(1) >>> ft(1.0) >>> fhru(1.0) >>> lnk(ACKER) >>> measuringheightwindspeed(10.0) >>> lai(10.0) >>> wmax(300.0) >>> with model.add_aetmodel_v1("evap_aet_morsim"): ... pass >>> model.aetmodel.sequences.inputs.windspeed.descr_device 'my_element'
- property numericshape: tuple[int, ...]¶
The shape of the array of temporary values required for the relevant numerical solver.
The class
ELSModel
, being the base of the “dam” model, uses the “Explicit Lobatto Sequence” for solving differential equations and therefore requires up to eleven array fields for storing temporary values. Hence, thenumericshape
of the 0-dimensional sequenceInflow
is eleven:>>> from hydpy import prepare_model >>> model = prepare_model("dam") >>> model.sequences.fluxes.inflow.numericshape (11,)
Changing the
shape
through a little trick (just for demonstration purposes) shows that there are eleven entries for each “normal”Inflow
value:>>> from hydpy.models.dam.dam_fluxes import Inflow >>> shape = Inflow.shape >>> Inflow.shape = (2,) >>> model.sequences.fluxes.inflow.numericshape (11, 2) >>> Inflow.shape = shape
Erroneous configurations result in the following error:
>>> del model.numconsts >>> model.sequences.fluxes.inflow.numericshape Traceback (most recent call last): ... AttributeError: The `numericshape` of a sequence like `inflow` depends on the configuration of the actual integration algorithm. While trying to query the required configuration data `nmb_stages` of the model associated with element `?`, the following error occurred: 'Model' object has no attribute 'numconsts'
- class hydpy.core.sequencetools.ModelIOSequence(subvars: ModelSequences[ModelSequence, FastAccess])[source]¶
Bases:
ModelSequence
,IOSequence
Base class for sequences with time series functionalities to be handled by
Model
objects.
- class hydpy.core.sequencetools.InputSequence(subvars: ModelSequences[ModelSequence, FastAccess])[source]¶
Bases:
ModelIOSequence
Base class for input sequences of
Model
objects.InputSequence
objects provide their master model with input data, which is possible in two ways: either by providing their individually managed data (usually read from a file) or data shared with an input node (usually calculated by another model). This flexibility allows, for example, to let application modelhland_96
read already preprocessed precipitation time series or to couple it with application models likeconv_nn
, which interpolates precipitation during the simulation run.The second mechanism (coupling
InputSequence
objects with input nodes) is relatively new, and we might adjust the relevant interfaces in the future. As soon as we finally settle things, we will improve the following example and place it more prominently. In short, it shows that working with both types of input data sources at the same time works well and that the differentdeploymode
options are supported:>>> from hydpy import Element, FusedVariable, HydPy, Node, print_vector, pub, TestIO >>> from hydpy.aliases import hland_inputs_T, hland_inputs_P >>> hp = HydPy("HydPy-H-Lahn") >>> pub.timegrids = "1996-01-01", "1996-01-06", "1d" >>> node_t = Node("node_t", variable=hland_inputs_T) >>> node_p = Node("node_p", variable=FusedVariable("Precip", hland_inputs_P)) >>> node_q = Node("node_q") >>> land_dill_assl = Element("land_dill_assl", inputs=[node_t, node_p], ... outlets=node_q)
>>> from hydpy.core.testtools import prepare_full_example_1 >>> prepare_full_example_1() >>> import os >>> with TestIO(): ... os.chdir("HydPy-H-Lahn/control/default") ... with open("land_dill_assl.py") as controlfile: ... exec(controlfile.read(), {}, locals()) ... parameters.update() ... land_dill_assl.model = model
>>> aetmodel = model.aetmodel >>> petmodel = model.aetmodel.petmodel
>>> model.sequences.inputs.t.inputflag True >>> model.sequences.inputs.p.inputflag True >>> petmodel.sequences.inputs.normalevapotranspiration.inputflag False
>>> hp.update_devices(nodes=[node_t, node_p, node_q], elements=land_dill_assl) >>> hp.prepare_inputseries() >>> hp.prepare_factorseries() >>> hp.prepare_fluxseries() >>> with TestIO(): ... hp.load_inputseries()
>>> hp.nodes.prepare_allseries() >>> node_t.deploymode = "oldsim" >>> node_t.sequences.sim.series = 1.0, 2.0, 3.0, 4.0, 5.0 >>> node_p.deploymode = "obs" >>> node_p.sequences.obs.series = 0.0, 4.0, 0.0, 8.0, 0.0
>>> hp.simulate()
>>> print_vector(model.sequences.inputs.t.series) 1.0, 2.0, 3.0, 4.0, 5.0 >>> print_vector(model.sequences.factors.tc.series[:, 0]) 2.323207, 3.323207, 4.323207, 5.323207, 6.323207 >>> print_vector(model.sequences.inputs.p.series) 0.0, 4.0, 0.0, 8.0, 0.0 >>> print_vector(model.sequences.fluxes.pc.series[:, 0]) 0.0, 3.2514, 0.0, 6.5028, 0.0 >>> print_vector(petmodel.sequences.inputs.normalevapotranspiration.series) 0.3, 0.3, 0.3, 0.3, 0.3 >>> print_vector( ... aetmodel.sequences.fluxes.potentialsoilevapotranspiration.series[:, 0]) 0.309, 0.317657, 0.369, 0.352975, 0.432
- STANDARD_NAME: ClassVar[StandardInputNames]¶
- property descr_sequence: str¶
Either a model-specific or a standard HydPy string describing the input sequence instance.
By default, the returned string equals those of other
ModelSequence
subclasses:>>> from hydpy import pub >>> from hydpy.core.filetools import SequenceManager >>> pub.sequencemanager = SequenceManager()
>>> from hydpy.models.hland_96 import * >>> parameterstep() >>> inputs.t.descr_sequence 'hland_96_input_t'
When activating the standard “HydPy” convention instead of the “model-specific” convention,
descr_sequence
returns the standard name selected by the respectiveInputSequence
subclass:>>> with pub.sequencemanager.convention("HydPy"): ... inputs.t.descr_sequence <StandardInputNames.AIR_TEMPERATURE: 'air_temperature'>
- set_pointer(double: Double) None [source]¶
Prepare a pointer referencing the given
Double
object.Method
set_pointer()
should be relevant for framework developers and eventually for some model developers only.
- property inputflag: bool¶
A flag telling if the actual
InputSequence
object queries its data from an input node (True
) or uses individually managed data, usually read from a data file (False
).See the main documentation on class
InputSequence
for further information.
- class hydpy.core.sequencetools.OutputSequence(subvars: ModelSequences[ModelSequence, FastAccess])[source]¶
Bases:
ModelIOSequence
Base class for
FactorSequence
,FluxSequence
andStateSequence
.OutputSequence
subclasses implement an optional output mechanism. Generally, as all instances ofModelSequence
subclasses, output sequences handle values calculated within a simulation time step. With an activatedoutputflag
, they also pass their internal values to an output node (see the documentation on classElement
), which makes them accessible to other models.This output mechanism (coupling
OutputSequence
objects with output nodes) is relatively new, and we might adjust the relevant interfaces in the future. Additionally, it works for 0-dimensional output sequences only so far. As soon as we finally settle things, we will improve the following example and place it more prominently. In short, it shows that everything works well for the differentdeploymode
options:>>> from hydpy import Element, HydPy, Node, print_vector, pub, Selection, TestIO >>> from hydpy.aliases import ( ... hland_fluxes_Perc, hland_fluxes_Q0, hland_fluxes_Q1, hland_states_UZ) >>> hp = HydPy("HydPy-H-Lahn") >>> pub.timegrids = "1996-01-01", "1996-01-06", "1d" >>> node_q0 = Node("node_q0", variable=hland_fluxes_Q0) >>> node_q1 = Node("node_q1", variable=hland_fluxes_Q1) >>> node_perc = Node("node_perc", variable=hland_fluxes_Perc) >>> node_uz = Node("node_uz", variable=hland_states_UZ) >>> node_q = Node("node_q") >>> land_dill_assl = Element("land_dill_assl", ... outlets=node_q, ... outputs=[node_q0, node_q1, node_perc, node_uz])
>>> from hydpy.core.testtools import prepare_full_example_1 >>> prepare_full_example_1() >>> import os >>> with TestIO(): ... os.chdir("HydPy-H-Lahn/control/default") ... with open("land_dill_assl.py") as controlfile: ... exec(controlfile.read(), {}, locals()) ... parameters.update() ... land_dill_assl.model = model
>>> model.sequences.fluxes.q0.outputflag True >>> model.sequences.fluxes.q1.outputflag True >>> model.sequences.fluxes.perc.outputflag True >>> model.sequences.fluxes.qt.outputflag False >>> model.sequences.states.uz.outputflag True >>> model.sequences.states.lz.outputflag False
>>> hp.update_devices(nodes=[node_q0, node_q1, node_perc, node_uz], ... elements=land_dill_assl) >>> with TestIO(): ... hp.load_conditions()
>>> hp.prepare_inputseries() >>> with TestIO(): ... hp.load_inputseries() >>> hp.prepare_fluxseries() >>> hp.prepare_stateseries() >>> hp.nodes.prepare_allseries()
>>> node_q0.deploymode = "oldsim" >>> node_q0.sequences.sim.series = 1.0 >>> node_q0.sequences.obs.series = 2.0 >>> node_q1.deploymode = "obs" >>> node_q1.sequences.obs.series = 3.0 >>> node_perc.deploymode = "newsim" >>> node_perc.sequences.obs.series = 4.0 >>> node_uz.sequences.obs.series = 5.0
>>> hp.simulate()
>>> print_vector(node_q0.sequences.sim.series) 1.0, 1.0, 1.0, 1.0, 1.0 >>> print_vector(node_q0.sequences.obs.series) 2.0, 2.0, 2.0, 2.0, 2.0
>>> print_vector(model.sequences.fluxes.q1.series) 0.530782, 0.539976, 0.548629, 0.556786, 0.564477 >>> print_vector(node_q1.sequences.sim.series) 0.530782, 0.539976, 0.548629, 0.556786, 0.564477 >>> print_vector(node_q1.sequences.obs.series) 3.0, 3.0, 3.0, 3.0, 3.0
>>> print_vector(model.sequences.fluxes.perc.series) 0.694084, 0.693611, 0.693239, 0.693098, 0.693012 >>> print_vector(node_perc.sequences.sim.series) 0.694084, 0.693611, 0.693239, 0.693098, 0.693012 >>> print_vector(node_perc.sequences.obs.series) 4.0, 4.0, 4.0, 4.0, 4.0
>>> print_vector(model.sequences.states.uz.series) 5.628278, 4.368269, 3.337343, 2.452946, 1.662766 >>> print_vector(node_uz.sequences.sim.series) 5.628278, 4.368269, 3.337343, 2.452946, 1.662766 >>> print_vector(node_uz.sequences.obs.series) 5.0, 5.0, 5.0, 5.0, 5.0
- set_pointer(double: Double) None [source]¶
Prepare a pointer referencing the given
Double
object.Method
set_pointer()
should be relevant for framework developers and eventually for some model developers only.
- property outputflag: bool¶
A flag telling if the actual
OutputSequence
object passes its data to an output node (True
) or not (False
).See the main documentation on class
OutputSequence
for further information.
- class hydpy.core.sequencetools.DependentSequence(subvars: ModelSequences[ModelSequence, FastAccess])[source]¶
Bases:
OutputSequence
Base class for
FactorSequence
andFluxSequence
.- shape¶
A tuple containing the actual lengths of all dimensions.
FactorSequence
andFluxSequence
objects come with some additional fastaccess attributes, which should only be of interest to framework developers. One such attribute is the results array, handling the (intermediate or final) calculation results for factor and flux sequences, as shown in the following example for the 0-dimensional flux sequenceRH
of thewland_wag
model:>>> from hydpy import prepare_model, print_vector, pub >>> model = prepare_model("wland_wag") >>> print_vector(model.sequences.fluxes.rh.fastaccess._rh_results) 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0
For 1-dimensional numerical factor and flux sequences, the results attribute is
None
initially, as propertynumericshape
is unknown. Setting theshape
attribute of the respectiveFactorSequence
orFluxSequence
object (we selectEI
as an example) prepares all “fastaccess attributes” automatically:>>> ei = model.sequences.fluxes.ei >>> ei.fastaccess._ei_results
>>> ei.shape = (2,) >>> ei.shape (2,) >>> ei.fastaccess._ei_results.shape (11, 2)
- class hydpy.core.sequencetools.FactorSequence(subvars: ModelSequences[ModelSequence, FastAccess])[source]¶
Bases:
DependentSequence
Base class for factor sequences of
Model
objects.
- class hydpy.core.sequencetools.FluxSequence(subvars: ModelSequences[ModelSequence, FastAccess])[source]¶
Bases:
DependentSequence
Base class for flux sequences of
Model
objects.
- class hydpy.core.sequencetools.ConditionSequence(subvars: ModelSequences[ModelSequence, FastAccess])[source]¶
Bases:
ModelSequence
Base class for
StateSequence
andLogSequence
.Class
ConditionSequence
should not be subclassed by model developers directly. Inherit fromStateSequence
orLogSequence
instead.- trim(lower=None, upper=None) bool [source]¶
Apply
trim()
of modulevariabletools
.
- reset()[source]¶
Reset the value of the actual
StateSequence
orLogSequence
object to the last value defined by “calling” the object.We use the
lland_knauf
application model, which handles sequences derived fromStateSequence
(takingInzp
as an example) and fromLogSequence
(takingLoggedSunshineDuration
as an example):>>> from hydpy import prepare_model, pub >>> model = prepare_model("lland_knauf")
After defining their shapes, both sequences contain
nan
values:>>> inzp = model.sequences.states.inzp >>> inzp.shape = (2,) >>> inzp inzp(nan, nan) >>> lsd = model.sequences.logs.loggedsunshineduration >>> lsd.shape = 2 >>> lsd loggedsunshineduration(nan, nan)
Before “calling” the sequences method
reset()
does nothing:>>> inzp.values = 0.0 >>> inzp.reset() >>> inzp inzp(0.0, 0.0) >>> lsd.values = 0.0 >>> lsd.reset() >>> lsd loggedsunshineduration(0.0, 0.0)
After “calling” the sequences method
reset()
reuses the respective arguments:>>> with pub.options.warntrim(False): ... inzp(0.0, 1.0) >>> inzp.values = 0.0 >>> inzp inzp(0.0, 0.0) >>> with pub.options.warntrim(False): ... inzp.reset() >>> inzp inzp(0.0, 1.0) >>> lsd(1.0, 2.0) >>> lsd.values = 3.0 >>> lsd loggedsunshineduration(3.0, 3.0) >>> lsd.reset() >>> lsd loggedsunshineduration(1.0, 2.0)
- class hydpy.core.sequencetools.StateSequence(subvars: ModelSequences[ModelSequence, FastAccess])[source]¶
Bases:
OutputSequence
,ConditionSequence
Base class for state sequences of
Model
objects.Each
StateSequence
object can handle states at two different “time points”: at the beginning of a simulation step via propertyold
and the end of a simulation step via propertynew
. These properties are reflected by two different fastaccess attributes. fastaccess_new is an alias for the standard fastaccess attribute storing the customary information. fastaccess_old is an additional feature for keeping the supplemental information.We demonstrate the above explanations using state sequence
SM
of the base modelhland_96
with a shape of two:>>> from hydpy import prepare_model, print_vector >>> model = prepare_model("hland") >>> model.parameters.control.fc.shape = (2,) >>> model.parameters.control.fc = 100.0 >>> sm = model.sequences.states.sm >>> sm.shape = (2,)
Initially, no values are available at all:
>>> sm sm(nan, nan) >>> print_vector(sm.values) nan, nan >>> print_vector(sm.new) nan, nan >>> print_vector(sm.old) nan, nan
The typical way to define state values, especially within condition files, is to “call” state sequence objects, which sets both the “old” and the “new” states to the given value(s):
>>> sm(1.0) >>> print_vector(sm.values) 1.0, 1.0 >>> print_vector(sm.new) 1.0, 1.0 >>> print_vector(sm.old) 1.0, 1.0
Alternatively, one can assign values to property
new
or propertyold
(note that usingnew
is identical with using thevalue
property):>>> sm.new = 2.0, 3.0 >>> sm sm(2.0, 3.0) >>> print_vector(sm.values) 2.0, 3.0 >>> print_vector(sm.new) 2.0, 3.0 >>> print_vector(sm.old) 1.0, 1.0
>>> sm.old = 200.0 >>> sm sm(2.0, 3.0) >>> print_vector(sm.values) 2.0, 3.0 >>> print_vector(sm.new) 2.0, 3.0 >>> print_vector(sm.old) 200.0, 200.0
If you assign problematic values to property
old
, it raises similar error messages as propertyvalue
:>>> sm.old = 1.0, 2.0, 3.0 Traceback (most recent call last): ... ValueError: While trying to set the old value(s) of state sequence `sm`, the following error occurred: While trying to convert the value(s) `(1.0, 2.0, 3.0)` to a numpy ndarray with shape `(2,)` and type `float`, the following error occurred: could not broadcast input array from shape (3,) into shape (2,)
Just for completeness: Method
new2old()
effectively takes the new values as old ones, but more efficiently than using the propertiesnew
andold
(the Python methodnew2old()
is usually replaced by model-specific, cythonized version when working in Cython mode):>>> sm.new2old() >>> print_vector(sm.values) 2.0, 3.0 >>> print_vector(sm.new) 2.0, 3.0 >>> print_vector(sm.old) 2.0, 3.0
- shape¶
A tuple containing the actual lengths of all dimensions.
StateSequence
objects come with some additional fastaccess attributes, which should only be of interest to framework developers. One such attribute is the results array, handling the (intermediate or final) calculation results for state sequence, as shown in the following example for the 0-dimensional sequenceHS
of thewland_wag
model:>>> from hydpy import prepare_model, print_vector, pub >>> model = prepare_model("wland_wag") >>> print_vector(model.sequences.states.hs.fastaccess._hs_results) 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0
For 1-dimensional numerical state sequences, the results attribute is
None
initially, as propertynumericshape
is unknown. Setting theshape
attribute of the respectiveStateSequence
object (we selectIC
as an example) prepares all “fastaccess attributes” automatically:>>> ic = model.sequences.states.ic >>> ic.fastaccess._ic_results
>>> ic.shape = (2,) >>> ic.shape (2,) >>> ic.fastaccess._ic_results.shape (11, 2)
- property new¶
State(s) after calling a
Model
calculation method. (Alias for propertyvalue
).Property
new
handles, in contrast to propertyold
, the newly calculated state values during each simulation step. It supports testing and debugging of individualModel
methods but is typically irrelevant when scripting HydPy workflows.
- property old¶
State(s) before calling a
Model
calculation method.Note the similarity to property
new
. However, propertyold
references the initial states of the respective simulation step, which should not be changed byModel
calculation methods.
- class hydpy.core.sequencetools.LogSequence(subvars: ModelSequences[ModelSequence, FastAccess])[source]¶
Bases:
ConditionSequence
Base class for logging values required for later calculations.
Class
LogSequence
serves similar purposes asStateSequence
but is less strict in its assumptions. WhileStateSequence
objects always handle two states (theold
and thenew
one),LogSequence
objects are supposed to remember an arbitrary or sequence-specific number of values, which can be state values but, for example, also flux values. A typical use case is to store “old” values of effective precipitation to calculate “new” values of direct discharge using the unit hydrograph concept in later simulation steps.It is up to the model developer to ensure that a
LogSequence
subclass has the correct dimensionality and shape to store the required information. By convention, the “memory” of eachLogSequence
should be placed on the first axis for non-scalar properties.As
StateSequence
objects,LogSequence
objects store relevant information to start a new simulation run where another one has ended and are thus written into and read from condition files.
- class hydpy.core.sequencetools.LogSequenceFixed(subvars: ModelSequences[ModelSequence, FastAccess])[source]¶
Bases:
LogSequence
Base class for log sequences with a fixed shape.
- shape¶
Sequences derived from
LogSequenceFixed
initialise themselves with a predefined shape.We take parameter
LoggedRequiredRemoteRelease
of base modeldam
as an example:>>> from hydpy.models.dam import * >>> parameterstep() >>> logs.loggedrequiredremoterelease.shape (1,)
Property
shape
results in the following exception when you try to set a new shape:>>> logs.loggedrequiredremoterelease.shape = 2 Traceback (most recent call last): ... AttributeError: The shape of sequence `loggedrequiredremoterelease` cannot be changed, but this was attempted for element `?`.
See the documentation on property
shape
of classVariable
for further information.
- class hydpy.core.sequencetools.AideSequence(subvars: ModelSequences[ModelSequence, FastAccess])[source]¶
Bases:
ModelSequence
Base class for aide sequences of
Model
objects.Aide sequences store data only relevant for calculating an individual simulation time step but must be shared between different calculation methods of a
Model
object.
- class hydpy.core.sequencetools.LinkSequence(subvars: ModelSequences[ModelSequence, FastAccess])[source]¶
Bases:
ModelSequence
Base class for link sequences of
Model
objects.LinkSequence
objects do not handle values themselves. Instead, they point to the values handled byNodeSequence
objects, using the functionalities provided by the Cython modulepointerutils
. MultipleLinkSequence
objects of different application models can query and modify the sameNodeSequence
values, allowing differentModel
objects to share information and interact with each other.A note for developers:
LinkSequence
subclasses must be either 0-dimensional or 1-dimensional.Users might encounter the following exception that is a safety measure to prevent segmentation faults, as the error message suggests:
>>> from hydpy.core.sequencetools import LinkSequence >>> seq = LinkSequence(None) >>> seq linksequence(?) >>> seq.value Traceback (most recent call last): ... hydpy.core.exceptiontools.AttributeNotReady: While trying to query the value(s) of link sequence `linksequence` of element `?`, the following error occurred: Proper connections are missing (which could result in segmentation faults when using it, so please be careful).
- set_pointer(double: Double, idx: int = 0) None [source]¶
Prepare a pointer referencing the given
Double
object.For 1-dimensional sequence objects, one also needs to specify the relevant index position of the pointer via argument idx.
Method
set_pointer()
should be relevant for framework developers and eventually for some model developers only.
- property value¶
The actual value(s) the
LinkSequence
object is pointing at.Changing a
value
of aLinkSequence
object seems very much like changing avalue
of any otherVariable
object. However, be aware that you are changing a value handled by aNodeSequence
object. We demonstrate this by using the HydPy-H-Lahn example project through invoking functionprepare_full_example_2()
:>>> from hydpy.core.testtools import prepare_full_example_2 >>> hp, pub, TestIO = prepare_full_example_2()
We focus on the
musk_classic
application model stream_lahn_marb_lahn_leun routing inflow from node lahn_marb to node lahn_leun:>>> model = hp.elements.stream_lahn_marb_lahn_leun.model
The first example shows that the 0-dimensional outlet sequence
Q
points to theSim
sequence of node lahn_leun:>>> model.sequences.outlets.q q(0.0) >>> hp.nodes.lahn_leun.sequences.sim = 1.0 >>> model.sequences.outlets.q q(1.0) >>> model.sequences.outlets.q(2.0) >>> hp.nodes.lahn_leun.sequences.sim sim(2.0)
The second example shows that the 1-dimensional inlet sequence
Q
points to theSim
sequence of node lahn_marb:>>> model.sequences.inlets.q q(0.0) >>> hp.nodes.lahn_marb.sequences.sim = 1.0 >>> model.sequences.inlets.q q(1.0) >>> model.sequences.inlets.q(2.0) >>> hp.nodes.lahn_marb.sequences.sim sim(2.0)
Direct querying the values of both link sequences shows that the value of the 0-dimensional outlet sequence is scalar, of course, and that the value of the 1-dimensional inlet sequence is one entry of a vector:
>>> from hydpy import print_vector, round_ >>> round_(model.sequences.outlets.q.value) 2.0 >>> print_vector(model.sequences.inlets.q.values) 2.0
Assigning incorrect data leads to the usual error messages:
>>> model.sequences.outlets.q.value = 1.0, 2.0 Traceback (most recent call last): ... ValueError: While trying to assign the value(s) (1.0, 2.0) to link sequence `q` of element `stream_lahn_marb_lahn_leun`, the following error occurred: 2 values are assigned to the scalar variable `q` of element `stream_lahn_marb_lahn_leun`. >>> model.sequences.inlets.q.values = 1.0, 2.0 Traceback (most recent call last): ... ValueError: While trying to assign the value(s) (1.0, 2.0) to link sequence `q` of element `stream_lahn_marb_lahn_leun`, the following error occurred: While trying to convert the value(s) `(1.0, 2.0)` to a numpy ndarray with shape `(1,)` and type `float`, the following error occurred: could not broadcast input array from shape (2,) into shape (1,)
In the example above, the 1-dimensional inlet sequence
Q
only points a singleNodeSequence
value. We now prepare aexch_branch_hbv96
application model instance to show what happens when connecting a 1-dimensionalLinkSequence
object (Branched
) with threeNodeSequence
objects (see the documentation of application modelexch_branch_hbv96
for more details):>>> from hydpy import Element, Nodes, prepare_model >>> model = prepare_model("exch_branch_hbv96") >>> nodes = Nodes("input1", "input2", "output1", "output2", "output3") >>> branch = Element("branch", ... inlets=["input1", "input2"], ... outlets=["output1", "output2", "output3"]) >>> model.parameters.control.xpoints( ... 0.0, 2.0, 4.0, 6.0) >>> model.parameters.control.ypoints( ... output1=[0.0, 1.0, 2.0, 3.0], ... output2=[0.0, 1.0, 0.0, 0.0], ... output3=[0.0, 0.0, 2.0, 6.0]) >>> branch.model = model
Our third example demonstrates that each field of the values of a 1-dimensional
LinkSequence
objects points to anotherNodeSequence
object:>>> nodes.output1.sequences.sim = 1.0 >>> nodes.output2.sequences.sim = 2.0 >>> nodes.output3.sequences.sim = 3.0 >>> model.sequences.outlets.branched branched(1.0, 2.0, 3.0) >>> model.sequences.outlets.branched = 4.0, 5.0, 6.0 >>> nodes.output1.sequences.sim sim(4.0) >>> nodes.output2.sequences.sim sim(5.0) >>> nodes.output3.sequences.sim sim(6.0)
- shape¶
A tuple containing the actual lengths of all dimensions.
Property
shape
of classLinkSequence
works similarly as the generalshape
property of classVariable
. Still, you need to be extra careful due to the pointer mechanism underlying classLinkSequence
. Change the shape of a link sequence for good reasons only. Please read the documentation on propertyvalue
first and then see the following examples, which are, again, based on the HydPy-H-Lahn example project and application modelmusk_classic
:>>> from hydpy.core.testtools import prepare_full_example_2 >>> hp, pub, TestIO = prepare_full_example_2() >>> model = hp.elements.stream_lahn_marb_lahn_leun.model
The default mechanisms of HydPy prepare both 0-dimensional and 1-dimensional link sequences with a proper shape (which, for inlet sequence | musk_inlets.Q|, depends on the number of connected
Node
objects):>>> model.sequences.outlets.q.shape () >>> model.sequences.inlets.q.shape (1,)
Attempting to set the only possible shape of 0-dimensional link sequences or any different shape results in the standard behaviour:
>>> model.sequences.outlets.q.shape = () >>> model.sequences.outlets.q.shape = (1,) Traceback (most recent call last): ... ValueError: While trying to set the shape of link sequence`q` of element `stream_lahn_marb_lahn_leun`, the following error occurred: The shape information of 0-dimensional variables as `q` of element `stream_lahn_marb_lahn_leun` can only be `()`, but `(1,)` is given.
Changing the shape of 1-dimensional link sequences is supported but destroys the connection to the
NodeSequence
values of the respective nodes. Therefore, he following exception prevents segmentation faults until proper connections are available:>>> model.sequences.inlets.q.shape = (2,) >>> model.sequences.inlets.q.shape (2,) >>> model.sequences.inlets.q.shape = 1 >>> model.sequences.inlets.q.shape (1,) >>> model.sequences.inlets.q Traceback (most recent call last): ... RuntimeError: While trying to query the value(s) of link sequence `q` of element `stream_lahn_marb_lahn_leun`, the following error occurred: The pointer of the actual `PPDouble` instance at index `0` requested, but not prepared yet via `set_pointer`.
>>> model.sequences.inlets.q(1.0) Traceback (most recent call last): ... RuntimeError: While trying to assign the value(s) 1.0 to link sequence `q` of element `stream_lahn_marb_lahn_leun`, the following error occurred: The pointer of the actual `PPDouble` instance at index `0` requested, but not prepared yet via `set_pointer`.
Querying the shape of a link sequence should rarely result in errors. However, if we enforce it by deleting the fastaccess attribute, we get an error message:
>>> del model.sequences.inlets.q.fastaccess >>> model.sequences.inlets.q.shape Traceback (most recent call last): ... AttributeError: While trying to query the shape of link sequence`q` of element `stream_lahn_marb_lahn_leun`, the following error occurred: 'Q' object has no attribute 'fastaccess'
- class hydpy.core.sequencetools.InletSequence(subvars: ModelSequences[ModelSequence, FastAccess])[source]¶
Bases:
LinkSequence
Base class for inlet link sequences of
Model
objects.
- class hydpy.core.sequencetools.OutletSequence(subvars: ModelSequences[ModelSequence, FastAccess])[source]¶
Bases:
LinkSequence
Base class for outlet link sequences of
Model
objects.
- class hydpy.core.sequencetools.ReceiverSequence(subvars: ModelSequences[ModelSequence, FastAccess])[source]¶
Bases:
LinkSequence
Base class for receiver link sequences of
Model
objects.
- class hydpy.core.sequencetools.SenderSequence(subvars: ModelSequences[ModelSequence, FastAccess])[source]¶
Bases:
LinkSequence
Base class for sender link sequences of
Model
objects.
- class hydpy.core.sequencetools.NodeSequence(subvars: NodeSequences)[source]¶
Bases:
IOSequence
Base class for all sequences to be handled by
Node
objects.- property initinfo: tuple[Double, bool]¶
Return a
Double
instead of afloat
object as the first tuple entry.
- property descr_sequence: str¶
Description of the
NodeSequence
object, including thevariable
to be represented.>>> from hydpy import Node >>> Node("test_node_1", "T").sequences.sim.descr_sequence 'sim_t'
>>> from hydpy import FusedVariable >>> from hydpy.aliases import hland_inputs_T, lland_inputs_TemL >>> Temp = FusedVariable("Temp", hland_inputs_T, lland_inputs_TemL) >>> Node("test_node_2", Temp).sequences.sim.descr_sequence 'sim_temp'
- property descr_device: str¶
Description of the
Node
object theNodeSequence
object belongs to.>>> from hydpy import Node >>> Node("test_node_2").sequences.sim.descr_device 'test_node_2'
- property value¶
The actual sequence value.
For framework users, the property
value
of classNodeSequence
works as usual (explained in the documentation on propertyshape
of classVariable
). However, framework developers should note thatNodeSequence
objects useDouble
objects for storing their values and making them accessible toPDouble
andPPDouble
objects as explained in detail in the documentation on classLinkSequence
. This mechanism is hidden for framework users via conversions to typefloat
for safety reasons:>>> from hydpy import Node >>> sim = Node("node").sequences.sim >>> sim(1.0) >>> sim sim(1.0) >>> sim.value 1.0 >>> sim.fastaccess.sim Double(1.0)
>>> sim.value = 2.0 >>> sim sim(2.0)
Node sequences return errors like the following if they receive misspecified values or are ill-configured:
>>> sim.value = 1.0, 2.0 Traceback (most recent call last): ... TypeError: While trying to assign the value `(1.0, 2.0)` to sequence `sim` of node `node`, the following error occurred: float() argument must be a string or a... number, not 'tuple'
>>> sim.name = None >>> sim.value Traceback (most recent call last): ... TypeError: While trying to query the value of sequence `None` of node `node`, the following error occurred: ...attribute name must be string...
- property seriescomplete: bool¶
True/False flag indicating whether simulated or observed data is fully available or not.
We use the observation series of node dill_assl of the HydPy-H-Lahn project:
>>> from hydpy.core.testtools import prepare_full_example_2 >>> hp, pub, TestIO = prepare_full_example_2() >>> obs = hp.nodes.dill_assl.sequences.obs
When the sequence does not handle any time series data,
seriescomplete
isFalse
:>>> obs.prepare_series(allocate_ram=False) >>> obs.series Traceback (most recent call last): ... hydpy.core.exceptiontools.AttributeNotReady: Sequence `obs` of node `dill_assl` is not requested to make any time series data available. >>> obs.seriescomplete False
As long as any time series data is missing,
seriescomplete
is stillFalse
:>>> obs.prepare_series() >>> obs.series[:-1] = 1.0 >>> obs.series InfoArray([ 1., 1., 1., nan]) >>> obs.seriescomplete False
Only with all data being not
nan
,seriescomplete
isTrue
:>>> obs.series[-1] = 1.0 >>> obs.seriescomplete True
- class hydpy.core.sequencetools.Sim(subvars: NodeSequences)[source]¶
Bases:
NodeSequence
Class for handling those values of
Node
objects that are “simulated”, meaning calculated by hydrological models.- load_series() None [source]¶
Read time series data like method
load_series()
of classIOSequence
but with special handling of missing data.The method’s “special handling” is to convert errors to warnings. We explain the reasons in the documentation on method
load_series()
of classObs
, from which we borrow the following examples. The only differences are that methodload_series()
of classSim
does not disable propertymemoryflag
and uses the optionwarnmissingsimfile
instead ofwarnmissingobsfile
:>>> from hydpy.core.testtools import prepare_full_example_1 >>> prepare_full_example_1() >>> from hydpy import HydPy, pub, TestIO >>> hp = HydPy("HydPy-H-Lahn") >>> pub.timegrids = "1996-01-01", "1996-01-06", "1d" >>> with TestIO(): ... hp.prepare_network() ... hp.prepare_models() ... hp.prepare_simseries() >>> sim = hp.nodes.dill_assl.sequences.sim >>> with TestIO(): ... sim.load_series() Traceback (most recent call last): ... UserWarning: While trying to load the time series data of sequence `sim` of node `dill_assl`, the following error occurred: [Errno 2] No such file or directory: '...dill_assl_sim_q.asc' >>> sim.series InfoArray([nan, nan, nan, nan, nan])
>>> sim.series = 1.0 >>> with TestIO(): ... sim.save_series() >>> sim.series = 0.0 >>> with TestIO(): ... sim.load_series() >>> sim.series InfoArray([1., 1., 1., 1., 1.])
>>> import numpy >>> sim.series[2] = numpy.nan >>> with TestIO(), pub.sequencemanager.overwrite(True): ... sim.save_series() >>> with TestIO(): ... sim.load_series() Traceback (most recent call last): ... UserWarning: While trying to load the time series data of sequence `sim` of node `dill_assl`, the following error occurred: The series array of sequence `sim` of node `dill_assl` contains 1 nan value. >>> sim.series InfoArray([ 1., 1., nan, 1., 1.])
>>> sim.series = 0.0 >>> with TestIO(), pub.options.warnmissingsimfile(False): ... sim.load_series() >>> sim.series InfoArray([ 1., 1., nan, 1., 1.])
- class hydpy.core.sequencetools.Obs(subvars: NodeSequences)[source]¶
Bases:
NodeSequence
Class for handling those values of
Node
objects that are observed, meaning read from data files.- load_series() None [source]¶
Read time series data like method
load_series()
of classIOSequence
but with special handling of missing data.When reading incomplete time series data, HydPy usually raises a
RuntimeError
to prevent from performing erroneous calculations. This functionality makes sense for meteorological input data that is a strict requirement for hydrological simulations. However, the same often does not hold for the time series ofObs
sequences, e.g. representing measured discharge. Measured discharge is often an optional input or only used for comparison purposes.According to this reasoning, HydPy raises (at most) a
UserWarning
in case of missing or incomplete external time series data ofObs
sequences. The following examples show this based on the HydPy-H-Lahn project, mainly focussing on theObs
sequence of node dill_assl, which is ready for handling time series data at the end of the following steps:>>> from hydpy.core.testtools import prepare_full_example_1 >>> prepare_full_example_1() >>> from hydpy import HydPy, pub, TestIO >>> hp = HydPy("HydPy-H-Lahn") >>> pub.timegrids = "1996-01-01", "1996-01-06", "1d" >>> with TestIO(): ... hp.prepare_network() ... hp.prepare_models() ... hp.prepare_obsseries() >>> obs = hp.nodes.dill_assl.sequences.obs >>> obs.ramflag True
Trying to read non-existing data raises the following warning and disables the sequence’s ability to handle time series data:
>>> import os >>> with TestIO(): ... os.remove(hp.nodes.dill_assl.sequences.obs.filepath) ... hp.load_obsseries() Traceback (most recent call last): ... UserWarning: The `memory flag` of sequence `obs` of node `dill_assl` had to be set to `False` due to the following problem: While trying to load the time series data of sequence `obs` of node `dill_assl`, the following error occurred: [Errno 2] No such file or directory: '...dill_assl_obs_q.asc'
>>> obs.ramflag False
After writing a complete data file, everything works fine:
>>> obs.prepare_series() >>> obs.series = 1.0 >>> with TestIO(): ... obs.save_series() >>> obs.series = 0.0 >>> with TestIO(): ... obs.load_series() >>> obs.series InfoArray([1., 1., 1., 1., 1.])
Reading incomplete data also results in a warning message, but does not disable the
memoryflag
:>>> import numpy >>> obs.series[2] = numpy.nan >>> with TestIO(), pub.sequencemanager.overwrite(True): ... obs.save_series() >>> with TestIO(): ... obs.load_series() Traceback (most recent call last): ... UserWarning: While trying to load the time series data of sequence `obs` of node `dill_assl`, the following error occurred: The series array of sequence `obs` of node `dill_assl` contains 1 nan value. >>> obs.memoryflag True
Option
warnmissingobsfile
allows disabling the warning messages without altering the functionalities described above:>>> hp.prepare_obsseries() >>> with TestIO(): ... os.remove(hp.nodes.lahn_marb.sequences.obs.filepath) ... with pub.options.warnmissingobsfile(False): ... hp.load_obsseries() >>> obs.series InfoArray([ 1., 1., nan, 1., 1.]) >>> hp.nodes.lahn_marb.sequences.obs.memoryflag False
- class hydpy.core.sequencetools.NodeSequences(master: devicetools.Node, cls_fastaccess: type[FastAccessNodeSequence] | None = None, cymodel: CyModelProtocol | None = None)[source]¶
Bases:
IOSequences
[devicetools.Node
,NodeSequence
,FastAccessNodeSequence
]Base class for handling
Sim
andObs
sequence objects.Basically,
NodeSequences
works like the differentModelSequences
subclasses used for handlingModelSequence
objects. The main difference is that they do not reference aSequences
object (which is only handled byElement
objects but not byNode
objects). Instead, they directly reference their masterNode
object via the attributenode
:>>> from hydpy import Node >>> node = Node("node") >>> node.sequences.node Node("node", variable="Q")
The implemented methods just call the same method of the underlying fastaccess attribute, which is an instance of (a Cython extension class of) the Python class
FastAccessNodeSequence
.- node: devicetools.Node¶
- load_data(idx: int) None [source]¶
Call method
load_data()
of the current fastaccess attribute.>>> from hydpy import Node, pub >>> with pub.options.usecython(False): ... node = Node("node") >>> from unittest import mock >>> method = "hydpy.core.sequencetools.FastAccessNodeSequence.load_data" >>> with mock.patch(method) as mocked: ... node.sequences.load_data(5) >>> mocked.call_args_list [call(5)]
- load_simdata(idx: int) None [source]¶
Call method
load_simdata()
of the current fastaccess attribute.>>> from hydpy import Node, pub >>> with pub.options.usecython(False): ... node = Node("node") >>> from unittest import mock >>> method = "hydpy.core.sequencetools.FastAccessNodeSequence.load_simdata" >>> with mock.patch(method) as mocked: ... node.sequences.load_simdata(5) >>> mocked.call_args_list [call(5)]
- load_obsdata(idx: int) None [source]¶
Call method
load_obsdata()
of the current fastaccess attribute.>>> from hydpy import Node, pub >>> with pub.options.usecython(False): ... node = Node("node") >>> from unittest import mock >>> method = "hydpy.core.sequencetools.FastAccessNodeSequence.load_obsdata" >>> with mock.patch(method) as mocked: ... node.sequences.load_obsdata(5) >>> mocked.call_args_list [call(5)]
- save_data(idx: int) None [source]¶
Call method
save_data()
of the current fastaccess attribute.>>> from hydpy import Node, pub >>> with pub.options.usecython(False): ... node = Node("node") >>> from unittest import mock >>> method = "hydpy.core.sequencetools.FastAccessNodeSequence.save_data" >>> with mock.patch(method) as mocked: ... node.sequences.save_data(5) >>> mocked.call_args_list [call(5)]
- save_simdata(idx: int) None [source]¶
Call method
save_simdata()
of the current fastaccess attribute.>>> from hydpy import Node, pub >>> with pub.options.usecython(False): ... node = Node('node') >>> from unittest import mock >>> method = "hydpy.core.sequencetools.FastAccessNodeSequence.save_simdata" >>> with mock.patch(method) as mocked: ... node.sequences.save_simdata(5) >>> mocked.call_args_list [call(5)]