def nodes(self): """A |Nodes| collection of all required nodes. >>> from hydpy import RiverBasinNumbers2Selection >>> rbns2s = RiverBasinNumbers2Selection( ... (111, 113, 1129, 11269, 1125, 11261, ... 11262, 1123, 1124, 1122, 1121)) Note that the required outlet node is added: >>> rbns2s.nodes Nodes("node_1123", "node_1125", "node_11269", "node_1129", "node_113", "node_outlet") It is both possible to change the prefix names of the nodes and the name of the outlet node separately: >>> rbns2s.node_prefix = 'b_' >>> rbns2s.last_node = 'l_node' >>> rbns2s.nodes Nodes("b_1123", "b_1125", "b_11269", "b_1129", "b_113", "l_node") """ return (devicetools.Nodes(self.node_prefix + routers for routers in self._router_numbers) + devicetools.Node(self.last_node))
def __call__(self, *args, **kwargs) -> None: nodes = [] coordinates = numpy.empty((len(kwargs), 2), dtype=float) for idx, (name, values) in enumerate(kwargs.items()): nodes.append(devicetools.Node(name)) coordinates[idx, :] = values self.nodes = tuple(nodes) self.__hydpy__set_shape__((len(nodes), 2)) self.__hydpy__set_value__(coordinates)
def __call__(self, *args, **kwargs) -> None: nodes = [] heights = numpy.empty(len(kwargs), dtype=float) for idx, (name, value) in enumerate(kwargs.items()): nodes.append(devicetools.Node(name)) heights[idx] = value self.nodes = tuple(nodes) self.__hydpy__set_shape__(len(nodes)) self.__hydpy__set_value__(heights)
def nodes(self) -> devicetools.Nodes: """A |Nodes| object containing all required nodes, including the outlet node. >>> from hydpy import RiverBasinNumbers2Selection >>> rbns2s = RiverBasinNumbers2Selection( ... (111, 113, 1129, 11269, 1125, 11261, ... 11262, 1123, 1124, 1122, 1121)) >>> rbns2s.nodes Nodes("node_1123", "node_1125", "node_11269", "node_1129", "node_113", "node_outlet") It is both possible to change the prefix names of the nodes and the name of the outlet node separately: >>> rbns2s.node_prefix = "b_" >>> rbns2s.last_node = "l_node" >>> rbns2s.nodes Nodes("b_1123", "b_1125", "b_11269", "b_1129", "b_113", "l_node") """ return devicetools.Nodes( self.node_prefix + routers for routers in self._router_numbers) + devicetools.Node( self.last_node)
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
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