Implement confidence intervals for irm_kmi.get_forecasts_radar

This commit is contained in:
Jules 2024-06-01 20:35:28 +02:00
parent 0812ef5eef
commit a952e3566f
Signed by: jdejaegh
GPG key ID: 99D6D184CA66933A
5 changed files with 1625 additions and 29 deletions

View file

@ -2,6 +2,7 @@
import asyncio
import logging
from datetime import datetime, timedelta
from statistics import mean
from typing import Any, List, Tuple
import async_timeout
@ -23,7 +24,7 @@ from .const import IRM_KMI_TO_HA_CONDITION_MAP as CDT_MAP
from .const import MAP_WARNING_ID_TO_SLUG as SLUG_MAP
from .const import OPTION_STYLE_SATELLITE, OUT_OF_BENELUX, STYLE_TO_PARAM_MAP
from .data import (AnimationFrameData, CurrentWeatherData, IrmKmiForecast,
ProcessedCoordinatorData, RadarAnimationData, WarningData)
ProcessedCoordinatorData, RadarAnimationData, WarningData, IrmKmiRadarForecast)
from .pollen import PollenParser
from .rain_graph import RainGraph
from .utils import disable_from_config, get_config_value, preferred_language
@ -322,16 +323,26 @@ class IrmKmiCoordinator(TimestampDataUpdateCoordinator):
return forecasts
@staticmethod
def radar_list_to_forecast(data: dict | None) -> List[Forecast] | None:
def radar_list_to_forecast(data: dict | None) -> List[IrmKmiRadarForecast] | None:
if data is None:
return None
sequence = data.get("sequence", [])
ratios = [f['value'] / f['position'] for f in sequence if f['position'] > 0]
if len(ratios) > 0:
ratio = mean(ratios)
else:
ratio = 0
forecast = list()
for f in data.get("sequence", []):
for f in sequence:
forecast.append(
Forecast(
IrmKmiRadarForecast(
datetime=f.get("time"),
native_precipitation=f.get('value')
native_precipitation=f.get('value'),
rain_forecast_max=round(f.get('positionHigher')*ratio, 2),
rain_forecast_min=round(f.get('positionLower')*ratio, 2),
might_rain=f.get('positionHigher') > 0
)
)
return forecast

View file

@ -12,6 +12,13 @@ class IrmKmiForecast(Forecast):
text: str | None
class IrmKmiRadarForecast(Forecast):
"""Forecast class to handle rain forecast from the IRM KMI rain radar"""
rain_forecast_max: float
rain_forecast_min: float
might_rain: bool
class CurrentWeatherData(TypedDict, total=False):
"""Class to hold the currently observable weather at a given location"""
condition: str | None

File diff suppressed because it is too large Load diff

View file

@ -11,7 +11,7 @@ from custom_components.irm_kmi.const import CONF_LANGUAGE_OVERRIDE
from custom_components.irm_kmi.coordinator import IrmKmiCoordinator
from custom_components.irm_kmi.data import (CurrentWeatherData, IrmKmiForecast,
ProcessedCoordinatorData,
RadarAnimationData)
RadarAnimationData, IrmKmiRadarForecast)
from custom_components.irm_kmi.pollen import PollenParser
from tests.conftest import get_api_data
@ -238,17 +238,52 @@ def test_radar_forecast() -> None:
result = IrmKmiCoordinator.radar_list_to_forecast(api_data.get('animation'))
expected = [
Forecast(datetime="2023-12-26T17:00:00+01:00", native_precipitation=0),
Forecast(datetime="2023-12-26T17:10:00+01:00", native_precipitation=0),
Forecast(datetime="2023-12-26T17:20:00+01:00", native_precipitation=0),
Forecast(datetime="2023-12-26T17:30:00+01:00", native_precipitation=0),
Forecast(datetime="2023-12-26T17:40:00+01:00", native_precipitation=0.1),
Forecast(datetime="2023-12-26T17:50:00+01:00", native_precipitation=0.01),
Forecast(datetime="2023-12-26T18:00:00+01:00", native_precipitation=0.12),
Forecast(datetime="2023-12-26T18:10:00+01:00", native_precipitation=1.2),
Forecast(datetime="2023-12-26T18:20:00+01:00", native_precipitation=2),
Forecast(datetime="2023-12-26T18:30:00+01:00", native_precipitation=0),
Forecast(datetime="2023-12-26T18:40:00+01:00", native_precipitation=0)
IrmKmiRadarForecast(datetime="2023-12-26T17:00:00+01:00", native_precipitation=0, might_rain=False,
rain_forecast_max=0, rain_forecast_min=0),
IrmKmiRadarForecast(datetime="2023-12-26T17:10:00+01:00", native_precipitation=0, might_rain=False,
rain_forecast_max=0, rain_forecast_min=0),
IrmKmiRadarForecast(datetime="2023-12-26T17:20:00+01:00", native_precipitation=0, might_rain=False,
rain_forecast_max=0, rain_forecast_min=0),
IrmKmiRadarForecast(datetime="2023-12-26T17:30:00+01:00", native_precipitation=0, might_rain=False,
rain_forecast_max=0, rain_forecast_min=0),
IrmKmiRadarForecast(datetime="2023-12-26T17:40:00+01:00", native_precipitation=0.1, might_rain=False,
rain_forecast_max=0, rain_forecast_min=0),
IrmKmiRadarForecast(datetime="2023-12-26T17:50:00+01:00", native_precipitation=0.01, might_rain=False,
rain_forecast_max=0, rain_forecast_min=0),
IrmKmiRadarForecast(datetime="2023-12-26T18:00:00+01:00", native_precipitation=0.12, might_rain=False,
rain_forecast_max=0, rain_forecast_min=0),
IrmKmiRadarForecast(datetime="2023-12-26T18:10:00+01:00", native_precipitation=1.2, might_rain=False,
rain_forecast_max=0, rain_forecast_min=0),
IrmKmiRadarForecast(datetime="2023-12-26T18:20:00+01:00", native_precipitation=2, might_rain=False,
rain_forecast_max=0, rain_forecast_min=0),
IrmKmiRadarForecast(datetime="2023-12-26T18:30:00+01:00", native_precipitation=0, might_rain=False,
rain_forecast_max=0, rain_forecast_min=0),
IrmKmiRadarForecast(datetime="2023-12-26T18:40:00+01:00", native_precipitation=0, might_rain=False,
rain_forecast_max=0, rain_forecast_min=0)
]
assert expected == result
def test_radar_forecast_rain_interval() -> None:
api_data = get_api_data('forecast_with_rain_on_radar.json')
result = IrmKmiCoordinator.radar_list_to_forecast(api_data.get('animation'))
_12 = IrmKmiRadarForecast(
datetime='2024-05-30T18:00:00+02:00',
native_precipitation=0.89,
might_rain=True,
rain_forecast_max=1.12,
rain_forecast_min=0.50
)
_13 = IrmKmiRadarForecast(
datetime="2024-05-30T18:10:00+02:00",
native_precipitation=0.83,
might_rain=True,
rain_forecast_max=1.09,
rain_forecast_min=0.64
)
assert result[12] == _12
assert result[13] == _13

View file

@ -9,7 +9,7 @@ from homeassistant.core import HomeAssistant
from pytest_homeassistant_custom_component.common import MockConfigEntry
from custom_components.irm_kmi import IrmKmiCoordinator, IrmKmiWeather
from custom_components.irm_kmi.data import ProcessedCoordinatorData
from custom_components.irm_kmi.data import ProcessedCoordinatorData, IrmKmiRadarForecast
from tests.conftest import get_api_data
@ -115,17 +115,28 @@ async def test_radar_forecast_service(
result_service: List[Forecast] = weather.get_forecasts_radar_service(False)
expected = [
Forecast(datetime="2023-12-26T17:00:00+01:00", native_precipitation=0),
Forecast(datetime="2023-12-26T17:10:00+01:00", native_precipitation=0),
Forecast(datetime="2023-12-26T17:20:00+01:00", native_precipitation=0),
Forecast(datetime="2023-12-26T17:30:00+01:00", native_precipitation=0),
Forecast(datetime="2023-12-26T17:40:00+01:00", native_precipitation=0.1),
Forecast(datetime="2023-12-26T17:50:00+01:00", native_precipitation=0.01),
Forecast(datetime="2023-12-26T18:00:00+01:00", native_precipitation=0.12),
Forecast(datetime="2023-12-26T18:10:00+01:00", native_precipitation=1.2),
Forecast(datetime="2023-12-26T18:20:00+01:00", native_precipitation=2),
Forecast(datetime="2023-12-26T18:30:00+01:00", native_precipitation=0),
Forecast(datetime="2023-12-26T18:40:00+01:00", native_precipitation=0)
IrmKmiRadarForecast(datetime="2023-12-26T17:00:00+01:00", native_precipitation=0, might_rain=False,
rain_forecast_max=0, rain_forecast_min=0),
IrmKmiRadarForecast(datetime="2023-12-26T17:10:00+01:00", native_precipitation=0, might_rain=False,
rain_forecast_max=0, rain_forecast_min=0),
IrmKmiRadarForecast(datetime="2023-12-26T17:20:00+01:00", native_precipitation=0, might_rain=False,
rain_forecast_max=0, rain_forecast_min=0),
IrmKmiRadarForecast(datetime="2023-12-26T17:30:00+01:00", native_precipitation=0, might_rain=False,
rain_forecast_max=0, rain_forecast_min=0),
IrmKmiRadarForecast(datetime="2023-12-26T17:40:00+01:00", native_precipitation=0.1, might_rain=False,
rain_forecast_max=0, rain_forecast_min=0),
IrmKmiRadarForecast(datetime="2023-12-26T17:50:00+01:00", native_precipitation=0.01, might_rain=False,
rain_forecast_max=0, rain_forecast_min=0),
IrmKmiRadarForecast(datetime="2023-12-26T18:00:00+01:00", native_precipitation=0.12, might_rain=False,
rain_forecast_max=0, rain_forecast_min=0),
IrmKmiRadarForecast(datetime="2023-12-26T18:10:00+01:00", native_precipitation=1.2, might_rain=False,
rain_forecast_max=0, rain_forecast_min=0),
IrmKmiRadarForecast(datetime="2023-12-26T18:20:00+01:00", native_precipitation=2, might_rain=False,
rain_forecast_max=0, rain_forecast_min=0),
IrmKmiRadarForecast(datetime="2023-12-26T18:30:00+01:00", native_precipitation=0, might_rain=False,
rain_forecast_max=0, rain_forecast_min=0),
IrmKmiRadarForecast(datetime="2023-12-26T18:40:00+01:00", native_precipitation=0, might_rain=False,
rain_forecast_max=0, rain_forecast_min=0)
]
assert result_service == expected[5:]