... | ... | @@ -13,6 +13,7 @@ On s'appuie pour les explications sur : |
|
|
|
|
|
illustrations ; [fenêtre matplotlib de GenerateurCruesMaxAnnuels avec widgets et nouveaux boutons](https://gitlab.irstea.fr/christine.poulard/atelier-matplotlib/-/blob/master/AtelierG_widgetsEtBoutonsToolbar.png)
|
|
|
|
|
|
|
|
|
![Sample2Gumbel screenshot](/images/DixAnsAvecCentennaleEtQuinquennale.png)
|
|
|
|
|
|
|
... | ... | @@ -29,19 +30,21 @@ On signale ici qu'il existe aussi une bibliothèque iPython pour ajouter des wid |
|
|
mon_objet_qui_existe_dans_le_main.slider = mon_slider_dans_la_fonction.
|
|
|
Le même problème existe pour les images intégrées dans une interface, il faut absolument leur donner un nom pour que l'objet correspondant ne soit pas jeté par le GC.
|
|
|
|
|
|
### à propos des codes :
|
|
|
### à propos des codes
|
|
|
On présente ici surtout deux codes, vous pouvez choisir de lire celui qui vous parle le plus. On a laissé deux versions de chaque code, une simple et une un peu mieux finie mais du coup un peu plus complexe.
|
|
|
|
|
|
**ProbaCruesMaxAn_SurNannees.py** : c'est le code le plus simple, qui traite d'une seule fonction qui tient en une ligne et qui dépend de deux paramètres, N (nombre d'années) et T (période de retour, inverse d'une fréquence). Sa courbe est tracée avec "plot" ; on représente les probas par des points, sans ligne pour les relier, car ce sont des probas discrètes :
|
|
|
La figure est munie de deux sliders qui font varier N et T, et qui activent tous les deux la même fonction de mise à jour du tracé : recalcul et remplacement des vecteurs x et y de la courbe (méthode set_data). Le titre change aussi.
|
|
|
Les "sliders" sont intéressants pour faire varier "en direct", et créer presque des animations en direct, mais il est difficile de viser une valeur en particulier. Le widget "textBox" serait meilleur pour saisir des valeurs.
|
|
|
***ProbaCruesMaxAn_SurNannees_stairs** est une autre version qui propose un graphique en escalier, intéressant car on doit jouer avec les Locator et Formatter pour que l'étiquette se place au milieu de chaque marche d'escalier.
|
|
|
***ProbaCruesMaxAn_SurNannees_stairs** est une autre version qui propose en plus un graphique en escalier, intéressant car on doit jouer avec les Locator et Formatter pour que l'étiquette se place au milieu de chaque marche d'escalier.
|
|
|
|
|
|
**Chegodaiev.py** : c'est ce code qui est commenté ici. C'est une petite démonstration des fréquence empiriques, avec la formule de Tchégodaiev et une formule plus générique paramétrée par a et b, dont les valeurs sont modifiables avec des "sliders". Une case à cocher permet de changer l'abscisse de fréquence en période de retour.
|
|
|
Il est utilisable, mais il reste quelques maladresses à rectifier, dans les définitions des xlim par exemple ou le choix des méthodes de tracé pour Tchgodaiev (les vlines allant de 0 à la valeur max ne sont pas forcément le meilleur choix, et surtout ils sont bien plus compliqués à mettre à jour !). Comme il a aussi une vocation d'exercice, on a utilisé le widget "checkbutton" même si le rendu est catastrophique... Un simple bouton serait mieux.
|
|
|
**Chegodaiev.py** : code simple pour illustrer la notion de fréquence empirique, avec la formule de Tchégodaiev et une formule plus générique paramétrée par a et b, dont les valeurs sont modifiables avec des "sliders". Une case à cocher permet de changer l'abscisse de fréquence en période de retour.
|
|
|
Il est utilisable, mais il reste quelques maladresses, dans les définitions des xlim par exemple ou le choix des méthodes de tracé pour Tchgodaiev (les vlines allant de 0 à la valeur max ne sont pas forcément le meilleur choix, et surtout ils sont bien plus compliqués à mettre à jour !). Comme il a aussi une vocation d'exercice, on a utilisé le widget "checkbutton" même si le rendu est catastrophique... Un simple bouton serait mieux.
|
|
|
|
|
|
**GenerateurCruesMaxAnnuelles.py** est un peu plus complexe et un peu mieux fini ; il est également ajouté au dépôt pour lecture (retours toujours appréciés ! on pourrait proposer de déclarer beaucoup d'objets comme attributs de la classe SerieGumbel pour éviter de les trimballer en file indienne comme arguments de fonction ou, pire, comme global...).
|
|
|
Il reprend les bases de Chegodaiev.py (en corrigeant quelques maladresses) pour créer une chronique d'observation de max annuels suivant une loi connue de Gumbel, de 10 ans en 10 ans, afin d'observer la variabilité de la chronique. On compare sur une autre vignette la loi ayant servi à la constitution de l'échantillon avec la relation Q(T) déduite des observations: plus on étend la période d'observation, plus on va converger vers la 'vraie' distribution (que l'on ne connaît pas dans le monde réel...). Un bouton "remise à zéro" efface la chronique et repart d'une série de 10 ans, ce qui permet aussi de voir que quel que soit le tirage de 10 ans les positions empiriques sont identiques (tant que a et b restent inchangées)...
|
|
|
Une [version plus aboutie est mise en ligne dans un autre projet](https://gitlab.irstea.fr/christine.poulard/hydrotools-_-demo-and-processing-tools), avec plus de fonctionnalités, déclanchées par des boutons ajoutés à la toolbar.
|
|
|
**GenerateurCruesMaxAnnuelles.py** : code non commenté ici mais il est ajouté au dépôt pour information.
|
|
|
C'est une étape intermédiaire entre Chegodaiev.py (dont il corrige quelques maladresses) et un code qui commence à être diffusable, **Sample2Gumbel**. Comme **Sample2Gumbel** est appelé à évoluer, on a préféré citer ici l'étape intermédiaire sur laquelle on ne reviendra pas.
|
|
|
Il s'agit de créer une chronique d'observation de max annuels suivant une loi connue de Gumbel, de 10 ans en 10 ans, afin d'observer la variabilité des crues (ou des pluies d'ailleurs). On compare sur une autre vignette la loi ayant servi à la constitution de l'échantillon avec la relation Q(T) déduite des observations: plus on étend la période d'observation, plus on va converger vers la 'vraie' distribution (que l'on ne connaît pas dans le monde réel...). Un bouton "remise à zéro" efface la chronique et repart d'une série de 10 ans, ce qui permet aussi de voir que quel que soit le tirage de 10 ans les positions empiriques sont identiques (tant que a et b restent inchangées)...
|
|
|
La version plus aboutie, [Sample2Gumbel](https://gitlab.irstea.fr/christine.poulard/hydrotools-_-demo-and-processing-tools), est mise en ligne dans un groupe public "démos et outils". Elle dispose de plus de fonctionnalités, déclenchées par des icônes ajoutées à la toolbar plutôt que par les "boutons" de matplotlib, bien pratiques mais toujours pas très reconnaissables en tant que boutons.
|
|
|
|
|
|
|
|
|
# CODE **ProbaCruesMaxAn_SurNannees.py**
|
... | ... | @@ -52,14 +55,14 @@ On peut donc représenter ces probabilités en fonction de k soit par **plot** a |
|
|
On rappelle que la période de retour **T** est l’inverse de **f**, la fréquence au dépassement : **T= 1/f**.
|
|
|
On raisonne avec les crues maximales annuelles, on ne retient de chaque année que la plus forte occurrence de crue. Une crue centennale est dépassée en moyenne une fois tous les 100 ans et a donc une chance sur 100 d’être dépassée une année donnée : T=100 ans et f=1/100.
|
|
|
|
|
|
Si on illustre par un arbre des possibles, le nombre de réalisations pour lesquelles on a exactement **k** crues supérieures au niveau voulu est égal au nombre de façons de sélectionner **k** positions parmi **N**, soit **C(N,k)**. Pour ces **C(N,k)** réalisations, on a **k** fois un tirage de probabilité **f** et le reste du temps, soit **(N-p)** tirages, un tirage de probabilité complémentaire **(1-f)**.
|
|
|
Si on illustre par un arbre des possibles, le nombre de réalisations pour lesquelles on a exactement **k** crues supérieures au niveau voulu est égal au nombre de façons de sélectionner **k** positions parmi **N**, soit **C(N,k)**. Pour ces **C(N,k)** réalisations, on a **k** fois un tirage de probabilité **f** et le reste du temps, soit **(N-k)** tirages, un tirage de probabilité complémentaire **(1-f)**.
|
|
|
|
|
|
La probabilité d’avoir sur **N** années données exactement **k** crues qui dépassent le niveau de la crue de période de retour T=1/f se calcule donc par la formule : **C(N,k).f^k.(1-f)^(N-k).**
|
|
|
|
|
|
``` python
|
|
|
from scipy.special import comb
|
|
|
def proba_crue(n, k, f):
|
|
|
""" Probabilité d’avoir exactement k crues de fréquence f en n années : C(n,k)*f^p*(1-f)^(N-k)
|
|
|
""" Probabilité d’avoir exactement k crues de fréquence f en n années : C(n,k)*f^k*(1-f)^(N-k)
|
|
|
"""
|
|
|
return comb(n, k)*(f**k)*((1-f)**(n-k))
|
|
|
```
|
... | ... | @@ -90,7 +93,7 @@ On calcule les probabilités avec ces valeurs par défaut, et on recueille les r |
|
|
``` python
|
|
|
k, liste_probas_exactement, liste_probas_auplus = calcul_courbes(n, 1 / T)
|
|
|
```
|
|
|
Deux **sliders** vont permettre ensuite de modifier **N** et **T** ; on va relancer les calculs et tracer des résultats dès qu'ils seront modifiés. Ici, on a choisi de répercuter la modification aux vraibles N et T définies dans le corps du programme. Ce n'est pas forcément la meilleure façon de faire, mais pour un petit code cela ne paose pas de problème et cela va nous permettre de manipuler la notion de portée des variables.
|
|
|
Deux **sliders** vont permettre ensuite de modifier **N** et **T** ; on va relancer les calculs et tracer des résultats dès qu'ils seront modifiés. Ici, on a choisi de répercuter la modification aux vraibles N et T définies dans le corps du programme. Ce n'est pas forcément la meilleure façon de faire, mais pour un petit code avec donc peu de variables cela ne pose pas de problème (pas d'ambiguité possible) et cela va nous permettre de manipuler la notion de portée des variables.
|
|
|
|
|
|
|
|
|
## 2. La figure
|
... | ... | @@ -101,7 +104,7 @@ La figure est divisée en une grille de 1 colonne et 4 lignes, dont une ligne pl |
|
|
``` python
|
|
|
fig, (ax, ax_espace, ax_sn, ax_sT) = plt.subplots(nrows=4, ncols=1, gridspec_kw={'height_ratios':[6,1, 1,1]}, sharex=False)
|
|
|
```
|
|
|
Ensuite, il faut enlever les traits matérialisant les vignettes et rendre la vignette "intervalle" transparente, afin justement qu'elle joue sont rôle de marge,
|
|
|
Ensuite, il faut enlever les traits matérialisant les vignettes et rendre la vignette "intercalaire" transparente, afin qu'elle ne masque pas ce qui débord des autres axes.
|
|
|
``` python
|
|
|
for ax_s in [ax_espace, ax_sn, ax_sT]:
|
|
|
ax_s.xaxis.set_visible(False)
|
... | ... | |