itemtools¶
This module implements so-called exchange items, simplifying the
modification of the values of Parameter
and Sequence_
objects.
Module itemtools
implements the following members:
ExchangeSpecification
Specification of a specificParameter
orSequence_
type.
ExchangeItem
Base class for exchanging values with multipleParameter
orSequence_
objects of a certain type.
ChangeItem
Base class for changing the values of multipleParameter
orSequence_
objects of a specific type.
SetItem
Item for assigningvalue
to multipleParameter
orSequence_
objects of a specific type.
MathItem
Base class for performing some mathematical operations on the given values before assigning them to the handled target variables.
GetItem
Base class for querying the values of multipleParameter
orSequence_
objects of a specific type.
-
class
hydpy.core.itemtools.
ExchangeSpecification
(master: str, variable: str)[source]¶ Bases:
object
Specification of a specific
Parameter
orSequence_
type.ExchangeSpecification
is a helper class forExchangeItem
and its subclasses. Its constructor interprets two strings (without any checks on plausibility) and makes their information available as attributes. The following tests list the expected cases:>>> from hydpy.core.itemtools import ExchangeSpecification >>> ExchangeSpecification("hland_v1", "fluxes.qt") ExchangeSpecification("hland_v1", "fluxes.qt") >>> ExchangeSpecification("hland_v1", "fluxes.qt.series") ExchangeSpecification("hland_v1", "fluxes.qt.series") >>> ExchangeSpecification("node", "sim") ExchangeSpecification("node", "sim") >>> ExchangeSpecification("node", "sim.series") ExchangeSpecification("node", "sim.series")
The following attributes are accessible:
>>> spec = ExchangeSpecification("hland_v1", "fluxes.qt") >>> spec ExchangeSpecification("hland_v1", "fluxes.qt") >>> spec.master 'hland_v1' >>> spec.subgroup 'fluxes' >>> spec.variable 'qt' >>> spec.series False
-
property
specstring
¶ The string corresponding to the current values of subgroup, state, and variable.
>>> from hydpy.core.itemtools import ExchangeSpecification >>> spec = ExchangeSpecification("hland_v1", "fluxes.qt") >>> spec.specstring 'fluxes.qt' >>> spec.series = True >>> spec.specstring 'fluxes.qt.series' >>> spec.subgroup = None >>> spec.specstring 'qt.series'
-
property
-
class
hydpy.core.itemtools.
ExchangeItem
[source]¶ Bases:
object
Base class for exchanging values with multiple
Parameter
orSequence_
objects of a certain type.-
targetspecs
: hydpy.core.itemtools.ExchangeSpecification¶
-
device2target
: Dict[Union[hydpy.core.devicetools.Node, hydpy.core.devicetools.Element], hydpy.core.variabletools.Variable[Any, Any]]¶
-
collect_variables
(selections: hydpy.core.selectiontools.Selections) → None[source]¶ Apply method
insert_variables()
to collect the relevant target variables handled by the devices of the givenSelections
object.We prepare the LahnH example project to be able to use its
Selections
object:>>> from hydpy.examples import prepare_full_example_2 >>> hp, pub, TestIO = prepare_full_example_2()
We change the type of a specific application model to the type of its base model for reasons explained later:
>>> from hydpy.models.hland import Model >>> hp.elements.land_lahn_3.model.__class__ = Model
We prepare a
SetItem
as an example, handling allIc
sequences corresponding to any application models derived fromhland
:>>> from hydpy import SetItem >>> item = SetItem("ic", "hland", "states.ic", 0) >>> item.targetspecs ExchangeSpecification("hland", "states.ic")
Applying method
collect_variables()
connects theSetItem
object with all four relevantIc
objects:>>> item.collect_variables(pub.selections) >>> land_dill = hp.elements.land_dill >>> sequence = land_dill.model.sequences.states.ic >>> item.device2target[land_dill] is sequence True >>> for element in sorted(item.device2target, key=lambda x: x.name): ... print(element) land_dill land_lahn_1 land_lahn_2 land_lahn_3
Asking for
Ic
objects corresponding to application modelhland_v1
only, results in skipping theElement
land_lahn_3 (handling thehland
base model due to the hack above):>>> item = SetItem("ic", "hland_v1", "states.ic", 0) >>> item.collect_variables(pub.selections) >>> for element in sorted(item.device2target, key=lambda x: x.name): ... print(element) land_dill land_lahn_1 land_lahn_2
Selecting a series of a variable instead of the variable itself only affects the targetspec attribute:
>>> item = SetItem("t", "hland_v1", "inputs.t.series", 0) >>> item.collect_variables(pub.selections) >>> item.targetspecs ExchangeSpecification("hland_v1", "inputs.t.series") >>> sequence = land_dill.model.sequences.inputs.t >>> item.device2target[land_dill] is sequence True
To pass an ill-defined subgroup name results in the following error:
>>> from hydpy import SetItem >>> item = SetItem("ic", "hland", "wrong_group.wrong_variable", 0) >>> item.collect_variables(pub.selections) Traceback (most recent call last): ... RuntimeError: Model `hland_v1` of element `land_dill` does neither handle a parameter of sequence subgroup named `wrong_group.
It is both possible to address sequences of
Node
objects, as well as their time series, by arguments “node” and “nodes”:>>> item = SetItem("sim", "node", "sim", 0) >>> item.collect_variables(pub.selections) >>> dill = hp.nodes.dill >>> item.targetspecs ExchangeSpecification("node", "sim") >>> item.device2target[dill] is dill.sequences.sim True >>> for node in sorted(item.device2target, key=lambda x: x.name): ... print(node) dill lahn_1 lahn_2 lahn_3 >>> item = SetItem("sim", "nodes", "sim.series", 0) >>> item.collect_variables(pub.selections) >>> item.targetspecs ExchangeSpecification("nodes", "sim.series") >>> for node in sorted(item.device2target, key=lambda x: x.name): ... print(node) dill lahn_1 lahn_2 lahn_3
-
insert_variables
(device2variable: Dict[Union[hydpy.core.devicetools.Node, hydpy.core.devicetools.Element], hydpy.core.variabletools.Variable[Any, Any]], exchangespec: hydpy.core.itemtools.ExchangeSpecification, selections: hydpy.core.selectiontools.Selections) → None[source]¶ Determine the relevant target or base variables (as defined by the given
ExchangeSpecification
object) handled by the givenSelections
object and insert them into the given device2variable dictionary.
-
-
class
hydpy.core.itemtools.
ChangeItem
[source]¶ Bases:
hydpy.core.itemtools.ExchangeItem
Base class for changing the values of multiple
Parameter
orSequence_
objects of a specific type.-
device2target
: Dict[Union[hydpy.core.devicetools.Node, hydpy.core.devicetools.Element], hydpy.core.variabletools.Variable[Any, Any]]¶
-
property
shape
¶ The shape of the target variables.
Trying to access property
shape
before calling methodcollect_variables()
results in the following error:>>> from hydpy import SetItem >>> SetItem("name", "master", "target", 0).shape Traceback (most recent call last): ... RuntimeError: The shape of SetItem `name` has not been determined so far.
See method
collect_variables()
for further information.
-
property
value
¶ The value(s) that can be used to change the values of target variables through applying method
update_variables()
of classChangeItem
.>>> from hydpy.examples import prepare_full_example_2 >>> hp, pub, TestIO = prepare_full_example_2() >>> from hydpy import SetItem >>> item = SetItem("ic", "hland", "states.ic", 0) >>> item.collect_variables(pub.selections) >>> item.value = 1 >>> item.value array(1.0) >>> item.value = 1, 2 Traceback (most recent call last): ... ValueError: When trying to convert the value(s) `(1, 2)` assigned to SetItem `ic` to a numpy array of shape `()` and type `float`, the following error occurred: could not broadcast input array from shape (2,) into shape ()
-
update_variables
() → None[source]¶ Subclasses must define a mathematical operation for updating the values of target variables.
>>> from hydpy.core.itemtools import ChangeItem >>> ChangeItem().update_variables() Traceback (most recent call last): ... NotImplementedError
-
collect_variables
(selections: hydpy.core.selectiontools.Selections) → None[source]¶ Apply method
collect_variables()
of the base classExchangeItem
and determine theshape
of the currentChangeItem
object afterwards, depending on its dimensionality and eventually on the shape of its target variables.For the following examples, we prepare the LahnH example project:
>>> from hydpy.examples import prepare_full_example_2 >>> hp, pub, TestIO = prepare_full_example_2()
0-dimensional change-items do not have a variable shape, which is indicated by an empty tuple:
>>> from hydpy import SetItem >>> item = SetItem("ic", "hland", "states.ic", 0) >>> item.collect_variables(pub.selections) >>> item.shape ()
1-dimensional change-items take the shape of their target variables, which must be equal for all instances:
>>> item = SetItem("ic", "hland", "states.ic", 1) >>> item.collect_variables(pub.selections) Traceback (most recent call last): ... RuntimeError: SetItem `ic` cannot handle target variables of different shapes.
>>> for element in hp.elements.catchment: ... element.model.parameters.control.nmbzones(3) >>> item = SetItem("ic", "hland", "states.ic", 1) >>> item.collect_variables(pub.selections) >>> item.shape (3,)
Passing a
Selections
object not containing any relevant target variables results in the following error:>>> item = SetItem("ic", "hland", "states.ic", 1) >>> from hydpy import Selections >>> item.collect_variables(Selections()) Traceback (most recent call last): ... RuntimeError: Cannot determine the shape of the actual `SetItem` object, as the given `Selections` object does not handle any relevant target variables.
-
update_variable
(variable: hydpy.core.variabletools.Variable[Any, Any], value: numpy.ndarray) → None[source]¶ Assign the given value(s) to the given target or base variable.
If the assignment fails,
update_variable()
raises an error like the following:>>> from hydpy.examples import prepare_full_example_2 >>> hp, pub, TestIO = prepare_full_example_2() >>> item = SetItem("alpha", "hland_v1", "control.alpha", 0) >>> item.collect_variables(pub.selections) >>> item.update_variables() Traceback (most recent call last): ... TypeError: When trying to update a target variable of SetItem `alpha` with the value(s) `None`, the following error occurred: While trying to set the value(s) of variable `alpha` of element `...`, the following error occurred: The given value `None` cannot be converted to type `float`.
-
-
class
hydpy.core.itemtools.
SetItem
(name: str, master: str, target: str, ndim: int)[source]¶ Bases:
hydpy.core.itemtools.ChangeItem
Item for assigning
value
to multipleParameter
orSequence_
objects of a specific type.-
targetspecs
: hydpy.core.itemtools.ExchangeSpecification¶
-
device2target
: Dict[Union[hydpy.core.devicetools.Node, hydpy.core.devicetools.Element], hydpy.core.variabletools.Variable[Any, Any]]¶
-
update_variables
() → None[source]¶ Assign the current objects
value
to the values of the target variables.We use the LahnH project in the following:
>>> from hydpy.examples import prepare_full_example_2 >>> hp, pub, TestIO = prepare_full_example_2()
In the first example, a 0-dimensional
SetItem
changes the value of the 0-dimensional parameterAlpha
:>>> from hydpy.core.itemtools import SetItem >>> item = SetItem("alpha", "hland_v1", "control.alpha", 0) >>> item SetItem("alpha", "hland_v1", "control.alpha", 0) >>> item.collect_variables(pub.selections) >>> item.value is None True >>> land_dill = hp.elements.land_dill >>> land_dill.model.parameters.control.alpha alpha(1.0) >>> item.value = 2.0 >>> item.value array(2.0) >>> land_dill.model.parameters.control.alpha alpha(1.0) >>> item.update_variables() >>> land_dill.model.parameters.control.alpha alpha(2.0)
In the second example, a 0-dimensional
SetItem
changes the values of the 1-dimensional parameterFC
:>>> item = SetItem("fc", "hland_v1", "control.fc", 0) >>> item.collect_variables(pub.selections) >>> item.value = 200.0 >>> land_dill.model.parameters.control.fc fc(278.0) >>> item.update_variables() >>> land_dill.model.parameters.control.fc fc(200.0)
In the third example, a 1-dimensional
SetItem
changes the values of the 1-dimensional sequenceIc
:>>> for element in hp.elements.catchment: ... element.model.parameters.control.nmbzones(5) ... element.model.parameters.control.icmax(4.0) >>> item = SetItem("ic", "hland_v1", "states.ic", 1) >>> item.collect_variables(pub.selections) >>> land_dill.model.sequences.states.ic ic(nan, nan, nan, nan, nan) >>> item.value = 2.0 >>> item.update_variables() >>> land_dill.model.sequences.states.ic ic(2.0, 2.0, 2.0, 2.0, 2.0) >>> item.value = 1.0, 2.0, 3.0, 4.0, 5.0 >>> item.update_variables() >>> land_dill.model.sequences.states.ic ic(1.0, 2.0, 3.0, 4.0, 4.0)
-
-
class
hydpy.core.itemtools.
MathItem
(name: str, master: str, target: str, base: str, ndim: int)[source]¶ Bases:
hydpy.core.itemtools.ChangeItem
Base class for performing some mathematical operations on the given values before assigning them to the handled target variables.
Subclasses of
MathItem
likeAddItem
handle not only target variables but also base variables:>>> from hydpy import AddItem >>> item = AddItem( ... "sfcf", "hland_v1", "control.sfcf", "control.rfcf", 0) >>> item AddItem("sfcf", "hland_v1", "control.sfcf", "control.rfcf", 0) >>> item.targetspecs ExchangeSpecification("hland_v1", "control.sfcf") >>> item.basespecs ExchangeSpecification("hland_v1", "control.rfcf")
Generally, a
MathItem
calculates the target variable of a specificDevice
object by using its currentvalue
and the value(s) of the base variable of the sameDevice
.-
basespecs
: hydpy.core.itemtools.ExchangeSpecification¶
-
device2base
: Dict[Union[hydpy.core.devicetools.Node, hydpy.core.devicetools.Element], hydpy.core.variabletools.Variable[Any, Any]]¶
-
collect_variables
(selections: hydpy.core.selectiontools.Selections) → None[source]¶ Apply method
collect_variables()
of the base classChangeItem
and also apply methodinsert_variables()
of classExchangeItem
to collect the relevant base variables handled by the devices of the givenSelections
object.>>> from hydpy.examples import prepare_full_example_2 >>> hp, pub, TestIO = prepare_full_example_2() >>> from hydpy import AddItem >>> item = AddItem("alpha", "hland_v1", "control.sfcf", "control.rfcf", 0) >>> item.collect_variables(pub.selections) >>> land_dill = hp.elements.land_dill >>> control = land_dill.model.parameters.control >>> item.device2target[land_dill] is control.sfcf True >>> item.device2base[land_dill] is control.rfcf True >>> for device in sorted(item.device2base, key=lambda x: x.name): ... print(device) land_dill land_lahn_1 land_lahn_2 land_lahn_3
-
-
class
hydpy.core.itemtools.
AddItem
(name: str, master: str, target: str, base: str, ndim: int)[source]¶ Bases:
hydpy.core.itemtools.MathItem
MathItem
subclass performing additions.-
update_variables
() → None[source]¶ Add the general
value
with theDevice
specific base variable and assign the result to the respective target variable.>>> from hydpy.examples import prepare_full_example_2 >>> hp, pub, TestIO = prepare_full_example_2() >>> from hydpy.models.hland_v1 import FIELD >>> for element in hp.elements.catchment: ... control = element.model.parameters.control ... control.nmbzones(3) ... control.zonetype(FIELD) ... control.rfcf(1.1) >>> from hydpy.core.itemtools import AddItem >>> item = AddItem( ... "sfcf", "hland_v1", "control.sfcf", "control.rfcf", 1) >>> item.collect_variables(pub.selections) >>> land_dill = hp.elements.land_dill >>> land_dill.model.parameters.control.sfcf sfcf(?) >>> item.value = -0.1, 0.0, 0.1 >>> item.update_variables() >>> land_dill.model.parameters.control.sfcf sfcf(1.0, 1.1, 1.2)
>>> land_dill.model.parameters.control.rfcf.shape = 2 >>> land_dill.model.parameters.control.rfcf = 1.1 >>> item.update_variables() Traceback (most recent call last): ... ValueError: When trying to add the value(s) `[-0.1 0. 0.1]` of AddItem `sfcf` and the value(s) `[ 1.1 1.1]` of variable `rfcf` of element `land_dill`, the following error occurred: operands could not be broadcast together with shapes (2,) (3,)...
-
basespecs
: hydpy.core.itemtools.ExchangeSpecification¶
-
device2base
: Dict[Union[hydpy.core.devicetools.Node, hydpy.core.devicetools.Element], hydpy.core.variabletools.Variable[Any, Any]]¶
-
device2target
: Dict[Union[hydpy.core.devicetools.Node, hydpy.core.devicetools.Element], hydpy.core.variabletools.Variable[Any, Any]]¶
-
targetspecs
: hydpy.core.itemtools.ExchangeSpecification¶
-
-
class
hydpy.core.itemtools.
GetItem
(master: str, target: str)[source]¶ Bases:
hydpy.core.itemtools.ExchangeItem
Base class for querying the values of multiple
Parameter
orSequence_
objects of a specific type.-
collect_variables
(selections: hydpy.core.selectiontools.Selections) → None[source]¶ Apply method
collect_variables()
of the base classExchangeItem
and determine the ndim attribute of the currentChangeItem
object afterwards.The value of ndim depends on whether the values of the target variable or its time series are of interest:
>>> from hydpy.examples import prepare_full_example_2 >>> hp, pub, TestIO = prepare_full_example_2() >>> from hydpy.core.itemtools import SetItem >>> for target in ("states.lz", "states.lz.series", ... "states.sm", "states.sm.series"): ... item = GetItem("hland_v1", target) ... item.collect_variables(pub.selections) ... print(item, item.ndim) GetItem("hland_v1", "states.lz") 0 GetItem("hland_v1", "states.lz.series") 1 GetItem("hland_v1", "states.sm") 1 GetItem("hland_v1", "states.sm.series") 2
-
yield_name2value
(idx1: Optional[int] = None, idx2: Optional[int] = None) → Iterator[Tuple[str, str]][source]¶ Sequentially return name-value-pairs describing the current state of the target variables.
The names are automatically generated and contain both the name of the
Device
of the respectiveVariable
object and the target description:>>> from hydpy.examples import prepare_full_example_2 >>> hp, pub, TestIO = prepare_full_example_2() >>> from hydpy.core.itemtools import SetItem >>> item = GetItem("hland_v1", "states.lz") >>> item.collect_variables(pub.selections) >>> hp.elements.land_dill.model.sequences.states.lz = 100.0 >>> for name, value in item.yield_name2value(): ... print(name, value) land_dill_states_lz 100.0 land_lahn_1_states_lz 8.18711 land_lahn_2_states_lz 10.14007 land_lahn_3_states_lz 7.52648 >>> item = GetItem("hland_v1", "states.sm") >>> item.collect_variables(pub.selections) >>> hp.elements.land_dill.model.sequences.states.sm = 2.0 >>> for name, value in item.yield_name2value(): ... print(name, value) land_dill_states_sm [2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0] land_lahn_1_states_sm [99.27505, ..., 142.84148] ...
When querying time series, one can restrict the span of interest by passing index values:
>>> item = GetItem("nodes", "sim.series") >>> item.collect_variables(pub.selections) >>> hp.nodes.dill.sequences.sim.series = 1.0, 2.0, 3.0, 4.0 >>> for name, value in item.yield_name2value(): ... print(name, value) dill_sim_series [1.0, 2.0, 3.0, 4.0] lahn_1_sim_series [nan, ... ... >>> for name, value in item.yield_name2value(2, 3): ... print(name, value) dill_sim_series [3.0] lahn_1_sim_series [nan] ...
-