sequencetools¶
This module implements tools for defining and handling different kinds of the sequences (time-series) of hydrological models.
Module sequencetools
implements the following members:
FastAccessIOSequenceType
Type variable.
IOSequenceType
Type variable.
IOSequencesType
Type variable.
LinkSequenceType
Type variable.
LinkSequencesType
Type variable.
ModelIOSequenceType
Type variable.
ModelIOSequencesType
Type variable.
ModelSequenceType
Type variable.
ModelSequencesType
Type variable.
OutputSequenceType
Type variable.
OutputSequencesType
Type variable.
SequenceType
Type variable.
SequencesType
Type variable.
SubSequencesType
Type variable.
FastAccessIOSequence
Provides fast access to the values of the sequences of a sequence subgroup and supports the handling of internal data series during simulations.
FastAccessInputSequence
FastAccessIOSequence
subclass specialised for input sequences.
FastAccessOutputSequence
FastAccessIOSequence
subclass specialised for output sequences.
FastAccessLinkSequence
FastAccessIOSequence
subclass specialised for link sequences.
FastAccessNodeSequence
FastAccessIOSequence
subclass specialised forNode
objects.
InfoArray
numpy
ndarray
subclass that stores and tries to keep an additional info attribute.
Sequences
Base class for handling all sequences of a specific model.
SubSequences
Base class for handling subgroups of sequences.
ModelSequences
Base class for handling model-related subgroups of sequences.
IOSequences
Subclass ofSubSequences
, specialised for handlingIOSequence
objects.
ModelIOSequences
Base class for handling model-related subgroups ofIOSequence
objects.
InputSequences
Base class for handlingInputSequence
objects.
OutputSequences
Base class for handlingOutputSequence
objects.
FluxSequences
Base class for handlingFluxSequence
objects.
StateSequences
Base class for handlingStateSequence
objects.
LogSequences
Base class for handlingLogSequence
objects.
AideSequences
Base class for handlingAideSequence
objects.
LinkSequences
Base class for handlingLinkSequence
objects.
InletSequences
Base class for handling “inlet”LinkSequence
objects.
OutletSequences
Base class for handling “outlet”LinkSequence
objects.
ReceiverSequences
Base class for handling “receiver”LinkSequence
objects.
SenderSequences
Base class for handling “sender”LinkSequence
objects.
Sequence_
Base class for defining different kinds of sequences.
IOSequence
Base class for sequences with input/output functionalities.
ModelSequence
Base class for sequences to be handled byModel
objects.
ModelIOSequence
Base class for sequences with input/output functionalities to be handled byModel
objects.
InputSequence
Base class for input sequences ofModel
objects.
OutputSequence
Base class forFluxSequence
andStateSequence
.
FluxSequence
Base class for flux sequences ofModel
objects.
ConditionSequence
Base class forStateSequence
andLogSequence
.
StateSequence
Base class for state sequences ofModel
objects.
LogSequence
Base class for logging sequences ofModel
objects.
AideSequence
Base class for aide sequences ofModel
objects.
LinkSequence
Base class for link sequences ofModel
objects.
InletSequence
Base class for inlet link sequences ofModel
objects.
OutletSequence
Base class for outlet link sequences ofModel
objects.
ReceiverSequence
Base class for receiver link sequences ofModel
objects.
SenderSequence
Base class for sender link sequences ofModel
objects.
NodeSequence
Base class for all sequences to be handled byNode
objects.
Sim
Class for handling those values ofNode
objects that are “simulated”, meaning calculated by hydrological models.
Obs
Class for handling those values ofNode
objects that are observed, meaning read from data files.
NodeSequences
Base class for handlingSim
andObs
sequence objects.
-
class
hydpy.core.sequencetools.
FastAccessIOSequence
[source]¶ Bases:
hydpy.core.variabletools.FastAccess
Provides fast access to the values of the sequences of a sequence subgroup and supports the handling of internal data series during simulations.
The following details are of relevance for HydPy developers only.
FastAccessIOSequence
is applied in Python mode only. In Cython mode it is replaced by model-specific Cython extension classes, which are computationally more efficient. For compatibility with these extension classes,FastAccessIOSequence
objects work with dynamically set instance members. Suppose there is a sequence named seq1 which is 2-dimensional, then its associated attributes are:seq1 (
ndarray
): The actual sequence values._seq1_ndim (
int
): 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 internal data in RAM?_seq1_diskflag (
bool
): Handle internal data on disk?_seq1_path (
str
): Path of the internal data file._seq1_file (
open()
): Object handling the internal data file.
Note that the respective
SubSequences
andSequence_
objects initialise, change, and apply these dynamical attributes. To handle them directly is error-prone and thus not recommended.-
open_files
(idx: int) → None[source]¶ Open all files with an activated disk flag and seek the position indicated by the given index.
-
close_files
() → None[source]¶ Close the internal data files of all handled sequences with an activated
diskflag
.
-
load_data
(idx: int) → None[source]¶ Load the internal data of all sequences with an activated
memoryflag
.Read from a file if the corresponding disk flag is activated; read from working memory if the corresponding ram flag is activated.
-
class
hydpy.core.sequencetools.
FastAccessInputSequence
[source]¶ Bases:
hydpy.core.sequencetools.FastAccessIOSequence
FastAccessIOSequence
subclass specialised for input sequences.-
set_pointerinput
(name: str, pdouble: hydpy.cythons.autogen.pointerutils.PDouble) → None[source]¶ Use the given
PDouble
object as the pointer for the 0-dimensionalInputSequence
object with the given name.
-
-
class
hydpy.core.sequencetools.
FastAccessOutputSequence
[source]¶ Bases:
hydpy.core.sequencetools.FastAccessIOSequence
FastAccessIOSequence
subclass specialised for output sequences.-
set_pointeroutput
(name: str, pdouble: hydpy.cythons.autogen.pointerutils.PDouble) → None[source]¶ Use the given
PDouble
object as the pointer for the 0-dimensionalOutputSequence
object with the given name.
-
-
class
hydpy.core.sequencetools.
FastAccessLinkSequence
[source]¶ Bases:
hydpy.core.variabletools.FastAccess
FastAccessIOSequence
subclass specialised for link sequences.-
alloc
(name: str, length: int) → None[source]¶ Allocate enough memory for the given vector length for the
LinkSequence
with the given name.Cython extension classes need to define
alloc()
if there is at least one 1-dimensionalLinkSequence
subclasses.
-
dealloc
(name: str) → None[source]¶ Free the previously allocated memory of the
LinkSequence
with the given name.Cython extension classes need to define
alloc()
if there is at least one 1-dimensionalLinkSequence
subclasses.
-
set_pointer0d
(name: str, value: hydpy.cythons.autogen.pointerutils.Double)[source]¶ Use the given
PDouble
object as the pointer of the 0-dimensionalLinkSequence
object with the given name.Cython extension classes need to define
set_pointer0d()
if there is at least one 0-dimensionalLinkSequence
subclasses.
-
set_pointer1d
(name: str, value: hydpy.cythons.autogen.pointerutils.Double, idx: int)[source]¶ Use the given
PDouble
object as one of the pointers of the 1-dimensionalLinkSequence
object with the given name.The given index defines the vector position of the pointer.
Cython extension classes need to define
set_pointer0d()
if there is at least one 1-dimensionalLinkSequence
subclasses.
-
get_value
(name: str) → Union[float, numpy.ndarray][source]¶ Return the actual value(s) the
LinkSequence
object with the given name is pointing to.
-
-
class
hydpy.core.sequencetools.
FastAccessNodeSequence
[source]¶ Bases:
hydpy.core.sequencetools.FastAccessIOSequence
FastAccessIOSequence
subclass specialised forNode
objects.In contrast to other
FastAccessIOSequence
subclasses,FastAccessNodeSequence
only needs to handle a fixed number of sequences,Sim
andObs
. It thus can define the related attributes explicitly.-
sim
: hydpy.cythons.autogen.pointerutils.Double¶
-
obs
: hydpy.cythons.autogen.pointerutils.Double¶
-
load_data
(idx: int) → None[source]¶ Call both method
load_simdata()
and methodload_obsdata()
.
-
save_data
(idx: int) → None[source]¶ Alias for method
save_simdata()
.
-
-
class
hydpy.core.sequencetools.
InfoArray
(array, info=None)[source]¶ Bases:
numpy.ndarray
numpy
ndarray
subclass that stores and tries to keep an additional info attribute.>>> from hydpy.core.sequencetools import InfoArray >>> array = InfoArray([1.0, 2.0], info="this array is short") >>> array InfoArray([ 1., 2.]) >>> array.info 'this array is short' >>> subarray = array[:1] >>> subarray InfoArray([ 1.]) >>> subarray.info 'this array is short'
-
class
hydpy.core.sequencetools.
Sequences
(model: modeltools.Model, cls_inlets: Optional[Type[InletSequences]] = None, cls_receivers: Optional[Type[ReceiverSequences]] = None, cls_inputs: Optional[Type[InputSequences]] = None, cls_fluxes: Optional[Type[FluxSequences]] = None, cls_states: Optional[Type[StateSequences]] = None, cls_logs: Optional[Type[LogSequences]] = None, cls_aides: Optional[Type[AideSequences]] = None, cls_outlets: Optional[Type[OutletSequences]] = None, cls_senders: Optional[Type[SenderSequences]] = None, cymodel: Optional[hydpy.core.typingtools.CyModelProtocol] = None, cythonmodule: Optional[module] = None)[source]¶ Bases:
object
Base class for handling all sequences of a specific model.
Sequences
objects handle nine sequence subgroups as attributes such as the inlets and the receivers subsequences:>>> from hydpy.examples import prepare_full_example_2 >>> hp, pub, TestIO = prepare_full_example_2() >>> sequences = hp.elements.land_dill.model.sequences >>> bool(sequences.inlets) False >>> bool(sequences.fluxes) True
Iteration makes only the non-empty subgroups available which are handling
Sequence_
objects:>>> for subseqs in sequences: ... print(subseqs.name) inputs fluxes states logs outlets >>> len(sequences) 5
Class
Sequences
provides some methods related to reading and writing time-series data, which (directly or indirectly) call the corresponding methods of the handledIOSequence
objects. In most cases, users should prefer to use the related methods of classHydPy
but using the ones of classSequences
can be more convenient when analysing a specific model in-depth.To introduce these methods, we first change two IO-related settings:
>>> from hydpy import round_ >>> pub.options.checkseries = False >>> pub.sequencemanager.generaloverwrite = True
Method
activate_ram()
and methoddeactivate_ram()
enables/disables handling time-series in rapid access memory and methodsave_series()
writes time-series to files:>>> sequences.activate_ram() >>> sequences.inputs.t.ramflag True >>> sequences.inputs.t.series = 1.0, 2.0, 3.0, 4.0 >>> with TestIO(): ... sequences.save_series() >>> sequences.deactivate_ram() >>> sequences.inputs.t.ramflag False >>> sequences.inputs.t.series Traceback (most recent call last): ... AttributeError: Sequence `t` of element `land_dill` is not requested to make any internal data available.
Method
activate_disk()
anddeactivate_disk()
enables/disables handling time-series on disk and methodload_series()
reads time-series from files:>>> with TestIO(): ... sequences.activate_disk() >>> sequences.inputs.t.diskflag True >>> with TestIO(): ... sequences.load_series() ... round_(sequences.inputs.t.series) 1.0, 2.0, 3.0, 4.0 >>> with TestIO(): ... sequences.deactivate_disk() >>> sequences.inputs.t.diskflag False >>> hasattr(sequences.inputs.t, "series") False
Methods
ram2disk()
anddisk2ram()
allow moving data from RAM to disk and from disk to RAM, respectively:>>> sequences.activate_ram() >>> sequences.inputs.t.ramflag True >>> sequences.inputs.t.series = 1.0, 2.0, 3.0, 4.0 >>> with TestIO(): ... sequences.ram2disk() >>> sequences.inputs.t.diskflag True >>> with TestIO(): ... round_(sequences.inputs.t.series) 1.0, 2.0, 3.0, 4.0 >>> with TestIO(): ... sequences.disk2ram() >>> round_(sequences.inputs.t.series) 1.0, 2.0, 3.0, 4.0
The documentation on class
IOSequence
explains the underlying functionalities of classIOSequence
in more detail.>>> pub.options.checkseries = True >>> pub.sequencemanager.generaloverwrite = False
-
model
: modeltools.Model¶
-
inlets
: InletSequences¶
-
receivers
: ReceiverSequences¶
-
inputs
: InputSequences¶
-
fluxes
: FluxSequences¶
-
states
: StateSequences¶
-
logs
: LogSequences¶
-
aides
: AideSequences¶
-
outlets
: OutletSequences¶
-
senders
: SenderSequences¶
-
property
iosubsequences
¶ Yield all relevant
IOSequences
objects handled by the currentSequences
object.The currently available IO-subgroups are inputs, fluxes, and states.
>>> from hydpy import prepare_model >>> model = prepare_model("hland_v1", "1d") >>> for subseqs in model.sequences.iosubsequences: ... print(subseqs.name) inputs fluxes states
However, not all models implement sequences for all these subgroups. Property
iosubsequences
only yields those subgroups which are non-empty:>>> model = prepare_model("hstream_v1", "1d") >>> for subseqs in model.sequences.iosubsequences: ... print(subseqs.name) states
-
activate_disk
() → None[source]¶ Call method
activate_disk()
of all handledIOSequences
objects.
-
deactivate_disk
() → None[source]¶ Call method
deactivate_disk()
of all handledIOSequences
objects.
-
activate_ram
() → None[source]¶ Call method
activate_ram()
of all handledIOSequences
objects.
-
deactivate_ram
() → None[source]¶ Call method
deactivate_ram()
of all handledIOSequences
objects.
-
ram2disk
()[source]¶ Call method
ram2disk()
of all handledIOSequences
objects.
-
disk2ram
()[source]¶ Call method
disk2ram()
of all handledIOSequences
objects.
-
load_series
()[source]¶ Call method
load_series()
of all handledIOSequences
objects.
-
save_series
()[source]¶ Call method
save_ext()
of all handledIOSequences
objects.
-
open_files
(idx: int = 0) → None[source]¶ Call method
open_files()
of all handledIOSequences
objects.
-
close_files
() → None[source]¶ Call method
close_files()
of all handledIOSequences
objects.
-
load_data
(idx: int) → None[source]¶ Call method
load_data()
of the handledInputSequences
object.
-
save_data
(idx: int) → None[source]¶ Call method
save_data()
of the handledFluxSequences
andStateSequences
objects.
-
reset
() → None[source]¶ Call method
reset()
of all handledConditionSequence
objects.
-
property
conditionsequences
¶ Generator object yielding all conditions (
StateSequence
andLogSequence
objects).
-
property
conditions
¶ A nested dictionary which contains the values of all condition sequences.
See the documentation on property
conditions
for further information.
-
load_conditions
(filename: Optional[str] = None) → None[source]¶ Read the initial conditions from a file and assign them to the respective
StateSequence
andLogSequence
objects handled by the actualSequences
object.The documentation on method
load_conditions()
of classHydPy
explains how to read and write condition values for complete HydPy projects in the most convenient manner. However, using the underlying methodsload_conditions()
andsave_conditions()
directly offers the advantage to specify alternative filenames. We demonstrate this through using the land_dillElement
object of the LahnH example project and focussing on the values of state sequenceSM
:>>> from hydpy.examples import prepare_full_example_2 >>> hp, pub, TestIO = prepare_full_example_2() >>> sequences = hp.elements.land_dill.model.sequences >>> sequences.states.sm sm(185.13164, 181.18755, 199.80432, 196.55888, 212.04018, 209.48859, 222.12115, 220.12671, 230.30756, 228.70779, 236.91943, 235.64427)
From now on, we work in the freshly created condition directory test:
>>> with TestIO(): ... pub.conditionmanager.currentdir = "test"
We set all soil moisture values to zero and write the updated values to the file cold_start.py:
>>> sequences.states.sm(0.0)
>>> with TestIO(): ... sequences.save_conditions("cold_start.py")
Trying to reload from the written file (after changing the soil moisture values again) without passing the file name fails due to assuming the elements name as file name base:
>>> sequences.states.sm(100.0) >>> with TestIO(): ... sequences.load_conditions() Traceback (most recent call last): ... FileNotFoundError: While trying to load the initial conditions of element `land_dill`, the following error occurred: [Errno 2] No such file or directory: '...land_dill.py'
One does not need to state the file extensions (.py) explicitly:
>>> with TestIO(): ... sequences.load_conditions("cold_start") >>> sequences.states.sm sm(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
Note that determining the file name automatically requires a proper reference to the related
Element
object:>>> del sequences.model.element >>> with TestIO(): ... sequences.save_conditions() Traceback (most recent call last): ... RuntimeError: While trying to save the actual conditions of element `?`, the following error occurred: To load or save the conditions of a model from or to a file, its filename must be known. This can be done, by passing filename to method `load_conditions` or `save_conditions` directly. But in complete HydPy applications, it is usally assumed to be consistent with the name of the element handling the model. Actually, neither a filename is given nor does the model know its master element.
-
save_conditions
(filename: Optional[str] = None) → None[source]¶ Query the actual conditions of the
StateSequence
andLogSequence
objects handled by the actualSequences
object and write them into an initial condition file.See the documentation on method
load_conditions()
for further information.
-
trim_conditions
() → None[source]¶ Call method
trim()
of each handledConditionSequence
.trim_conditions()
is just a convenience function for calling methodtrim()
of allStateSequence
andLogSequence
objects returned by propertyconditionsequences
. We demonstrate its functionality by preparing an instance of application modellland_v1
, 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_v1", "1d") ... 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: GroupType, cls_fastaccess: Optional[Type[FastAccessType]] = None)[source]¶ Bases:
hydpy.core.variabletools.SubVariables
[hydpy.core.sequencetools.SequencesType
,hydpy.core.sequencetools.SequenceType
,hydpy.core.variabletools.FastAccessType
]Base class for handling subgroups of sequences.
Each
SubSequences
object has a fastaccess attribute. When working in pure Python mode, this is an instance either of (a subclass of) classFastAccess
:>>> from hydpy import classname, Node, prepare_model, pub >>> with pub.options.usecython(False): ... model = prepare_model("lland_v1") >>> 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 (which is the default mode and much faster), fastaccess is an object of Cython extension class FastAccessNodeSequence of module sequenceutils or of a Cython extension class specialised for the respective model and sequence group:
>>> with pub.options.usecython(True): ... model = prepare_model("lland_v1") >>> classname(model.sequences.inputs.fastaccess) 'InputSequences' >>> from hydpy.cythons.sequenceutils import FastAccessNodeSequence >>> with pub.options.usecython(True): ... node = Node("test2") >>> isinstance(Node("test2").sequences.fastaccess, FastAccessNodeSequence) True
See the documentation of similar class
SubParameters
for further information. However, note the difference that model developers should not subclassSubSequences
directly but specialised subclasses likeFluxSequences
orStateSequences
instead.-
property
name
¶ The class name in lower case letters omitting the last eight characters (“equences”).
>>> from hydpy.core.sequencetools import StateSequences >>> class StateSequences(StateSequences): ... CLASSES = () >>> StateSequences(None).name 'states'
-
vars
: GroupType¶
-
property
-
class
hydpy.core.sequencetools.
ModelSequences
(master: hydpy.core.sequencetools.Sequences, cls_fastaccess: Optional[Type[FastAccessType]] = None, cymodel: Optional[hydpy.core.typingtools.CyModelProtocol] = None)[source]¶ Bases:
hydpy.core.sequencetools.SubSequences
[hydpy.core.sequencetools.Sequences
,hydpy.core.sequencetools.ModelSequenceType
,hydpy.core.variabletools.FastAccessType
]Base class for handling model-related subgroups of sequences.
-
class
hydpy.core.sequencetools.
IOSequences
(master: GroupType, cls_fastaccess: Optional[Type[FastAccessType]] = None)[source]¶ Bases:
hydpy.core.sequencetools.SubSequences
[hydpy.core.sequencetools.SequencesType
,hydpy.core.sequencetools.IOSequenceType
,hydpy.core.sequencetools.FastAccessIOSequenceType
]Subclass of
SubSequences
, specialised for handlingIOSequence
objects.-
activate_ram
()[source]¶ Call method
activate_ram()
of all handledIOSequence
objects.
-
deactivate_ram
()[source]¶ Call method
deactivate_ram()
of all handledIOSequence
objects.
-
activate_disk
()[source]¶ Call method
activate_disk()
of all handledIOSequence
objects.
-
deactivate_disk
()[source]¶ Call method
deactivate_disk()
of all handledIOSequence
objects.
-
ram2disk
()[source]¶ Call method
ram2disk()
of all handledIOSequence
objects.
-
disk2ram
()[source]¶ Call method
disk2ram()
of all handledIOSequence
objects.
-
load_series
()[source]¶ Call method
load_ext()
of all handledIOSequence
objects.
-
save_series
()[source]¶ Call method
save_ext()
of all handledIOSequence
objects.
-
open_files
(idx: int = 0) → None[source]¶ Call method
open_files()
of theFastAccessIOSequence
object handled as attribute fastaccess.
-
close_files
()[source]¶ Call method
close_files()
of theFastAccessIOSequence
object handled as attribute fastaccess.
-
vars
: GroupType¶
-
-
class
hydpy.core.sequencetools.
ModelIOSequences
(master: hydpy.core.sequencetools.Sequences, cls_fastaccess: Optional[Type[FastAccessType]] = None, cymodel: Optional[hydpy.core.typingtools.CyModelProtocol] = None)[source]¶ Bases:
hydpy.core.sequencetools.IOSequences
[hydpy.core.sequencetools.Sequences
,hydpy.core.sequencetools.ModelIOSequenceType
,hydpy.core.sequencetools.FastAccessIOSequenceType
],hydpy.core.sequencetools.ModelSequences
[hydpy.core.sequencetools.ModelIOSequenceType
,hydpy.core.sequencetools.FastAccessIOSequenceType
]Base class for handling model-related subgroups of
IOSequence
objects.-
load_data
(idx: int) → None[source]¶ Call method
load_data()
of theFastAccessIOSequence
object handled as attribute fastaccess.
-
save_data
(idx: int) → None[source]¶ Call method
save_data()
of theFastAccessIOSequence
object handled as attribute fastaccess.
-
vars
: GroupType¶
-
-
class
hydpy.core.sequencetools.
InputSequences
(master: hydpy.core.sequencetools.Sequences, cls_fastaccess: Optional[Type[FastAccessType]] = None, cymodel: Optional[hydpy.core.typingtools.CyModelProtocol] = None)[source]¶ Bases:
hydpy.core.sequencetools.ModelIOSequences
[InputSequence
,hydpy.core.sequencetools.FastAccessInputSequence
]Base class for handling
InputSequence
objects.-
vars
: GroupType¶
-
-
class
hydpy.core.sequencetools.
OutputSequences
(master: hydpy.core.sequencetools.Sequences, cls_fastaccess: Optional[Type[FastAccessType]] = None, cymodel: Optional[hydpy.core.typingtools.CyModelProtocol] = None)[source]¶ Bases:
hydpy.core.sequencetools.ModelIOSequences
[hydpy.core.sequencetools.OutputSequenceType
,hydpy.core.sequencetools.FastAccessOutputSequence
]Base class for handling
OutputSequence
objects.-
update_outputs
() → None[source]¶ Call method
update_outputs()
of theFastAccessOutputSequence
object handled as attribute fastaccess.
-
vars
: GroupType¶
-
-
class
hydpy.core.sequencetools.
FluxSequences
(master: hydpy.core.sequencetools.Sequences, cls_fastaccess: Optional[Type[FastAccessType]] = None, cymodel: Optional[hydpy.core.typingtools.CyModelProtocol] = None)[source]¶ Bases:
hydpy.core.sequencetools.OutputSequences
[FluxSequence
]Base class for handling
FluxSequence
objects.-
property
name
¶ Always return the string “fluxes”.
-
property
numericsequences
¶ Iterator for numerical flux sequences.
numerical means that the NUMERIC class attribute of the actual sequence is True:
>>> from hydpy import prepare_model >>> model = prepare_model("dam_v001") >>> len(model.sequences.fluxes) 11 >>> for seq in model.sequences.fluxes.numericsequences: ... print(seq) inflow(nan) actualrelease(nan) flooddischarge(nan) outflow(nan)
-
vars
: GroupType¶
-
property
-
class
hydpy.core.sequencetools.
StateSequences
(master: hydpy.core.sequencetools.Sequences, cls_fastaccess: Optional[Type[FastAccessType]] = None, cymodel: Optional[hydpy.core.typingtools.CyModelProtocol] = None)[source]¶ Bases:
hydpy.core.sequencetools.OutputSequences
[StateSequence
]Base class for handling
StateSequence
objects.-
new2old
() → None[source]¶ Call method
new2old()
of all handledStateSequence
objects.
-
reset
() → None[source]¶ Call method
reset()
of all handledStateSequence
objects.
-
-
class
hydpy.core.sequencetools.
LogSequences
(master: hydpy.core.sequencetools.Sequences, cls_fastaccess: Optional[Type[FastAccessType]] = None, cymodel: Optional[hydpy.core.typingtools.CyModelProtocol] = None)[source]¶ Bases:
hydpy.core.sequencetools.ModelSequences
[LogSequence
,hydpy.core.variabletools.FastAccess
]Base class for handling
LogSequence
objects.-
reset
() → None[source]¶ Call method
reset()
of all handledLogSequence
objects.
-
-
class
hydpy.core.sequencetools.
AideSequences
(master: hydpy.core.sequencetools.Sequences, cls_fastaccess: Optional[Type[FastAccessType]] = None, cymodel: Optional[hydpy.core.typingtools.CyModelProtocol] = None)[source]¶ Bases:
hydpy.core.sequencetools.ModelSequences
[AideSequence
,hydpy.core.variabletools.FastAccess
]Base class for handling
AideSequence
objects.
-
class
hydpy.core.sequencetools.
LinkSequences
(master: hydpy.core.sequencetools.Sequences, cls_fastaccess: Optional[Type[FastAccessType]] = None, cymodel: Optional[hydpy.core.typingtools.CyModelProtocol] = None)[source]¶ Bases:
hydpy.core.sequencetools.ModelSequences
[hydpy.core.sequencetools.LinkSequenceType
,hydpy.core.sequencetools.FastAccessLinkSequence
]Base class for handling
LinkSequence
objects.
-
class
hydpy.core.sequencetools.
InletSequences
(master: hydpy.core.sequencetools.Sequences, cls_fastaccess: Optional[Type[FastAccessType]] = None, cymodel: Optional[hydpy.core.typingtools.CyModelProtocol] = None)[source]¶ Bases:
hydpy.core.sequencetools.LinkSequences
[InletSequence
]Base class for handling “inlet”
LinkSequence
objects.
-
class
hydpy.core.sequencetools.
OutletSequences
(master: hydpy.core.sequencetools.Sequences, cls_fastaccess: Optional[Type[FastAccessType]] = None, cymodel: Optional[hydpy.core.typingtools.CyModelProtocol] = None)[source]¶ Bases:
hydpy.core.sequencetools.LinkSequences
[OutletSequence
]Base class for handling “outlet”
LinkSequence
objects.
-
class
hydpy.core.sequencetools.
ReceiverSequences
(master: hydpy.core.sequencetools.Sequences, cls_fastaccess: Optional[Type[FastAccessType]] = None, cymodel: Optional[hydpy.core.typingtools.CyModelProtocol] = None)[source]¶ Bases:
hydpy.core.sequencetools.LinkSequences
[ReceiverSequence
]Base class for handling “receiver”
LinkSequence
objects.
-
class
hydpy.core.sequencetools.
SenderSequences
(master: hydpy.core.sequencetools.Sequences, cls_fastaccess: Optional[Type[FastAccessType]] = None, cymodel: Optional[hydpy.core.typingtools.CyModelProtocol] = None)[source]¶ Bases:
hydpy.core.sequencetools.LinkSequences
[SenderSequence
]Base class for handling “sender”
LinkSequence
objects.
-
class
hydpy.core.sequencetools.
Sequence_
(subvars: SubVariablesType)[source]¶ Bases:
hydpy.core.variabletools.Variable
[hydpy.core.sequencetools.SubSequencesType
,hydpy.core.variabletools.FastAccessType
]Base class for defining different kinds of sequences.
Note that model developers should not derive their model-specific sequence classes from
Sequence_
directly but from the “final” subclasses provided in modulesequencetools
(e.g.FluxSequence
).From the model developer perspective and especially from the user perspective,
Sequence_
is only a small extension of its base classVariable
. One relevant extension is that (only the) 0-dimensional sequence objects come with a predefined shape:>>> from hydpy import prepare_model >>> model = prepare_model("lland_v1", "1d") >>> model.sequences.fluxes.qa.shape () >>> evpo = model.sequences.fluxes.evpo >>> evpo.shape Traceback (most recent call last): ... hydpy.core.exceptiontools.AttributeNotReady: Shape information for variable `evpo` can only be retrieved after it has been defined.
For high numbers of entries, the string representation puts the names of the constants within a list (to make the string representations executable under Python 3.6; this behaviour changes as soon as Python 3.7 becomes the oldest supported version):
>>> evpo.shape = (255,) >>> evpo evpo(nan, nan, ..., nan, nan) >>> evpo.shape = (256,) >>> evpo evpo([nan, nan, ..., nan, nan])
For consistency with the usage of
Parameter
subclasses,Sequence_
objects are also “callable” for setting their values (but in a much less and flexible manner):>>> evpo(2.0) >>> evpo evpo([2.0, 2.0, ..., 2.0, 2.0])
Under the hood, class
Sequence_
also prepares some attributes of itsFastAccess
object, used for performing the actual simulation calculations. Framework developers should note that the respective fastaccess attributes contain both the name of the sequence and the name of the original attribute in lower case letters. We take NDIM as an example:>>> evpo.fastaccess._evpo_ndim 1
Some of these attributes require updating under some situations. For example, other sequences than
AideSequence
objects require a “length” attribute, which needs to be updated each time the sequence’s shape changes:>>> evpo.fastaccess._evpo_length 256
-
TYPE
¶
-
-
property
subseqs
¶ Alias for attribute subvars.
-
property
initinfo
¶ A
tuple
containing the initial value andTrue
or a missing value andFalse
, depending on the actualSequence_
subclass and the actual value of optionusedefaultvalues
.In the following, we do not explain property
initinfo
itself but show how it affects initialising newSequence_
objects. Therefore, let us define a sequence test class and prepare a function for initialising it and connecting the resulting instance to aModelSequences
object:>>> from hydpy.core.sequencetools import Sequence_, ModelSequences >>> from hydpy.core.variabletools import FastAccess >>> class Test(Sequence_): ... NDIM = 0 ... _CLS_FASTACCESS_PYTHON = FastAccess >>> class SubGroup(ModelSequences): ... CLASSES = (Test,) ... _CLS_FASTACCESS_PYTHON = FastAccess >>> def prepare(): ... subseqs = SubGroup(None) ... test = Test(subseqs) ... test.__hydpy__connect_variable2subgroup__() ... return test
By default, making use of the INIT attribute is disabled:
>>> prepare() test(nan)
Enable it through setting
usedefaultvalues
toTrue
:>>> from hydpy import pub >>> with pub.options.usedefaultvalues(True): ... prepare() test(0.0)
Attribute INIT of class
Sequence_
comes with the value 0.0 by default, which should be reasonable for mostSequence_
subclasses. However, subclasses can define other values. Most importantly, note the possibility to set INIT to None for sequences that do not allow defining 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: SubVariablesType)[source]¶ Bases:
hydpy.core.sequencetools.Sequence_
[hydpy.core.sequencetools.IOSequencesType
,hydpy.core.sequencetools.FastAccessIOSequenceType
]Base class for sequences with input/output functionalities.
The
IOSequence
subclassesInputSequence
,FluxSequence
,StateSequence
, andNodeSequence
all implement similar special properties, which configure the processes of reading and writing time-series files. In the following, property filetype_ext is taken as an example to explain how to handle them:Usually, each sequence queries its current “external” file type from the
SequenceManager
object stored in modulepub
:>>> from hydpy import pub >>> from hydpy.core.filetools import SequenceManager >>> pub.sequencemanager = SequenceManager()
Depending if the actual sequence stems from
InputSequence
,FluxSequence
,StateSequence
, orNodeSequence
, eitherinputfiletype
,fluxfiletype
,statefiletype
, ornodefiletype
are queried:>>> pub.sequencemanager.inputfiletype = "npy" >>> pub.sequencemanager.fluxfiletype = "asc" >>> pub.sequencemanager.nodefiletype = "nc" >>> from hydpy.core import sequencetools as st >>> st.InputSequence(None).filetype_ext 'npy' >>> st.FluxSequence(None).filetype_ext 'asc' >>> st.NodeSequence(None).filetype_ext 'nc'
Alternatively, you can specify filetype_ext for each sequence object individually:
>>> seq = st.InputSequence(None) >>> seq.filetype_ext 'npy' >>> seq.filetype_ext = "nc" >>> seq.filetype_ext 'nc' >>> del seq.filetype_ext >>> seq.filetype_ext 'npy'
If neither a specific definition nor a
SequenceManager
object is available, property filetype_ext raises the following error:>>> del pub.sequencemanager >>> seq.filetype_ext Traceback (most recent call last): ... RuntimeError: For sequence `inputsequence` attribute filetype_ext cannot be determined. Either set it manually or prepare `pub.sequencemanager` correctly.
How to read and write time-series files is explained in the documentation on modules
filetools
andnetcdftools
in some detail. However, reading and writing time-series files is disabled by default, due to reasons of efficiency. You first need to prepare theseries
attribute of the relevantIOSequence
objects. Typically, you do this by calling methods likeprepare_inputseries()
of classHydPy
. Here, we use the related features theIOSequence
class itself, which is a little more complicated but also more flexible when scripting complex workflows.We use the LahnH example project and focus on the input and flux sequences:
>>> from hydpy.examples import prepare_full_example_2 >>> hp, pub, TestIO = prepare_full_example_2() >>> inputs = hp.elements.land_lahn_1.model.sequences.inputs >>> fluxes = hp.elements.land_lahn_1.model.sequences.fluxes
IOSequence
objects come with the propertiesramflag
anddiskflag
, telling if the respective time-series is available in RAM, on disk, or not available at all. Input sequences are the only ones who need to have one flag activated. Otherwise, the input series would not be available during simulation runs. For example, input sequenceT
stores its time-series data in RAM internally, which is the much faster approach and should be preferred, as long as limited storage is not an issue:>>> inputs.t.ramflag True >>> inputs.t.diskflag False >>> from hydpy import repr_, round_ >>> round_(inputs.t.series, 1) -0.7, -1.5, -4.2, -7.4
Convenience function
prepare_full_example_2()
also activates theramflag
of all flux sequences, which is not necessary to perform a successful simulation but is required to query the complete time-series of simulated values afterwards (otherwise, only the last simulated value would available after a simulation run):>>> fluxes.tc.ramflag True >>> round_(fluxes.tc.series[:, 0]) nan, nan, nan, nan
Use
activate_ram()
oractivate_disk()
to force a sequence to handle time-series data in RAM or on disk, respectively. We now activate thediskflag
of flux sequenceTMean
(which automatically disables theramflag
). Note that we need to change the current working directory to the iotesting directory temporarily (by using classTestIO
) to make sure to create that the related file in the right directory:>>> with TestIO(): ... fluxes.tmean.activate_disk() ... repr_(fluxes.tmean.filepath_int) '...iotesting/LahnH/series/temp/land_lahn_1_flux_tmean.bin'
The user can access the time-series data in the same manner as if being handled in RAM:
>>> fluxes.tmean.ramflag False >>> fluxes.tmean.diskflag True >>> with TestIO(): ... round_(fluxes.tmean.series) nan, nan, nan, nan
For completeness of testing, we also activate the
diskflag
of a 1-dimensional sequence:>>> from pprint import pprint >>> with TestIO(): ... fluxes.fracrain.activate_disk() ... pprint(sorted(os.listdir("LahnH/series/temp"))) ['land_lahn_1_flux_fracrain.bin', 'land_lahn_1_flux_tmean.bin']
Apply methods
deactivate_ram()
ordeactivate_disk()
for sequences that do not provide data relevant for your analysis:>>> fluxes.ep.deactivate_ram() >>> fluxes.ep.ramflag False >>> fluxes.ep.diskflag False >>> fluxes.ep.series Traceback (most recent call last): ... AttributeError: Sequence `ep` of element `land_lahn_1` is not requested to make any internal data available.
After a simulation run, the
series
of flux sequenceEP
is still not available but the time-series data of the other discussed series with either trueramflag
ordiskflag
values are:>>> with TestIO(): ... hp.simulate()
>>> fluxes.ep.series = 1.0 Traceback (most recent call last): ... AttributeError: Sequence `ep` of element `land_lahn_1` is not requested to make any internal data available.
>>> round_(fluxes.q1.series, 1) 0.4, 0.4, 0.4, 0.4 >>> round_(fluxes.tc.series[:, 0], 1) 0.2, -0.6, -3.4, -6.6 >>> with TestIO(): ... round_(fluxes.tmean.series, 1) -1.0, -1.8, -4.5, -7.7 >>> with TestIO(): ... round_(fluxes.fracrain.series[:, 0], 1) 0.3, 0.0, 0.0, 0.0
You cannot only access the time-series data of individual
IOSequence
objects, but you can also modify it. See, for example, the simulated time series for flux sequencePC
(adjusted precipitation), which is zero, because the values of input sequenceP
(given precipitation) are also zero:>>> round_(fluxes.pc.series[:, 0], 1) 0.0, 0.0, 0.0, 0.0
We can assign different values to attribute
series
of sequenceP
, perform a new simulation run, and see that the newly calculated time-series of sequencePC
reflects our data modification:>>> inputs.p.ramflag True >>> inputs.p.series = 10.0 >>> with TestIO(): ... hp.simulate() >>> round_(fluxes.pc.series[:, 0], 1) 10.2, 11.3, 11.3, 11.3
Next, we show that the same feature works for time-series data handled on disk. Therefore, we first call method
ram2disk()
, which disablesramflag
and enablesdiskflag
without any loss of information:>>> with TestIO(): ... inputs.p.ram2disk() ... pprint(sorted(os.listdir("LahnH/series/temp"))) ['land_lahn_1_flux_fracrain.bin', 'land_lahn_1_flux_tmean.bin', 'land_lahn_1_input_p.bin'] >>> inputs.p.ramflag False >>> inputs.p.diskflag True >>> with TestIO(): ... round_(inputs.p.series, 1) 10.0, 10.0, 10.0, 10.0
Data modifications still influence simulation runs as to be expected:
>>> with TestIO(): ... inputs.p.series = 20.0 ... hp.simulate() ... round_(fluxes.pc.series[:, 0], 1) 20.5, 22.6, 22.6, 22.6
Method
disk2ram()
is the counterpart toram2disk()
:>>> with TestIO(): ... inputs.p.disk2ram() ... pprint(sorted(os.listdir("LahnH/series/temp"))) ['land_lahn_1_flux_fracrain.bin', 'land_lahn_1_flux_tmean.bin'] >>> inputs.p.ramflag True >>> inputs.p.diskflag False >>> round_(inputs.p.series, 1) 20.0, 20.0, 20.0, 20.0
Method
deactivate_disk()
works analogue todeactivate_ram()
:>>> with TestIO(): ... fluxes.fracrain.deactivate_disk() ... pprint(sorted(os.listdir("LahnH/series/temp"))) ['land_lahn_1_flux_tmean.bin'] >>> fluxes.fracrain.ramflag False >>> fluxes.fracrain.diskflag False
Both methods
deactivate_ram()
anddeactivate_disk()
do nothing in case the respective flag isFalse
already:>>> fluxes.pc.deactivate_ram() >>> with TestIO(): ... fluxes.fracrain.deactivate_disk()
You can query property
memoryflag
, if you are only interested to know if a sequence handles stores its time-series data, but not how:>>> fluxes.pc.memoryflag False >>> fluxes.tmean.memoryflag True >>> inputs.p.memoryflag True
Another convenience property is
seriesshape
, which combines the length of the simulation period with the shape of the individualIOSequence
object:>>> inputs.p.seriesshape (4,) >>> fluxes.pc.seriesshape (4, 13)
Note that resetting the
shape
of amIOSequence
object does not change how it handles its internal time-series data, but results in a loss of current information:>>> fluxes.tc.seriesshape (4, 13) >>> fluxes.fastaccess._tc_length 13 >>> round_(fluxes.tc.series[:, 0], 1) 0.2, -0.6, -3.4, -6.6
>>> fluxes.tc.shape = (2,) >>> fluxes.tc.seriesshape (4, 2) >>> fluxes.fastaccess._tc_length 2 >>> round_(fluxes.tc.series[:, 0], 1) nan, nan, nan, nan
Resetting the
shape
ofIOSequence
objects which are not storing their internal time-series data works too:>>> fluxes.pc.seriesshape (4, 13) >>> fluxes.fastaccess._pc_length 13 >>> round_(fluxes.pc.series[:, 0], 1) Traceback (most recent call last): ... AttributeError: Sequence `pc` of element `land_lahn_1` is not requested to make any internal data available.
>>> fluxes.pc.shape = (2,) >>> fluxes.pc.seriesshape (4, 2) >>> fluxes.fastaccess._pc_length 2 >>> round_(fluxes.pc.series[:, 0], 1) Traceback (most recent call last): ... AttributeError: Sequence `pc` of element `land_lahn_1` is not requested to make any internal data available.
-
filetype_ext
: ClassVar[hydpy.core.sequencetools._FileType]¶
-
dirpath_ext
: ClassVar[hydpy.core.sequencetools._DirPathProperty]¶
-
aggregation_ext
: ClassVar[hydpy.core.sequencetools._AggregationProperty]¶
-
overwrite_ext
: ClassVar[hydpy.core.sequencetools._OverwriteProperty]¶
-
rawfilename
¶ DefaultProperty
handling the filename without ending for external and internal data files.>>> from hydpy.core.sequencetools import StateSequence >>> class Test(StateSequence): ... descr_device = "node1" ... descr_sequence = "subgroup_test" >>> Test(None).rawfilename 'node1_subgroup_test'
-
filename_ext
¶ The full filename of the external data file.
The “external” filename consists of
rawfilename
and offiletype_ext
. For simplicity, we add the attribute rawfilename to the initialised sequence object in the following example:>>> from hydpy.core.sequencetools import StateSequence >>> seq = StateSequence(None) >>> seq.rawfilename = "test" >>> seq.filetype_ext = "nc" >>> seq.filename_ext 'test.nc'
-
property
filename_int
¶ The full filename of the internal data file.
The “internal” filename consists of
rawfilename
and the file ending .bin. For simplicity, we add the attribute rawfilename to the initialised sequence object in the following example:>>> from hydpy.core.sequencetools import StateSequence >>> seq = StateSequence(None) >>> seq.rawfilename = "test" >>> seq.filename_int 'test.bin'
-
dirpath_int
¶ The absolute path of the directory of the internal data file.
Usually, each sequence queries its current “internal” directory path from the
SequenceManager
object stored in modulepub
:>>> from hydpy import pub, repr_, TestIO >>> from hydpy.core.filetools import SequenceManager >>> pub.sequencemanager = SequenceManager()
We overwrite
basepath
and prepare a folder in the iotesting directory to simplify the following examples:>>> basepath = SequenceManager.basepath >>> SequenceManager.basepath = "test" >>> TestIO.clear() >>> import os >>> with TestIO(): ... os.makedirs("test/temp")
Generally, property
dirpath_int
queries propertytempdirpath
:>>> from hydpy.core import sequencetools as st >>> seq = st.InputSequence(None) >>> with TestIO(): ... repr_(seq.dirpath_int) 'test/temp'
Alternatively, you can specify
dirpath_int
for each sequence object individually:>>> seq.dirpath_int = "path" >>> os.path.split(seq.dirpath_int) ('', 'path') >>> del seq.dirpath_int >>> with TestIO(): ... os.path.split(seq.dirpath_int) ('test', 'temp')
If neither a specific definition nor a
SequenceManager
object is, property dirpath_int raises the following error:>>> del pub.sequencemanager >>> seq.dirpath_int Traceback (most recent call last): ... RuntimeError: For sequence `inputsequence` the directory of the internal data file cannot be determined. Either set it manually or prepare `pub.sequencemanager` correctly.
Remove the basepath mock:
>>> SequenceManager.basepath = basepath
-
filepath_ext
¶ The absolute path to the external data file.
The path pointing to the “external” file consists of
dirpath_ext
andfilename_ext
. For simplicity, we define both manually in the following example:>>> from hydpy.core.sequencetools import StateSequence >>> seq = StateSequence(None) >>> seq.dirpath_ext = "path" >>> seq.filename_ext = "file.npy" >>> from hydpy import repr_ >>> repr_(seq.filepath_ext) 'path/file.npy'
-
filepath_int
¶ The absolute path to the internal data file.
The path pointing to the “internal” file consists of
dirpath_int
andfilename_int
, which itself is defined by rawfilename. For simplicity, we define both manually in the following example:>>> from hydpy.core.sequencetools import StateSequence >>> seq = StateSequence(None) >>> seq.dirpath_int = "path" >>> seq.rawfilename = "file" >>> from hydpy import repr_ >>> repr_(seq.filepath_int) 'path/file.bin'
-
update_fastaccess
() → None[source]¶ Update the
FastAccessIOSequence
object handled by the actualIOSequence
object.Users do not need to apply the method
update_fastaccess()
directly. The following information should be relevant for framework developers only.The main documentation on class
Sequence_
mentions that theFastAccessIOSequence
attribute handles some information about its sequences, but this information needs to be kept up-to-date by the sequences themselves. This updating is the task of methodupdate_fastaccess()
, which some other methods of classIOSequence
call. We show this via the hidden attribute length, which is 0 after initialisation, and automatically set to another value when assigning it to propertyshape
ofIOSequence
subclasses asNKor
:>>> from hydpy import prepare_model >>> model = prepare_model("lland_v1") >>> nkor = model.sequences.fluxes.nkor >>> nkor.fastaccess._nkor_length 0 >>> nkor.shape = (3,) >>> nkor.fastaccess._nkor_length 3
-
activate_ram
() → None[source]¶ Demand reading/writing internal data from/to RAM.
See the main documentation on class
IOSequence
for further information.
-
activate_disk
() → None[source]¶ Demand reading/writing internal data from/to hard disk.
See the main documentation on class
IOSequence
for further information.
-
deactivate_ram
() → None[source]¶ Prevent from reading/writing internal data from/to hard disk.
See the main documentation on class
IOSequence
for further information.
-
deactivate_disk
() → None[source]¶ Prevent from reading/writing internal data from/to hard disk.
See the main documentation on class
IOSequence
for further information.
-
ram2disk
() → None[source]¶ Move internal data from RAM to disk.
See the main documentation on class
IOSequence
for further information.
-
disk2ram
() → None[source]¶ Move internal data from disk to RAM.
See the main documentation on class
IOSequence
for further information.
-
property
ramflag
¶ A flag telling if the actual
IOSequence
object makes its internal time-series data available using RAM space.See the main documentation on class
IOSequence
for further information.
-
property
diskflag
¶ A flag telling if the actual
IOSequence
object makes its internal time-series data available using disk space.See the main documentation on class
IOSequence
for further information.
-
property
memoryflag
¶ A flag telling if the actual
IOSequence
object makes its internal time-series data available somehow.See the main documentation on class
IOSequence
for further information.
-
property
shape
¶ A tuple containing the actual lengths of all dimensions.
When setting a new
shape
of anIOSequence
object, one automatically calls methodupdate_fastaccess()
and, if necessary, prepares the new internalseries
array.See the main documentation on class
IOSequence
for further information.
-
property
seriesshape
¶ The shape of the whole time-series (time being the first dimension).
-
property
numericshape
¶ The shape of the array of temporary values required for the relevant numerical solver.
The class
ELSModel
, being the base of the “dam” model, uses the “Explicit Lobatto Sequence” for solving differential equations and therefore requires up to eleven array fields for storing temporary values. Hence, thenumericshape
of the 0-dimensional sequenceInflow
is eleven:>>> from hydpy import prepare_model >>> model = prepare_model("dam") >>> model.sequences.fluxes.inflow.numericshape (11,)
Changing the
shape
through a little trick (just for demonstration purposes) shows that there are eleven entries for each “normal”Inflow
value:>>> from hydpy.models.dam.dam_fluxes import Inflow >>> shape = Inflow.shape >>> Inflow.shape = (2,) >>> model.sequences.fluxes.inflow.numericshape (11, 2) >>> Inflow.shape = shape
Erroneous configurations result in the following error:
>>> del model.numconsts >>> model.sequences.fluxes.inflow.numericshape Traceback (most recent call last): ... AttributeError: The `numericshape` of a sequence like `inflow` depends on the configuration of the actual integration algorithm. While trying to query the required configuration data `nmb_stages` of the model associated with element `?`, the following error occurred: 'Model' object has no attribute 'numconsts'
-
property
series
¶ Internal time-series data within an
InfoArray
covering the whole initialisation period (defined by thesim
Timegrid
of the globalTimegrids
object available in modulepub
).
-
property
simseries
¶ Read and write access to the data of property
series
for the actual simulation period (defined by thesim
Timegrid
of the globalTimegrids
object available in modulepub
).>>> from hydpy.examples import prepare_full_example_2 >>> hp, pub, TestIO = prepare_full_example_2() >>> t = hp.elements.land_lahn_1.model.sequences.inputs.t >>> pub.timegrids.sim.dates = "1996-01-02", "1996-01-04" >>> from hydpy import print_values >>> print_values(t.series) -0.705395, -1.505553, -4.221268, -7.446349 >>> print_values(t.simseries) -1.505553, -4.221268 >>> t.simseries = 1.0, 2.0 >>> print_values(t.series) -0.705395, 1.0, 2.0, -7.446349
-
property
evalseries
¶ Read and write access to the data of property
series
for the actual evaluation period (defined by theeval_
Timegrid
of the globalTimegrids
object available in modulepub
).>>> from hydpy.examples import prepare_full_example_2 >>> hp, pub, TestIO = prepare_full_example_2() >>> t = hp.elements.land_lahn_1.model.sequences.inputs.t >>> pub.timegrids.eval_.dates = "1996-01-02", "1996-01-04" >>> from hydpy import print_values >>> print_values(t.series) -0.705395, -1.505553, -4.221268, -7.446349 >>> print_values(t.evalseries) -1.505553, -4.221268 >>> t.evalseries = 1.0, 2.0 >>> print_values(t.series) -0.705395, 1.0, 2.0, -7.446349
-
load_ext
() → None[source]¶ Read the internal data from an external data file.
Method
load_ext()
only calls methodload_file()
of classSequenceManager
passing itself as the only argument. Hence, see the documentation on the classSequenceManager
for further information. The following example only shows the error messages whenload_file()
is missing due to incomplete project configurations:>>> from hydpy.core.sequencetools import StateSequence >>> StateSequence(None).load_ext() Traceback (most recent call last): ... hydpy.core.exceptiontools.AttributeNotReady: While trying to load the external 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: numpy.ndarray) → numpy.ndarray[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. If you want to call it directly for some reasons, you need to make sure that the shape of the givennumpy
ndarray
fits the givenTimegrid
object.Often, time-series data available in (external) data files cover a longer period than required for an actual simulation run. Method
adjust_series()
selects the relevant data by comparing the initialisationTimegrid
available in modulepub
and the given “data”Timegrid
object. We explain this behaviour by using the LahnH example project and focussing on theObs
sequence ofNode
dill:>>> from hydpy.examples import prepare_full_example_2 >>> hp, pub, TestIO = prepare_full_example_2() >>> obs = hp.nodes.dill.sequences.obs
With identical initialisation and data time grids, method
adjust_series()
returns the given data completely:>>> from hydpy import Timegrid >>> import numpy >>> with TestIO(), pub.options.checkseries(False): ... obs.adjust_series(Timegrid("1996-01-01", "1996-01-05", "1d"), ... numpy.arange(4, dtype=float)) array([ 0., 1., 2., 3.])
For “too long” available data, it only returns the relevant one:
>>> with TestIO(), pub.options.checkseries(False): ... obs.adjust_series(Timegrid("1995-12-31", "1996-01-07", "1d"), ... numpy.arange(7, dtype=float)) array([ 1., 2., 3., 4.])
For “too short” available data, the behaviour differs depending on option
checkseries
. Withcheckseries
being enabled, methodadjust_series()
raises aRuntimeError
. Withcheckseries
being disabled, it extends the given array withnan
values (using methodadjust_short_series()
):>>> with TestIO(), pub.options.checkseries(True): ... obs.adjust_series(Timegrid("1996-01-02", "1996-01-04", "1d"), ... numpy.zeros((3,))) Traceback (most recent call last): ... RuntimeError: For sequence `obs` of node `dill` 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 external data file `...dill_obs_q.asc` (Timegrid("1996-01-02 00:00:00", "1996-01-04 00:00:00", "1d")).
>>> with TestIO(), pub.options.checkseries(False): ... obs.adjust_series(Timegrid("1996-01-02", "1996-01-04", "1d"), ... numpy.zeros((2,))) array([ nan, 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` is `()` but according to the external data file `...dill_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 external data file `...dill_obs_q.asc`, the date time step of sequence `obs` of node `dill` is `1h` but the actual simulation time step is `1d`.
-
adjust_short_series
(timegrid: timetools.Timegrid, values: numpy.ndarray) → numpy.ndarray[source]¶ Adjust a short time-series to a longer time grid.
Mostly, time-series data to be read from external data files should span (at least) the whole initialisation period of a HydPy project. However, for some variables which are only used for comparison (e.g. observed runoff used for calibration), incomplete time-series might also be helpful. Method
adjust_short_series()
adjusts such incomplete series to the public initialisation time grid stored in modulepub
. It is automatically called in methodadjust_series()
when necessary provided that the optioncheckseries
is disabled.Assume the initialisation period of a HydPy project spans five days:
>>> from hydpy import pub >>> pub.timegrids = "2000.01.10", "2000.01.15", "1d"
Prepare a node series object for observational data:
>>> from hydpy.core.sequencetools import Obs >>> obs = Obs(None)
Prepare a test function that expects the time grid of the data and the data itself, which returns the adjusted array through calling 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 Timegrid >>> test(Timegrid("2000.01.05", "2000.01.20", "1d")) array([ 1., 1., 1., 1., 1.]) >>> test(Timegrid("2000.01.12", "2000.01.15", "1d")) array([ nan, nan, 1., 1., 1.]) >>> test(Timegrid("2000.01.12", "2000.01.17", "1d")) array([ nan, nan, 1., 1., 1.]) >>> test(Timegrid("2000.01.10", "2000.01.13", "1d")) array([ 1., 1., 1., nan, nan]) >>> test(Timegrid("2000.01.08", "2000.01.13", "1d")) array([ 1., 1., 1., nan, nan]) >>> test(Timegrid("2000.01.12", "2000.01.13", "1d")) array([ nan, nan, 1., nan, nan]) >>> test(Timegrid("2000.01.05", "2000.01.10", "1d")) array([ nan, nan, nan, nan, nan]) >>> test(Timegrid("2000.01.05", "2000.01.08", "1d")) array([ nan, nan, nan, nan, nan]) >>> test(Timegrid("2000.01.15", "2000.01.18", "1d")) array([ nan, nan, nan, nan, nan]) >>> test(Timegrid("2000.01.16", "2000.01.18", "1d")) array([ nan, nan, nan, nan, nan])
After enabling option
usedefaultvalues
, the missing values are initialised with zero instead of nan:>>> with pub.options.usedefaultvalues(True): ... test(Timegrid("2000.01.12", "2000.01.17", "1d")) array([ 0., 0., 1., 1., 1.])
-
check_completeness
() → None[source]¶ Raise a
RuntimeError
if theseries
contains at least onenan
value and if the optioncheckseries
is enabled.>>> from hydpy import pub >>> pub.timegrids = "2000-01-01", "2000-01-11", "1d" >>> from hydpy.core.sequencetools import StateSequence, StateSequences >>> class Seq(StateSequence): ... NDIM = 0 ... NUMERIC = False >>> class StateSequences(StateSequences): ... CLASSES = (Seq,) >>> seq = Seq(StateSequences(None)) >>> seq.__hydpy__connect_variable2subgroup__() >>> seq.activate_ram() >>> 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_ext
() → None[source]¶ Write the internal data into an external data file.
Method
save_ext()
only calls methodsave_file()
of classSequenceManager
passing itself as the only argument. Hence, see the documentation on class theSequenceManager
for further information. The following example only shows the error messages whensave_file()
is missing due to incomplete project configurations:>>> from hydpy.core.sequencetools import StateSequence >>> StateSequence(None).save_ext() Traceback (most recent call last): ... hydpy.core.exceptiontools.AttributeNotReady: While trying to save the external 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 date with method
average_series()
of classIOSequence
and write the result to file using methodsave_file()
of classSequenceManager
.The main documentation on class
SequenceManager
provides some examples.
-
average_series
(*args, **kwargs) → hydpy.core.sequencetools.InfoArray[source]¶ Average the actual time-series of the
Variable
object for all time points.Method
average_series()
works similarly as methodaverage_values()
of classVariable
, from which we borrow some examples. However, firstly, we have to prepare aTimegrids
object to define theseries
length:>>> from hydpy import pub >>> pub.timegrids = "2000-01-01", "2000-01-04", "1d"
As shown for method
average_values()
, for 0-dimensionalIOSequence
objects the result of methodaverage_series()
equalsseries
itself:>>> from hydpy.core.sequencetools import StateSequence, StateSequences >>> class SoilMoisture(StateSequence): ... NDIM = 0 ... NUMERIC = False >>> class StateSequences(StateSequences): ... CLASSES = (SoilMoisture,) >>> sm = SoilMoisture(StateSequences(None)) >>> sm.__hydpy__connect_variable2subgroup__() >>> sm.activate_ram() >>> import numpy >>> sm.series = numpy.array([190.0, 200.0, 210.0]) >>> sm.average_series() InfoArray([ 190., 200., 210.])
For
IOSequence
objects with an increased dimensionality, we require a weighting parameter:>>> SoilMoisture.NDIM = 1 >>> sm.shape = 3 >>> sm.activate_ram() >>> 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 how to use 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() 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 along dimension 0; dimension is 3 but corresponding boolean dimension is 2
-
aggregate_series
(*args, **kwargs) → hydpy.core.sequencetools.InfoArray[source]¶ Aggregate time-series data based on the actual
aggregation_ext
attribute ofIOSequence
subclasses.We prepare some nodes and elements with the help of method
prepare_io_example_1()
and select a 1-dimensional flux sequence of typeNKor
as an example:>>> from hydpy.examples import prepare_io_example_1 >>> nodes, elements = prepare_io_example_1() >>> seq = elements.element3.model.sequences.fluxes.nkor
If
aggregation_ext
is none, the original time-series values are returned:>>> seq.aggregation_ext 'none' >>> seq.aggregate_series() InfoArray([[ 24., 25., 26.], [ 27., 28., 29.], [ 30., 31., 32.], [ 33., 34., 35.]])
If
aggregation_ext
is mean, methodaggregate_series()
is called:>>> seq.aggregation_ext = "mean" >>> seq.aggregate_series() InfoArray([ 25., 28., 31., 34.])
In case the state of the sequence is invalid:
>>> seq.aggregation_ext = "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_ext = "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)
-
-
class
hydpy.core.sequencetools.
ModelSequence
(subvars: SubVariablesType)[source]¶ Bases:
hydpy.core.sequencetools.Sequence_
[hydpy.core.sequencetools.ModelSequencesType
,hydpy.core.variabletools.FastAccessType
]Base class for sequences to be handled by
Model
objects.-
property
descr_sequence
¶ Description of the
ModelSequence
object itself and theSubSequences
group it belongs to.>>> from hydpy import prepare_model >>> from hydpy.models import test_v1 >>> model = prepare_model(test_v1) >>> model.sequences.fluxes.q.descr_sequence 'flux_q'
-
property
descr_model
¶ Description of the
Model
theModelSequence
object belongs to.>>> from hydpy import prepare_model >>> from hydpy.models import test, test_v1 >>> model = prepare_model(test) >>> model.sequences.fluxes.q.descr_model 'test' >>> model = prepare_model(test_v1) >>> model.sequences.fluxes.q.descr_model 'test_v1'
-
property
descr_device
¶ Description of the
Element
object theModelSequence
object belongs to.>>> from hydpy import prepare_model, Element >>> element = Element("test_element_1") >>> from hydpy.models import test_v1 >>> model = prepare_model(test_v1) >>> model.sequences.fluxes.q.descr_device '?' >>> element.model = model >>> model.sequences.fluxes.q.descr_device 'test_element_1'
-
subvars
: SubVariablesType¶
-
property
-
class
hydpy.core.sequencetools.
ModelIOSequence
(subvars: SubVariablesType)[source]¶ Bases:
hydpy.core.sequencetools.ModelSequence
[hydpy.core.sequencetools.ModelIOSequencesType
,hydpy.core.sequencetools.FastAccessIOSequenceType
],hydpy.core.sequencetools.IOSequence
[hydpy.core.sequencetools.ModelIOSequencesType
,hydpy.core.sequencetools.FastAccessIOSequenceType
]Base class for sequences with input/output functionalities to be handled by
Model
objects.-
subvars
: SubVariablesType¶
-
-
class
hydpy.core.sequencetools.
InputSequence
(subvars: SubVariablesType)[source]¶ Bases:
hydpy.core.sequencetools.ModelIOSequence
[hydpy.core.sequencetools.InputSequences
,hydpy.core.sequencetools.FastAccessInputSequence
]Base class for input sequences of
Model
objects.InputSequence
objects provide their master model with input data, which is possible in two ways: either by providing their individually managed data (usually read from file) or data shared with an input node (usually calculated by another model). This flexibility allows, for example, to let application modelhland_v1
read already preprocessed precipitation time-series or to couple it with application modelconv_v001
, which interpolates precipitation during the simulation run.The second mechanism (coupling
InputSequence
objects with input nodes) is rather new, and we might adjust the relevant interfaces in the future. As soon as we finally settled things, we improve the following example and place it more prominently. In short, it shows that working with both types of input data sources at the same time works well and that the differentdeploymode
options are supported:>>> from hydpy import Element, FusedVariable, HydPy, Node, print_values, pub, TestIO >>> from hydpy.inputs import hland_T, hland_P >>> hp = HydPy("LahnH") >>> pub.timegrids = "1996-01-01", "1996-01-06", "1d" >>> node_t = Node("node_t", variable=hland_T) >>> node_p = Node("node_p", variable=FusedVariable("Precip", hland_P)) >>> node_q = Node("node_q") >>> land_dill = Element("land_dill", ... inputs=[node_t, node_p], ... outlets=node_q)
>>> from hydpy.examples import prepare_full_example_1 >>> prepare_full_example_1() >>> import os >>> with TestIO(): ... os.chdir("LahnH/control/default") ... with open("land_dill.py") as controlfile: ... exec(controlfile.read(), {}, locals()) ... parameters.update() ... land_dill.model = model
>>> model.sequences.inputs.t.inputflag True >>> model.sequences.inputs.p.inputflag True >>> model.sequences.inputs.epn.inputflag False
>>> hp.update_devices(nodes=[node_t, node_p, node_q], elements=land_dill) >>> hp.prepare_inputseries() >>> 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_values(model.sequences.inputs.t.series) 1.0, 2.0, 3.0, 4.0, 5.0 >>> print_values(model.sequences.fluxes.tc.series[:, 0]) 2.05, 3.05, 4.05, 5.05, 6.05 >>> print_values(model.sequences.inputs.p.series) 0.0, 4.0, 0.0, 8.0, 0.0 >>> print_values(model.sequences.fluxes.pc.series[:, 0]) 0.0, 3.441339, 0.0, 6.882678, 0.0 >>> print_values(model.sequences.inputs.epn.series) 0.285483, 0.448182, 0.302786, 0.401946, 0.315023 >>> print_values(model.sequences.fluxes.epc.series[:, 0]) 0.314763, 0.524569, 0.46086, 0.689852, 0.630047
-
filetype_ext
: ClassVar[_FileType]¶ Ending of the external data file.
Attribute filetype_ext is connected with attribute inputfiletype of class
SequenceManager
, as shown by the following technical example (see the documentation on classIOSequence
for some explanations on the usage of this and similar properties ofIOSequence
subclasses):>>> from hydpy.core.filetools import SequenceManager >>> temp = SequenceManager.inputfiletype >>> SequenceManager.inputfiletype = "global" >>> from hydpy import pub >>> pub.sequencemanager = SequenceManager() >>> from hydpy.core.sequencetools import InputSequence >>> sequence = InputSequence(None) >>> sequence.filetype_ext 'global' >>> sequence.filetype_ext = "local" >>> sequence.filetype_ext 'local' >>> del sequence.filetype_ext >>> sequence.filetype_ext 'global' >>> SequenceManager.inputfiletype = temp
-
dirpath_ext
: ClassVar[_DirPathProperty]¶ Absolute path of the directory of the external data file.
Attribute dirpath_ext is connected with attribute inputdirpath of class
SequenceManager
, as shown by the following technical example (see the documentation on classIOSequence
for some explanations on the usage of this and similar properties ofIOSequence
subclasses):>>> from hydpy.core.filetools import SequenceManager >>> temp = SequenceManager.inputdirpath >>> SequenceManager.inputdirpath = "global" >>> from hydpy import pub >>> pub.sequencemanager = SequenceManager() >>> from hydpy.core.sequencetools import InputSequence >>> sequence = InputSequence(None) >>> sequence.dirpath_ext 'global' >>> sequence.dirpath_ext = "local" >>> sequence.dirpath_ext 'local' >>> del sequence.dirpath_ext >>> sequence.dirpath_ext 'global' >>> SequenceManager.inputdirpath = temp
-
aggregation_ext
: ClassVar[_AggregationProperty]¶ Type of aggregation performed when writing the time-series data to an external data file.
Attribute aggregation_ext is connected with attribute inputaggregation of class
SequenceManager
, as shown by the following technical example (see the documentation on classIOSequence
for some explanations on the usage of this and similar properties ofIOSequence
subclasses):>>> from hydpy.core.filetools import SequenceManager >>> temp = SequenceManager.inputaggregation >>> SequenceManager.inputaggregation = "global" >>> from hydpy import pub >>> pub.sequencemanager = SequenceManager() >>> from hydpy.core.sequencetools import InputSequence >>> sequence = InputSequence(None) >>> sequence.aggregation_ext 'global' >>> sequence.aggregation_ext = "local" >>> sequence.aggregation_ext 'local' >>> del sequence.aggregation_ext >>> sequence.aggregation_ext 'global' >>> SequenceManager.inputaggregation = temp
-
overwrite_ext
: ClassVar[_OverwriteProperty]¶ True/False flag indicating if overwriting an existing data file is allowed or not.
Attribute overwrite_ext is connected with attribute inputoverwrite of class
SequenceManager
, as shown by the following technical example (see the documentation on classIOSequence
for some explanations on the usage of this and similar properties ofIOSequence
subclasses):>>> from hydpy.core.filetools import SequenceManager >>> temp = SequenceManager.inputoverwrite >>> SequenceManager.inputoverwrite = "global" >>> from hydpy import pub >>> pub.sequencemanager = SequenceManager() >>> from hydpy.core.sequencetools import InputSequence >>> sequence = InputSequence(None) >>> sequence.overwrite_ext 'global' >>> sequence.overwrite_ext = "local" >>> sequence.overwrite_ext 'local' >>> del sequence.overwrite_ext >>> sequence.overwrite_ext 'global' >>> SequenceManager.inputoverwrite = temp
-
set_pointer
(double: hydpy.cythons.autogen.pointerutils.Double) → None[source]¶ Prepare a pointer referencing the given
Double
object.Method
set_pointer()
should be of relevance for framework developers and eventually for some model developers only.
-
property
inputflag
¶ A flag telling if the actual
InputSequence
object queries its data from an input node (True
) or uses individually managed data, usually read from a data file (False
).See the main documentation on class
InputSequence
for further information.
-
subvars
: SubVariablesType¶
-
-
class
hydpy.core.sequencetools.
OutputSequence
(subvars: SubVariablesType)[source]¶ Bases:
hydpy.core.sequencetools.ModelIOSequence
[hydpy.core.sequencetools.OutputSequencesType
,hydpy.core.sequencetools.FastAccessOutputSequence
]Base class for
FluxSequence
andStateSequence
.OutputSequence
subclasses implement an optional output mechanism. Generally, as all instances ofModelSequence
subclasses, output sequences handle values calculated within a simulation time step. With an activatedoutputflag
, they also pass their internal values to an output node (see the documentation on classElement
), which makes them accessible to other models.This output mechanism (coupling
OutputSequence
objects with output nodes) is rather 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 settled things, we improve the following example and place it more prominently. In short, it shows that everything works well for the differentdeploymode
options:>>> from hydpy import Element, HydPy, Node, print_values, pub, Selection, TestIO >>> from hydpy.outputs import hland_Perc, hland_Q0, hland_Q1, hland_UZ >>> hp = HydPy("LahnH") >>> pub.timegrids = "1996-01-01", "1996-01-06", "1d" >>> node_q0 = Node("node_q0", variable=hland_Q0) >>> node_q1 = Node("node_q1", variable=hland_Q1) >>> node_perc = Node("node_perc", variable=hland_Perc) >>> node_uz = Node("node_uz", variable=hland_UZ) >>> node_q = Node("node_q") >>> land_dill = Element("land_dill", ... outlets=node_q, ... outputs=[node_q0, node_q1, node_perc, node_uz])
>>> from hydpy.examples import prepare_full_example_1 >>> prepare_full_example_1() >>> import os >>> with TestIO(): ... os.chdir("LahnH/control/default") ... with open("land_dill.py") as controlfile: ... exec(controlfile.read(), {}, locals()) ... parameters.update() ... land_dill.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) >>> 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_values(node_q0.sequences.sim.series) 1.0, 1.0, 1.0, 1.0, 1.0 >>> print_values(node_q0.sequences.obs.series) 2.0, 2.0, 2.0, 2.0, 2.0
>>> print_values(model.sequences.fluxes.q1.series) 0.530696, 0.539661, 0.548003, 0.555721, 0.562883 >>> print_values(node_q1.sequences.sim.series) 0.530696, 0.539661, 0.548003, 0.555721, 0.562883 >>> print_values(node_q1.sequences.obs.series) 3.0, 3.0, 3.0, 3.0, 3.0
>>> print_values(model.sequences.fluxes.perc.series) 0.692545, 0.689484, 0.687425, 0.684699, 0.682571 >>> print_values(node_perc.sequences.sim.series) 0.692545, 0.689484, 0.687425, 0.684699, 0.682571 >>> print_values(node_perc.sequences.obs.series) 4.0, 4.0, 4.0, 4.0, 4.0
>>> print_values(model.sequences.states.uz.series) 5.620222, 4.359519, 3.33013, 2.450124, 1.66734 >>> print_values(node_uz.sequences.sim.series) 5.620222, 4.359519, 3.33013, 2.450124, 1.66734 >>> print_values(node_uz.sequences.obs.series) 5.0, 5.0, 5.0, 5.0, 5.0
-
set_pointer
(double: hydpy.cythons.autogen.pointerutils.Double) → None[source]¶ Prepare a pointer referencing the given
Double
object.Method
set_pointer()
should be of relevance for framework developers and eventually for some model developers only.
-
property
outputflag
¶ A flag telling if the actual
OutputSequence
object passes its data to an output node (True
) or not (False
).See the main documentation on class
OutputSequence
for further information.
-
subvars
: SubVariablesType¶
-
filetype_ext
: ClassVar[_FileType]¶
-
dirpath_ext
: ClassVar[_DirPathProperty]¶
-
aggregation_ext
: ClassVar[_AggregationProperty]¶
-
overwrite_ext
: ClassVar[_OverwriteProperty]¶
-
-
class
hydpy.core.sequencetools.
FluxSequence
(subvars: SubVariablesType)[source]¶ Bases:
hydpy.core.sequencetools.OutputSequence
[hydpy.core.sequencetools.FluxSequences
]Base class for flux sequences of
Model
objects.-
filetype_ext
: ClassVar[_FileType]¶ Ending of the external data file.
Attribute filetype_ext is connected with attribute fluxfiletype of class
SequenceManager
, as shown by the following technical example (see the documentation on classIOSequence
for some explanations on the usage of this and similar properties ofIOSequence
subclasses):>>> from hydpy.core.filetools import SequenceManager >>> temp = SequenceManager.fluxfiletype >>> SequenceManager.fluxfiletype = "global" >>> from hydpy import pub >>> pub.sequencemanager = SequenceManager() >>> from hydpy.core.sequencetools import FluxSequence >>> sequence = FluxSequence(None) >>> sequence.filetype_ext 'global' >>> sequence.filetype_ext = "local" >>> sequence.filetype_ext 'local' >>> del sequence.filetype_ext >>> sequence.filetype_ext 'global' >>> SequenceManager.fluxfiletype = temp
-
dirpath_ext
: ClassVar[_DirPathProperty]¶ Absolute path of the directory of the external data file.
Attribute dirpath_ext is connected with attribute fluxdirpath of class
SequenceManager
, as shown by the following technical example (see the documentation on classIOSequence
for some explanations on the usage of this and similar properties ofIOSequence
subclasses):>>> from hydpy.core.filetools import SequenceManager >>> temp = SequenceManager.fluxdirpath >>> SequenceManager.fluxdirpath = "global" >>> from hydpy import pub >>> pub.sequencemanager = SequenceManager() >>> from hydpy.core.sequencetools import FluxSequence >>> sequence = FluxSequence(None) >>> sequence.dirpath_ext 'global' >>> sequence.dirpath_ext = "local" >>> sequence.dirpath_ext 'local' >>> del sequence.dirpath_ext >>> sequence.dirpath_ext 'global' >>> SequenceManager.fluxdirpath = temp
-
aggregation_ext
: ClassVar[_AggregationProperty]¶ Type of aggregation performed when writing the time-series data to an external data file.
Attribute aggregation_ext is connected with attribute fluxaggregation of class
SequenceManager
, as shown by the following technical example (see the documentation on classIOSequence
for some explanations on the usage of this and similar properties ofIOSequence
subclasses):>>> from hydpy.core.filetools import SequenceManager >>> temp = SequenceManager.fluxaggregation >>> SequenceManager.fluxaggregation = "global" >>> from hydpy import pub >>> pub.sequencemanager = SequenceManager() >>> from hydpy.core.sequencetools import FluxSequence >>> sequence = FluxSequence(None) >>> sequence.aggregation_ext 'global' >>> sequence.aggregation_ext = "local" >>> sequence.aggregation_ext 'local' >>> del sequence.aggregation_ext >>> sequence.aggregation_ext 'global' >>> SequenceManager.fluxaggregation = temp
-
overwrite_ext
: ClassVar[_OverwriteProperty]¶ True/False flag indicating if overwriting an existing data file is allowed or not.
Attribute overwrite_ext is connected with attribute fluxoverwrite of class
SequenceManager
, as shown by the following technical example (see the documentation on classIOSequence
for some explanations on the usage of this and similar properties ofIOSequence
subclasses):>>> from hydpy.core.filetools import SequenceManager >>> temp = SequenceManager.fluxoverwrite >>> SequenceManager.fluxoverwrite = "global" >>> from hydpy import pub >>> pub.sequencemanager = SequenceManager() >>> from hydpy.core.sequencetools import FluxSequence >>> sequence = FluxSequence(None) >>> sequence.overwrite_ext 'global' >>> sequence.overwrite_ext = "local" >>> sequence.overwrite_ext 'local' >>> del sequence.overwrite_ext >>> sequence.overwrite_ext 'global' >>> SequenceManager.fluxoverwrite = temp
-
property
shape
¶ A tuple containing the actual lengths of all dimensions.
FluxSequence
objects come with some additional fastaccess attributes, which should be of interest for framework developers only. However, model developers should note that we did implement only 0-dimensionalFluxSequence
subclasses with aTrue
NUMERIC flag so far. Hence, we still need to prove the complete functionality of our design of 1-dimensionalFluxSequence
subclasses with aTrue
NUMERIC flag.One example of a 0-dimensional sequence is the results array, handling the (intermediate or final) calculation results for flux sequence
Inflow
of thedam
model:>>> from hydpy import prepare_model, print_values, pub >>> model = prepare_model("dam_v001") >>> inflow = model.sequences.fluxes.inflow >>> print_values(inflow.fastaccess._inflow_results) 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0
We now show the still not thoroughly tested functionality of 1-dimensional numerical flux sequences by changing the dimensionality of class
Inflow
and working in pure Python mode. Now, the results attribute isNone
initially, as propertynumericshape
is unknown. However, setting theshape
attribute ofFluxSequence
objects prepares all “fastaccess attributes” automatically:>>> from hydpy.models.dam.dam_fluxes import Inflow >>> Inflow.NDIM = 1 >>> with pub.options.usecython(False): ... model = prepare_model("dam_v001") >>> inflow = model.sequences.fluxes.inflow >>> inflow.fastaccess._inflow_results
>>> inflow.shape = (2,) >>> inflow.shape (2,) >>> inflow.fastaccess._inflow_results.shape (11, 2)
>>> Inflow.NDIM = 0
-
subvars
: SubVariablesType¶
-
-
class
hydpy.core.sequencetools.
ConditionSequence
(subvars: SubVariablesType)[source]¶ Bases:
hydpy.core.sequencetools.ModelSequence
[hydpy.core.sequencetools.ModelSequencesType
,hydpy.core.variabletools.FastAccessType
]Base class for
StateSequence
andLogSequence
.Class
ConditionSequence
should not be subclassed by model developers directly. Inherit fromStateSequence
orLogSequence
instead.-
trim
(lower=None, upper=None)[source]¶ Apply
trim()
of modulevariabletools
.
-
reset
()[source]¶ Reset the value of the actual
StateSequence
orLogSequence
object to the last value defined by “calling” the object.We use the
lland_v2
application model, which handles sequences derived fromStateSequence
(takingInzp
as an example) and fromLogSequence
(takingWET0
as an example):>>> from hydpy import prepare_model, pub >>> model = prepare_model("lland_v2")
After defining their shapes, both sequences contain
nan
values:>>> inzp = model.sequences.states.inzp >>> inzp.shape = (2,) >>> inzp inzp(nan, nan) >>> wet0 = model.sequences.logs.wet0 >>> wet0.shape = 2 >>> wet0 wet0([[nan, nan]])
Before “calling” the sequences, method
reset()
does nothing:>>> inzp.values = 0.0 >>> inzp.reset() >>> inzp inzp(0.0, 0.0) >>> wet0.values = 0.0 >>> wet0.reset() >>> wet0 wet0([[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) >>> wet0(1.0, 2.0) >>> wet0.values = 3.0 >>> wet0 wet0([[3.0, 3.0]]) >>> wet0.reset() >>> wet0 wet0([[1.0, 2.0]])
-
-
class
hydpy.core.sequencetools.
StateSequence
(subvars: SubVariablesType)[source]¶ Bases:
hydpy.core.sequencetools.OutputSequence
[hydpy.core.sequencetools.StateSequences
],hydpy.core.sequencetools.ConditionSequence
[hydpy.core.sequencetools.StateSequences
,hydpy.core.sequencetools.FastAccessOutputSequence
]Base class for state sequences of
Model
objects.Each
StateSequence
object is capable in handling states at two different “time points”: at the beginning of a simulation step via propertyold
and the end of a simulation step via propertynew
. These properties are reflected by two different fastaccess attributes. fastaccess_new is an alias for the standard fastaccess attribute storing the customary information. fastaccess_old is an additional feature for storing the supplemental information.We demonstrate the above explanations using state sequence
SM
of base modelhland_v1
with a shape of two:>>> from hydpy import prepare_model >>> model = prepare_model("hland", "1d") >>> 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) >>> sm.values array([ nan, nan]) >>> sm.new array([ nan, nan]) >>> sm.old array([ 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) >>> sm.values array([ 1., 1.]) >>> sm.new array([ 1., 1.]) >>> sm.old array([ 1., 1.])
Alternatively, one can assign values to property
new
or propertyold
(note that usingnew
is identical with using thevalue
property):>>> sm.new = 2.0, 3.0 >>> sm sm(2.0, 3.0) >>> sm.values array([ 2., 3.]) >>> sm.new array([ 2., 3.]) >>> sm.old array([ 1., 1.])
>>> sm.old = 200.0 >>> sm sm(2.0, 3.0) >>> sm.values array([ 2., 3.]) >>> sm.new array([ 2., 3.]) >>> sm.old array([ 200., 200.])
Assigning problematic values to property
old
results in very similar error messages as assigning problematic values to propertyvalue
:>>> sm.old = 1.0, 2.0, 3.0 Traceback (most recent call last): ... ValueError: While trying to set the old value(s) of state sequence `sm`, the following error occurred: While trying to convert the value(s) `(1.0, 2.0, 3.0)` to a numpy ndarray with shape `(2,)` and type `float`, the following error occurred: could not broadcast input array from shape (3,) into shape (2,)
Just for completeness: Method
new2old()
effectively takes the new values as old ones, but more efficiently than using the propertiesnew
andold
, as it used during simulation runs (in fact, the Python methodnew2old()
is usually replaced by model-specific, cythonized version when working in Cython mode):>>> sm.new2old() >>> sm.values array([ 2., 3.]) >>> sm.new array([ 2., 3.]) >>> sm.old array([ 2., 3.])
-
filetype_ext
: ClassVar[_FileType]¶ Ending of the external data file.
Attribute filetype_ext is connected with attribute statefiletype of class
SequenceManager
, as shown by the following technical example (see the documentation on classIOSequence
for some explanations on the usage of this and similar properties ofIOSequence
subclasses):>>> from hydpy.core.filetools import SequenceManager >>> temp = SequenceManager.statefiletype >>> SequenceManager.statefiletype = "global" >>> from hydpy import pub >>> pub.sequencemanager = SequenceManager() >>> from hydpy.core.sequencetools import StateSequence >>> sequence = StateSequence(None) >>> sequence.filetype_ext 'global' >>> sequence.filetype_ext = "local" >>> sequence.filetype_ext 'local' >>> del sequence.filetype_ext >>> sequence.filetype_ext 'global' >>> SequenceManager.statefiletype = temp
-
dirpath_ext
: ClassVar[_DirPathProperty]¶ Absolute path of the directory of the external data file.
Attribute dirpath_ext is connected with attribute statedirpath of class
SequenceManager
, as shown by the following technical example (see the documentation on classIOSequence
for some explanations on the usage of this and similar properties ofIOSequence
subclasses):>>> from hydpy.core.filetools import SequenceManager >>> temp = SequenceManager.statedirpath >>> SequenceManager.statedirpath = "global" >>> from hydpy import pub >>> pub.sequencemanager = SequenceManager() >>> from hydpy.core.sequencetools import StateSequence >>> sequence = StateSequence(None) >>> sequence.dirpath_ext 'global' >>> sequence.dirpath_ext = "local" >>> sequence.dirpath_ext 'local' >>> del sequence.dirpath_ext >>> sequence.dirpath_ext 'global' >>> SequenceManager.statedirpath = temp
-
aggregation_ext
: ClassVar[_AggregationProperty]¶ Type of aggregation performed when writing the time-series data to an external data file.
Attribute aggregation_ext is connected with attribute stateaggregation of class
SequenceManager
, as shown by the following technical example (see the documentation on classIOSequence
for some explanations on the usage of this and similar properties ofIOSequence
subclasses):>>> from hydpy.core.filetools import SequenceManager >>> temp = SequenceManager.stateaggregation >>> SequenceManager.stateaggregation = "global" >>> from hydpy import pub >>> pub.sequencemanager = SequenceManager() >>> from hydpy.core.sequencetools import StateSequence >>> sequence = StateSequence(None) >>> sequence.aggregation_ext 'global' >>> sequence.aggregation_ext = "local" >>> sequence.aggregation_ext 'local' >>> del sequence.aggregation_ext >>> sequence.aggregation_ext 'global' >>> SequenceManager.stateaggregation = temp
-
overwrite_ext
: ClassVar[_OverwriteProperty]¶ True/False flag indicating if overwriting an existing data file is allowed or not.
Attribute overwrite_ext is connected with attribute stateoverwrite of class
SequenceManager
, as shown by the following technical example (see the documentation on classIOSequence
for some explanations on the usage of this and similar properties ofIOSequence
subclasses):>>> from hydpy.core.filetools import SequenceManager >>> temp = SequenceManager.stateoverwrite >>> SequenceManager.stateoverwrite = "global" >>> from hydpy import pub >>> pub.sequencemanager = SequenceManager() >>> from hydpy.core.sequencetools import StateSequence >>> sequence = StateSequence(None) >>> sequence.overwrite_ext 'global' >>> sequence.overwrite_ext = "local" >>> sequence.overwrite_ext 'local' >>> del sequence.overwrite_ext >>> sequence.overwrite_ext 'global' >>> SequenceManager.stateoverwrite = temp
-
property
shape
¶ A tuple containing the actual lengths of all dimensions.
StateSequence
objects come with some additional fastaccess attributes, which should be of interest for framework developers only. However, model developers should note that we did implement only 1-dimensionalStateSequence
subclasses with aTrue
NUMERIC flag so far. We still need to prove the complete functionality of our design of 1-dimensionalStateSequence
subclasses with aTrue
NUMERIC flag.One example of a 0-dimensional sequence is the results array, handling the (intermediate or final) calculation results for state sequence
WaterVolume
of thedam
model:>>> from hydpy import prepare_model, print_values, pub >>> model = prepare_model("dam_v001") >>> watervolume = model.sequences.states.watervolume >>> print_values(watervolume.fastaccess._watervolume_results) 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0
We now show the still not thoroughly tested functionality of 1-dimensional numerical state sequences by changing the dimensionality of class
WaterVolume
and working in pure Python mode. Now, the results attribute isNone
initially, as propertynumericshape
is unknown. However, setting theshape
attribute ofStateSequence
objects prepares all “fastaccess attributes” automatically:>>> from hydpy.models.dam.dam_states import WaterVolume >>> WaterVolume.NDIM = 1 >>> with pub.options.usecython(False): ... model = prepare_model("dam_v001") >>> watervolume = model.sequences.states.watervolume >>> watervolume.fastaccess._watervolume_results
>>> watervolume.shape = (2,) >>> watervolume.shape (2,) >>> watervolume.fastaccess._watervolume_results.shape (11, 2)
>>> WaterVolume.NDIM = 0
-
property
new
¶ State(s) after calling a
Model
calculation method. (Alias for propertyvalue
).Property
new
handles, in contrast to propertyold
, the newly calculated state values during each simulation step. It supports testing and debugging of individualModel
methods but istypically irrelevant when scripting HydPy workflows.
-
property
old
¶ State(s) before calling a
Model
calculation method.Note the similarity to property
new
. However, propertyold
references the initial states of the respective simulation step, which should not be changed byModel
calculation methods.
-
-
class
hydpy.core.sequencetools.
LogSequence
(subvars: SubVariablesType)[source]¶ Bases:
hydpy.core.sequencetools.ConditionSequence
[hydpy.core.sequencetools.LogSequences
,hydpy.core.variabletools.FastAccess
]Base class for logging sequences of
Model
objects.Class
LogSequence
serves similar purposes as classStateSequence
, but is less strict in its assumptions. WhileStateSequence
objects always handle two states (theold
and thenew
one),LogSequence
objects are supposed to remember an arbitrary or sequence-specific number of values, which can be state values but for example also flux values. A typical use case is to store “old” values of effective precipitation to calculate “new” values of direct discharge using the unit hydrograph concept in later simulation steps.It is up to the model developer to make sure that a
LogSequence
subclass has the right dimensionality and shape to store the required information. By convention, the “memory” of eachLogSequence
should be placed on the first axis for non-scalar properties.As
StateSequence
objects,LogSequence
objects store relevant information to start a new simulation run where another one has ended, and are thus written into and read from condition files.-
subvars
: SubVariablesType¶
-
-
class
hydpy.core.sequencetools.
AideSequence
(subvars: SubVariablesType)[source]¶ Bases:
hydpy.core.sequencetools.ModelSequence
[hydpy.core.sequencetools.AideSequences
,hydpy.core.variabletools.FastAccess
]Base class for aide sequences of
Model
objects.Aide sequences store data that is of importance only temporarily but must be shared by different calculation methods of a
Model
object.-
subvars
: SubVariablesType¶
-
-
class
hydpy.core.sequencetools.
LinkSequence
(subvars: SubVariablesType)[source]¶ Bases:
hydpy.core.sequencetools.ModelSequence
[hydpy.core.sequencetools.LinkSequencesType
,hydpy.core.sequencetools.FastAccessLinkSequence
]Base class for link sequences of
Model
objects.LinkSequence
objects do not handle values themselves. Instead, they point to the values handledNodeSequence
objects, using the functionalities provided by the Cython modulepointerutils
. MultipleLinkSequence
objects of different application models can query and modify the sameNodeSequence
values, allowing differentModel
objects to share information and interact with each other.A note for developers:
LinkSequence
subclasses must be either 0-dimensional or 1-dimensional.Users might encounter the following exception, which is a safety measure to — as the error message suggests — prevent from segmentation faults:
>>> from hydpy.core.sequencetools import LinkSequence >>> seq = LinkSequence(None) >>> seq linksequence(?) >>> seq.value Traceback (most recent call last): ... AttributeError: 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: hydpy.cythons.autogen.pointerutils.Double, idx: int = 0) → None[source]¶ Prepare a pointer referencing the given
Double
object.For 1-dimensional sequence objects, one also needs to specify the relevant index position of the pointer via argument idx.
Method
set_pointer()
should be of relevance for framework developers and eventually for some model developers only.
-
property
value
¶ The actual value(s) the
LinkSequence
object is pointing at.Changing a
value
of aLinkSequence
object seems very much like changing avalue
of any otherVariable
object. However, be aware that you are changing a value that is handled by aNodeSequence
object. We demonstrate this by using the LahnH example project through invoking functionprepare_full_example_2()
:>>> from hydpy.examples import prepare_full_example_2 >>> hp, pub, TestIO = prepare_full_example_2()
We focus on the
hstream_v1
application model stream_lahn_1_lahn_2 routing inflow from node lahn_1 to node lahn_2:>>> model = hp.elements.stream_lahn_1_lahn_2.model
The first example shows that the 0-dimensional outlet sequence
Q
points to theSim
sequence of node lahn_2:>>> model.sequences.outlets.q q(0.0) >>> hp.nodes.lahn_2.sequences.sim = 1.0 >>> model.sequences.outlets.q q(1.0) >>> model.sequences.outlets.q(2.0) >>> hp.nodes.lahn_2.sequences.sim sim(2.0)
The second example shows that the 1-dimensional inlet sequence
Q
points to theSim
sequence of node lahn_1:>>> model.sequences.inlets.q q(0.0) >>> hp.nodes.lahn_1.sequences.sim = 1.0 >>> model.sequences.inlets.q q(1.0) >>> model.sequences.inlets.q(2.0) >>> hp.nodes.lahn_1.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:
>>> model.sequences.outlets.q.value 2.0 >>> model.sequences.inlets.q.values array([ 2.])
Assigning bad data results in the standard 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_1_lahn_2`, the following error occurred: 2 values are assigned to the scalar variable `q` of element `stream_lahn_1_lahn_2`. >>> 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_1_lahn_2`, the following error occurred: While trying to convert the value(s) `(1.0, 2.0)` to a numpy ndarray with shape `(1,)` and type `float`, the following error occurred: could not broadcast input array from shape (2,) into shape (1,)
In the example above, the 1-dimensional inlet sequence
Q
points to the value of a singleNodeSequence
value only. We now prepare ahbranch_v1
application model instance to show what happens when connecting a 1-dimensionalLinkSequence
object (Branched
) with threeNodeSequence
objects (see the documentation of application modelhbranch_v1
for more details):>>> from hydpy import Element, Nodes, prepare_model >>> model = prepare_model("hbranch_v1") >>> nodes = Nodes("input1", "input2", "output1", "output2", "output3") >>> branch = Element("branch", ... inlets=["input1", "input2"], ... outlets=["output1", "output2", "output3"]) >>> model.parameters.control.xpoints( ... 0.0, 2.0, 4.0, 6.0) >>> model.parameters.control.ypoints( ... output1=[0.0, 1.0, 2.0, 3.0], ... output2=[0.0, 1.0, 0.0, 0.0], ... output3=[0.0, 0.0, 2.0, 6.0]) >>> branch.model = model
Our third example demonstrates that each field of the values of a 1-dimensional
LinkSequence
objects points to anotherNodeSequence
object:>>> nodes.output1.sequences.sim = 1.0 >>> nodes.output2.sequences.sim = 2.0 >>> nodes.output3.sequences.sim = 3.0 >>> model.sequences.outlets.branched branched(1.0, 2.0, 3.0) >>> model.sequences.outlets.branched = 4.0, 5.0, 6.0 >>> nodes.output1.sequences.sim sim(4.0) >>> nodes.output2.sequences.sim sim(5.0) >>> nodes.output3.sequences.sim sim(6.0)
-
property
shape
¶ A tuple containing the actual lengths of all dimensions.
Property
shape
of classLinkSequence
works similarly as the generalshape
property of classVariable
but you need to be extra careful due to the pointer mechanism underlying classLinkSequence
. Change the shape of a link sequence for good reasons only. Please read the documentation on propertyvalue
first and then see the following examples which are, again, based on the LahnH example project and application modelhstream_v1
:>>> from hydpy.examples import prepare_full_example_2 >>> hp, pub, TestIO = prepare_full_example_2() >>> model = hp.elements.stream_lahn_1_lahn_2.model
The default mechanisms of HydPy prepare both 0-dimensional and 1-dimensional link sequences with a proper shape (which, for inlet sequence
Q
, depends on the number of connectedNode
objects):>>> model.sequences.outlets.q.shape () >>> model.sequences.inlets.q.shape (1,)
Trying to set the only possible shape of 0-dimensional link sequences or to set 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_1_lahn_2`, the following error occurred: The shape information of 0-dimensional variables as `q` of element `stream_lahn_1_lahn_2` can only be `()`, but `(1,)` is given.
Changing the shape of 1-dimensional link sequences is supported but results in losing the connection to the
NodeSequence
values of the respective nodes. The following exception is raised to prevent 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_1_lahn_2`, 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_1_lahn_2`, 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 like the following:
>>> 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_1_lahn_2`, the following error occurred: 'Q' object has no attribute 'fastaccess'
-
-
class
hydpy.core.sequencetools.
InletSequence
(subvars: SubVariablesType)[source]¶ Bases:
hydpy.core.sequencetools.LinkSequence
[hydpy.core.sequencetools.InletSequences
]Base class for inlet link sequences of
Model
objects.-
subvars
: SubVariablesType¶
-
-
class
hydpy.core.sequencetools.
OutletSequence
(subvars: SubVariablesType)[source]¶ Bases:
hydpy.core.sequencetools.LinkSequence
[hydpy.core.sequencetools.OutletSequences
]Base class for outlet link sequences of
Model
objects.-
subvars
: SubVariablesType¶
-
-
class
hydpy.core.sequencetools.
ReceiverSequence
(subvars: SubVariablesType)[source]¶ Bases:
hydpy.core.sequencetools.LinkSequence
[hydpy.core.sequencetools.ReceiverSequences
]Base class for receiver link sequences of
Model
objects.-
subvars
: SubVariablesType¶
-
-
class
hydpy.core.sequencetools.
SenderSequence
(subvars: SubVariablesType)[source]¶ Bases:
hydpy.core.sequencetools.LinkSequence
[hydpy.core.sequencetools.SenderSequences
]Base class for sender link sequences of
Model
objects.-
subvars
: SubVariablesType¶
-
-
class
hydpy.core.sequencetools.
NodeSequence
(subvars: SubVariablesType)[source]¶ Bases:
hydpy.core.sequencetools.IOSequence
[NodeSequences
,hydpy.core.sequencetools.FastAccessNodeSequence
]Base class for all sequences to be handled by
Node
objects.-
filetype_ext
: ClassVar[_FileType]¶ Ending of the external data file.
Attribute filetype_ext is connected with attribute nodefiletype of class
SequenceManager
, as shown by the following technical example (see the documentation on classIOSequence
for some explanations on the usage of this and similar properties ofIOSequence
subclasses):>>> from hydpy.core.filetools import SequenceManager >>> temp = SequenceManager.nodefiletype >>> SequenceManager.nodefiletype = "global" >>> from hydpy import pub >>> pub.sequencemanager = SequenceManager() >>> from hydpy.core.sequencetools import NodeSequence >>> sequence = NodeSequence(None) >>> sequence.filetype_ext 'global' >>> sequence.filetype_ext = "local" >>> sequence.filetype_ext 'local' >>> del sequence.filetype_ext >>> sequence.filetype_ext 'global' >>> SequenceManager.nodefiletype = temp
-
dirpath_ext
: ClassVar[_DirPathProperty]¶ Absolute path of the directory of the external data file.
Attribute dirpath_ext is connected with attribute nodedirpath of class
SequenceManager
, as shown by the following technical example (see the documentation on classIOSequence
for some explanations on the usage of this and similar properties ofIOSequence
subclasses):>>> from hydpy.core.filetools import SequenceManager >>> temp = SequenceManager.nodedirpath >>> SequenceManager.nodedirpath = "global" >>> from hydpy import pub >>> pub.sequencemanager = SequenceManager() >>> from hydpy.core.sequencetools import NodeSequence >>> sequence = NodeSequence(None) >>> sequence.dirpath_ext 'global' >>> sequence.dirpath_ext = "local" >>> sequence.dirpath_ext 'local' >>> del sequence.dirpath_ext >>> sequence.dirpath_ext 'global' >>> SequenceManager.nodedirpath = temp
-
aggregation_ext
: ClassVar[_AggregationProperty]¶ Type of aggregation performed when writing the time-series data to an external data file.
Attribute aggregation_ext is connected with attribute nodeaggregation of class
SequenceManager
, as shown by the following technical example (see the documentation on classIOSequence
for some explanations on the usage of this and similar properties ofIOSequence
subclasses):>>> from hydpy.core.filetools import SequenceManager >>> temp = SequenceManager.nodeaggregation >>> SequenceManager.nodeaggregation = "global" >>> from hydpy import pub >>> pub.sequencemanager = SequenceManager() >>> from hydpy.core.sequencetools import NodeSequence >>> sequence = NodeSequence(None) >>> sequence.aggregation_ext 'global' >>> sequence.aggregation_ext = "local" >>> sequence.aggregation_ext 'local' >>> del sequence.aggregation_ext >>> sequence.aggregation_ext 'global' >>> SequenceManager.nodeaggregation = temp
-
overwrite_ext
: ClassVar[_OverwriteProperty]¶ True/False flag indicating if overwriting an existing data file is allowed or not.
Attribute overwrite_ext is connected with attribute nodeoverwrite of class
SequenceManager
, as shown by the following technical example (see the documentation on classIOSequence
for some explanations on the usage of this and similar properties ofIOSequence
subclasses):>>> from hydpy.core.filetools import SequenceManager >>> temp = SequenceManager.nodeoverwrite >>> SequenceManager.nodeoverwrite = "global" >>> from hydpy import pub >>> pub.sequencemanager = SequenceManager() >>> from hydpy.core.sequencetools import NodeSequence >>> sequence = NodeSequence(None) >>> sequence.overwrite_ext 'global' >>> sequence.overwrite_ext = "local" >>> sequence.overwrite_ext 'local' >>> del sequence.overwrite_ext >>> sequence.overwrite_ext 'global' >>> SequenceManager.nodeoverwrite = temp
-
property
descr_sequence
¶ Description of the
NodeSequence
object including thevariable
to be represented.>>> from hydpy import Node >>> Node("test_node_1", "T").sequences.sim.descr_sequence 'sim_t'
>>> from hydpy import FusedVariable >>> from hydpy.inputs import hland_T, lland_TemL >>> Temp = FusedVariable("Temp", hland_T, lland_TemL) >>> Node("test_node_2", Temp).sequences.sim.descr_sequence 'sim_temp'
-
property
descr_device
¶ Description of the
Node
object theNodeSequence
object belongs to.>>> from hydpy import Node >>> Node("test_node_2").sequences.sim.descr_device 'test_node_2'
-
property
value
¶ The actual sequence value.
For framework users, property
value
of classNodeSequence
works as usual and explained in the documentation on propertyshape
of classVariable
. However, framework developers should note thatNodeSequence
objects useDouble
objects for storing their values and making them accessible toPDouble
andPPDouble
objects as explained in detail in the documentation on classLinkSequence
. For safety reasons, this mechanism is hidden for framework users via conversions to typefloat
:>>> 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 in case they receive misspecified values or 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'
>>> del sim.fastaccess >>> sim.value Traceback (most recent call last): ... AttributeError: While trying to query the value of sequence `sim` of node `node`, the following error occurred: 'Sim' object has no attribute 'fastaccess'
-
property
seriescomplete
¶ True/False flag indicating whether simulated or observed data is fully available or not.
We use the observation series of node dill of the LahnH project as an example:
>>> from hydpy.examples import prepare_full_example_2 >>> hp, pub, TestIO = prepare_full_example_2() >>> obs = hp.nodes.dill.sequences.obs
When the sequence does not handle any time-series data,
seriescomplete
isFalse
:>>> obs.deactivate_ram() >>> obs.series Traceback (most recent call last): ... AttributeError: Sequence `obs` of node `dill` is not requested to make any internal data available. >>> obs.seriescomplete False
As long as any time-series data is missing,
seriescomplete
is stillFalse
:>>> obs.activate_ram() >>> obs.series[:-1] = 1.0 >>> obs.series InfoArray([ 1., 1., 1., nan]) >>> obs.seriescomplete False
Only with all data being not
nan
,seriescomplete
isTrue
:>>> obs.series[-1] = 1.0 >>> obs.seriescomplete True
-
-
class
hydpy.core.sequencetools.
Sim
(subvars: SubVariablesType)[source]¶ Bases:
hydpy.core.sequencetools.IOSequence
[NodeSequences
,hydpy.core.sequencetools.FastAccessNodeSequence
]Class for handling those values of
Node
objects that are “simulated”, meaning calculated by hydrological models.-
load_ext
() → None[source]¶ Read time-series data like method
load_ext()
of classIOSequence
but with special handling of missing data.The method’s “special handling” is to convert errors to warnings. We explain the reasons in the documentation on method
load_ext()
of classObs
, from which we borrow the following examples. The only differences are that methodload_ext()
of classSim
does not disable propertymemoryflag
and uses the optionwarnmissingsimfile
instead ofwarnmissingobsfile
:>>> from hydpy.examples import prepare_full_example_1 >>> prepare_full_example_1() >>> from hydpy import HydPy, pub, TestIO >>> hp = HydPy("LahnH") >>> pub.timegrids = "1996-01-01", "1996-01-06", "1d" >>> with TestIO(): ... hp.prepare_network() ... hp.prepare_models() ... hp.prepare_simseries() >>> sim = hp.nodes.dill.sequences.sim >>> with TestIO(): ... sim.load_ext() Traceback (most recent call last): ... UserWarning: While trying to load the external data of sequence `sim` of node `dill`, the following error occurred: [Errno 2] No such file or directory: '...dill_sim_q.asc' >>> sim.series InfoArray([ nan, nan, nan, nan, nan])
>>> sim.series = 1.0 >>> with TestIO(): ... sim.save_ext() >>> sim.series = 0.0 >>> with TestIO(): ... sim.load_ext() >>> sim.series InfoArray([ 1., 1., 1., 1., 1.])
>>> import numpy >>> sim.series[2] = numpy.nan >>> with TestIO(): ... pub.sequencemanager.nodeoverwrite = True ... sim.save_ext() >>> with TestIO(): ... sim.load_ext() Traceback (most recent call last): ... UserWarning: While trying to load the external data of sequence `sim` of node `dill`, the following error occurred: The series array of sequence `sim` of node `dill` contains 1 nan value. >>> sim.series InfoArray([ 1., 1., nan, 1., 1.])
>>> sim.series = 0.0 >>> with TestIO(): ... with pub.options.warnmissingsimfile(False): ... sim.load_ext() >>> sim.series InfoArray([ 1., 1., nan, 1., 1.])
-
subvars
: SubVariablesType¶
-
-
class
hydpy.core.sequencetools.
Obs
(subvars: SubVariablesType)[source]¶ Bases:
hydpy.core.sequencetools.IOSequence
[NodeSequences
,hydpy.core.sequencetools.FastAccessNodeSequence
]Class for handling those values of
Node
objects that are observed, meaning read from data files.-
load_ext
() → None[source]¶ Read time-series data like method
load_ext()
of classIOSequence
but with special handling of missing data.When reading incomplete time-series data, HydPy usually raises a
RuntimeError
to prevent from performing erroneous calculations. For instance, this makes sense for meteorological input data, being a strict requirement for hydrological simulations. However, the same often does not hold for the time-series ofObs
sequences, e.g. representing measured discharge. Measured discharge is often handled as an optional input value, or even used for comparison purposes only.According to this reasoning, HydPy raises (at most) a
UserWarning
in case of missing or incomplete external time-series data ofObs
sequences. The following examples show this based on the LahnH project, mainly focussing on theObs
sequence of node dill, which is ready for handling time-series data at the end of the following steps:>>> from hydpy.examples import prepare_full_example_1 >>> prepare_full_example_1() >>> from hydpy import HydPy, pub, TestIO >>> hp = HydPy("LahnH") >>> pub.timegrids = "1996-01-01", "1996-01-06", "1d" >>> with TestIO(): ... hp.prepare_network() ... hp.prepare_models() ... hp.prepare_obsseries() >>> obs = hp.nodes.dill.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:
>>> with TestIO(): ... hp.load_obsseries() Traceback (most recent call last): ... UserWarning: The `memory flag` of sequence `obs` of node `dill` had to be set to `False` due to the following problem: While trying to load the external data of sequence `obs` of node `dill`, the following error occurred: [Errno 2] No such file or directory: '...dill_obs_q.asc' >>> obs.ramflag False
After writing a complete external data file, everything works fine:
>>> obs.activate_ram() >>> obs.series = 1.0 >>> with TestIO(): ... obs.save_ext() >>> obs.series = 0.0 >>> with TestIO(): ... obs.load_ext() >>> 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.nodeoverwrite = True ... obs.save_ext() >>> with TestIO(): ... obs.load_ext() Traceback (most recent call last): ... UserWarning: While trying to load the external data of sequence `obs` of node `dill`, the following error occurred: The series array of sequence `obs` of node `dill` contains 1 nan value. >>> obs.memoryflag True
Option
warnmissingobsfile
allows disabling the warning messages without altering the functionalities described above:>>> hp.prepare_obsseries() >>> with TestIO(): ... with pub.options.warnmissingobsfile(False): ... hp.load_obsseries() >>> obs.series InfoArray([ 1., 1., nan, 1., 1.]) >>> hp.nodes.lahn_1.sequences.obs.memoryflag False
-
subvars
: SubVariablesType¶
-
-
class
hydpy.core.sequencetools.
NodeSequences
(master: devicetools.Node, cls_fastaccess: Optional[Type[hydpy.core.sequencetools.FastAccessNodeSequence]] = None, cymodel: Optional[hydpy.core.typingtools.CyModelProtocol] = None)[source]¶ Bases:
hydpy.core.sequencetools.IOSequences
[devicetools.Node
,hydpy.core.sequencetools.NodeSequence
,hydpy.core.sequencetools.FastAccessNodeSequence
]Base class for handling
Sim
andObs
sequence objects.Basically,
NodeSequences
works like the differentModelSequences
subclasses used for handlingModelSequence
objects. The main difference is that they do not reference aSequences
object (which is only handled byElement
objects but not byNode
objects). Instead, they reference their masterNode
object via the attribute node directly:>>> 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)]
-