#!/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/>.
#
########################################################################
"""
Modélisations hydrologiques - Projet PLATHYNES - Hydrogrammes unitaires
"""
import inspect
import pandas as pnd
import pyspc.core.exception as _exception
[docs]
def build(ts=60, tb=60, c=0, params=None):
"""
Construire un hydrogramme unitaire.
Parameters
----------
ts : int
Pas de temps de calcul, en min.
tb : int
Durée de l'hydrogramme unitaire en min.
c : int
Position du centre de l'hydrogramme unitaire, en min.
Défaut: 0. L'hydrogramme est alors centré en 0.
params : dict
Formulations demandées et leurs paramètres
- clé : str
- valeurs : list
Returns
-------
df : pandas.DataFrame
Hydrogrammes unitaires
See Also
--------
pyspc.model.plathynes.unit_hydrograph.plot
Examples
--------
>>> from pyspc.model.plathynes import unit_hydrograph as uh
>>> ts = 60
>>> tb = 840
>>> c = 0
>>> params = {
... 'FBN': [1.5, 0.3],
... 'FPU': [5],
... 'RE1': [],
... 'TG1': [-4],
... }
CAS CENTRE (c == 0)
>>> df = uh.build(ts=ts, tb=tb, c=c, params=params)
>>> df
FBN FPU RE1 TG1
-6 0.066394 0.000149 0.071429 0.047619
-5 0.118480 0.002380 0.071429 0.095238
-4 0.137048 0.012049 0.071429 0.142857
-3 0.135565 0.038079 0.071429 0.129870
-2 0.122396 0.092967 0.071429 0.116883
-1 0.104168 0.192777 0.071429 0.103896
0 0.085180 0.357143 0.071429 0.090909
1 0.067690 0.192777 0.071429 0.077922
2 0.052580 0.092967 0.071429 0.064935
3 0.039958 0.038079 0.071429 0.051948
4 0.029564 0.012049 0.071429 0.038961
5 0.020973 0.002380 0.071429 0.025974
6 0.013644 0.000149 0.071429 0.012987
7 0.006360 0.000000 0.071429 0.000000
CAS DECENTRE (c != 0)
>>> c = -120
>>> df = uh.build(ts=ts, tb=tb, c=c, params=params)
>>> df
FBN FPU RE1 TG1
-8 0.066394 0.000149 0.071429 0.047619
-7 0.118480 0.002380 0.071429 0.095238
-6 0.137048 0.012049 0.071429 0.142857
-5 0.135565 0.038079 0.071429 0.129870
-4 0.122396 0.092967 0.071429 0.116883
-3 0.104168 0.192777 0.071429 0.103896
-2 0.085180 0.357143 0.071429 0.090909
-1 0.067690 0.192777 0.071429 0.077922
0 0.052580 0.092967 0.071429 0.064935
1 0.039958 0.038079 0.071429 0.051948
2 0.029564 0.012049 0.071429 0.038961
3 0.020973 0.002380 0.071429 0.025974
4 0.013644 0.000149 0.071429 0.012987
5 0.006360 0.000000 0.071429 0.000000
"""
_exception.check_numeric(ts)
_exception.raise_valueerror(ts <= 0, "'ts' strictement positif")
_exception.check_numeric(tb)
_exception.raise_valueerror(tb < 0, "'tb' positif")
_exception.raise_valueerror(tb % ts != 0, "'tb' multiple de 'ts'")
_exception.check_numeric(c)
_exception.raise_valueerror(c % ts != 0, "'c' multiple de 'ts'")
if params is None:
params = {n: [] for n in UH_DICT}
_exception.check_dict(params)
nb = int(tb/ts)
nc = int(c/ts)
index = list(range(1, nb+1))
df = pnd.concat([UH_DICT[n](index, *params[n])
for n in params if n in UH_DICT],
axis=1)
df.index = [int(-nb/2) + nc + x for x in df.index]
return df
[docs]
def plot(df, subplots=False, filename='unit_hydrograph.png'):
"""
Tracer un hydrogramme unitaire.
Parameters
----------
df : pandas.DataFrame
Hydrogrammes unitaires
subplots : bool
1 sous figure par hydrogramme unitaire (True) ou les regrouper (False)
filename : str
Fichier à écrire
Returns
-------
filename : str
Fichier à écrire
See Also
--------
pyspc.model.plathynes.unit_hydrograph.build
Examples
--------
"""
figsize = (11.67, 8.27)
if subplots:
figsize = (8.27, 11.67)
ax = df.plot(marker='o', subplots=subplots,
title="Hydrogramme Unitaire plathynes",
figsize=figsize)
if subplots:
for sax in ax:
sax.set_xticks(df.index)
sax.set_xticklabels(df.index.astype(str))
ylim = sax.get_ylim()
sax.set_ylim((0, ylim[-1]))
fig = sax.get_figure()
else:
ax.set_xticks(df.index)
ax.set_xticklabels(df.index.astype(str))
ylim = ax.get_ylim()
ax.set_ylim((0, ylim[-1]))
fig = ax.get_figure()
fig.tight_layout()
fig.savefig(filename, dpi=300)
return filename
[docs]
def FBN(index, alpha=1, kappa=1):
"""
Hydrogramme unitaire selon Berthet (2010).
Parameters
----------
index : list, pandas.Index
Indices temporels sur lesquels il faut déterminer l'hydrogramme
alpha : float
Paramètre alpha (forme). Défaut: 1
kappa : float
Paramètre kappa (mode). Défaut: 1
Returns
-------
df : pandas.DataFrame
Hydrogramme unitaire
Notes
-----
Equation 1.3.1 de Note_besoinMOHYS_V4.odt
Examples
--------
>>> from pyspc.model.plathynes import unit_hydrograph as uh
>>> index = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
>>> alpha = 1.5
>>> kappa = 0.3
>>> df = uh.FBN(index, alpha, kappa)
>>> df
FBN
1 0.066394
2 0.118480
3 0.137048
4 0.135565
5 0.122396
6 0.104168
7 0.085180
8 0.067690
9 0.052580
10 0.039958
11 0.029564
12 0.020973
13 0.013644
14 0.006360
"""
_exception.check_numeric(alpha)
_exception.raise_valueerror(alpha <= 0, "'alpha' strictement positif")
_exception.check_numeric(kappa)
_exception.raise_valueerror(kappa < 0, "'kappa' positif ou nul")
fitname = inspect.stack()[0][3]
values = []
nb = len(index)
for i in index:
if i <= 0:
values.append(0)
elif i > nb:
values.append(0)
else:
values.append(
(i ** alpha) / (i ** alpha + kappa * (nb - i) ** alpha)
- ((i - 1) ** alpha)
/ ((i - 1) ** alpha + kappa * (nb - i + 1) ** alpha)
)
pdf = pnd.DataFrame({fitname: values}, index=index)
return pdf
[docs]
def FPU(index, alpha=1):
"""
Hydrogramme unitaire selon Le Moine - PUISSANCE.
Parameters
----------
index : list, pandas.Index
Indices temporels sur lesquels il faut déterminer l'hydrogramme
alpha : float
Paramètre alpha (forme). Strictement positif. Défaut: 1
Returns
-------
df : pandas.DataFrame
Hydrogramme unitaire
Notes
-----
Equation 1.3.4 de Note_besoinMOHYS_V4.odt
Examples
--------
>>> from pyspc.model.plathynes import unit_hydrograph as uh
>>> index = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
>>> alpha = 5
>>> df = uh.FPU(index, alpha)
>>> df
FPU
1 0.000149
2 0.002380
3 0.012049
4 0.038079
5 0.092967
6 0.192777
7 0.357143
8 0.192777
9 0.092967
10 0.038079
11 0.012049
12 0.002380
13 0.000149
14 0.000000
"""
_exception.check_numeric(alpha)
_exception.raise_valueerror(alpha <= 0, "'alpha' strictement positif")
fitname = inspect.stack()[0][3]
values = []
nb = len(index)
for i in index:
if i <= nb / 2:
values.append(
alpha * ((2 * i) / nb) ** (alpha - 1) / nb
)
elif nb / 2 < i <= nb:
values.append(
alpha * (2 * (nb - i) / nb) ** (alpha - 1) / nb
)
else:
values.append(0)
pdf = pnd.DataFrame({fitname: values}, index=index)
return pdf
[docs]
def RE1(index):
"""
Hydrogramme unitaire de forme géométrique RECTANGLE.
Parameters
----------
index : list, pandas.Index
Indices temporels sur lesquels il faut déterminer l'hydrogramme
Returns
-------
df : pandas.DataFrame
Hydrogramme unitaire
Notes
-----
Equation 1.3.2 de Note_besoinMOHYS_V4.odt
See Also
--------
scipy.stats.uniform
Examples
--------
>>> from pyspc.model.plathynes import unit_hydrograph as uh
>>> index = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
>>> df = uh.RE1(index)
>>> df
RE1
1 0.071429
2 0.071429
3 0.071429
4 0.071429
5 0.071429
6 0.071429
7 0.071429
8 0.071429
9 0.071429
10 0.071429
11 0.071429
12 0.071429
13 0.071429
14 0.071429
"""
fitname = inspect.stack()[0][3]
nb = len(index)
values = [1 / nb for x in index]
pdf = pnd.DataFrame({fitname: values}, index=index)
return pdf
[docs]
def TG1(index, d=0):
"""
Hydrogramme unitaire de forme géométrique TRIANGLE.
Parameters
----------
index : list, pandas.Index
Indices temporels sur lesquels il faut déterminer l'hydrogramme
d : int
Mode du triangle (positionnement du maximum). Défaut: 0
Returns
-------
df : pandas.DataFrame
Hydrogramme unitaire
Notes
-----
Equation 1.3.3 de Note_besoinMOHYS_V4.odt
See Also
--------
scipy.stats.triang
Examples
--------
>>> from pyspc.model.plathynes import unit_hydrograph as uh
>>> index = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
>>> df = uh.TG1(index)
>>> df
TG1
1 0.020408
2 0.040816
3 0.061224
4 0.081633
5 0.102041
6 0.122449
7 0.142857
8 0.122449
9 0.102041
10 0.081633
11 0.061224
12 0.040816
13 0.020408
14 0.000000
>>> df = uh.TG1(index, d=0)
>>> df
TG1
1 0.020408
2 0.040816
3 0.061224
4 0.081633
5 0.102041
6 0.122449
7 0.142857
8 0.122449
9 0.102041
10 0.081633
11 0.061224
12 0.040816
13 0.020408
14 0.000000
>>> df = uh.TG1(index, d=-4)
>>> df
TG1
1 0.047619
2 0.095238
3 0.142857
4 0.129870
5 0.116883
6 0.103896
7 0.090909
8 0.077922
9 0.064935
10 0.051948
11 0.038961
12 0.025974
13 0.012987
14 0.000000
"""
nb = len(index)
_exception.raise_valueerror(
d < -nb/2 or d > nb/2,
f"'d' entre {-int(nb/2)} et {int(nb/2)}")
fitname = inspect.stack()[0][3]
values = []
for i in index:
if 0 < i <= d + nb / 2:
values.append(
2 * i / (nb * (d + nb/2))
)
elif d + nb / 2 < i <= nb:
values.append(
2 * (nb - i) / (nb * (nb/2 - d))
)
else:
values.append(0)
pdf = pnd.DataFrame({fitname: values}, index=index)
return pdf
UH_DICT = {'FBN': FBN, 'FPU': FPU, 'RE1': RE1, 'TG1': TG1}
"""Dictionnaire des fonctions de construction des hydrogrammes unitaires"""