Skip to content

Commit

Permalink
Update the code-style and documentation-style names of all models of …
Browse files Browse the repository at this point in the history
…the HydPy-Conv model family as defined in issue #99.
  • Loading branch information
tyralla committed Jun 20, 2024
1 parent 87296be commit b9ff2e3
Show file tree
Hide file tree
Showing 10 changed files with 105 additions and 100 deletions.
2 changes: 1 addition & 1 deletion hydpy/auxs/xmltools.py
Original file line number Diff line number Diff line change
Expand Up @@ -2784,7 +2784,7 @@ def get_mathitemsinsertion(cls, indent: int) -> str:
</complexContent>
</complexType>
<BLANKLINE>
<complexType name="conv_v001_mathitemType">
<complexType name="conv_idw_mathitemType">
...
"""
blanks = " " * (indent * 4)
Expand Down
11 changes: 5 additions & 6 deletions hydpy/core/devicetools.py
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ class FusedVariable:
connectable.
Using class |FusedVariable| is easiest to explain by a concrete example. Assume we
use |conv_v001| to interpolate the air temperature for a specific location. We use
use |conv_nn| to interpolate the air temperature for a specific location. We use
this temperature as input to an |meteo_temp_io| model, which passes it to an
|evap_ret_fao56| model, which requires this and other meteorological data to
calculate potential evapotranspiration. Further, we pass the estimated potential
Expand All @@ -279,7 +279,7 @@ class FusedVariable:
Additionally, |lland_dd| requires temperature data itself for modelling snow
processes, introducing the problem that we need to use the same data (the output of
|conv_v001|) as the input of two differently named input sequences
|conv_nn|) as the input of two differently named input sequences
(|meteo_inputs.Temperature| and |lland_inputs.TemL| for |meteo_temp_io| and
|lland_dd|, respectively).
Expand Down Expand Up @@ -318,11 +318,11 @@ class FusedVariable:
Now we can prepare the different model objects and assign them to their
corresponding elements (note that parameters |conv_control.InputCoordinates| and
|conv_control.OutputCoordinates| of |conv_v001| first require information on the
|conv_control.OutputCoordinates| of |conv_nn| first require information on the
location of the relevant nodes):
>>> from hydpy import prepare_model
>>> model_conv = prepare_model("conv_v001")
>>> model_conv = prepare_model("conv_nn")
>>> model_conv.parameters.control.inputcoordinates(t1=(0, 0))
>>> model_conv.parameters.control.outputcoordinates(t2=(1, 1))
>>> model_conv.parameters.control.maxnmbinputs(1)
Expand All @@ -340,8 +340,7 @@ class FusedVariable:
>>> t1.sequences.sim = -273.15
Model |conv_v001| can now perform a simulation step and pass its output to node
`t2`:
Model |conv_nn| can now perform a simulation step and pass its output to node `t2`:
>>> conv.model.simulate(0)
>>> t2.sequences.sim
Expand Down
2 changes: 1 addition & 1 deletion hydpy/core/sequencetools.py
Original file line number Diff line number Diff line change
Expand Up @@ -2833,7 +2833,7 @@ class InputSequence(ModelIOSequence):
read from a file) or data shared with an input node (usually calculated by another
model). This flexibility allows, for example, to let application model |hland_v1|
read already preprocessed precipitation time series or to couple it with
application models like |conv_v001|, which interpolates precipitation during the
application models like |conv_nn|, which interpolates precipitation during the
simulation run.
The second mechanism (coupling |InputSequence| objects with input nodes) is
Expand Down
40 changes: 19 additions & 21 deletions hydpy/core/testtools.py
Original file line number Diff line number Diff line change
Expand Up @@ -1526,38 +1526,36 @@ def update_integrationtests(
applicationmodel: Union[types.ModuleType, str],
resultfilepath: str = "update_integrationtests.txt",
) -> None:
"""Write the docstring of the given application model, updated with
the current simulation results, to file.
Sometimes, even tiny model-related changes bring a great deal of work
concerning *HydPy's* integration test strategy. For example, if you
modify the value of a fixed parameter, the results of possibly dozens
of integration tests of your application model might become wrong.
In such situations, function |update_integrationtests| helps you in
replacing all integration tests results at once. Therefore, it
calculates the new results, updates the old module docstring and
writes it. You only need to copy-paste the printed result into the
affected module. But be aware that function |update_integrationtests|
cannot guarantee the correctness of the new results. Whenever in doubt
if the new results are really correct under all possible conditions,
you should inspect and replace each integration test result manually.
"""Write the docstring of the given application model, updated with the current
simulation results, to file.
Sometimes, even tiny model-related changes bring a great deal of work concerning
*HydPy's* integration test strategy. For example, if you modify the value of a
fixed parameter, the results of possibly dozens of integration tests of your
application model might become wrong. In such situations, function
|update_integrationtests| helps you in replacing all integration tests results at
once. Therefore, it calculates the new results, updates the old module docstring
and writes it. You only need to copy-paste the printed result into the affected
module. But be aware that function |update_integrationtests| cannot guarantee the
correctness of the new results. Whenever in doubt if the new results are really
correct under all possible conditions, you should inspect and replace each
integration test result manually.
In the following example, we disable method |conv_model.Pass_Outputs_V1|
temporarily. Accordingly, application model |conv_v001| does not pass
any output to its outlet nodes, which is why the last four columns of
both integration test tables now contain zero value only (we can perform
this mocking-based test in Python-mode only):
temporarily. Accordingly, application model |conv_nn| does not pass any output to
its outlet nodes, which is why the last four columns of both integration test
tables now contain zero value only (we can perform this mocking-based test in
Python-mode only):
>>> from hydpy import pub, TestIO, update_integrationtests
>>> from unittest import mock
>>> pass_output = "hydpy.models.conv.conv_model.Pass_Outputs_V1.__call__"
>>> with TestIO(), pub.options.usecython(False), mock.patch(pass_output):
... update_integrationtests("conv_v001", "temp.txt")
... update_integrationtests("conv_nn", "temp.txt")
... with open("temp.txt") as resultfile:
... print(resultfile.read()) # doctest: +ELLIPSIS
Number of replacements: 2
<BLANKLINE>
Nearest-neighbour interpolation.
... test()
| date | inputs | outputs | in1 | in2 | out1 \
| out2 | out3 | out4 |
Expand Down
22 changes: 8 additions & 14 deletions hydpy/docs/rst/HydPy-Conv.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,20 @@
HydPy-Conv
==========

`HydPy-Conv` models are no real hydrological models. Instead, they serve as converters
HydPy-Conv models are no real hydrological models. Instead, they serve as converters
that allow connecting different kinds of models providing output and requiring input
that does not fit immediately. The most typical use case is interpolating data, which
is implemented by the application model |conv_v001| using the nearest-neighbour, by
application model |conv_v002| using the inverse distance weighted approach, and by
application model |conv_v003| combining inverse distance weighting with linear
is implemented by the application model |conv_nn| using the nearest-neighbour, by
application model |conv_idw| using the inverse distance weighted approach, and by
application model |conv_idw_ed| combining inverse distance weighting with linear
regression.

Base model:
Available models:

.. toctree::
:maxdepth: 1

conv

Application model:

.. toctree::
:maxdepth: 1

conv_v001
conv_v002
conv_v003
conv_nn
conv_idw
conv_idw_ed
4 changes: 2 additions & 2 deletions hydpy/models/conv/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
"""The HydPy-Conv model family allows connecting different kinds of models providing
output and requiring input that does not fit immediately.
"""The |conv.DOCNAME.complete| model family allows connecting different kinds of models
providing output and requiring input that does not fit immediately.
"""
# import...
# ...from HydPy
Expand Down
12 changes: 7 additions & 5 deletions hydpy/models/conv/conv_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -564,7 +564,9 @@ def __call__(model: modeltools.Model) -> None:


class Model(modeltools.AdHocModel):
"""The HydPy-Conv model."""
"""|conv.DOCNAME.complete|."""

DOCNAME = modeltools.DocName(short="Conv")

INLET_METHODS = (Pick_Inputs_V1,)
RECEIVER_METHODS = ()
Expand All @@ -586,7 +588,7 @@ class Model(modeltools.AdHocModel):


class BaseModel(modeltools.AdHocModel):
"""Base class for all HydPy-Conv application models."""
"""Base class for all |conv.DOCNAME.complete| application models."""

def connect(self):
"""Connect the |InletSequence| and |OutletSequence| objects of the actual model
Expand All @@ -606,7 +608,7 @@ def connect(self):
the names of the |Node| objects as keyword arguments to pass the corresponding
coordinates:
>>> from hydpy.models.conv_v001 import *
>>> from hydpy.models.conv_nn import *
>>> parameterstep()
>>> inputcoordinates(
... in1=(0.0, 3.0),
Expand Down Expand Up @@ -645,8 +647,8 @@ def connect(self):
>>> conv.model = model
Traceback (most recent call last):
...
RuntimeError: While trying to connect model `conv_v001` of element `conv`, \
the following error occurred: The node handled by control parameter outputcoordinates \
RuntimeError: While trying to connect model `conv_nn` of element `conv`, the \
following error occurred: The node handled by control parameter outputcoordinates \
(out1 and out2) are not the same as the outlet nodes handled by element conv (out1, \
out2, and out3).
"""
Expand Down
30 changes: 17 additions & 13 deletions hydpy/models/conv_v002.py → hydpy/models/conv_idw.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
# -*- coding: utf-8 -*-
# pylint: disable=line-too-long, unused-wildcard-import
"""Inverse distance weighted interpolation.
Version 2 of HydPy-Conv performs simple inverse distance weighted interpolations
between an arbitrary number of models (or data files) providing output and an arbitrary
number of models requiring input.
"""
|conv_idw| performs simple inverse distance weighted interpolations between an
arbitrary number of models (or data files) providing output and an arbitrary number of
models requiring input.
Integration tests
=================
Expand All @@ -16,14 +15,14 @@
>>> from hydpy import Element, Node, pub
>>> pub.timegrids = "2000-01-01", "2000-01-04", "1d"
|conv_v002| implements no parameter with values depending on the simulation step size,
|conv_idw| implements no parameter with values depending on the simulation step size,
which is why we can pass anything (or nothing) to function |parameterstep| without
changing the following results:
>>> from hydpy.models.conv_v002 import *
>>> from hydpy.models.conv_idw import *
>>> parameterstep()
Due to the following configuration, |conv_v002| queries its input from the inlet nodes
Due to the following configuration, |conv_idw| queries its input from the inlet nodes
`in1`, `in2`, and `in3` and passes the interpolation results to the outlet nodes
`out1`, `out2`, `out3`, and `out4`:
Expand Down Expand Up @@ -54,10 +53,10 @@
>>> maxnmbinputs(3)
|conv_v002| does not implement any state or log sequences and thus has no memory at
all, making finalising the test setup quite easy. We only need to define time series
for both inlet nodes. Note that we set some |numpy| |numpy.nan| values to demonstrate
how |conv_v002| deals with missing values:
|conv_idw| does not implement any state or log sequences and thus has no memory at all,
making finalising the test setup quite easy. We only need to define time series for
both inlet nodes. Note that we set some |numpy| |numpy.nan| values to demonstrate how
|conv_idw| deals with missing values:
>>> element.model = model
>>> from hydpy.core.testtools import IntegrationTest
Expand Down Expand Up @@ -95,12 +94,17 @@
"""
# import...
# ...from HydPy
from hydpy.core import modeltools
from hydpy.exe.modelimports import *
from hydpy.models.conv import conv_model


class Model(conv_model.BaseModel):
"""Version 2 of the HydPy-Conv model."""
"""|conv_idw.DOCNAME.complete|."""

DOCNAME = modeltools.DocName(
short="Conv-IDW", description="inverse distance weighted interpolation"
)

INLET_METHODS = (conv_model.Pick_Inputs_V1,)
RECEIVER_METHODS = ()
Expand Down
50 changes: 27 additions & 23 deletions hydpy/models/conv_v003.py → hydpy/models/conv_idw_ed.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
# -*- coding: utf-8 -*-
# pylint: disable=line-too-long, unused-wildcard-import
"""Inverse distance weighted interpolation with external drift.
Version 3 of HydPy-Conv extends version 2 by taking an additional statistical
relationship between the interpolated variable and an arbitrary independent variable
into account. A typical use case is elevation-dependent temperature interpolation.
You can understand the approach of |conv_v003| as a simplification of External Drift
Kriging.
"""
|conv_idw_ed| extends |conv_idw| by taking an additional statistical relationship
between the interpolated variable and an arbitrary independent variable into account.
A typical use case is elevation-dependent temperature interpolation. You can
understand the approach of |conv_idw_ed| as a simplification of External Drift Kriging.
The algorithm works as follows (we take elevation-dependent temperature interpolation
as an example):
Expand All @@ -19,7 +17,7 @@
* Calculate the residuals (differences between predictions and measurements) at all
stations.
* Interpolate the residuals based on the same inverse distance weighting approach as
applied by application model |conv_v002|.
applied by application model |conv_idw|.
* Combine the predicted temperature values and the interpolated residuals to gain the
final interpolation results at all target points.
Expand All @@ -33,14 +31,14 @@
.. how_to_understand_integration_tests::
We start the following explanations with repeating the examples documented for
application model |conv_v002|. Hence, we first define identical test settings (please
see the documentation on application model |conv_v002| for more information):
application model |conv_idw|. Hence, we first define identical test settings (please
see the documentation on application model |conv_idw| for more information):
>>> from hydpy import Element, Node, pub
>>> pub.timegrids = "2000-01-01", "2000-01-04", "1d"
>>> from hydpy.models.conv_v003 import *
>>> from hydpy.models.conv_idw_ed import *
>>> parameterstep()
>>> in1, in2, in3 = Node("in1"), Node("in2"), Node("in3")
Expand All @@ -67,8 +65,8 @@
... in2.sequences.sim.series = 3.0, 2.0, nan
... in3.sequences.sim.series = 4.0, nan, nan
Next, we prepare the additional parameters of |conv_v003|. Most importantly, we define
the values of the independent variable for all input and output nodes:
Next, we prepare the additional parameters of |conv_idw_ed|. Most importantly, we
define the values of the independent variable for all input and output nodes:
>>> inputheights(in1=0.0,
... in2=2.0,
Expand All @@ -80,16 +78,16 @@
In our example calculations, we use three input nodes. However, we first set the
number of data-points that must be available to estimate the linear model to four,
which of course is impossible. Hence, |conv_v003| will always use the default values.
We set both of them to zero and thus effectively disable the "external drift"
functionality so that |conv_v003| works exactly like |conv_v002|:
which of course is impossible. Hence, |conv_idw_ed| will always use the default
values. We set both of them to zero and thus effectively disable the "external drift"
functionality so that |conv_idw_ed| works exactly like |conv_idw|:
>>> minnmbinputs(4)
>>> defaultconstant(0.0)
>>> defaultfactor(0.0)
Under the given configuration, |conv_v003| reproduces the results of the test examples
documented for application model |conv_v002| precisely:
Under the given configuration, |conv_idw_ed| reproduces the results of the test
examples documented for application model |conv_idw| precisely:
>>> test()
| date | inputs | actualconstant | actualfactor | inputpredictions | outputpredictions | inputresiduals | outputresiduals | outputs | in1 | in2 | in3 | out1 | out2 | out3 | out4 |
Expand All @@ -107,7 +105,7 @@
| 2000-01-03 | nan nan nan | 0.0 | 0.0 | 0.0 0.0 0.0 | 0.0 0.0 0.0 0.0 | nan nan nan | nan nan nan nan | nan nan nan nan | nan | nan | nan | nan | nan | nan | nan |
Now we enable the "external drift" functionality by providing non-zero default values.
Hence, |conv_v003| employs the same linear model in all simulation time steps:
Hence, |conv_idw_ed| employs the same linear model in all simulation time steps:
>>> maxnmbinputs(3)
>>> defaultfactor(1.0)
Expand All @@ -120,7 +118,7 @@
| 2000-01-03 | nan nan nan | 2.0 | 1.0 | 2.0 4.0 6.0 | 2.0 3.0 4.0 5.0 | nan nan nan | nan nan nan nan | nan nan nan nan | nan | nan | nan | nan | nan | nan | nan |
If we set the required number of data-points to three (two would also be fine),
|conv_v003| estimates the parameters of the linear model (|ActualFactor| and
|conv_idw_ed| estimates the parameters of the linear model (|ActualFactor| and
|ActualConstant|) in the first time step on its own, and falls back to the default
values in the remaining time steps:
Expand All @@ -137,8 +135,8 @@
correlation at the input nodes. Hence, all residuals (calculated for the input nodes
and interpolated for the output nodes) are zero. In the second time step, there is no
correlation. Hence, all values predicted by the linear model are the same. The third
time step shows that |conv_v003| handles the special (but not uncommon) case of missing
variability in the input values well:
time step shows that |conv_idw_ed| handles the special (but not uncommon) case of
missing variability in the input values well:
>>> in1.sequences.sim.series = 4.0, 0.0, 0.0
>>> in2.sequences.sim.series = 3.0, 1.0, 0.0
Expand All @@ -152,12 +150,18 @@
"""
# import...
# ...from HydPy
from hydpy.core import modeltools
from hydpy.exe.modelimports import *
from hydpy.models.conv import conv_model


class Model(conv_model.BaseModel):
"""Version 3 of the HydPy-Conv model."""
"""|conv_idw_ed.DOCNAME.complete|."""

DOCNAME = modeltools.DocName(
short="Conv-IDW-ED",
description="inverse distance weighted interpolation with external drift",
)

INLET_METHODS = (conv_model.Pick_Inputs_V1,)
RECEIVER_METHODS = ()
Expand Down
Loading

0 comments on commit b9ff2e3

Please sign in to comment.