Beispiel #1
0
    def read2dict(cls, filename, info):
        """Read the control parameters from the given path (and its
        auxiliary paths, where appropriate) and store them in the given
        |dict| object `info`.

        Note that the |dict| `info` can be used to feed information
        into the execution of control files.  Use this method only if you
        are completely sure on how the control parameter import of HydPy
        works.  Otherwise, you should most probably prefer to use
        |ControlManager.load_file|.
        """
        if not filename.endswith('.py'):
            filename += '.py'
        path = os.path.join(cls._workingpath, filename)
        try:
            if path not in cls._registry:
                with open(path) as file_:
                    cls._registry[path] = file_.read()
            exec(cls._registry[path], {}, info)
        except BaseException:
            objecttools.augment_excmessage(
                'While trying to load the control file `%s`' % path)
        if 'model' not in info:
            raise IOError(
                'Model parameters cannot be loaded from control file `%s`.  '
                'Please refer to the HydPy documentation on how to prepare '
                'control files properly.' % path)
Beispiel #2
0
 def load_files(self):
     """Load nodes and elements from all network files and return them in
     a |Selections| instance.  Each single network file defines a separate
     |Selection| instance.  Additionally, all |Element| and |Node| objects
     are bundled in a selection named `complete`.
     """
     selections = selectiontools.Selections()
     for (filename, path) in zip(self.filenames, self.filepaths):
         # Ensure both `Node` and `Element`start with a `fresh` memory.
         devicetools.Node.gather_new_nodes()
         devicetools.Element.gather_new_elements()
         try:
             info = runpy.run_path(path)
         except BaseException:
             objecttools.augment_excmessage(
                 'While trying to load the network file `%s`' % path)
         try:
             selections += selectiontools.Selection(
                 filename.split('.')[0], info['Node'].gather_new_nodes(),
                 info['Element'].gather_new_elements())
         except KeyError as exc:
             raise KeyError(
                 'The class `%s` cannot be loaded from the network '
                 'file `%s`.  Please refer to the HydPy documentation '
                 'on how to prepare network files properly.' %
                 (exc.args[0], filename))
     selections += selectiontools.Selection(
         'complete', info['Node'].registered_nodes(),
         info['Element'].registered_elements())
     return selections
Beispiel #3
0
 def _apply_method(self, method) -> None:
     try:
         method()
     except BaseException:
         self._statuscode = 500
         objecttools.augment_excmessage(
             f'While trying to execute method `{method.__name__}`')
Beispiel #4
0
 def _convertandtest(self, values, name):
     """Try to convert the given values to a |numpy| |numpy.ndarray| and
     check if it is plausible.  If so, return the array, other raise
     a |ValueError| or re-raise a |numpy| specific exception.
     """
     try:
         array = numpy.array(values, dtype=int)
     except BaseException:
         objecttools.augment_excmessage(
             'While trying to assign a new `%s` '
             'index array to an Indexer object'
             % name)
     if array.ndim != 1:
         raise ValueError(
             'The `%s` index array of an Indexer object must be '
             '1-dimensional.  However, the given value has interpreted '
             'as a %d-dimensional object.'
             % (name, array.ndim))
     if pub.timegrids is not None:
         if len(array) != len(pub.timegrids.init):
             raise ValueError(
                 'The %s` index array of an Indexer object must have a '
                 'number of entries fitting to the initialization time '
                 'period precisely.  However, the given value has been '
                 'interpreted to be of length %d and the length of the '
                 'Timegrid object representing the actual initialization '
                 'time period is %d.'
                 % (name, len(array), len(pub.timegrids.init)))
     return array
Beispiel #5
0
 def _convertandtest(values, name):
     try:
         type_ = float if isinstance(values[0], float) else int
         array = numpy.array(values, dtype=type_)
     except BaseException:
         objecttools.augment_excmessage(
             f"While trying to assign a new `{name}` "
             f"index array to an Indexer object"
         )
     if array.ndim != 1:
         raise ValueError(
             f"The `{name}` index array of an Indexer object must be "
             f"1-dimensional.  However, the given value has interpreted "
             f"as a {array.ndim}-dimensional object."
         )
     timegrids = exceptiontools.getattr_(hydpy.pub, "timegrids")
     if timegrids is not None:
         if len(array) != len(timegrids.init):
             raise ValueError(
                 f"The `{name}` index array of an Indexer object must have "
                 f"a number of entries fitting to the initialization time "
                 f"period precisely.  However, the given value has been "
                 f"interpreted to be of length `{len(array)}` and the "
                 f"length of the Timegrid object representing the actual "
                 f"initialisation period is `{len(timegrids.init)}`."
             )
     return array
Beispiel #6
0
 def __call__(self, *args, **kwargs):
     self._soil = None
     try:
         super().__call__(*args, **kwargs)
     except NotImplementedError as exc:
         try:
             soil = kwargs.pop("soil", None)
             if soil is None:
                 raise exc
             if kwargs:
                 raise TypeError(
                     f"It is not allowed to combine keyword `soil` with "
                     f"other keywords, but the following ones are also "
                     f"used: {objecttools.enumeration(kwargs.keys())}."
                 ) from None
             try:
                 self(self._SOIL2VALUE[soil])
                 self._soil = soil
             except KeyError:
                 value2name = wland_constants.CONSTANTS.value2name
                 names = (f"{value2name[value]} ({value})"
                          for value in self._SOIL2VALUE.keys())
                 raise ValueError(
                     f"The given soil constant `{soil}` is not among the "
                     f"available ones.  Please use one of the following "
                     f"constants: {objecttools.enumeration(names)}."
                 ) from None
         except BaseException:
             objecttools.augment_excmessage(
                 f"While trying the set the value of parameter "
                 f"{objecttools.elementphrase(self)}")
Beispiel #7
0
    def save_file(self, filename, text):
        """Save the given text under the given condition filename and the
        current path.

        If the current directory is not defined explicitly, the directory
        name is constructed with the actual simulation end date.  If
        such an directory does not exist, it is created immediately.
        """
        _defaultdir = self._defaultdir
        try:
            if not filename.endswith('.py'):
                filename += '.py'
            try:
                self._defaultdir = ('init_' +
                                    pub.timegrids.sim.lastdate.string('os'))
            except AttributeError:
                pass
            path = os.path.join(self.currentpath, filename)
            with open(path, 'w', encoding="utf-8") as file_:
                file_.write(text)
        except BaseException:
            objecttools.augment_excmessage(
                'While trying to write the conditions file `%s`' % filename)
        finally:
            self._defaultdir = _defaultdir
Beispiel #8
0
    def update_variable(self, variable, value) -> None:
        """Assign the given value(s) to the given target or base variable.

        If the assignment fails, |ChangeItem.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()    # doctest: +ELLIPSIS
        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`.
        """
        try:
            variable(value)
        except BaseException:
            objecttools.augment_excmessage(
                f"When trying to update a target variable of "
                f"{type(self).__name__} `{self.name}` "
                f"with the value(s) `{value}`")
Beispiel #9
0
 def __call__(self, *args, **kwargs):
     try:
         shape = (len(kwargs), self.subpars.xpoints.shape[0])
     except exceptiontools.AttributeNotReady:
         raise RuntimeError(
             f"The shape of parameter {objecttools.elementphrase(self)} "
             f"depends on the shape of parameter `xpoints`, which has "
             f"not been defined so far."
         ) from None
     if shape[0] == 0:
         raise ValueError(
             f"For parameter {objecttools.elementphrase(self)} "
             f"no branches are defined.  Do this via keyword "
             f"arguments as explained in the documentation."
         )
     branched = self.subpars.pars.model.sequences.outlets.branched
     if (branched.shape[0] != 0) and (branched.shape[0] != shape[0]):
         raise RuntimeError(
             "The number of branches of the hbranch model should not "
             "be changed during run time.  If you really need to do "
             "this, first initialize a new `branched` sequence and "
             "connect it to the respective outlet nodes properly."
         )
     self.shape = shape
     self.values = numpy.nan
     for idx, (key, value) in enumerate(sorted(kwargs.items())):
         if key not in devicetools.Node.query_all():
             try:
                 pub.projectname
             except RuntimeError:
                 pass
             else:
                 raise RuntimeError(
                     f"Parameter {objecttools.elementphrase(self)} is "
                     f"supposed to branch to node `{key}`, but such a "
                     f"node is not available."
                 )
         try:
             self.values[idx] = value
         except BaseException:
             if shape[1] != len(value):
                 raise ValueError(
                     f"Each branch requires the same number of supporting "
                     f"points as given for parameter `xpoints`, which is "
                     f"{shape[1]}, but for branch `{key}` of parameter "
                     f"{objecttools.elementphrase(self)} {len(value)} "
                     f"values are given."
                 ) from None
             objecttools.augment_excmessage(
                 f"While trying to set the values for branch `{key}` "
                 f"of parameter {objecttools.elementphrase(self)}"
             )
     if branched.shape == (0,):
         branched.shape = shape[0]
     self.subpars.pars.model.sequences.fluxes.outputs.shape = shape[0]
     self.subpars.pars.model.nodenames.clear()
     for idx, key in enumerate(sorted(kwargs.keys())):
         setattr(self, key, self.values[idx])
         self.subpars.pars.model.nodenames.append(key)
Beispiel #10
0
 def value(self, value):
     try:
         self._value = numpy.full(self.shape, value, dtype=float)
     except BaseException:
         objecttools.augment_excmessage(
             f"When trying to convert the value(s) `{value}` assigned "
             f"to {type(self).__name__} `{self.name}` to a "
             f"numpy array of shape `{self.shape}` and type `float`")
Beispiel #11
0
 def value(self, value):
     try:
         self._value = numpy.full(self.shape, value, dtype=float)
     except BaseException:
         objecttools.augment_excmessage(
             f'When trying to convert the value(s) `{value}` assigned '
             f'to {objecttools.classname(self)} `{self.name}` to a '
             f'numpy array of shape `{self.shape}` and type `float`')
Beispiel #12
0
 def __delete__(self, obj):
     try:
         obj.currentdir = self.value
         del obj.currentdir
     except IOError:
         objecttools.augment_excmessage(
             'While trying to delete the input sequence directory')
     finally:
         self.value = None
Beispiel #13
0
 def connect(self):
     """Connect the link sequences of the actual model."""
     try:
         for group in ('inlets', 'receivers', 'outlets', 'senders'):
             self._connect_subgroup(group)
     except BaseException:
         objecttools.augment_excmessage(
             'While trying to build the node connection of the `%s` '
             'sequences of the model handled by element `%s`' %
             (group[:-1], objecttools.devicename(self)))
Beispiel #14
0
 def __iadd__(self, values):
     try:
         for model in self._get_models(values):
             self._dict[str(model)] = Variable2Auxfile(_master=self,
                                                       _model=model)
         return self
     except BaseException:
         objecttools.augment_excmessage(
             'While trying to add one ore more models '
             'to the actual auxiliary file handler')
Beispiel #15
0
 def __exit__(self, exception, message, traceback_):
     if not self.texts:
         self.print_('no failures occurred')
     else:
         for text in self.texts:
             self.print_(text)
     sys.stdout = self.stdout
     sys.stderr = self.stderr
     if exception:
         objecttools.augment_excmessage()
Beispiel #16
0
 def __call__(self, *args, **kwargs):
     try:
         args = [timetools.Period(args[0]).seconds]
     except BaseException:
         objecttools.augment_excmessage(
             'While trying the set the value of parameter `maxdt` '
             'of the lake model handled by element `%s`' %
             objecttools.devicename(self),
             '(An example: set `max dt` to 3600 seconds by writing '
             '`maxdt("1h"))')
     super().__call__(*args, **kwargs)
Beispiel #17
0
 def __set__(self, obj, directory):
     obj._inputdir = None
     try:
         obj.currentdir = directory
         self.value = directory
     except IOError:
         objecttools.augment_excmessage(
             'While trying to set the %s sequence directory' %
             self.sequence_type)
     finally:
         obj._currentdir = None
Beispiel #18
0
 def __get__(self, obj, type_=None):
     if obj is None:
         return self
     try:
         obj.currentdir = self.value
         return obj._currentdir
     except IOError:
         objecttools.augment_excmessage(
             'While trying to get the %s sequence directory' %
             self.sequence_type)
     finally:
         obj._currentdir = None
Beispiel #19
0
 def __call__(self, *args, **kwargs):
     """The prefered way to pass values to |DMax| instances
     within parameter control files.
     """
     try:
         lland_parameters.ParameterSoil.__call__(self, *args, **kwargs)
     except TypeError:
         args = kwargs.get('r_dmax')
         if args is not None:
             self.value = 2.4192 * self.apply_timefactor(numpy.array(args))
             self.trim()
         else:
             objecttools.augment_excmessage()
Beispiel #20
0
 def __isub__(self, values):
     try:
         for model in self._get_models(values):
             try:
                 del self._dict[str(model)]
             except KeyError:
                 raise AttributeError(
                     f'The handler does not contain model `{model}`.')
         return self
     except BaseException:
         objecttools.augment_excmessage(
             'While trying to remove one or more models '
             'from the actual auxiliary file handler')
Beispiel #21
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
Beispiel #22
0
 def __setattr__(self, filename, variables):
     try:
         self._check_filename(filename)
         new_vars = objecttools.extract(variables,
                                        (typingtools.VariableProtocol, ))
         for new_var in new_vars:
             self._check_variable(new_var)
             fn2var = self._type2filename2variable.get(type(new_var), {})
             self._check_duplicate(fn2var, new_var, filename)
             fn2var[filename] = copy.deepcopy(new_var)
             self._type2filename2variable[type(new_var)] = fn2var
     except BaseException:
         objecttools.augment_excmessage(
             'While trying to extend the range of variables handled by '
             'the actual Variable2AuxFile object')
Beispiel #23
0
 def __call__(self, *args, **kwargs):
     """The prefered way to pass values to |DMax| instances
     within parameter control files.
     """
     try:
         lland_parameters.ParameterSoil.__call__(self, *args, **kwargs)
     except TypeError:
         args = kwargs.get("r_dmax")
         if args is not None:
             self.value = (0.1008 *
                           hydpy.pub.timegrids.init.stepsize.hours *
                           numpy.array(args))
             self.trim()
         else:
             objecttools.augment_excmessage()
Beispiel #24
0
 def __setattr__(self, key, value):
     if hasattr(self, key) and not key.startswith('th_'):
         object.__setattr__(self, key, value)
     else:
         std_key = self._standardize_key(key)
         try:
             try:
                 self._coefs[std_key] = value.arma.coefs
             except AttributeError:
                 self._coefs[std_key] = (tuple(float(v) for v in value[0]),
                                         tuple(float(v) for v in value[1]))
         except BaseException:
             objecttools.augment_excmessage(
                 f'While trying to set a new threshold ({key}) '
                 f'coefficient pair for parameter `{self.name}` '
                 f'of element `{objecttools.devicename(self.subpars)}`')
Beispiel #25
0
 def __setattr__(self, key, value):
     if self._has_predefined_attr(key):
         object.__setattr__(self, key, value)
     else:
         std_key = self._standardize_key(key)
         try:
             try:
                 self._coefs[std_key] = value.arma.coefs
             except AttributeError:
                 self._coefs[std_key] = (tuple(float(v) for v in value[0]),
                                         tuple(float(v) for v in value[1]))
         except BaseException:
             objecttools.augment_excmessage(
                 'While trying to set a new threshold (%s) coefficient '
                 'pair for parameter `%s` of element `%s`' %
                 (key, self.name, objecttools.devicename(self.subpars)))
Beispiel #26
0
    def move_dll(self):
        """Try to find the resulting dll file and to move it into the
        `cythons` package.

        Things to be aware of:
          * The file extension either `pyd` (Window) or `so` (Linux).
          * The folder containing the dll file is system dependent, but is
            always a subfolder of the `cythons` package.
          * Under Linux, the filename might contain system information, e.g.
            ...cpython-36m-x86_64-linux-gnu.so.
        """
        dirinfos = os.walk(self.buildpath)
        next(dirinfos)
        system_dependent_filename = None
        for dirinfo in dirinfos:
            for filename in dirinfo[2]:
                if (filename.startswith(self.cyname)
                        and filename.endswith(dllextension)):
                    system_dependent_filename = filename
                    break
            if system_dependent_filename:
                try:
                    shutil.move(
                        os.path.join(dirinfo[0], system_dependent_filename),
                        os.path.join(self.cydirpath,
                                     self.cyname + dllextension))
                    break
                except BaseException:
                    prefix = ('After trying to cythonize module %s, when '
                              'trying to move the final cython module %s '
                              'from directory %s to directory %s' %
                              (self.pyname, system_dependent_filename,
                               self.buildpath, self.cydirpath))
                    suffix = ('A likely error cause is that the cython module '
                              '%s does already exist in this directory and is '
                              'currently blocked by another Python process.  '
                              'Maybe it helps to close all Python processes '
                              'and restart the cyhonization afterwards.' %
                              self.cyname + dllextension)
                    objecttools.augment_excmessage(prefix, suffix)
        else:
            raise IOError('After trying to cythonize module %s, the resulting '
                          'file %s could neither be found in directory %s nor '
                          'its subdirectories.  The distul report should tell '
                          'whether the file has been stored somewhere else,'
                          'is named somehow else, or could not be build at '
                          'all.' % self.buildpath)
Beispiel #27
0
 def __setattr__(self, name: str, value: object) -> None:
     if name.startswith("toy_"):
         try:
             if not isinstance(value, InterpAlgorithm):
                 raise TypeError(
                     f"{objecttools.value_of_type(value).capitalize()} has been "
                     f"given, but an object of type `InterpAlgorithm` is required."
                 )
             self._add_toyalgorithpair(name, value)
             self.refresh()
         except BaseException:
             objecttools.augment_excmessage(
                 f"While trying to assign a new interpolator to parameter "
                 f"{objecttools.elementphrase(self)} based on the string `{name}`"
             )
     else:
         object.__setattr__(self, name, value)
Beispiel #28
0
 def __delattr__(self, name: str) -> None:
     if name.startswith("toy_"):
         try:
             try:
                 del self._toy2algorithm[timetools.TOY(name)]
             except KeyError:
                 raise AttributeError(
                     f"No interpolator is registered under a TOY object named "
                     f"`{timetools.TOY(name)}`.") from None
             self.refresh()
         except BaseException:
             objecttools.augment_excmessage(
                 f"While trying to remove an interpolator from parameter "
                 f"{objecttools.elementphrase(self)} based on the string `{name}`"
             )
     else:
         object.__delattr__(self, name)
Beispiel #29
0
 def __setattr__(self, key: str, value: object) -> None:
     if hasattr(self, key) and not key.startswith("th_"):
         object.__setattr__(self, key, value)
     else:
         std_key = self._standardize_key(key)
         try:
             try:
                 self._coefs[std_key] = value.arma.coefs
             except AttributeError:
                 self._coefs[std_key] = (
                     tuple(float(v) for v in value[0]),
                     tuple(float(v) for v in value[1]),
                 )
         except BaseException:
             objecttools.augment_excmessage(
                 f"While trying to set a new threshold ({key}) coefficient pair "
                 f"for parameter {objecttools.elementphrase(self)}")
Beispiel #30
0
 def save_files(self, selections):
     """Save the nodes and elements from each |Selection| object contained
     within the given |Selections| instance to a separate network file of
     the same name.
     """
     try:
         currentpath = self.currentpath
         selections = selectiontools.Selections(selections)
         for selection in selections:
             if selection.name == 'complete':
                 continue
             path = os.path.join(currentpath, selection.name + '.py')
             selection.save(path=path, write_nodes=True)
     except BaseException:
         objecttools.augment_excmessage(
             'While trying to save selections `%s` into network files' %
             selections)