sequencetools¶
This module implements tools for defining and handling different kinds of hydrological model sequences (time series).
Module sequencetools implements the following members:
TypeFastAccessIOSequence_coType variable.
TypeIOSequence_coType variable.
TypeLinkSequence_coType variable.
TypeModelIOSequence_coType variable.
TypeModelSequence_coType variable.
TypeModelSequencesType variable.
TypeOutputSequence_coType variable.
TypeSequence_coType variable.
TypeSequencesType variable.
FastAccessIOSequenceProvides fast access to the values of theIOSequenceobjects of a specific subgroup and supports handling time series data during simulations.
FastAccessInputSequenceFastAccessIOSequencesubclass specialised for input sequences.
FastAccessOutputSequenceFastAccessIOSequencesubclass specialised for output sequences.
FastAccessLinkSequenceFastAccessIOSequencesubclass specialised for link sequences.
FastAccessNodeSequenceFastAccessIOSequencesubclass specialised forNodeobjects.
InfoArraynumpyndarraysubclass with an additional attribute describing the (potential) aggregation of the handled data.
StandardInputNamesStandard names for theInputSequencesubclasses of the various models.
SequencesBase class for handling all sequences of a specific model.
SubSequencesBase class for handling subgroups of sequences.
ModelSequencesBase class for handling model-related subgroups of sequences.
SeriesModeThe type of propertyseriesmodeof classIOSequence.
IOSequencesSubclass ofSubSequences, specialised for handlingIOSequenceobjects.
ModelIOSequencesBase class for handling model-related subgroups ofIOSequenceobjects.
InputSequencesBase class for handlingInputSequenceobjects.
OutputSequencesBase class for handlingOutputSequenceobjects.
FactorSequencesBase class for handlingFactorSequenceobjects.
FluxSequencesBase class for handlingFluxSequenceobjects.
StateSequencesBase class for handlingStateSequenceobjects.
LogSequencesBase class for handlingLogSequenceobjects.
AideSequencesBase class for handlingAideSequenceobjects.
LinkSequencesBase class for handlingLinkSequenceobjects.
InletSequencesBase class for handling “inlet”LinkSequenceobjects.
OutletSequencesBase class for handling “outlet”LinkSequenceobjects.
ReceiverSequencesBase class for handling “receiver”LinkSequenceobjects.
SenderSequencesBase class for handling “sender”LinkSequenceobjects.
Sequence_Base class for defining different kinds of sequences.
IOSequenceBase class for sequences with input/output functionalities.
ModelSequenceBase class for sequences to be handled byModelobjects.
ModelIOSequenceBase class for sequences with time series functionalities to be handled byModelobjects.
InputSequenceBase class for input sequences ofModelobjects.
OutputSequenceBase class forFactorSequence,FluxSequenceandStateSequence.
DependentSequenceBase class forFactorSequenceandFluxSequence.
FactorSequenceBase class for factor sequences ofModelobjects.
FluxSequenceBase class for flux sequences ofModelobjects.
ConditionSequenceBase class forStateSequenceandLogSequence.
StateSequenceBase class for state sequences ofModelobjects.
LogSequenceBase class for logging values required for later calculations.
LogSequenceFixedBase class for log sequences with a fixed shape.
AideSequenceBase class for aide sequences ofModelobjects.
LinkSequenceBase class for link sequences ofModelobjects.
InletSequenceBase class for inlet link sequences ofModelobjects.
OutletSequenceBase class for outlet link sequences ofModelobjects.
ReceiverSequenceBase class for receiver link sequences ofModelobjects.
SenderSequenceBase class for sender link sequences ofModelobjects.
NodeSequenceBase class for all sequences to be handled byNodeobjects.
SimClass for handling those values ofNodeobjects that are “simulated”, meaning calculated by hydrological models.
ObsClass for handling those values ofNodeobjects that are observed, meaning read from data files.
NodeSequencesBase class for handlingSimandObssequence objects.
- class hydpy.core.sequencetools.FastAccessIOSequence[source]¶
Bases:
FastAccessProvides fast access to the values of the
IOSequenceobjects of a specific subgroup and supports handling time series data during simulations.The following details are of relevance for HydPy developers only.
FastAccessIOSequenceis 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,FastAccessIOSequenceobjects 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
IOSequencesandIOSequenceobjects 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 theseriesattribute of the respectiveIOSequenceobject.
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 theseriesattribute of the respectiveIOSequenceobject.
It is possible to write data to a NetCDF file and pass it to
seriessimultaneously.
- class hydpy.core.sequencetools.FastAccessInputSequence[source]¶
Bases:
FastAccessIOSequenceFastAccessIOSequencesubclass specialised for input sequences.- set_pointerinput(name: str, pdouble: PDouble) None[source]¶
Use the given
PDoubleobject as the pointer for the 0-dimensionalInputSequenceobject with the given name.
- class hydpy.core.sequencetools.FastAccessOutputSequence[source]¶
Bases:
FastAccessIOSequenceFastAccessIOSequencesubclass specialised for output sequences.- set_pointeroutput(name: str, pdouble: PDouble) None[source]¶
Use the given
PDoubleobject as the pointer for the 0-dimensionalOutputSequenceobject with the given name.
- class hydpy.core.sequencetools.FastAccessLinkSequence[source]¶
Bases:
FastAccessFastAccessIOSequencesubclass specialised for link sequences.- alloc(name: str, length: int) None[source]¶
Allocate enough memory for the given vector length of the
LinkSequenceobject with the given name.Cython extension classes need to define
alloc()if the model handles at least one 1-dimensionalLinkSequencesubclass.
- dealloc(name: str) None[source]¶
Free the previously allocated memory of the
LinkSequenceobject with the given name.Cython extension classes need to define
dealloc()if the model handles at least one 1-dimensionalLinkSequencesubclass.
- set_pointer0d(name: str, value: Double) None[source]¶
Define a pointer referencing the given
Doubleobject for the 0-dimensionalLinkSequenceobject with the given name.Cython extension classes need to define
set_pointer0d()if the model handles at least one 0-dimensionalLinkSequencesubclasses.
- set_pointer1d(name: str, value: Double, idx: int) None[source]¶
Define a pointer referencing the given
Doubleobject for the 1-dimensionalLinkSequenceobject 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-dimensionalLinkSequencesubclasses.
- class hydpy.core.sequencetools.FastAccessNodeSequence[source]¶
Bases:
FastAccessIOSequenceFastAccessIOSequencesubclass specialised forNodeobjects.In contrast to other
FastAccessIOSequencesubclasses,FastAccessNodeSequenceonly needs to handle a fixed number of sequences,SimandObs. 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
seriesattribute of the currentSimobject.
- save_simdata(idx: int) None[source]¶
Save the next sim sequence value to a NetCDF file and/or to the
seriesattribute of theSimobject.
- load_obsdata(idx: int) None[source]¶
Load the next sim sequence value from a NetCDF file or, with second priority, from the
seriesattribute of theObsobject.
- save_obsdata(idx: int) None[source]¶
Save the next sim sequence value to a NetCDF file and/or to the
seriesattribute of theObsobject.
- 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
nanif modified beforehand by methodfill_obsdata().
- class hydpy.core.sequencetools.InfoArray(array: ndarray[tuple[int, ...], dtype[float64]], aggregation: Literal['unmodified', 'mean'] | None = None)[source]¶
Bases:
ndarray[tuple[int, …],dtype[float64]]numpyndarraysubclass 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(*values)[source]¶
Bases:
StrEnumStandard names for the
InputSequencesubclasses 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:
objectBase class for handling all sequences of a specific model.
Sequencesobjects 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
Sequencesprovides some methods related to reading and writing time series data, which (directly or indirectly) call the corresponding methods of the handledIOSequenceobjects. In most cases, users should prefer to use the related methods of classHydPy, but using the ones of classSequencescan 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, andStateSequenceobject, as the following technical test suggests. The documentation on classIOSequenceexplains 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
IOSequencesobjects handled by the currentSequencesobject.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
iosubsequencesproperty 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 attributeinputswith read_jit=jit and of attributesfactors,fluxes, andstateswith write_jit=jit.
- load_series()[source]¶
Call method
load_series()of all handledIOSequencesobjects.
- save_series()[source]¶
Call method
save_series()of all handledIOSequencesobjects.
- load_data(idx: int) None[source]¶
Call method
load_data()of the handledInputSequencesobject.
- save_data(idx: int) None[source]¶
Call method
save_data()of the handledInputSequences,FactorSequences,FluxSequences, andStateSequencesobjects.
- 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 handledConditionSequenceobjects.
- property conditionsequences: Iterator[ConditionSequence]¶
Generator object yielding all conditions (
StateSequenceandLogSequenceobjects).
- property conditions: dict[str, dict[str, float | ndarray[tuple[int, ...], dtype[float64]]]]¶
A nested dictionary that contains the values of all condition sequences of a single model instance.
See the documentation on property
conditionsfor further information.
- trim_conditions() None[source]¶
Call method
trim()of each handledConditionSequence.trim_conditions()is just a convenience function for calling methodtrim()of allStateSequenceandLogSequenceobjects 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
SubSequencesobject has a fastaccess attribute, which is an instance of (a subclass of) classFastAccesswhen 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
SubParametersfor further information. However, note the difference that model developers should not subclassSubSequencesdirectly but specialised subclasses likeFluxSequencesorStateSequencesinstead.
- 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:
objectThe type of property
seriesmodeof classIOSequence.- ramflag: bool¶
Corresponds to property
ramflagof classIOSequence.
- diskflag_reading: bool¶
Corresponds to property
diskflag_readingof classIOSequence.
- diskflag_writing: bool¶
Corresponds to property
diskflag_writingof 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 handlingIOSequenceobjects.- prepare_series(allocate_ram: bool = True, read_jit: bool = False, write_jit: bool = False) None[source]¶
Call method
prepare_series()of all handledIOSequenceobjects.
- load_series() None[source]¶
Call method
load_series()of all handledIOSequenceobjects with an activatedramflag.
- save_series() None[source]¶
Call method
save_series()of all handledIOSequenceobjects 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
IOSequenceobjects.- load_data(idx: int) None[source]¶
Call method
load_data()of theFastAccessIOSequenceobject handled as attribute fastaccess.
- save_data(idx: int) None[source]¶
Call method
save_data()of theFastAccessIOSequenceobject 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
InputSequenceobjects.
- 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
OutputSequenceobjects.- update_outputs() None[source]¶
Call method
update_outputs()of theFastAccessOutputSequenceobject handled as attribute fastaccess.
- property numericsequences: Iterator[TypeOutputSequence_co]¶
Iterator for “numerical” sequences.
“numerical” means that the
NUMERICclass 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
FactorSequenceobjects.
- 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
FluxSequenceobjects.
- 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
StateSequenceobjects.- new2old() None[source]¶
Call method
new2old()of all handledStateSequenceobjects.
- reset() None[source]¶
Call method
reset()of all handledStateSequenceobjects.
- 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
LogSequenceobjects.- reset() None[source]¶
Call method
reset()of all handledLogSequenceobjects.
- 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
AideSequenceobjects.
- 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
LinkSequenceobjects.
- 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”
LinkSequenceobjects.
- 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”
LinkSequenceobjects.
- 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”
LinkSequenceobjects.
- 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”
LinkSequenceobjects.
- class hydpy.core.sequencetools.Sequence_(subvars: SubVariables)[source]¶
Bases:
VariableBase 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
Parametersubclasses,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 itsFastAccessobject, 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
AideSequenceobjects 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
tuplecontaining the initial value andTrueor a missing value andFalse, depending on the actualSequence_subclass and the actual value of optionusedefaultvalues.In the following, we do not explain property
initinfoitself 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 aModelSequencesobject:>>> 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
usedefaultvaluestoTrue:>>> 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
filetoolsandnetcdftoolsin 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 theseriesattribute of the relevantIOSequenceobjects. Typically, you call methods likeprepare_inputseries()of classHydPy. Here, we instead use the related features of theIOSequenceclass 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
IOSequenceobject 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_readingand/ordiskflag_writingactivated?
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 theramflagof 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 sequencesContriAreaandTC(without handling their data in RAM) and the writing feature of the state sequencesSMandSP(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, anddiskflagfor querying the current configuration of individualIOSequenceobjects:>>> 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 (SMandSP) time series of the sequences with an activatedramflagare 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
ContriAreaandTC, you must first activate theirramflagand then load their data manually with methodload_series(). The latter requires some additional configuration effort (see the documentation on modulenetcdftoolsfor 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
SMandSPto 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
IOSequenceobjects, 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
seriesof sequenceP, perform a new simulation run, and see that the newly calculated time series of sequencePCreflects 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 individualIOSequenceobject:>>> inputs.p.seriesshape (4,) >>> fluxes.pc.seriesshape (4, 13)
Note that resetting the
shapeof anIOSequenceobject 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
shapeofIOSequenceobjects with a deactivatedramflagdata 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,
IOSequenceobjects query the current file type from theSequenceManagerobject available in the globalpubmodule:>>> 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
IOSequenceobject 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
SequenceManagerobject is available, propertyfiletyperaises 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,
IOSequenceobjects query the current aggregation mode from theSequenceManagerobject available in the globalpubmodule:>>> 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
IOSequenceobject 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
SequenceManagerobject is available, propertyaggregationraises 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,
IOSequenceobjects query the current overwrite flag from theSequenceManagerobject available in the globalpubmodule:>>> 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
IOSequenceobject 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
SequenceManagerobject is available, propertyoverwriteraises 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_deviceis 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,
dirpathis identical to the attributecurrentpathof theSequenceManagerobject 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
dirpathandfilename:>>> 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
FastAccessIOSequenceobject handled by the actualIOSequenceobject.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 theFastAccessIOSequenceattribute 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 classIOSequencecall. We show this via the hidden attribute length, which is 0 after initialisation, and automatically set to another value when assigning it to propertyshapeofIOSequencesubclasses 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[tuple[int, ...], dtype[float64]]) None[source]¶
Connect the current
IOSequenceobject 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
IOSequenceobject.See the main documentation on class
IOSequencefor general information on methodprepare_series(). Here, we only discuss the special case of passingNoneto 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
Noneto 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
IOSequenceobject makes its time series data directly available in RAM.See the main documentation on class
IOSequencefor further information.
- property diskflag_reading: bool¶
A flag telling if the actual
IOSequencereads its time series data on the fly from a NetCDF file during a simulation run.See the main documentation on class
IOSequencefor further information.
- property diskflag_writing: bool¶
A flag telling if the actual
IOSequencewrites its time series data on the fly to a NetCDF file during a simulation run.See the main documentation on class
IOSequencefor further information.
- property diskflag: bool¶
A flag telling if
diskflag_readingand/ordiskflag_writingof the currentIOSequenceobject 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
ramflagand/ordiskflagof the currentIOSequenceobject 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.seriesmodeallows 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
shapeof anIOSequenceobject, one automatically calls methodupdate_fastaccess()and, if necessary, prepares the new internalseriesarray.See the main documentation on class
IOSequencefor 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
IOSequenceobject within anInfoArraycovering the whole initialisation period (defined by theinitTimegridof the globalTimegridsobject available in modulepub).
- property simseries: InfoArray¶
Read and write access to the subset of the data of property
seriescovering the actual simulation period (defined by thesimTimegridof the globalTimegridsobject 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_Timegridof the globalTimegridsobject 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 classSequenceManagerpassing itself as the only argument. Hence, see the documentation on the classSequenceManagerfor 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 givennumpyndarrayfits the givenTimegridobject.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 initialisationTimegridavailable in modulepuband the given “data”Timegridobject. We explain this behaviour by using the HydPy-H-Lahn example project and focussing on theObssequence ofNodedill_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. Withcheckseriesbeing enabled, methodadjust_series()raises aRuntimeError. Withcheckseriesbeing disabled, it extends the given array withnanvalues (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 optioncheckseriesis 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 thatnanvalues 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
resetdisabled, 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
RuntimeErrorif theseriescontains at least onenanvalue and if the optioncheckseriesis 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
IOSequenceobject to a file.Method
save_series()only calls methodsave_file()of classSequenceManager, passing itself as the only argument. Hence, see the documentation on class theSequenceManagerfor 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 classIOSequenceand write the result to file using methodsave_file()of classSequenceManager.The main documentation on class
SequenceManagerprovides some examples.
- property seriesmatrix: ndarray[tuple[int, ...], dtype[float64]]¶
The actual
IOSequenceobject’s time series, arranged in a 2-dimensional matrix.For a 1-dimensional sequence object, property
seriesmatrixreturns 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,
seriesmatrixraises 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
IOSequenceobject 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 aTimegridsobject to define theserieslength:>>> from hydpy import pub >>> pub.timegrids = "2000-01-01", "2000-01-04", "1d"
As shown for method
average_values(), for 0-dimensionalIOSequenceobjects, the result of methodaverage_series()equalsseriesitself:>>> 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
IOSequenceobjects 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
aggregationattribute of the currentIOSequenceobject.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
aggregationis 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
aggregationis 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
IOSequenceobject and its context.
- abstract property descr_device: str¶
Description of the
Deviceobject theIOSequenceobject belongs to.
- class hydpy.core.sequencetools.ModelSequence(subvars: ModelSequences[ModelSequence, FastAccess])[source]¶
Bases:
Sequence_Base class for sequences to be handled by
Modelobjects.- property descr_sequence: str¶
Description of the
ModelSequenceobject itself and theModeltype andSubSequencesgroup 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
ModeltheModelSequenceobject 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
Elementobject theModelSequenceobject 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, thenumericshapeof the 0-dimensional sequenceInflowis eleven:>>> from hydpy import prepare_model >>> model = prepare_model("dam") >>> model.sequences.fluxes.inflow.numericshape (11,)
Changing the
shapethrough a little trick (just for demonstration purposes) shows that there are eleven entries for each “normal”Inflowvalue:>>> 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,IOSequenceBase class for sequences with time series functionalities to be handled by
Modelobjects.
- class hydpy.core.sequencetools.InputSequence(subvars: ModelSequences[ModelSequence, FastAccess])[source]¶
Bases:
ModelIOSequenceBase class for input sequences of
Modelobjects.InputSequenceobjects 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_96read 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
InputSequenceobjects 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 differentdeploymodeoptions 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
ModelSequencesubclasses:>>> 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_sequencereturns the standard name selected by the respectiveInputSequencesubclass:>>> 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
Doubleobject.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
InputSequenceobject 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
InputSequencefor further information.
- class hydpy.core.sequencetools.OutputSequence(subvars: ModelSequences[ModelSequence, FastAccess])[source]¶
Bases:
ModelIOSequenceBase class for
FactorSequence,FluxSequenceandStateSequence.OutputSequencesubclasses implement an optional output mechanism. Generally, as all instances ofModelSequencesubclasses, 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
OutputSequenceobjects 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 differentdeploymodeoptions:>>> 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
Doubleobject.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
OutputSequenceobject passes its data to an output node (True) or not (False).See the main documentation on class
OutputSequencefor further information.
- class hydpy.core.sequencetools.DependentSequence(subvars: ModelSequences[ModelSequence, FastAccess])[source]¶
Bases:
OutputSequenceBase class for
FactorSequenceandFluxSequence.- shape¶
A tuple containing the actual lengths of all dimensions.
FactorSequenceandFluxSequenceobjects 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 sequenceRHof thewland_wagmodel:>>> 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
Noneinitially, as propertynumericshapeis unknown. Setting theshapeattribute of the respectiveFactorSequenceorFluxSequenceobject (we selectEIas 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:
DependentSequenceBase class for factor sequences of
Modelobjects.
- class hydpy.core.sequencetools.FluxSequence(subvars: ModelSequences[ModelSequence, FastAccess])[source]¶
Bases:
DependentSequenceBase class for flux sequences of
Modelobjects.
- class hydpy.core.sequencetools.ConditionSequence(subvars: ModelSequences[ModelSequence, FastAccess])[source]¶
Bases:
ModelSequenceBase class for
StateSequenceandLogSequence.Class
ConditionSequenceshould not be subclassed by model developers directly. Inherit fromStateSequenceorLogSequenceinstead.- trim(lower=None, upper=None) bool[source]¶
Apply
trim()of modulevariabletools.
- reset()[source]¶
Reset the value of the actual
StateSequenceorLogSequenceobject to the last value defined by “calling” the object.We use the
lland_knaufapplication model, which handles sequences derived fromStateSequence(takingInzpas an example) and fromLogSequence(takingLoggedSunshineDurationas an example):>>> from hydpy import prepare_model, pub >>> model = prepare_model("lland_knauf")
After defining their shapes, both sequences contain
nanvalues:>>> 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,ConditionSequenceBase class for state sequences of
Modelobjects.Each
StateSequenceobject can handle states at two different “time points”: at the beginning of a simulation step via propertyoldand 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
SMof the base modelhland_96with 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
newor propertyold(note that usingnewis identical with using thevalueproperty):>>> 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 propertiesnewandold(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.
StateSequenceobjects 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 sequenceHSof thewland_wagmodel:>>> 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
Noneinitially, as propertynumericshapeis unknown. Setting theshapeattribute of the respectiveStateSequenceobject (we selectICas 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
Modelcalculation method. (Alias for propertyvalue).Property
newhandles, in contrast to propertyold, the newly calculated state values during each simulation step. It supports testing and debugging of individualModelmethods but is typically irrelevant when scripting HydPy workflows.
- property old¶
State(s) before calling a
Modelcalculation method.Note the similarity to property
new. However, propertyoldreferences the initial states of the respective simulation step, which should not be changed byModelcalculation methods.
- class hydpy.core.sequencetools.LogSequence(subvars: ModelSequences[ModelSequence, FastAccess])[source]¶
Bases:
ConditionSequenceBase class for logging values required for later calculations.
Class
LogSequenceserves similar purposes asStateSequencebut is less strict in its assumptions. WhileStateSequenceobjects always handle two states (theoldand thenewone),LogSequenceobjects 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
LogSequencesubclass has the correct dimensionality and shape to store the required information. By convention, the “memory” of eachLogSequenceshould be placed on the first axis for non-scalar properties.As
StateSequenceobjects,LogSequenceobjects 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:
LogSequenceBase class for log sequences with a fixed shape.
- shape¶
Sequences derived from
LogSequenceFixedinitialise themselves with a predefined shape.We take parameter
LoggedRequiredRemoteReleaseof base modeldamas an example:>>> from hydpy.models.dam import * >>> parameterstep() >>> logs.loggedrequiredremoterelease.shape (1,)
Property
shaperesults 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
shapeof classVariablefor further information.
- class hydpy.core.sequencetools.AideSequence(subvars: ModelSequences[ModelSequence, FastAccess])[source]¶
Bases:
ModelSequenceBase class for aide sequences of
Modelobjects.Aide sequences store data only relevant for calculating an individual simulation time step but must be shared between different calculation methods of a
Modelobject.
- class hydpy.core.sequencetools.LinkSequence(subvars: ModelSequences[ModelSequence, FastAccess])[source]¶
Bases:
ModelSequenceBase class for link sequences of
Modelobjects.LinkSequenceobjects do not handle values themselves. Instead, they point to the values handled byNodeSequenceobjects, using the functionalities provided by the Cython modulepointerutils. MultipleLinkSequenceobjects of different application models can query and modify the sameNodeSequencevalues, allowing differentModelobjects to share information and interact with each other.A note for developers:
LinkSequencesubclasses 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
Doubleobject.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
LinkSequenceobject is pointing at.Changing a
valueof aLinkSequenceobject seems very much like changing avalueof any otherVariableobject. However, be aware that you are changing a value handled by aNodeSequenceobject. 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_classicapplication 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
Qpoints to theSimsequence 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
Qpoints to theSimsequence 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
Qonly points a singleNodeSequencevalue. We now prepare aexch_branch_hbv96application model instance to show what happens when connecting a 1-dimensionalLinkSequenceobject (Branched) with threeNodeSequenceobjects (see the documentation of application modelexch_branch_hbv96for 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
LinkSequenceobjects points to anotherNodeSequenceobject:>>> 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
shapeof classLinkSequenceworks similarly as the generalshapeproperty 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 propertyvaluefirst 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
Nodeobjects):>>> 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
NodeSequencevalues 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:
LinkSequenceBase class for inlet link sequences of
Modelobjects.
- class hydpy.core.sequencetools.OutletSequence(subvars: ModelSequences[ModelSequence, FastAccess])[source]¶
Bases:
LinkSequenceBase class for outlet link sequences of
Modelobjects.
- class hydpy.core.sequencetools.ReceiverSequence(subvars: ModelSequences[ModelSequence, FastAccess])[source]¶
Bases:
LinkSequenceBase class for receiver link sequences of
Modelobjects.
- class hydpy.core.sequencetools.SenderSequence(subvars: ModelSequences[ModelSequence, FastAccess])[source]¶
Bases:
LinkSequenceBase class for sender link sequences of
Modelobjects.
- class hydpy.core.sequencetools.NodeSequence(subvars: NodeSequences)[source]¶
Bases:
IOSequenceBase class for all sequences to be handled by
Nodeobjects.- property initinfo: tuple[Double, bool]¶
Return a
Doubleinstead of afloatobject as the first tuple entry.
- property descr_sequence: str¶
Description of the
NodeSequenceobject, including thevariableto 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
Nodeobject theNodeSequenceobject 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
valueof classNodeSequenceworks as usual (explained in the documentation on propertyshapeof classVariable). However, framework developers should note thatNodeSequenceobjects useDoubleobjects for storing their values and making them accessible toPDoubleandPPDoubleobjects as explained in detail in the documentation on classLinkSequence. This mechanism is hidden for framework users via conversions to typefloatfor 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,
seriescompleteisFalse:>>> 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,
seriescompleteis 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,seriescompleteisTrue:>>> obs.series[-1] = 1.0 >>> obs.seriescomplete True
- class hydpy.core.sequencetools.Sim(subvars: NodeSequences)[source]¶
Bases:
NodeSequenceClass for handling those values of
Nodeobjects that are “simulated”, meaning calculated by hydrological models.- load_series() None[source]¶
Read time series data like method
load_series()of classIOSequencebut 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 classSimdoes not disable propertymemoryflagand uses the optionwarnmissingsimfileinstead 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:
NodeSequenceClass for handling those values of
Nodeobjects that are observed, meaning read from data files.- load_series() None[source]¶
Read time series data like method
load_series()of classIOSequencebut with special handling of missing data.When reading incomplete time series data, HydPy usually raises a
RuntimeErrorto 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 ofObssequences, 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
UserWarningin case of missing or incomplete external time series data ofObssequences. The following examples show this based on the HydPy-H-Lahn project, mainly focussing on theObssequence 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
warnmissingobsfileallows 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
SimandObssequence objects.Basically,
NodeSequencesworks like the differentModelSequencessubclasses used for handlingModelSequenceobjects. The main difference is that they do not reference aSequencesobject (which is only handled byElementobjects but not byNodeobjects). Instead, they directly reference their masterNodeobject 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)]