These helpers run client-side and do not call the API. They give the caller a chance to detect configurations that are likely to produce inaccurate results before incurring the wall-time cost of an actual analysis.
SEVERITY_LEVELS module-attribute
SEVERITY_LEVELS: tuple[str, ...] = ( "info", "ok", "marginal", "warning", "critical", )
Severity levels in increasing order of concern.
info is reserved for cases where the question does not apply (no positive-elevation hours in the window, or invalid input).
PreflightWarning
Bases: Exception
Raised by an opt-in pre-flight gate when the configuration is unlikely to produce reliable results.
Only raised when a caller explicitly opts in via preflight="raise". The default integration mode is "log" (logger warning, no raise).
SunContextResult
Bases: TypedDict
Structured result returned by estimate_sun_context_loss.
severity instance-attribute
severity: str
One of SEVERITY_LEVELS.
message instance-attribute
message: str
Human-readable explanation suitable for a banner.
min_sun_elevation_deg instance-attribute
min_sun_elevation_deg: Optional[float]
Lowest above-horizon sun elevation reached during the window (degrees). None when no positive-elevation hours were sampled.
min_sun_elevation_month instance-attribute
min_sun_elevation_month: Optional[int]
Month of the worst-case hour. None for sub-horizon or zero-sample windows.
min_sun_elevation_day instance-attribute
min_sun_elevation_day: Optional[int]
Day of the month of the worst-case hour. None for sub-horizon or zero-sample windows.
min_sun_elevation_hour instance-attribute
min_sun_elevation_hour: Optional[int]
Hour of the worst-case hour. None for sub-horizon or zero-sample windows.
pattern instance-attribute
pattern: Optional[str]
Human-readable hemisphere/season/time-band label, e.g. "Northern hemisphere, winter, late morning".
buffer_breakeven_height_m instance-attribute
buffer_breakeven_height_m: float
Tallest building whose full shadow fits inside buffer_m at the worst-case elevation.
shadow_at_typical_building_m instance-attribute
shadow_at_typical_building_m: float
Shadow length of a typical_building_height_m building at the worst-case elevation.
shadow_at_max_building_m instance-attribute
shadow_at_max_building_m: Optional[float]
Shadow length of a max_building_height_m building. None if that argument was not supplied.
estimate_sun_context_loss
estimate_sun_context_loss( *, lat: float, lon: float = 0.0, timezone_offset_h: Optional[float] = None, start_month: int, start_day: int, start_hour: int, end_month: int, end_day: int, end_hour: int, buffer_m: float = 128.0, typical_building_height_m: float = 25.0, max_building_height_m: Optional[float] = None, ) -> SunContextResult
Estimate whether a tile geometry-context buffer is sufficient.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
lat | float | Polygon centroid in degrees. Latitude drives sun-angle math; longitude drives the clock-hour to solar-hour correction (solar_hour = clock_hour + lon/15 - timezone_offset_h). | required |
lon | float | Polygon centroid in degrees. Latitude drives sun-angle math; longitude drives the clock-hour to solar-hour correction (solar_hour = clock_hour + lon/15 - timezone_offset_h). | required |
timezone_offset_h | Optional[float] | Offset of the locale's clock from UTC, in hours. None (the default) approximates it as round(lon / 15), which matches meridian-aligned time zones and is a fine first-order correction for the locales that don't. | None |
start_month | int | TimePeriod cascade-filter bounds. The function samples the (month, day, hour) grid that the API filter would itself process. Year-wrap windows (e.g. start_month=11, end_month=2) are handled. | required |
start_day | int | TimePeriod cascade-filter bounds. The function samples the (month, day, hour) grid that the API filter would itself process. Year-wrap windows (e.g. start_month=11, end_month=2) are handled. | required |
start_hour | int | TimePeriod cascade-filter bounds. The function samples the (month, day, hour) grid that the API filter would itself process. Year-wrap windows (e.g. start_month=11, end_month=2) are handled. | required |
end_month | int | TimePeriod cascade-filter bounds. The function samples the (month, day, hour) grid that the API filter would itself process. Year-wrap windows (e.g. start_month=11, end_month=2) are handled. | required |
end_day | int | TimePeriod cascade-filter bounds. The function samples the (month, day, hour) grid that the API filter would itself process. Year-wrap windows (e.g. start_month=11, end_month=2) are handled. | required |
end_hour | int | TimePeriod cascade-filter bounds. The function samples the (month, day, hour) grid that the API filter would itself process. Year-wrap windows (e.g. start_month=11, end_month=2) are handled. | required |
buffer_m | float | Effective per-cell context buffer. Pass 128 for the current SOLAR_TILING_CONFIG default, 205 for a wind-style 50% overlap (inner-256 crop), or whatever a custom configuration produces. | 128.0 |
typical_building_height_m | float | Reference building height for the headline severity. Default 25 is reasonable for European mid-rise; raise for high-rise contexts (50–100+ m). | 25.0 |
max_building_height_m | Optional[float] | Optional worst-case height. When supplied, drives the severity scoring (severity = breakeven / max(typical, max)) so that a single tall outlier does not slip past as ok. | None |
Returns:
| Type | Description |
|---|---|
SunContextResult | TypedDict with severity (one of SEVERITY_LEVELS), a human-readable message, and supporting numerical fields. The function never raises on bad input; it returns severity="info" with a diagnostic message instead. |
required_buffer_m
required_buffer_m(building_height_m: float, sun_elevation_deg: float) -> float
Geometric buffer needed for a single building's full shadow to fit.
Returns +inf for non-positive sun elevations.
run_preflight_safely
run_preflight_safely( payloads, polygon_centroid_lat: Optional[float] = None, polygon_centroid_lon: Optional[float] = None, mode: str = "log", logger=None, buffer_m: float = 128.0, ) -> None
Defensive wrapper around estimate_sun_context_loss for use inside the SDK's area-orchestration entry points.
The whole body is wrapped so that no preflight failure ever propagates — internal exceptions emit a debug log and return. Only an explicit mode="raise" plus a real warning/critical verdict will raise PreflightWarning.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
payloads | Single payload or iterable of payloads. Anything that is not a solar/thermal payload (no time_period / no latitude) is silently skipped. | required | |
polygon_centroid_lat | Optional[float] | Fallback location if a payload itself lacks latitude/longitude. | None |
mode | str | "off" — function is a no-op (still won't raise). "log" — emit logger.warning for warning/critical results. "raise" — additionally raise PreflightWarning for warning/critical results. Any other value is treated as "log". | 'log' |
logger | Optional logging.Logger used for the warning. Falls back to the module logger when None. | None | |
buffer_m | float | Effective per-cell context buffer for the active tiling config. Default 128 matches SOLAR_TILING_CONFIG's margin. | 128.0 |
solar_elevation_deg
solar_elevation_deg(lat_deg: float, doy: int, solar_hour: float) -> float
Return the approximate solar elevation in degrees.
Uses a sinusoidal declination model (δ ≈ 23.45° · sin(360°/365 · (n − 81))) and the standard altitude formula. Equation-of-time and atmospheric refraction are intentionally not modelled — accuracy is well within the ~5° tolerance required for a pre-flight gate.
Returns nan for a non-finite solar_hour (a literal +inf or -inf) rather than raising.