Skip to content
View as Markdown llms.txt

Preflight

Pre-flight diagnostics for SDK runs.

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.