Spaces:
Build error
Build error
| """ | |
| Modelo de dominio para anomalías detectadas. | |
| Este módulo define la entidad AnomalyPoint, cumpliendo con SRP. | |
| """ | |
| from dataclasses import dataclass | |
| from typing import Optional | |
| class AnomalyPoint: | |
| """ | |
| Representa un punto con posible anomalía detectada. | |
| Attributes: | |
| index: Índice del punto en la serie | |
| value: Valor observado | |
| expected: Valor esperado (mediana del pronóstico) | |
| lower_bound: Límite inferior del intervalo de confianza | |
| upper_bound: Límite superior del intervalo de confianza | |
| is_anomaly: Indica si el punto es una anomalía | |
| z_score: Puntuación Z del punto (opcional) | |
| severity: Severidad de la anomalía (low, medium, high) | |
| Example: | |
| >>> point = AnomalyPoint( | |
| ... index=5, | |
| ... value=200.0, | |
| ... expected=120.0, | |
| ... lower_bound=115.0, | |
| ... upper_bound=125.0, | |
| ... is_anomaly=True, | |
| ... z_score=4.5 | |
| ... ) | |
| >>> point.deviation | |
| 80.0 | |
| >>> point.severity | |
| 'high' | |
| """ | |
| index: int | |
| value: float | |
| expected: float | |
| lower_bound: float | |
| upper_bound: float | |
| is_anomaly: bool | |
| z_score: float = 0.0 | |
| severity: Optional[str] = None | |
| def __post_init__(self): | |
| """Cálculo automático de severidad""" | |
| if self.severity is None and self.is_anomaly: | |
| self.severity = self._calculate_severity() | |
| def deviation(self) -> float: | |
| """ | |
| Calcula la desviación del valor respecto al esperado. | |
| Returns: | |
| float: Diferencia absoluta entre valor y esperado | |
| """ | |
| return abs(self.value - self.expected) | |
| def deviation_percentage(self) -> float: | |
| """ | |
| Calcula el porcentaje de desviación. | |
| Returns: | |
| float: Desviación como porcentaje del valor esperado | |
| """ | |
| if self.expected == 0: | |
| return float('inf') if self.value != 0 else 0.0 | |
| return (self.deviation / abs(self.expected)) * 100 | |
| def _calculate_severity(self) -> str: | |
| """ | |
| Calcula la severidad de la anomalía basada en z_score. | |
| Returns: | |
| str: "low", "medium" o "high" | |
| """ | |
| abs_z = abs(self.z_score) | |
| if abs_z >= 4.0: | |
| return "high" | |
| elif abs_z >= 3.0: | |
| return "medium" | |
| else: | |
| return "low" | |
| def is_above_expected(self) -> bool: | |
| """Retorna True si el valor está por encima del esperado""" | |
| return self.value > self.expected | |
| def is_below_expected(self) -> bool: | |
| """Retorna True si el valor está por debajo del esperado""" | |
| return self.value < self.expected | |
| def to_dict(self) -> dict: | |
| """Serializa el punto a diccionario""" | |
| return { | |
| "index": self.index, | |
| "value": self.value, | |
| "expected": self.expected, | |
| "lower_bound": self.lower_bound, | |
| "upper_bound": self.upper_bound, | |
| "is_anomaly": self.is_anomaly, | |
| "z_score": self.z_score, | |
| "severity": self.severity, | |
| "deviation": self.deviation, | |
| "deviation_percentage": self.deviation_percentage | |
| } | |