Source code for better_lbnl_os.models.location

"""Location info domain model."""

from pydantic import BaseModel, Field


[docs] class LocationInfo(BaseModel): """Domain model for geocoded location information.""" geo_lat: float = Field(..., description="Latitude coordinate") geo_lng: float = Field(..., description="Longitude coordinate") zipcode: str | None = Field(None, description="Postal/ZIP code") state: str | None = Field(None, description="State or province") country_code: str = Field(default="US", description="ISO country code") noaa_station_id: str | None = Field(None, description="NOAA weather station ID") noaa_station_name: str | None = Field(None, description="NOAA weather station name") egrid_sub_region: str | None = Field(None, description="eGrid subregion for emissions")
[docs] def is_valid_coordinates(self) -> bool: """Check if coordinates are within valid latitude/longitude ranges. Returns: True if coordinates are valid, False otherwise """ return (-90 <= self.geo_lat <= 90) and (-180 <= self.geo_lng <= 180)
[docs] def calculate_distance_to(self, other: "LocationInfo") -> float: """Calculate distance to another location. Args: other: Another LocationInfo object Returns: Distance in kilometers """ from better_lbnl_os.utils.geography import haversine_distance return haversine_distance(self.geo_lat, self.geo_lng, other.geo_lat, other.geo_lng)
class LocationSummary(BaseModel): """Normalized location metadata for pricing/emission lookups.""" country_code: str = Field(default="US", description="ISO country code") state_code: str | None = Field(default=None, description="Two-letter state/province code") zipcode: str | None = Field(default=None, description="Postal/ZIP code") egrid_subregion: str | None = Field(default=None, description="eGrid subregion identifier") def to_metadata(self) -> dict[str, str | None]: """Return a dict view excluding unset fields.""" return self.model_dump(exclude_none=True) __all__ = ["LocationInfo", "LocationSummary"]