#!/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/>.
#
########################################################################
"""
Statistiques - Fréquence au non-dépassement
"""
import numpy as np
import pyspc.core.exception as _exception
RANK2FREQ = {
'Weibull': (0, 1),
'Adamowski': (0.25, 0.50),
'Chegodayev': (0.3, 0.4),
'Beard': (0.31, 0.38),
'Filliben': (0.3175, 0.365),
'YuHuand': (0.326, 0.348),
'Blom': (0.375, 0.25),
'Gringorten': (0.44, 0.12),
'Cunnane': (0.40, 0.20),
'Hazen': (0.50, 0),
'Larsen': (0.567, 0.134),
'California': (1, 0),
}
"""Paramètres de conversion rang vers fréquence, dans la littérature
voir: https://en.m.wikipedia.org/wiki/Q%E2%80%93Q_plot """
[docs]
def from_rank(r, n, method=None, a=None, b=None, check=None):
"""
Convertir un rang en fréquence au non-dépassement.
Parameters
----------
r : int
Rang
n : int
Taille de l'échantillon
method : str
Méthode de calcul. Voir RANK2FREQ
Other Parameters
----------------
a : float
Valeur au numérateur
b : float
Valeur au dénominateur
check : bool
Contrôler les paramètres avant exécution. Par défaut: True
Returns
-------
f : float
Fréquence au non-dépassement
Notes
-----
F = (r - a) / (n + b)
F = (r - a) / (n + 1 - 2a)
Examples
--------
>>> from pyspc.statistics.freq import from_rank
CAS METHODE SPECIFIQUE
>>> from_rank(1, 10, method='Gringorten')
0.05533596837944665
>>> from_rank(5, 10, method='Gringorten')
0.4505928853754941
>>> from_rank(10, 10, method='Gringorten')
0.9446640316205535
CAS DEFAUT (HAZEN)
>>> from_rank(1, 10)
0.05
>>> from_rank(5, 10)
0.45
>>> from_rank(10, 10)
0.95
CAS A ET/OU B FOURNI
>>> from_rank(1, 10, a=0, b=0)
0.1
>>> from_rank(5, 10, a=0, b=0)
0.5
>>> from_rank(10, 10, a=0, b=0)
1.0
>>> from_rank(1, 10, a=0.5, b=0)
0.05
>>> from_rank(5, 10, a=0.5, b=0)
0.45
>>> from_rank(10, 10, a=0.5, b=0)
0.95
>>> from_rank(1, 10, a=1, b=0)
0.0
>>> from_rank(5, 10, a=1, b=0)
0.4
>>> from_rank(10, 10, a=1, b=0)
0.9
See Also
--------
RANK2FREQ
"""
if check is None:
check = True
if check:
_exception.check_int(n)
_exception.check_int(r)
_exception.raise_valueerror(
n <= 0, text='Taille doit être positive')
_exception.raise_valueerror(
r <= 0 or r > n, text='Rang doit être dans [1...n]')
_exception.raise_valueerror(
method is not None and method not in RANK2FREQ,
text=f"Méthode doit être parmi [{', '.join(list(RANK2FREQ.keys()))}]")
if method is None:
_exception.raise_valueerror(
a is not None and not isinstance(a, (int, float)),
text='Paramètre a doit être un réel ou un entier')
_exception.raise_valueerror(
b is not None and not isinstance(b, (int, float)),
text='Paramètre b doit être un réel ou un entier')
if a is not None and b is None:
b = 1 - 2 * a
elif a is None and b is not None:
a = (1 - b) / 2
elif a is None and b is None:
a, b = RANK2FREQ['Hazen']
else:
a, b = RANK2FREQ[method]
return (r - a) / (n + b)
[docs]
def to_period(f, highflow=None, asint=None, check=None):
"""
Convertir un temps de retour en fréquence au non-dépassement.
Parameters
----------
f : float
Fréquence au non-dépassement
highflow : bool
Hautes eaux (True) ou Basses eaux (False). Défaut: True
asint : bool
Valeurs entières. Défaut: True
check : bool
Contrôler la fréquence entre 0 et 1. Défaut: True
Returns
-------
t : int
Temps de retour
Examples
--------
>>> from pyspc.statistics.freq import to_period
>>> to_period(0.5)
2
>>> to_period(0.9)
10
>>> to_period(0.1, highflow=False)
10
"""
if highflow is None:
highflow = True
if asint is None:
asint = True
if check is None:
check = True
_exception.check_bool(highflow)
_exception.check_float(f)
if check:
_exception.raise_valueerror(
f <= 0 or f >= 1, text='Fréquence doit être entre 0 et 1')
if np.isnan(f):
return np.nan
if highflow:
try:
x = 1 / (1-f)
if asint:
return int(round(x, 0))
return x
except ZeroDivisionError:
return np.nan
except OverflowError:
return np.inf
try:
x = 1 / f
if asint:
return int(round(x, 0))
return x
except ZeroDivisionError:
return np.nan
[docs]
def from_ugumbel(u):
"""
Convertir une variable de Gumbel en fréquence.
Parameters
----------
u : float
Variable de Gumbel
Returns
-------
f : float
Fréquence au non-dépassement
Examples
--------
>>> from pyspc.statistics.freq import to_ugumbel
>>> from_ugumbel(2.25)
0.90
>>> from_ugumbel(4.60)
0.99
"""
_exception.check_float(u)
return np.exp(-np.exp(-u))
[docs]
def to_ugumbel(f):
"""
Convertir une fréquence en variable de Gumbel.
Parameters
----------
f : float
Fréquence au non-dépassement
Returns
-------
u : float
Variable de Gumbel
Examples
--------
>>> from pyspc.statistics.freq import to_ugumbel
>>> to_ugumbel(0.90)
2.25
>>> to_ugumbel(0.99)
4.60
"""
if np.isnan(f):
return np.nan
_exception.check_float(f)
_exception.raise_valueerror(
f <= 0 or f >= 1, text='Fréquence doit être entre 0 et 1')
return -1 * np.log(-np.log(f))