Code source de pyspc.core.location

#!/usr/bin/python3
# -*- coding: utf-8 -*-
########################################################################
#
# This file is part of python module <pyspc>.
# Copyright (C) 2013-2021  R. Marty
#   (renaud.marty@developpement-durable.gouv.fr)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program (see COPYING.txt).
# If not, see <http://www.gnu.org/licenses/>.
#
########################################################################
"""
Objets natifs et convention de pyspc - Lieu(x) de observation/prévision
"""
import collections
import os.path

from pyspc.core.config import Config
import pyspc.core.exception as _exception
from .convention import LOCTYPE


[docs] class Location(): """ Lieu des séries Attributes ---------- code : str Code du lieu name : str Nom du lieu longname : str Nom complet du lieu river : str Nom du cours d'eau locality : list Liste des codes des communes associées loctype : str Type de lieu reach : Reach, str, list Tronçon de vigilance x : float Coordonnée X y : float Coordonnée Y z : float Altitude du lieu area : float Surface du bassin """
[docs] def __init__(self, code=None, name=None, longname=None, river=None, loctype=None, reach=None, locality=None, x=-1, y=-1, z=-1, area=-1): """ Lieu des séries Parameters ---------- code : str Code du lieu name : str Nom du lieu longname : str Nom complet du lieu river : str Nom du cours d'eau locality : list Liste des codes des communes associées loctype : str Type de lieu reach : Reach, str Tronçon de vigilance x : float Coordonnée X y : float Coordonnée Y z : float Altitude du lieu area : float Surface du bassin """ import pyspc.core.reach as _reach self._code = code self._name = name self._longname = longname self._river = river self._locality = locality if loctype in self.get_loctypes(): self._loctype = loctype else: raise ValueError('Type de lieu inconnu') self._x = float(x) self._y = float(y) self._z = float(z) self._area = float(area) if isinstance(reach, (_reach.Reach, list, str)) or reach is None: self._reach = reach else: raise ValueError('Tronçon incorrect')
def __str__(self): """ Afficher des méta-données de l'instance Location """ text = """ ************************************* *********** LOCATION **************** ************************************* * CODE LIEU = {_code} * NOM LIEU = {_name} * NOM COMPLET LIEU = {_longname} * COURS D'EAU = {_river} * TYPE LIEU = {_loctype} * COORDONNEES X = {_x:10.2f} m * COORDONNEES Y = {_y:10.2f} m * ALTITUDE LIEU = {_z:10.2f} m NGF * SURFACE LIEU = {_area:10.2f} km2 * COMMUNES = {_locality} * TRONCONS = {_reach} ************************************* """ return text.format(**vars(self)) @property def area(self): """Surface du bassin""" return self._area @property def code(self): """Code du lieu""" return self._code @code.setter def code(self, code): """Définir l'identifiant du lieu""" self._code = code @property def locality(self): """Codes des communes associées""" return self._locality @property def loctype(self): """Type de lieu""" return self._loctype @property def longname(self): """Nom complet du lieu""" return self._longname @property def name(self): """Nom du lieu""" return self._name @property def reach(self): """Tronçon de vigilance""" return self._reach @property def river(self): """Nom du cours d'eau""" return self._river @property def x(self): """Coordonnée X""" return self._x @property def y(self): """Coordonnée Y""" return self._y @property def z(self): """Altitude du lieu""" return self._z
[docs] @classmethod def get_loctypes(cls): """ Liste des types de lieu Returns ------- list Types de lieu """ return sorted(LOCTYPE)
[docs] class Locations(collections.OrderedDict): """ Classe des collections de lieux Location Attributes ---------- name : str Nom de la collection codes : list Codes des lieux """
[docs] def __init__(self, name='locations'): """ Initialiser l'instance de Locations Parameters ---------- name : str Nom de la collection """ super().__init__() self._name = name self._codes = []
def __str__(self): """ Afficher les méta-données de l'instance Locations """ strlocs = '' if len(self.keys()) > 0: counter = 0 for c in self.codes: counter += 1 strlocs += '\n * ----------------------------------' strlocs += f'\n * LIEU #{counter}' strlocs += f'\n * - CODE = {c}' text = """ ************************************* *********** LOCATIONS *************** ************************************* * NOM DE LA COLLECTION = {_name} * NOMBRE DE LIEUX = {length} {strlocs} ************************************* """ return text.format( **vars(self), length=len(self.keys()), strlocs=strlocs) @property def codes(self): """Codes des lieux""" return self._codes @property def name(self): """Nom de la collection""" return self._name
[docs] def add(self, loc=None, code=None, overwrite=False): """ Ajouter un lieu hydrologique dans la collection Parameters ---------- code : str Code du lieu loc : Location Instance du lieu overwrite : bool Écraser la donnée existante ? défaut: False """ _exception.raise_valueerror( not isinstance(loc, Location), 'Location incorrecte' ) if code is None: code = loc.code _exception.check_str(code) if overwrite: self[code] = loc else: self.setdefault(code, loc) self.refresh_codes()
[docs] def check_locs(self): """ Contrôler si la série est une instance Location """ return all([isinstance(v, Location) for k, v in self.items()])
[docs] def refresh_codes(self): """ Rafraîchir la liste des codes """ self._codes = list(self.keys())
[docs] @classmethod def from_Config(cls, config=None): """ Créer une instance Locations à partir d'un fichier de configuration ou d'une instance Config Parameters ---------- config : str, Config - Nom du fichier de configuration - Instance pysoc.core.config.Config """ name = os.path.basename(os.path.splitext(config)[0]) locs = Locations(name=name) if not isinstance(config, Config): config = Config(filename=config) config.read() for section in config: loc = Location( code=section, name=config[section].get('name', None), longname=config[section].get('longname', None), loctype=config[section].get('loctype', None), reach=config[section].get('reach', None), locality=config[section].get('locality', None), x=float(config[section].get('x', -1)), y=float(config[section].get('y', -1)), z=float(config[section].get('z', -1)), area=float(config[section].get('area', -1)), ) locs.add(code=section, loc=loc) return locs
[docs] def to_Config(self, filename=None): """ Créer une instance Config à partir d'une instance Locations Parameters ---------- filename : str Nom du fichier associé à la collection. Si non défini, le nom du fichier est défini à partir du nom de la collection Returns ------- Config Instance pyspc.core.config.Config """ if filename is None: filename = '{self.name}.txt' _exception.check_str(filename) config = Config(filename=filename) for k, loc in self.items(): config.setdefault(k, collections.OrderedDict()) config[k]['code'] = k config[k]['name'] = loc.name config[k]['longname'] = loc.longname config[k]['loctype'] = loc.loctype config[k]['reach'] = loc.reach config[k]['locality'] = loc.locality config[k]['river'] = loc.river config[k]['x'] = loc.x config[k]['y'] = loc.y config[k]['z'] = loc.z config[k]['area'] = loc.area return config