Source code for better_lbnl_os.models.weather

"""Weather domain models."""

from pydantic import BaseModel, Field


[docs] class WeatherData(BaseModel): """Domain model for weather data with calculation methods.""" station_id: str | None = Field(None, description="Weather station identifier") latitude: float = Field(..., description="Station latitude") longitude: float = Field(..., description="Station longitude") year: int = Field(..., description="Year of observation") month: int = Field(..., ge=1, le=12, description="Month of observation") avg_temp_c: float = Field(..., description="Monthly average temperature in Celsius") min_temp_c: float | None = Field(None, description="Minimum temperature in Celsius") max_temp_c: float | None = Field(None, description="Maximum temperature in Celsius") data_source: str = Field(default="OpenMeteo", description="Data source (NOAA, OpenMeteo, etc.)") @property def avg_temp_f(self) -> float: """Get average temperature in Fahrenheit.""" from better_lbnl_os.utils.calculations import celsius_to_fahrenheit return celsius_to_fahrenheit(self.avg_temp_c) @property def min_temp_f(self) -> float | None: """Get minimum temperature in Fahrenheit.""" if self.min_temp_c is not None: from better_lbnl_os.utils.calculations import celsius_to_fahrenheit return celsius_to_fahrenheit(self.min_temp_c) return None @property def max_temp_f(self) -> float | None: """Get maximum temperature in Fahrenheit.""" if self.max_temp_c is not None: from better_lbnl_os.utils.calculations import celsius_to_fahrenheit return celsius_to_fahrenheit(self.max_temp_c) return None
[docs] class WeatherSeries(BaseModel): """Monthly weather time series aligned to calendar months.""" months: list[__import__("datetime").date] = Field( default_factory=list, description="List of YYYY-MM-01 dates" ) degC: list[float] = Field(default_factory=list, description="Monthly average temperature in °C") degF: list[float] = Field(default_factory=list, description="Monthly average temperature in °F")
class WeatherStation(BaseModel): """Domain model for weather station information.""" station_id: str = Field(..., description="Station identifier (e.g., NOAA ID)") name: str = Field(..., description="Station name") latitude: float = Field(..., ge=-90, le=90, description="Station latitude") longitude: float = Field(..., ge=-180, le=180, description="Station longitude") elevation: float | None = Field(None, description="Station elevation in meters") distance_km: float | None = Field(None, description="Distance from target location in km") data_source: str = Field(default="NOAA", description="Data source") def distance_to(self, lat: float, lng: float) -> float: """Calculate distance to a given latitude/longitude. Args: lat: Target latitude lng: Target longitude Returns: Distance in kilometers """ from better_lbnl_os.utils.geography import haversine_distance return haversine_distance(self.latitude, self.longitude, lat, lng) __all__ = ["WeatherData", "WeatherSeries", "WeatherStation"]