Aller au contenu

Risques climatiques (kadi.weather.risk)

La classe Risk évalue les risques climatiques d'une localisation. Elle calcule les indices de sécheresse (SPI, Markov, Hurst) et prédit la probabilité de précipitation à court terme.

Elle est utilisée en interne par la façade Weather, mais peut aussi être instanciée directement pour des analyses spécifiques.


Importation directe

from kadi.weather import Risk

Initialisation

Risk n'est pas instanciée directement dans le cas courant : la façade Weather la crée automatiquement à la première utilisation d'une méthode de risque. Elle est alors accessible via weather.risk.

import kadi as kd

weather = kd.Weather(lat=9.3, lon=2.3, name="Parakou")

# Accès direct au composant Risk après un premier appel
secheresse = weather.drought()
risk = weather.risk   # Instance Risk disponible

Pour une instanciation directe :

from kadi.weather import Risk, Location
import pandas as pd

location = Location(lat=9.3, lon=2.3, name="Parakou")

# rainfall : pd.Series journalière indexée par date
# forecast : pd.DataFrame de prévisions météo

risk = Risk(location, rainfall, forecast)

Attributs publics :

Attribut Type Description
location Location Localisation associée
rainfall pd.Series Série historique de précipitations journalières
forecast pd.DataFrame Prévisions météorologiques

Méthodes

drought(method, window)

Calcule l'indice de sécheresse avec la méthode spécifiée.

# SPI sur une fenêtre de 3 mois
result = risk.drought(method="spi", window=3)
print(f"SPI 3 mois : {result['spi_3month']:.2f}")
print(f"Sévérité   : {result['drought_severity']}")

# Analyse Markov
result = risk.drought(method="markov")
print(f"P(sec|sec) : {result['markov_p_dry']:.2f}")

# Exposant de Hurst
result = risk.drought(method="hurst")
print(f"Hurst      : {result['hurst_exponent']:.2f}")

# Combinaison des trois méthodes
result = risk.drought(method="combined", window=3)

Paramètres :

Nom Type Défaut Description
method str 'spi' Méthode parmi 'spi', 'markov', 'hurst', 'combined'
window int 3 Fenêtre d'accumulation en mois (utilisée par le SPI)

Retour : dict - Les clés varient selon la méthode :

Clé Présente si Description
spi_Nmonth spi ou combined Valeur du SPI pour la fenêtre N
drought_severity spi ou combined Niveau de sévérité
markov_p_dry markov ou combined P(sec suivant
hurst_exponent hurst ou combined Exposant de Hurst H

Niveaux de sévérité SPI :

SPI Sévérité
> 1.0 no_drought (période humide)
-1.0 a 1.0 mild (conditions normales)
-1.5 a -1.0 moderate
< -1.5 severe

Exceptions :

  • ValidationError : méthode non supportée.

spi(window)

Calcule le Standardized Precipitation Index (SPI) selon McKee et al. (1993).

L'algorithme :

  1. Calcul du cumul de précipitations sur la fenêtre temporelle.
  2. Ajustement d'une loi Gamma sur les cumuls strictement positifs.
  3. Correction de masse de probabilité pour les jours sans pluie.
  4. Conversion en score SPI via la loi normale inverse.
spi_val = risk.spi(window=3)
print(f"SPI 3 mois : {spi_val:.2f}")

Paramètres :

Nom Type Défaut Description
window int 3 Fenêtre d'accumulation en mois

Retour : float - Valeur du SPI arrondie à 2 décimales. Vaut 0.0 si l'écart-type de la série est nul.

Exceptions :

  • DataError : série vide, moins de 30 fenêtres calculées, moins de 10 cumuls non nuls, ou échec de l'ajustement Gamma.

markov(thresh)

Calcule les probabilités de transition de Markov entre jours secs et jours humides.

trans = risk.markov(thresh=1.0)

print(f"P(sec  | sec précédent)    : {trans['p_dry_dry']:.2f}")
print(f"P(pluie | sec précédent)   : {trans['p_dry_wet']:.2f}")
print(f"P(sec  | pluie précédente) : {trans['p_wet_dry']:.2f}")
print(f"P(pluie | pluie précédente): {trans['p_wet_wet']:.2f}")

Paramètres :

Nom Type Défaut Description
thresh float 1.0 Seuil en mm pour qualifier un jour de humide

Retour : dict

Clé Description
p_dry_dry P(sec suivant / jour sec)
p_dry_wet P(humide suivant / jour sec)
p_wet_dry P(sec suivant / jour humide)
p_wet_wet P(humide suivant / jour humide)

Exceptions :

  • DataError : série historique vide.

hurst(window)

Calcule l'exposant de Hurst par la méthode de gamme rééchelonnée (R/S).

Un exposant H > 0.5 indique une persistance climatique (mémoire longue) : les périodes sèches ou humides ont tendance à se prolonger.

h = risk.hurst(window=1095)
print(f"Exposant de Hurst : {h:.2f}")

if h > 0.5:
    print("Persistance climatique détectée (mémoire longue).")
elif h < 0.5:
    print("Comportement antipersistant.")
else:
    print("Marche aléatoire (pas de mémoire).")

Paramètres :

Nom Type Défaut Description
window int 1095 Taille maximale de la fenêtre d'analyse en jours (environ 3 ans)

Retour : float - Exposant H, compris entre 0.01 et 0.99. Retourne 0.5 si la série est trop courte pour une régression fiable.

Exceptions :

  • DataError : moins de 100 jours de données.

rain_prob(days, min_mm)

Prévoit la probabilité de pluie pour les prochains jours.

Combine deux sources :

  • Prévisions Open-Meteo (pondération 70 %).
  • Probabilité de transition de Markov sur l'historique local (30 %).
proba = risk.rain_prob(days=3, min_mm=1.0)

print(f"Demain        : {proba['tomorrow'] * 100:.0f} %")
print(f"Dans 2 jours  : {proba['2_days'] * 100:.0f} %")
print(f"Message       : {proba['message']}")
print(f"Recommandation: {proba['recommendation']}")

Paramètres :

Nom Type Défaut Description
days int 1 Nombre de jours à prévoir (1 à 7)
min_mm float 1.0 Seuil de précipitation en mm pour qualifier un jour de humide

Retour : dict

Clé Type Description
tomorrow float Probabilité de pluie demain (si days >= 1)
N_days float Probabilité pour le jour N (N >= 2)
message str Phrase de synthèse avec le risque maximal
recommendation str Recommandation agronomique

Recommandations :

Risque maximal Recommandation
> 70 % Risque de lessivage élevé - repousser les traitements phytosanitaires
< 20 % Conditions sèches attendues - bon moment pour les traitements
Autre Vigilance recommandée pour les opérations au champ

Exceptions :

  • DataError : données de prévision absentes ou vides.

Méthodes dépréciées

Ancienne méthode Remplacée par Depuis
drought_index(method, window_months) drought(method, window) v1.2.0
markov_transition(threshold_mm) markov(thresh) v1.2.0
hurst_exponent(window) hurst(window) v1.2.0
rain_probability(days_ahead, min_rainfall_mm) rain_prob(days, min_mm) v1.2.0

Attributs dépréciés

Ancien attribut Remplacé par Depuis
rainfall_historical rainfall v1.2.0
forecast_data forecast v1.2.0

Risk

Évalue les risques climatiques (sécheresse, probabilité de pluie).

Attributs

location (Location): Localisation associée. rainfall (pd.Series): Série historique de précipitations journalières. forecast (pd.DataFrame): Prévisions météorologiques.

Source code in kadi/weather/risk.py
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
class Risk:
    """
    Évalue les risques climatiques (sécheresse, probabilité de pluie).

    Attributs:
        location (Location): Localisation associée.
        rainfall (pd.Series): Série historique de précipitations journalières.
        forecast (pd.DataFrame): Prévisions météorologiques.
    """

    def __init__(
        self,
        location: Location,
        rainfall_historical: pd.Series,
        forecast_data: pd.DataFrame,
    ):
        """
        Initialise les indicateurs de risque.

        Args:
            location (Location): Instance de la classe Location.
            rainfall_historical (pd.Series): Série historique de précipitations
                journalières.
            forecast_data (pd.DataFrame): DataFrame de prévisions météorologiques.
        """
        self.location = location
        # Nouveaux noms d'attributs
        self.rainfall = rainfall_historical
        self.forecast = forecast_data

    def drought(
        self,
        method: str = "spi",
        window: int = 3,
        window_months: Optional[int] = None,
    ) -> dict:
        """
        Calcule l'indice de sécheresse avec la méthode spécifiée.

        Args:
            method (str): Méthode de calcul parmi 'spi', 'markov', 'hurst' ou
                'combined' (toutes les méthodes combinées). Par défaut 'spi'.
            window (int): Fenêtre temporelle d'accumulation en mois pour le
                calcul du SPI. Par défaut 3.
            window_months (int, optionnel): Ancien nom du paramètre ``window``.

        Returns:
            dict: Dictionnaire avec les résultats de sécheresse. Les clés
                varient selon la méthode choisie (ex: 'spi_3month',
                'drought_severity', 'markov_p_dry', 'hurst_exponent').

        Raises:
            ValidationError: Si la méthode spécifiée n'est pas supportée.
        """
        if window_months is not None:
            warnings.warn(
                "Le paramètre 'window_months' est obsolète et sera supprimé dans "
                "KadiPy v2.0. Utilisez 'window' à la place.",
                category=DeprecationWarning,
                stacklevel=2,
            )
            window = window_months

        results = {}

        if method in ("spi", "combined"):
            spi_val = self.spi(window)
            results[f"spi_{window}month"] = spi_val
            results["drought_severity"] = self._severity(spi_val)

        if method in ("markov", "combined"):
            markov_res = self.markov()
            results["markov_p_dry"] = markov_res.get("p_dry_dry", 0.0)

        if method in ("hurst", "combined"):
            # L'exposant de Hurst nécessite une série assez longue
            hurst = self.hurst()
            results["hurst_exponent"] = round(hurst, 2)

        if method not in ("spi", "markov", "hurst", "combined"):
            raise ValidationError(
                f"Méthode {method} non supportée pour l'indice de sécheresse."
            )

        return results

    def spi(self, window: int = 3, window_months: Optional[int] = None) -> float:
        """
        Calcule le Standardized Precipitation Index (SPI) pour la période récente.

        La méthode suit la définition de McKee et al. (1993) :
        1. Calcul du cumul de précipitations sur la fenêtre temporelle.
        2. Ajustement d'une loi Gamma sur les cumuls strictement positifs.
        3. Correction de masse de probabilité pour les jours sans pluie.
        4. Conversion en score SPI via la loi normale inverse.

        Args:
            window (int): Fenêtre d'accumulation en mois.
            window_months (int, optionnel): Ancien nom du paramètre ``window``.

        Returns:
            float: Valeur du SPI arrondie à 2 décimales. Vaut 0.0 si tous les
                cumuls sont identiques (écart-type nul).

        Raises:
            DataError: Si la série est vide, si le nombre de fenêtres calculées
                est inférieur à 30, si les cumuls non nuls sont trop peu nombreux
                (moins de 10) pour ajuster une loi Gamma, ou si l'ajustement
                Gamma échoue numériquement.
        """
        if window_months is not None:
            warnings.warn(
                "Le paramètre 'window_months' est obsolète et sera supprimé dans "
                "KadiPy v2.0. Utilisez 'window' à la place.",
                category=DeprecationWarning,
                stacklevel=2,
            )
            window = window_months

        if self.rainfall.empty:
            raise DataError("Aucune donnée historique pour le calcul du SPI.")


        # Calcul des cumuls glissants sur la fenêtre temporelle
        days = window * 30
        rolling_sum = self.rainfall.rolling(
            window=days, min_periods=days // 2
        ).sum()
        rolling_sum = rolling_sum.dropna()

        # Vérification du nombre minimal de fenêtres
        if len(rolling_sum) < 30:
            raise DataError(
                "Pas assez de jours de données pour ajuster le modèle SPI "
                "(minimum 30 fenêtres requises)."
            )

        # Cas dégénéré : tous les cumuls sont identiques, le SPI est nul
        if rolling_sum.std() == 0:
            return 0.0

        # Valeur du cumul courant (point le plus récent de la série)
        current_val = float(rolling_sum.iloc[-1])

        # Calcul de la proportion de jours sans pluie (correction de masse)
        n_total = len(rolling_sum)
        n_zero = int((rolling_sum == 0).sum())
        q_zero = n_zero / n_total

        # Isolation des cumuls strictement positifs pour l'ajustement Gamma
        valid_data = rolling_sum[rolling_sum > 0].values

        if len(valid_data) < 10:
            raise DataError(
                "Pas assez de cumuls non nuls pour ajuster une loi Gamma "
                f"(trouvé {len(valid_data)}, minimum 10 requis). "
                "La période analysée est peut-être trop sèche."
            )

        # Ajustement de la loi Gamma (floc=0 fixe le paramètre de localisation)
        try:
            shape, loc, scale = stats.gamma.fit(valid_data, floc=0)
        except Exception as exc:
            raise DataError(
                f"L'ajustement de la loi Gamma a échoué : {exc}. "
                "Vérifiez la qualité de la série pluviométrique."
            ) from exc

        # Calcul de la probabilité cumulative avec correction de masse en 0
        if current_val == 0:
            # Les jours sans pluie tombent dans la masse ponctuelle en 0
            prob_cumul = q_zero / 2.0
        else:
            # Probabilité mixte : masse en 0 + CDF Gamma sur les valeurs positives
            prob_gamma = float(stats.gamma.cdf(current_val, shape, loc=loc, scale=scale))
            prob_cumul = q_zero + (1.0 - q_zero) * prob_gamma

        # Clip de sécurité pour éviter +/-inf lors de l'appel à norm.ppf
        prob_cumul = float(np.clip(prob_cumul, 1e-6, 1.0 - 1e-6))

        # Conversion en score SPI via la loi normale inverse
        spi_val = float(stats.norm.ppf(prob_cumul))
        return round(spi_val, 2)

    def markov(self, thresh: float = 1.0) -> dict:
        """
        Calcule les probabilités de transition de Markov entre jours secs et humides.

        Args:
            thresh (float): Seuil de précipitation en millimètres pour considérer
                un jour comme humide. Par défaut 1.0 mm.

        Returns:
            dict: Dictionnaire avec les quatre probabilités de transition :
                - 'p_dry_dry'  : P(sec | sec précédent)
                - 'p_dry_wet'  : P(humide | sec précédent)
                - 'p_wet_dry'  : P(sec | humide précédent)
                - 'p_wet_wet'  : P(humide | humide précédent)

        Raises:
            DataError: Si la série historique est vide.
        """
        if self.rainfall.empty:
            raise DataError(
                "Aucune donnée historique pour le calcul des probabilités "
                "de transition de Markov."
            )

        # États : 0 = sec, 1 = humide
        states = (self.rainfall >= thresh).astype(int)

        # Construction de la matrice de transitions
        transitions = pd.DataFrame(
            {"current": states.iloc[:-1].values, "next": states.iloc[1:].values}
        )

        counts = transitions.groupby(["current", "next"]).size().unstack(fill_value=0)

        # S'assure d'avoir la matrice 2x2
        for i in [0, 1]:
            if i not in counts.index:
                counts.loc[i] = [0, 0]
            for j in [0, 1]:
                if j not in counts.columns:
                    counts[j] = 0

        # Calcul des probabilités normalisées par ligne
        p0 = counts.loc[0].sum()
        p1 = counts.loc[1].sum()

        p00 = counts.loc[0, 0] / p0 if p0 > 0 else 0
        p01 = counts.loc[0, 1] / p0 if p0 > 0 else 0
        p10 = counts.loc[1, 0] / p1 if p1 > 0 else 0
        p11 = counts.loc[1, 1] / p1 if p1 > 0 else 0

        return {
            "p_dry_dry": round(p00, 2),
            "p_dry_wet": round(p01, 2),
            "p_wet_dry": round(p10, 2),
            "p_wet_wet": round(p11, 2),
        }

    def hurst(self, window: int = 1095) -> float:
        """
        Calcule l'exposant de Hurst par la méthode de gamme rééchelonnée (R/S).

        L'algorithme segmente la série en sous-fenêtres de tailles croissantes,
        calcule le rapport R/S moyen pour chaque taille, puis estime H par
        régression log-log. Un exposant H supérieur à 0.5 indique une persistance
        climatique (mémoire longue).

        Args:
            window (int): Taille maximale de la fenêtre d'analyse en jours.
                Par défaut 1095 (environ 3 ans). La fenêtre effective est
                plafonnée à la moitié de la longueur de la série.

        Returns:
            float: Exposant de Hurst H, compris entre 0.01 et 0.99. Retourne
                0.5 si la série est trop courte pour une régression fiable.

        Raises:
            DataError: Si la série historique contient moins de 100 jours.
        """
        if len(self.rainfall) < 100:
            raise DataError(
                "Pas assez de données pour l'exposant de Hurst "
                "(minimum 100 jours requis)."
            )

        data = self.rainfall.values
        n_total = len(data)

        # Taille de la plus petite fenêtre (assez grande pour un R/S stable)
        min_w = 10
        # Taille de la plus grande fenêtre (plafonnée à la moitié de la série)
        max_w = min(window, n_total // 2)

        window_sizes = []
        rs_means = []

        # Progression géométrique des tailles de fenêtre (facteur 1.5)
        w = min_w
        while w <= max_w:
            # Calcul du R/S moyen sur toutes les sous-séquences non chevauchantes
            num_segments = n_total // w
            rs_values_w = []

            for k in range(num_segments):
                segment = data[k * w: (k + 1) * w]
                seg_mean = np.mean(segment)
                centered = segment - seg_mean
                cum_dev = np.cumsum(centered)

                # Gamme (R) et écart-type (S) du segment
                r = np.max(cum_dev) - np.min(cum_dev)
                s = np.std(segment)

                if s > 0:
                    rs_values_w.append(r / s)

            if rs_values_w:
                window_sizes.append(w)
                rs_means.append(np.mean(rs_values_w))

            w = max(w + 1, int(w * 1.5))

        # Minimum de 3 points pour une régression fiable
        if len(window_sizes) < 3:
            return 0.5

        # Régression linéaire dans l'espace log-log : log(R/S) = H * log(N) + c
        log_n = np.log(np.array(window_sizes, dtype=float))
        log_rs = np.log(np.array(rs_means, dtype=float))
        coeffs = np.polyfit(log_n, log_rs, 1)

        # H est la pente de la droite de régression
        h = float(coeffs[0])
        return float(np.clip(h, 0.01, 0.99))

    def rain_prob(self, days: int = 1, min_mm: float = 1.0) -> dict:
        """
        Prévoit la probabilité de pluie pour les prochains jours.

        Combine deux sources d'information :
        1. Les prévisions API (Open-Meteo) pour le court terme.
        2. La probabilité de transition de Markov (calculée sur l'historique
           local) pour estimer la tendance climatique sous-jacente.
        La probabilité combinée pondère 70 % sur la prévision API et 30 %
        sur Markov.

        Args:
            days (int): Nombre de jours d'avance à calculer (1 à 7).
                Par défaut 1.
            min_mm (float): Seuil de précipitation en millimètres pour
                considérer un jour comme humide. Par défaut 1.0 mm.

        Returns:
            dict: Dictionnaire contenant :
                - 'tomorrow'   : probabilité de pluie demain (si days >= 1).
                - 'N_days'     : probabilité pour le jour N (N >= 2).
                - 'message'    : phrase de synthèse avec le risque maximal.
                - 'recommendation' : recommandation agronomique.

        Raises:
            DataError: Si les données de prévision sont absentes ou vides.
        """
        if self.forecast is None or self.forecast.empty:
            raise DataError(
                "Données de prévision indisponibles pour estimer la "
                "probabilité de pluie."
            )

        # Construction de la matrice de Markov depuis l'historique local
        try:
            markov = self.markov(min_mm)
            p_wet_if_wet = markov["p_wet_wet"]
            p_wet_if_dry = markov["p_dry_wet"]

            # État du dernier jour connu dans l'historique
            last_precip = (
                self.rainfall.iloc[-1]
                if not self.rainfall.empty
                else 0.0
            )
            current_p_wet = 1.0 if last_precip >= min_mm else 0.0
        except Exception:
            # Si Markov échoue, on ne l'utilise pas
            markov = None
            p_wet_if_wet = 0.5
            p_wet_if_dry = 0.5
            current_p_wet = 0.0

        df = self.forecast.head(days)
        probs = {}
        max_prob = 0.0

        for i, (date, row) in enumerate(df.iterrows()):
            forecast_precip = row.get("precipitation", 0.0)

            # 1. Probabilité issue de la prévision API (heuristique)
            prob_api = min(1.0, forecast_precip / (min_mm * 5))
            if forecast_precip < min_mm:
                prob_api *= 0.5

            # 2. Probabilité de Markov (probabilité conditionnelle d'un jour humide)
            prob_markov = (
                current_p_wet * p_wet_if_wet
                + (1.0 - current_p_wet) * p_wet_if_dry
            )

            # 3. Combinaison pondérée (API 70 %, Markov 30 %)
            prob_combined = 0.7 * prob_api + 0.3 * prob_markov

            # Mise à jour de l'état courant pour le jour suivant
            current_p_wet = prob_combined

            key = "tomorrow" if i == 0 else f"{i + 1}_days"
            probs[key] = round(prob_combined, 2)
            if prob_combined > max_prob:
                max_prob = prob_combined

        # Recommandations agronomiques selon le risque maximal
        msg = f"{int(max_prob * 100)} % de chance de pluie dans les {days} prochains jours."
        if max_prob > 0.7:
            rec = "Risque de lessivage élevé. Repousser les traitements phytosanitaires."
        elif max_prob < 0.2:
            rec = "Conditions sèches attendues. Bon moment pour les traitements phyto."
        else:
            rec = "Vigilance recommandée pour les opérations au champ."

        return {**probs, "message": msg, "recommendation": rec}

    def _severity(self, spi: float) -> str:
        """
        Interprète la valeur du SPI pour donner un niveau de sévérité.

        Args:
            spi (float): Valeur de l'indice SPI calculé par spi().

        Returns:
            str: Niveau de sévérité parmi :
                - 'no_drought' : SPI supérieur à 1.0 (période anormalement humide)
                - 'mild'       : -1.0 <= SPI <= 1.0 (conditions normales)
                - 'moderate'   : -1.5 <= SPI < -1.0
                - 'severe'     : SPI < -1.5
        """
        if spi > 1.0:
            return "no_drought"
        elif -1.0 <= spi <= 1.0:
            return "mild"
        elif -1.5 <= spi < -1.0:
            return "moderate"
        elif spi < -1.5:
            return "severe"
        return "unknown"

    # ----------------------------------------------------------------
    # Méthodes dépréciées (anciens noms publics)
    # ----------------------------------------------------------------

    def drought_index(self, method: str = "spi", window_months: int = 3) -> dict:
        """
        Ancienne méthode publique. Dépréciée depuis v1.2.0.

        Utilisez ``drought(method, window)`` à la place.

        Args:
            method (str): Méthode de calcul.
            window_months (int): Ancien nom de ``window``.

        Returns:
            dict: Résultats de l'indice de sécheresse.
        """
        warnings.warn(
            "Risk.drought_index() est obsolète et sera supprimé dans "
            "KadiPy v2.0. Utilisez drought() à la place.",
            category=DeprecationWarning,
            stacklevel=2,
        )
        return self.drought(method=method, window=window_months)

    def markov_transition(self, threshold_mm: float = 1.0) -> dict:
        """
        Ancienne méthode publique. Dépréciée depuis v1.2.0.

        Utilisez ``markov(thresh)`` à la place.

        Args:
            threshold_mm (float): Ancien nom de ``thresh``.

        Returns:
            dict: Probabilités de transition de Markov.
        """
        warnings.warn(
            "Risk.markov_transition() est obsolète et sera supprimé dans "
            "KadiPy v2.0. Utilisez markov() à la place.",
            category=DeprecationWarning,
            stacklevel=2,
        )
        return self.markov(thresh=threshold_mm)

    def hurst_exponent(self, window: int = 1095) -> float:
        """
        Ancienne méthode publique. Dépréciée depuis v1.2.0.

        Utilisez ``hurst(window)`` à la place.

        Args:
            window (int): Taille maximale de la fenêtre d'analyse.

        Returns:
            float: Exposant de Hurst H.
        """
        warnings.warn(
            "Risk.hurst_exponent() est obsolète et sera supprimé dans "
            "KadiPy v2.0. Utilisez hurst() à la place.",
            category=DeprecationWarning,
            stacklevel=2,
        )
        return self.hurst(window=window)

    def rain_probability(self, days_ahead: int = 1, min_rainfall_mm: float = 1.0) -> dict:
        """
        Ancienne méthode publique. Dépréciée depuis v1.2.0.

        Utilisez ``rain_prob(days, min_mm)`` à la place.

        Args:
            days_ahead (int): Ancien nom de ``days``.
            min_rainfall_mm (float): Ancien nom de ``min_mm``.

        Returns:
            dict: Probabilité de pluie et recommandations.
        """
        warnings.warn(
            "Risk.rain_probability() est obsolète et sera supprimé dans "
            "KadiPy v2.0. Utilisez rain_prob() à la place.",
            category=DeprecationWarning,
            stacklevel=2,
        )
        return self.rain_prob(days=days_ahead, min_mm=min_rainfall_mm)

    # ----------------------------------------------------------------
    # Propriétés de rétrocompatibilité (anciens noms d'attributs)
    # ----------------------------------------------------------------

    @property
    def rainfall_historical(self) -> pd.Series:
        """Ancien nom de ``rainfall``. Déprécié depuis v1.2.0."""
        warnings.warn(
            "Risk.rainfall_historical est obsolète et sera supprimé dans "
            "KadiPy v2.0. Utilisez Risk.rainfall à la place.",
            category=DeprecationWarning,
            stacklevel=2,
        )
        return self.rainfall

    @rainfall_historical.setter
    def rainfall_historical(self, value: pd.Series) -> None:
        """Ancien setter de ``rainfall``. Déprécié depuis v1.2.0."""
        warnings.warn(
            "Risk.rainfall_historical est obsolète et sera supprimé dans "
            "KadiPy v2.0. Utilisez Risk.rainfall à la place.",
            category=DeprecationWarning,
            stacklevel=2,
        )
        self.rainfall = value

    @property
    def forecast_data(self) -> pd.DataFrame:
        """Ancien nom de ``forecast``. Déprécié depuis v1.2.0."""
        warnings.warn(
            "Risk.forecast_data est obsolète et sera supprimé dans "
            "KadiPy v2.0. Utilisez Risk.forecast à la place.",
            category=DeprecationWarning,
            stacklevel=2,
        )
        return self.forecast

    @forecast_data.setter
    def forecast_data(self, value: pd.DataFrame) -> None:
        """Ancien setter de ``forecast``. Déprécié depuis v1.2.0."""
        warnings.warn(
            "Risk.forecast_data est obsolète et sera supprimé dans "
            "KadiPy v2.0. Utilisez Risk.forecast à la place.",
            category=DeprecationWarning,
            stacklevel=2,
        )
        self.forecast = value

rainfall_historical property writable

rainfall_historical: Series

Ancien nom de rainfall. Déprécié depuis v1.2.0.

forecast_data property writable

forecast_data: DataFrame

Ancien nom de forecast. Déprécié depuis v1.2.0.

__init__

__init__(location: Location, rainfall_historical: Series, forecast_data: DataFrame)

Initialise les indicateurs de risque.

Parameters:

Name Type Description Default
location Location

Instance de la classe Location.

required
rainfall_historical Series

Série historique de précipitations journalières.

required
forecast_data DataFrame

DataFrame de prévisions météorologiques.

required
Source code in kadi/weather/risk.py
def __init__(
    self,
    location: Location,
    rainfall_historical: pd.Series,
    forecast_data: pd.DataFrame,
):
    """
    Initialise les indicateurs de risque.

    Args:
        location (Location): Instance de la classe Location.
        rainfall_historical (pd.Series): Série historique de précipitations
            journalières.
        forecast_data (pd.DataFrame): DataFrame de prévisions météorologiques.
    """
    self.location = location
    # Nouveaux noms d'attributs
    self.rainfall = rainfall_historical
    self.forecast = forecast_data

drought

drought(method: str = 'spi', window: int = 3, window_months: Optional[int] = None) -> dict

Calcule l'indice de sécheresse avec la méthode spécifiée.

Parameters:

Name Type Description Default
method str

Méthode de calcul parmi 'spi', 'markov', 'hurst' ou 'combined' (toutes les méthodes combinées). Par défaut 'spi'.

'spi'
window int

Fenêtre temporelle d'accumulation en mois pour le calcul du SPI. Par défaut 3.

3
window_months (int, optionnel)

Ancien nom du paramètre window.

None

Returns:

Name Type Description
dict dict

Dictionnaire avec les résultats de sécheresse. Les clés varient selon la méthode choisie (ex: 'spi_3month', 'drought_severity', 'markov_p_dry', 'hurst_exponent').

Raises:

Type Description
ValidationError

Si la méthode spécifiée n'est pas supportée.

Source code in kadi/weather/risk.py
def drought(
    self,
    method: str = "spi",
    window: int = 3,
    window_months: Optional[int] = None,
) -> dict:
    """
    Calcule l'indice de sécheresse avec la méthode spécifiée.

    Args:
        method (str): Méthode de calcul parmi 'spi', 'markov', 'hurst' ou
            'combined' (toutes les méthodes combinées). Par défaut 'spi'.
        window (int): Fenêtre temporelle d'accumulation en mois pour le
            calcul du SPI. Par défaut 3.
        window_months (int, optionnel): Ancien nom du paramètre ``window``.

    Returns:
        dict: Dictionnaire avec les résultats de sécheresse. Les clés
            varient selon la méthode choisie (ex: 'spi_3month',
            'drought_severity', 'markov_p_dry', 'hurst_exponent').

    Raises:
        ValidationError: Si la méthode spécifiée n'est pas supportée.
    """
    if window_months is not None:
        warnings.warn(
            "Le paramètre 'window_months' est obsolète et sera supprimé dans "
            "KadiPy v2.0. Utilisez 'window' à la place.",
            category=DeprecationWarning,
            stacklevel=2,
        )
        window = window_months

    results = {}

    if method in ("spi", "combined"):
        spi_val = self.spi(window)
        results[f"spi_{window}month"] = spi_val
        results["drought_severity"] = self._severity(spi_val)

    if method in ("markov", "combined"):
        markov_res = self.markov()
        results["markov_p_dry"] = markov_res.get("p_dry_dry", 0.0)

    if method in ("hurst", "combined"):
        # L'exposant de Hurst nécessite une série assez longue
        hurst = self.hurst()
        results["hurst_exponent"] = round(hurst, 2)

    if method not in ("spi", "markov", "hurst", "combined"):
        raise ValidationError(
            f"Méthode {method} non supportée pour l'indice de sécheresse."
        )

    return results

spi

spi(window: int = 3, window_months: Optional[int] = None) -> float

Calcule le Standardized Precipitation Index (SPI) pour la période récente.

La méthode suit la définition de McKee et al. (1993) : 1. Calcul du cumul de précipitations sur la fenêtre temporelle. 2. Ajustement d'une loi Gamma sur les cumuls strictement positifs. 3. Correction de masse de probabilité pour les jours sans pluie. 4. Conversion en score SPI via la loi normale inverse.

Parameters:

Name Type Description Default
window int

Fenêtre d'accumulation en mois.

3
window_months (int, optionnel)

Ancien nom du paramètre window.

None

Returns:

Name Type Description
float float

Valeur du SPI arrondie à 2 décimales. Vaut 0.0 si tous les cumuls sont identiques (écart-type nul).

Raises:

Type Description
DataError

Si la série est vide, si le nombre de fenêtres calculées est inférieur à 30, si les cumuls non nuls sont trop peu nombreux (moins de 10) pour ajuster une loi Gamma, ou si l'ajustement Gamma échoue numériquement.

Source code in kadi/weather/risk.py
def spi(self, window: int = 3, window_months: Optional[int] = None) -> float:
    """
    Calcule le Standardized Precipitation Index (SPI) pour la période récente.

    La méthode suit la définition de McKee et al. (1993) :
    1. Calcul du cumul de précipitations sur la fenêtre temporelle.
    2. Ajustement d'une loi Gamma sur les cumuls strictement positifs.
    3. Correction de masse de probabilité pour les jours sans pluie.
    4. Conversion en score SPI via la loi normale inverse.

    Args:
        window (int): Fenêtre d'accumulation en mois.
        window_months (int, optionnel): Ancien nom du paramètre ``window``.

    Returns:
        float: Valeur du SPI arrondie à 2 décimales. Vaut 0.0 si tous les
            cumuls sont identiques (écart-type nul).

    Raises:
        DataError: Si la série est vide, si le nombre de fenêtres calculées
            est inférieur à 30, si les cumuls non nuls sont trop peu nombreux
            (moins de 10) pour ajuster une loi Gamma, ou si l'ajustement
            Gamma échoue numériquement.
    """
    if window_months is not None:
        warnings.warn(
            "Le paramètre 'window_months' est obsolète et sera supprimé dans "
            "KadiPy v2.0. Utilisez 'window' à la place.",
            category=DeprecationWarning,
            stacklevel=2,
        )
        window = window_months

    if self.rainfall.empty:
        raise DataError("Aucune donnée historique pour le calcul du SPI.")


    # Calcul des cumuls glissants sur la fenêtre temporelle
    days = window * 30
    rolling_sum = self.rainfall.rolling(
        window=days, min_periods=days // 2
    ).sum()
    rolling_sum = rolling_sum.dropna()

    # Vérification du nombre minimal de fenêtres
    if len(rolling_sum) < 30:
        raise DataError(
            "Pas assez de jours de données pour ajuster le modèle SPI "
            "(minimum 30 fenêtres requises)."
        )

    # Cas dégénéré : tous les cumuls sont identiques, le SPI est nul
    if rolling_sum.std() == 0:
        return 0.0

    # Valeur du cumul courant (point le plus récent de la série)
    current_val = float(rolling_sum.iloc[-1])

    # Calcul de la proportion de jours sans pluie (correction de masse)
    n_total = len(rolling_sum)
    n_zero = int((rolling_sum == 0).sum())
    q_zero = n_zero / n_total

    # Isolation des cumuls strictement positifs pour l'ajustement Gamma
    valid_data = rolling_sum[rolling_sum > 0].values

    if len(valid_data) < 10:
        raise DataError(
            "Pas assez de cumuls non nuls pour ajuster une loi Gamma "
            f"(trouvé {len(valid_data)}, minimum 10 requis). "
            "La période analysée est peut-être trop sèche."
        )

    # Ajustement de la loi Gamma (floc=0 fixe le paramètre de localisation)
    try:
        shape, loc, scale = stats.gamma.fit(valid_data, floc=0)
    except Exception as exc:
        raise DataError(
            f"L'ajustement de la loi Gamma a échoué : {exc}. "
            "Vérifiez la qualité de la série pluviométrique."
        ) from exc

    # Calcul de la probabilité cumulative avec correction de masse en 0
    if current_val == 0:
        # Les jours sans pluie tombent dans la masse ponctuelle en 0
        prob_cumul = q_zero / 2.0
    else:
        # Probabilité mixte : masse en 0 + CDF Gamma sur les valeurs positives
        prob_gamma = float(stats.gamma.cdf(current_val, shape, loc=loc, scale=scale))
        prob_cumul = q_zero + (1.0 - q_zero) * prob_gamma

    # Clip de sécurité pour éviter +/-inf lors de l'appel à norm.ppf
    prob_cumul = float(np.clip(prob_cumul, 1e-6, 1.0 - 1e-6))

    # Conversion en score SPI via la loi normale inverse
    spi_val = float(stats.norm.ppf(prob_cumul))
    return round(spi_val, 2)

markov

markov(thresh: float = 1.0) -> dict

Calcule les probabilités de transition de Markov entre jours secs et humides.

Parameters:

Name Type Description Default
thresh float

Seuil de précipitation en millimètres pour considérer un jour comme humide. Par défaut 1.0 mm.

1.0

Returns:

Name Type Description
dict dict

Dictionnaire avec les quatre probabilités de transition : - 'p_dry_dry' : P(sec | sec précédent) - 'p_dry_wet' : P(humide | sec précédent) - 'p_wet_dry' : P(sec | humide précédent) - 'p_wet_wet' : P(humide | humide précédent)

Raises:

Type Description
DataError

Si la série historique est vide.

Source code in kadi/weather/risk.py
def markov(self, thresh: float = 1.0) -> dict:
    """
    Calcule les probabilités de transition de Markov entre jours secs et humides.

    Args:
        thresh (float): Seuil de précipitation en millimètres pour considérer
            un jour comme humide. Par défaut 1.0 mm.

    Returns:
        dict: Dictionnaire avec les quatre probabilités de transition :
            - 'p_dry_dry'  : P(sec | sec précédent)
            - 'p_dry_wet'  : P(humide | sec précédent)
            - 'p_wet_dry'  : P(sec | humide précédent)
            - 'p_wet_wet'  : P(humide | humide précédent)

    Raises:
        DataError: Si la série historique est vide.
    """
    if self.rainfall.empty:
        raise DataError(
            "Aucune donnée historique pour le calcul des probabilités "
            "de transition de Markov."
        )

    # États : 0 = sec, 1 = humide
    states = (self.rainfall >= thresh).astype(int)

    # Construction de la matrice de transitions
    transitions = pd.DataFrame(
        {"current": states.iloc[:-1].values, "next": states.iloc[1:].values}
    )

    counts = transitions.groupby(["current", "next"]).size().unstack(fill_value=0)

    # S'assure d'avoir la matrice 2x2
    for i in [0, 1]:
        if i not in counts.index:
            counts.loc[i] = [0, 0]
        for j in [0, 1]:
            if j not in counts.columns:
                counts[j] = 0

    # Calcul des probabilités normalisées par ligne
    p0 = counts.loc[0].sum()
    p1 = counts.loc[1].sum()

    p00 = counts.loc[0, 0] / p0 if p0 > 0 else 0
    p01 = counts.loc[0, 1] / p0 if p0 > 0 else 0
    p10 = counts.loc[1, 0] / p1 if p1 > 0 else 0
    p11 = counts.loc[1, 1] / p1 if p1 > 0 else 0

    return {
        "p_dry_dry": round(p00, 2),
        "p_dry_wet": round(p01, 2),
        "p_wet_dry": round(p10, 2),
        "p_wet_wet": round(p11, 2),
    }

hurst

hurst(window: int = 1095) -> float

Calcule l'exposant de Hurst par la méthode de gamme rééchelonnée (R/S).

L'algorithme segmente la série en sous-fenêtres de tailles croissantes, calcule le rapport R/S moyen pour chaque taille, puis estime H par régression log-log. Un exposant H supérieur à 0.5 indique une persistance climatique (mémoire longue).

Parameters:

Name Type Description Default
window int

Taille maximale de la fenêtre d'analyse en jours. Par défaut 1095 (environ 3 ans). La fenêtre effective est plafonnée à la moitié de la longueur de la série.

1095

Returns:

Name Type Description
float float

Exposant de Hurst H, compris entre 0.01 et 0.99. Retourne 0.5 si la série est trop courte pour une régression fiable.

Raises:

Type Description
DataError

Si la série historique contient moins de 100 jours.

Source code in kadi/weather/risk.py
def hurst(self, window: int = 1095) -> float:
    """
    Calcule l'exposant de Hurst par la méthode de gamme rééchelonnée (R/S).

    L'algorithme segmente la série en sous-fenêtres de tailles croissantes,
    calcule le rapport R/S moyen pour chaque taille, puis estime H par
    régression log-log. Un exposant H supérieur à 0.5 indique une persistance
    climatique (mémoire longue).

    Args:
        window (int): Taille maximale de la fenêtre d'analyse en jours.
            Par défaut 1095 (environ 3 ans). La fenêtre effective est
            plafonnée à la moitié de la longueur de la série.

    Returns:
        float: Exposant de Hurst H, compris entre 0.01 et 0.99. Retourne
            0.5 si la série est trop courte pour une régression fiable.

    Raises:
        DataError: Si la série historique contient moins de 100 jours.
    """
    if len(self.rainfall) < 100:
        raise DataError(
            "Pas assez de données pour l'exposant de Hurst "
            "(minimum 100 jours requis)."
        )

    data = self.rainfall.values
    n_total = len(data)

    # Taille de la plus petite fenêtre (assez grande pour un R/S stable)
    min_w = 10
    # Taille de la plus grande fenêtre (plafonnée à la moitié de la série)
    max_w = min(window, n_total // 2)

    window_sizes = []
    rs_means = []

    # Progression géométrique des tailles de fenêtre (facteur 1.5)
    w = min_w
    while w <= max_w:
        # Calcul du R/S moyen sur toutes les sous-séquences non chevauchantes
        num_segments = n_total // w
        rs_values_w = []

        for k in range(num_segments):
            segment = data[k * w: (k + 1) * w]
            seg_mean = np.mean(segment)
            centered = segment - seg_mean
            cum_dev = np.cumsum(centered)

            # Gamme (R) et écart-type (S) du segment
            r = np.max(cum_dev) - np.min(cum_dev)
            s = np.std(segment)

            if s > 0:
                rs_values_w.append(r / s)

        if rs_values_w:
            window_sizes.append(w)
            rs_means.append(np.mean(rs_values_w))

        w = max(w + 1, int(w * 1.5))

    # Minimum de 3 points pour une régression fiable
    if len(window_sizes) < 3:
        return 0.5

    # Régression linéaire dans l'espace log-log : log(R/S) = H * log(N) + c
    log_n = np.log(np.array(window_sizes, dtype=float))
    log_rs = np.log(np.array(rs_means, dtype=float))
    coeffs = np.polyfit(log_n, log_rs, 1)

    # H est la pente de la droite de régression
    h = float(coeffs[0])
    return float(np.clip(h, 0.01, 0.99))

rain_prob

rain_prob(days: int = 1, min_mm: float = 1.0) -> dict

Prévoit la probabilité de pluie pour les prochains jours.

Combine deux sources d'information : 1. Les prévisions API (Open-Meteo) pour le court terme. 2. La probabilité de transition de Markov (calculée sur l'historique local) pour estimer la tendance climatique sous-jacente. La probabilité combinée pondère 70 % sur la prévision API et 30 % sur Markov.

Parameters:

Name Type Description Default
days int

Nombre de jours d'avance à calculer (1 à 7). Par défaut 1.

1
min_mm float

Seuil de précipitation en millimètres pour considérer un jour comme humide. Par défaut 1.0 mm.

1.0

Returns:

Name Type Description
dict dict

Dictionnaire contenant : - 'tomorrow' : probabilité de pluie demain (si days >= 1). - 'N_days' : probabilité pour le jour N (N >= 2). - 'message' : phrase de synthèse avec le risque maximal. - 'recommendation' : recommandation agronomique.

Raises:

Type Description
DataError

Si les données de prévision sont absentes ou vides.

Source code in kadi/weather/risk.py
def rain_prob(self, days: int = 1, min_mm: float = 1.0) -> dict:
    """
    Prévoit la probabilité de pluie pour les prochains jours.

    Combine deux sources d'information :
    1. Les prévisions API (Open-Meteo) pour le court terme.
    2. La probabilité de transition de Markov (calculée sur l'historique
       local) pour estimer la tendance climatique sous-jacente.
    La probabilité combinée pondère 70 % sur la prévision API et 30 %
    sur Markov.

    Args:
        days (int): Nombre de jours d'avance à calculer (1 à 7).
            Par défaut 1.
        min_mm (float): Seuil de précipitation en millimètres pour
            considérer un jour comme humide. Par défaut 1.0 mm.

    Returns:
        dict: Dictionnaire contenant :
            - 'tomorrow'   : probabilité de pluie demain (si days >= 1).
            - 'N_days'     : probabilité pour le jour N (N >= 2).
            - 'message'    : phrase de synthèse avec le risque maximal.
            - 'recommendation' : recommandation agronomique.

    Raises:
        DataError: Si les données de prévision sont absentes ou vides.
    """
    if self.forecast is None or self.forecast.empty:
        raise DataError(
            "Données de prévision indisponibles pour estimer la "
            "probabilité de pluie."
        )

    # Construction de la matrice de Markov depuis l'historique local
    try:
        markov = self.markov(min_mm)
        p_wet_if_wet = markov["p_wet_wet"]
        p_wet_if_dry = markov["p_dry_wet"]

        # État du dernier jour connu dans l'historique
        last_precip = (
            self.rainfall.iloc[-1]
            if not self.rainfall.empty
            else 0.0
        )
        current_p_wet = 1.0 if last_precip >= min_mm else 0.0
    except Exception:
        # Si Markov échoue, on ne l'utilise pas
        markov = None
        p_wet_if_wet = 0.5
        p_wet_if_dry = 0.5
        current_p_wet = 0.0

    df = self.forecast.head(days)
    probs = {}
    max_prob = 0.0

    for i, (date, row) in enumerate(df.iterrows()):
        forecast_precip = row.get("precipitation", 0.0)

        # 1. Probabilité issue de la prévision API (heuristique)
        prob_api = min(1.0, forecast_precip / (min_mm * 5))
        if forecast_precip < min_mm:
            prob_api *= 0.5

        # 2. Probabilité de Markov (probabilité conditionnelle d'un jour humide)
        prob_markov = (
            current_p_wet * p_wet_if_wet
            + (1.0 - current_p_wet) * p_wet_if_dry
        )

        # 3. Combinaison pondérée (API 70 %, Markov 30 %)
        prob_combined = 0.7 * prob_api + 0.3 * prob_markov

        # Mise à jour de l'état courant pour le jour suivant
        current_p_wet = prob_combined

        key = "tomorrow" if i == 0 else f"{i + 1}_days"
        probs[key] = round(prob_combined, 2)
        if prob_combined > max_prob:
            max_prob = prob_combined

    # Recommandations agronomiques selon le risque maximal
    msg = f"{int(max_prob * 100)} % de chance de pluie dans les {days} prochains jours."
    if max_prob > 0.7:
        rec = "Risque de lessivage élevé. Repousser les traitements phytosanitaires."
    elif max_prob < 0.2:
        rec = "Conditions sèches attendues. Bon moment pour les traitements phyto."
    else:
        rec = "Vigilance recommandée pour les opérations au champ."

    return {**probs, "message": msg, "recommendation": rec}

drought_index

drought_index(method: str = 'spi', window_months: int = 3) -> dict

Ancienne méthode publique. Dépréciée depuis v1.2.0.

Utilisez drought(method, window) à la place.

Parameters:

Name Type Description Default
method str

Méthode de calcul.

'spi'
window_months int

Ancien nom de window.

3

Returns:

Name Type Description
dict dict

Résultats de l'indice de sécheresse.

Source code in kadi/weather/risk.py
def drought_index(self, method: str = "spi", window_months: int = 3) -> dict:
    """
    Ancienne méthode publique. Dépréciée depuis v1.2.0.

    Utilisez ``drought(method, window)`` à la place.

    Args:
        method (str): Méthode de calcul.
        window_months (int): Ancien nom de ``window``.

    Returns:
        dict: Résultats de l'indice de sécheresse.
    """
    warnings.warn(
        "Risk.drought_index() est obsolète et sera supprimé dans "
        "KadiPy v2.0. Utilisez drought() à la place.",
        category=DeprecationWarning,
        stacklevel=2,
    )
    return self.drought(method=method, window=window_months)

markov_transition

markov_transition(threshold_mm: float = 1.0) -> dict

Ancienne méthode publique. Dépréciée depuis v1.2.0.

Utilisez markov(thresh) à la place.

Parameters:

Name Type Description Default
threshold_mm float

Ancien nom de thresh.

1.0

Returns:

Name Type Description
dict dict

Probabilités de transition de Markov.

Source code in kadi/weather/risk.py
def markov_transition(self, threshold_mm: float = 1.0) -> dict:
    """
    Ancienne méthode publique. Dépréciée depuis v1.2.0.

    Utilisez ``markov(thresh)`` à la place.

    Args:
        threshold_mm (float): Ancien nom de ``thresh``.

    Returns:
        dict: Probabilités de transition de Markov.
    """
    warnings.warn(
        "Risk.markov_transition() est obsolète et sera supprimé dans "
        "KadiPy v2.0. Utilisez markov() à la place.",
        category=DeprecationWarning,
        stacklevel=2,
    )
    return self.markov(thresh=threshold_mm)

hurst_exponent

hurst_exponent(window: int = 1095) -> float

Ancienne méthode publique. Dépréciée depuis v1.2.0.

Utilisez hurst(window) à la place.

Parameters:

Name Type Description Default
window int

Taille maximale de la fenêtre d'analyse.

1095

Returns:

Name Type Description
float float

Exposant de Hurst H.

Source code in kadi/weather/risk.py
def hurst_exponent(self, window: int = 1095) -> float:
    """
    Ancienne méthode publique. Dépréciée depuis v1.2.0.

    Utilisez ``hurst(window)`` à la place.

    Args:
        window (int): Taille maximale de la fenêtre d'analyse.

    Returns:
        float: Exposant de Hurst H.
    """
    warnings.warn(
        "Risk.hurst_exponent() est obsolète et sera supprimé dans "
        "KadiPy v2.0. Utilisez hurst() à la place.",
        category=DeprecationWarning,
        stacklevel=2,
    )
    return self.hurst(window=window)

rain_probability

rain_probability(days_ahead: int = 1, min_rainfall_mm: float = 1.0) -> dict

Ancienne méthode publique. Dépréciée depuis v1.2.0.

Utilisez rain_prob(days, min_mm) à la place.

Parameters:

Name Type Description Default
days_ahead int

Ancien nom de days.

1
min_rainfall_mm float

Ancien nom de min_mm.

1.0

Returns:

Name Type Description
dict dict

Probabilité de pluie et recommandations.

Source code in kadi/weather/risk.py
def rain_probability(self, days_ahead: int = 1, min_rainfall_mm: float = 1.0) -> dict:
    """
    Ancienne méthode publique. Dépréciée depuis v1.2.0.

    Utilisez ``rain_prob(days, min_mm)`` à la place.

    Args:
        days_ahead (int): Ancien nom de ``days``.
        min_rainfall_mm (float): Ancien nom de ``min_mm``.

    Returns:
        dict: Probabilité de pluie et recommandations.
    """
    warnings.warn(
        "Risk.rain_probability() est obsolète et sera supprimé dans "
        "KadiPy v2.0. Utilisez rain_prob() à la place.",
        category=DeprecationWarning,
        stacklevel=2,
    )
    return self.rain_prob(days=days_ahead, min_mm=min_rainfall_mm)