67 lines
1.7 KiB
Python
67 lines
1.7 KiB
Python
# meteo/solar.py
|
|
from __future__ import annotations
|
|
|
|
import pandas as pd
|
|
from astral import Observer
|
|
from astral.sun import elevation
|
|
|
|
|
|
def _ensure_datetime_index(index: pd.Index) -> pd.DatetimeIndex:
|
|
if not isinstance(index, pd.DatetimeIndex):
|
|
raise TypeError("Un DatetimeIndex est requis pour calculer l'élévation solaire.")
|
|
return index
|
|
|
|
|
|
def _prepare_index(index: pd.DatetimeIndex) -> pd.DatetimeIndex:
|
|
"""
|
|
Retourne une version timezone-aware (en UTC) du DatetimeIndex fourni.
|
|
"""
|
|
if index.tz is None:
|
|
return index.tz_localize("UTC")
|
|
return index.tz_convert("UTC")
|
|
|
|
|
|
def compute_solar_elevation_series(
|
|
index: pd.Index,
|
|
*,
|
|
latitude: float,
|
|
longitude: float,
|
|
elevation_m: float = 0.0,
|
|
series_name: str = "sun_elevation",
|
|
) -> pd.Series:
|
|
"""
|
|
Calcule l'élévation du soleil (en degrés) pour chaque timestamp de l'index.
|
|
"""
|
|
dt_index = _ensure_datetime_index(index)
|
|
observer = Observer(latitude=latitude, longitude=longitude, elevation=elevation_m)
|
|
utc_index = _prepare_index(dt_index)
|
|
|
|
values = [
|
|
float(elevation(observer, ts.to_pydatetime()))
|
|
for ts in utc_index
|
|
]
|
|
|
|
return pd.Series(values, index=dt_index, name=series_name)
|
|
|
|
|
|
def add_solar_elevation_column(
|
|
df: pd.DataFrame,
|
|
*,
|
|
latitude: float,
|
|
longitude: float,
|
|
elevation_m: float = 0.0,
|
|
column_name: str = "sun_elevation",
|
|
) -> pd.DataFrame:
|
|
"""
|
|
Ajoute une colonne `column_name` contenant l'élévation du soleil en degrés.
|
|
"""
|
|
series = compute_solar_elevation_series(
|
|
df.index,
|
|
latitude=latitude,
|
|
longitude=longitude,
|
|
elevation_m=elevation_m,
|
|
series_name=column_name,
|
|
)
|
|
df[column_name] = series
|
|
return df
|