Ejemplo n.º 1
0
 def _get_model(value):
     if isinstance(value, str):
         try:
             value = importlib.import_module('hydpy.models.' + value)
         except BaseException:
             objecttools.augment_excmessage(
                 'While trying to import a model named `%s`' % value)
     if isinstance(value, types.ModuleType):
         try:
             value = importtools.prepare_model(value)
         except BaseException:
             objecttools.augment_excmessage(
                 'While trying to prepare the model defined in'
                 'module `hydpy.models.%s`' % objecttools.modulename(value))
     return value
Ejemplo n.º 2
0
 def _get_models(values):
     for value in objecttools.extract(
             values, (str, types.ModuleType, modeltools.Model)):
         yield importtools.prepare_model(value)
Ejemplo n.º 3
0
def prepare_io_example_1() -> Tuple[devicetools.Nodes, devicetools.Elements]:
    """Prepare an IO example configuration for testing purposes.

    Function |prepare_io_example_1| is thought for testing the functioning
    of *HydPy* and thus should be of interest for framework developers only.
    It uses the application models |lland_v1| and |lland_v2|.  Here, we
    apply |prepare_io_example_1| and shortly discuss different aspects of
    the data it generates.

    >>> from hydpy.examples import prepare_io_example_1
    >>> nodes, elements = prepare_io_example_1()

    (1) It defines a short initialisation period of five days:

    >>> from hydpy import pub
    >>> pub.timegrids
    Timegrids("2000-01-01 00:00:00",
              "2000-01-05 00:00:00",
              "1d")

    (2) It creates a flat IO testing directory structure:

    >>> pub.sequencemanager.inputdirpath
    'inputpath'
    >>> pub.sequencemanager.fluxdirpath
    'outputpath'
    >>> pub.sequencemanager.statedirpath
    'outputpath'
    >>> pub.sequencemanager.nodedirpath
    'nodepath'
    >>> import os
    >>> from hydpy import TestIO
    >>> with TestIO():
    ...     print(sorted(filename for filename in os.listdir(".")
    ...                  if not filename.startswith("_")))
    ['inputpath', 'nodepath', 'outputpath']

    (3) It returns three |Element| objects handling either application model
    |lland_v1| or |lland_v2|, and two |Node| objects handling variables
    `Q` and `T`:

    >>> for element in elements:
    ...     print(element.name, element.model)
    element1 lland_v1
    element2 lland_v1
    element3 lland_v2
    >>> for node in nodes:
    ...     print(node.name, node.variable)
    node1 Q
    node2 T

    (4) It generates artificial time series data of the input sequence
    |lland_inputs.Nied|, the flux sequence |lland_fluxes.NKor|, and the
    state sequence |lland_states.BoWa| of each model instance, and the
    |Sim| sequence of each node instance.  For unambiguous test results,
    all generated values are unique:

    >>> nied1 = elements.element1.model.sequences.inputs.nied
    >>> nied1.series
    InfoArray([ 0.,  1.,  2.,  3.])
    >>> nkor1 = elements.element1.model.sequences.fluxes.nkor
    >>> nkor1.series
    InfoArray([[ 12.],
               [ 13.],
               [ 14.],
               [ 15.]])
    >>> bowa3 = elements.element3.model.sequences.states.bowa
    >>> bowa3.series
    InfoArray([[ 48.,  49.,  50.],
               [ 51.,  52.,  53.],
               [ 54.,  55.,  56.],
               [ 57.,  58.,  59.]])
    >>> sim2 = nodes.node2.sequences.sim
    >>> sim2.series
    InfoArray([ 64.,  65.,  66.,  67.])

    (5) All sequences carry |numpy.ndarray| objects with (deep) copies
    of the time series data for testing:

    >>> import numpy
    >>> (numpy.all(nied1.series == nied1.testarray) and
    ...  numpy.all(nkor1.series == nkor1.testarray) and
    ...  numpy.all(bowa3.series == bowa3.testarray) and
    ...  numpy.all(sim2.series == sim2.testarray))
    InfoArray(True, dtype=bool)
    >>> bowa3.series[1, 2] = -999.0
    >>> numpy.all(bowa3.series == bowa3.testarray)
    InfoArray(False, dtype=bool)
    """
    testtools.TestIO.clear()
    hydpy.pub.sequencemanager = filetools.SequenceManager()
    with testtools.TestIO():
        hydpy.pub.sequencemanager.inputdirpath = "inputpath"
        hydpy.pub.sequencemanager.fluxdirpath = "outputpath"
        hydpy.pub.sequencemanager.statedirpath = "outputpath"
        hydpy.pub.sequencemanager.nodedirpath = "nodepath"

    hydpy.pub.timegrids = "2000-01-01", "2000-01-05", "1d"

    node1 = devicetools.Node("node1")
    node2 = devicetools.Node("node2", variable="T")
    nodes = devicetools.Nodes(node1, node2)
    element1 = devicetools.Element("element1", outlets=node1)
    element2 = devicetools.Element("element2", outlets=node1)
    element3 = devicetools.Element("element3", outlets=node1)
    elements = devicetools.Elements(element1, element2, element3)

    element1.model = importtools.prepare_model("lland_v1")
    element2.model = importtools.prepare_model("lland_v1")
    element3.model = importtools.prepare_model("lland_v2")

    for idx, element in enumerate(elements):
        parameters = element.model.parameters
        parameters.control.nhru(idx + 1)
        parameters.control.lnk(lland.ACKER)
        parameters.derived.absfhru(10.0)

    # pylint: disable=not-callable
    # pylint usually understands that all options are callable
    # but, for unknown reasons, not in the following line:
    with hydpy.pub.options.printprogress(False):
        nodes.prepare_simseries()
        elements.prepare_inputseries()
        elements.prepare_fluxseries()
        elements.prepare_stateseries()
    # pylint: enable=not-callable

    def init_values(seq, value1_):
        value2_ = value1_ + len(seq.series.flatten())
        values_ = numpy.arange(value1_, value2_, dtype=float)
        seq.testarray = values_.reshape(seq.seriesshape)
        seq.series = seq.testarray.copy()
        return value2_

    value1 = 0
    for subname, seqname in zip(["inputs", "fluxes", "states"],
                                ["nied", "nkor", "bowa"]):
        for element in elements:
            subseqs = getattr(element.model.sequences, subname)
            value1 = init_values(getattr(subseqs, seqname), value1)
    for node in nodes:
        value1 = init_values(node.sequences.sim, value1)

    return nodes, elements
Ejemplo n.º 4
0
def prepare_io_example_1() -> Tuple[devicetools.Nodes, devicetools.Elements]:
    """Prepare an IO example configuration for testing purposes.

    Function |prepare_io_example_1| is thought for testing the functioning of *HydPy*
    and thus should be of interest for framework developers only.  It uses the
    application models |lland_v1|, |lland_v2|, and |hland_v1|.  Here, we apply
    |prepare_io_example_1| and shortly discuss different aspects of its generated data.

    >>> from hydpy.examples import prepare_io_example_1
    >>> nodes, elements = prepare_io_example_1()

    (1) It defines a short initialisation period of five days:

    >>> from hydpy import pub
    >>> pub.timegrids
    Timegrids("2000-01-01 00:00:00",
              "2000-01-05 00:00:00",
              "1d")

    (2) It prepares an empty directory for IO testing:

    >>> import os
    >>> from hydpy import repr_, TestIO
    >>> with TestIO():  # doctest: +ELLIPSIS
    ...     repr_(pub.sequencemanager.currentpath)
    ...     os.listdir("project/series/default")
    '...iotesting/project/series/default'
    []

    (3) It returns four |Element| objects handling either application model |lland_v1|
    |lland_v2|, or |hland_v1|, and two |Node| objects handling variables `Q` and `T`:

    >>> for element in elements:
    ...     print(element.name, element.model)
    element1 lland_v1
    element2 lland_v1
    element3 lland_v2
    element4 hland_v1
    >>> for node in nodes:
    ...     print(node.name, node.variable)
    node1 Q
    node2 T

    (4) It generates artificial time series data for the input sequence
    |lland_inputs.Nied|, the flux sequence |lland_fluxes.NKor|, and the state sequence
    |lland_states.BoWa| of each |lland| model instance, the state sequence
    |hland_states.SP| of the |hland_v1| model instance, and the |Sim| sequence of each
    node instance.  For precise test results, all generated values are unique:

    >>> nied1 = elements.element1.model.sequences.inputs.nied
    >>> nied1.series
    InfoArray([0., 1., 2., 3.])
    >>> nkor1 = elements.element1.model.sequences.fluxes.nkor
    >>> nkor1.series
    InfoArray([[12.],
               [13.],
               [14.],
               [15.]])
    >>> bowa3 = elements.element3.model.sequences.states.bowa
    >>> bowa3.series
    InfoArray([[48., 49., 50.],
               [51., 52., 53.],
               [54., 55., 56.],
               [57., 58., 59.]])
    >>> sim2 = nodes.node2.sequences.sim
    >>> sim2.series
    InfoArray([64., 65., 66., 67.])
    >>> sp4 = elements.element4.model.sequences.states.sp
    >>> sp4.series
    InfoArray([[[68., 69., 70.],
                [71., 72., 73.]],
    <BLANKLINE>
               [[74., 75., 76.],
                [77., 78., 79.]],
    <BLANKLINE>
               [[80., 81., 82.],
                [83., 84., 85.]],
    <BLANKLINE>
               [[86., 87., 88.],
                [89., 90., 91.]]])

    (5) All sequences carry |numpy.ndarray| objects with (deep) copies of the
    time-series data for testing:

    >>> import numpy
    >>> (numpy.all(nied1.series == nied1.testarray) and
    ...  numpy.all(nkor1.series == nkor1.testarray) and
    ...  numpy.all(bowa3.series == bowa3.testarray) and
    ...  numpy.all(sim2.series == sim2.testarray) and
    ...  numpy.all(sp4.series == sp4.testarray))
    InfoArray(True)
    >>> bowa3.series[1, 2] = -999.0
    >>> numpy.all(bowa3.series == bowa3.testarray)
    InfoArray(False)
    """
    testtools.TestIO.clear()

    hydpy.pub.projectname = "project"
    hydpy.pub.sequencemanager = filetools.SequenceManager()
    with testtools.TestIO():
        os.makedirs("project/series/default")

    hydpy.pub.timegrids = "2000-01-01", "2000-01-05", "1d"

    node1 = devicetools.Node("node1")
    node2 = devicetools.Node("node2", variable="T")
    nodes = devicetools.Nodes(node1, node2)
    element1 = devicetools.Element("element1", outlets=node1)
    element2 = devicetools.Element("element2", outlets=node1)
    element3 = devicetools.Element("element3", outlets=node1)
    element4 = devicetools.Element("element4", outlets=node1)
    elements_lland = devicetools.Elements(element1, element2, element3)
    elements = elements_lland + element4

    element1.model = importtools.prepare_model("lland_v1")
    element2.model = importtools.prepare_model("lland_v1")
    element3.model = importtools.prepare_model("lland_v2")
    element4.model = importtools.prepare_model("hland_v1")

    for idx, element in enumerate(elements_lland):
        parameters = element.model.parameters
        parameters.control.nhru(idx + 1)
        parameters.control.lnk(lland.ACKER)
        parameters.derived.absfhru(10.0)
    control = element4.model.parameters.control
    control.nmbzones(3)
    control.sclass(2)
    control.zonetype(hland.FIELD)
    control.zonearea.values = 10.0

    # pylint: disable=not-callable
    # pylint usually understands that all options are callable
    # but, for unknown reasons, not in the following line:
    with hydpy.pub.options.printprogress(False):
        nodes.prepare_simseries(allocate_ram=False)  # ToDo: add option "reset"
        nodes.prepare_simseries(allocate_ram=True)
        elements.prepare_inputseries(allocate_ram=False)
        elements.prepare_inputseries(allocate_ram=True)
        elements.prepare_factorseries(allocate_ram=False)
        elements.prepare_factorseries(allocate_ram=True)
        elements.prepare_fluxseries(allocate_ram=False)
        elements.prepare_fluxseries(allocate_ram=True)
        elements.prepare_stateseries(allocate_ram=False)
        elements.prepare_stateseries(allocate_ram=True)
    # pylint: enable=not-callable

    def init_values(seq: TestIOSequence, value1_: float) -> float:
        value2_ = value1_ + len(seq.series.flatten())
        values_ = numpy.arange(value1_, value2_, dtype=float)
        seq.testarray = values_.reshape(seq.seriesshape)
        seq.series = seq.testarray.copy()
        return value2_

    value1 = 0.0
    for subname, seqname in zip(["inputs", "fluxes", "states"],
                                ["nied", "nkor", "bowa"]):
        for element in elements_lland:
            subseqs = getattr(element.model.sequences, subname)
            value1 = init_values(getattr(subseqs, seqname), value1)
    for node in nodes:
        value1 = init_values(node.sequences.sim,
                             value1)  # type: ignore[arg-type]
    init_values(element4.model.sequences.states.sp,
                value1)  # type: ignore[arg-type]

    return nodes, elements
Ejemplo n.º 5
0
 def _get_model(
     value: Union[str, types.ModuleType, modeltools.Model],
 ) -> modeltools.Model:
     if isinstance(value, modeltools.Model):
         return value
     return importtools.prepare_model(value)
Ejemplo n.º 6
0
    def search_modeltypes(self,
                          *models: ModelTypesArg,
                          name: str = 'modeltypes') -> 'Selection':
        """Return a |Selection| object containing only the elements
        currently handling models of the given types.

        >>> from hydpy.examples import prepare_full_example_2
        >>> hp, pub, _ = prepare_full_example_2()

        You can pass both |Model| objects and names and, as a keyword
        argument, the name of the newly created |Selection| object:

        >>> test = pub.selections.complete.copy('test')
        >>> from hydpy import prepare_model
        >>> hland_v1 = prepare_model('hland_v1')

        >>> test.search_modeltypes(hland_v1)
        Selection("modeltypes",
                  nodes=(),
                  elements=("land_dill", "land_lahn_1", "land_lahn_2",
                            "land_lahn_3"))
        >>> test.search_modeltypes(
        ...     hland_v1, 'hstream_v1', 'lland_v1', name='MODELTYPES')
        Selection("MODELTYPES",
                  nodes=(),
                  elements=("land_dill", "land_lahn_1", "land_lahn_2",
                            "land_lahn_3", "stream_dill_lahn_2",
                            "stream_lahn_1_lahn_2", "stream_lahn_2_lahn_3"))

        Wrong model specifications result in errors like the following:

        >>> test.search_modeltypes('wrong')
        Traceback (most recent call last):
        ...
        ModuleNotFoundError: While trying to determine the elements of \
selection `test` handling the model defined by the argument(s) `wrong` \
of type(s) `str`, the following error occurred: \
No module named 'hydpy.models.wrong'

        Method |Selection.select_modeltypes| restricts the current selection to
        the one determined with the method the |Selection.search_modeltypes|:

        >>> test.select_modeltypes(hland_v1)
        Selection("test",
                  nodes=(),
                  elements=("land_dill", "land_lahn_1", "land_lahn_2",
                            "land_lahn_3"))

        On the contrary, the method |Selection.deselect_upstream| restricts
        the current selection to all devices not determined by method the
        |Selection.search_upstream|:

        >>> pub.selections.complete.deselect_modeltypes(hland_v1)
        Selection("complete",
                  nodes=(),
                  elements=("stream_dill_lahn_2", "stream_lahn_1_lahn_2",
                            "stream_lahn_2_lahn_3"))
        """
        try:
            typelist = []
            for model in models:
                if not isinstance(model, modeltools.Model):
                    model = importtools.prepare_model(model)
                typelist.append(type(model))
            typetuple = tuple(typelist)
            selection = Selection(name)
            for element in self.elements:
                if isinstance(element.model, typetuple):
                    selection.elements += element
            return selection
        except BaseException:
            values = objecttools.enumeration(models)
            classes = objecttools.enumeration(
                objecttools.classname(model) for model in models)
            objecttools.augment_excmessage(
                f'While trying to determine the elements of selection '
                f'`{self.name}` handling the model defined by the '
                f'argument(s) `{values}` of type(s) `{classes}`')