Tiling
Tiling infrastructure: grid generation, orchestration, and merging.
TileService
Generate a grid of tiles covering a GeoJSON polygon.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
polygon
|
dict
|
A GeoJSON Polygon object ( |
required |
logger
|
Logger
|
Python logger instance. |
required |
analysis_type
|
AnalysesName
|
Reserved for future per-type tile size differentiation. |
None
|
max_tiles_override
|
int
|
Override the default maximum number of non-empty tiles (100 by
default). |
None
|
polygon
instance-attribute
polygon: dict = validate_polygon(polygon)
Validated GeoJSON Polygon.
points
instance-attribute
points: List[Point] = [
Point(latitude=pos[1], longitude=pos[0]) for pos in ring[:-1]
]
Internal polygon vertices as Point objects (lat/lon named fields).
logger
instance-attribute
logger: Logger = logger
Logger passed to the service.
analysis_type
instance-attribute
analysis_type: Optional[Union[AnalysesName, str]] = analysis_type
Analysis type the grid is generated for, or None.
tile_size
instance-attribute
tile_size: TileSize = TileSize(
x=self.config.inference_size_m, y=self.config.inference_size_m
)
Tile size in meters, from the tiling config.
max_non_empty
instance-attribute
max_non_empty: Optional[int] = max_tiles_override
The caller's override of the maximum non-empty tiles, or None.
config
instance-attribute
config: TilingConfig = get_tiling_config(
str(analysis_type) if analysis_type else None
)
Tiling configuration for the analysis type.
generate_tiles_for_polygon
generate_tiles_for_polygon() -> List[List[Tile]]
Generate a grid of tiles covering the polygon's bounding box.
Returns:
| Type | Description |
|---|---|
list[list[Tile]]
|
2-D grid where |
Raises:
| Type | Description |
|---|---|
PolygonValidationError
|
If the number of non-empty tiles exceeds the cap in force. The
message names the tile count, the cap, the grid family, the
|
AreaPreview
dataclass
Preview and cost estimate for an area analysis before submission.
would_bill_jobs, estimated_time_s and estimated_cost_tokens
are priced from the planned number of jobs, never from tile_count
alone. Grid analyses submit one job per tile, so
would_bill_jobs == tile_count there. A facade
(analysis_surfaces) run can split a tile into several billed
sub-batches when its estimated sensor count exceeds the server cap.
Passing payload= (with buildings= if the geometry is not
embedded) runs the same offline batch split run_area submits, so
would_bill_jobs reflects the real job count before any HTTP call.
Warnings
Without payload=, would_bill_jobs falls back to tile_count,
which is safe when there is no facade geometry to preview yet but an
under-estimate for a facade payload.
Attributes:
| Name | Type | Description |
|---|---|---|
tile_count |
int
|
Number of tiles covering the polygon. |
estimated_time_s |
float
|
Estimated run time in seconds. |
estimated_cost_tokens |
int
|
Estimated cost in tokens. |
would_bill_jobs |
int or None
|
Number of jobs the run would submit and bill. |
sensor_count |
int or None
|
Total sensors across the planned batches. |
AreaResult
dataclass
Bases: _PhysicalGridMixin
Public result from an area analysis.
Attributes:
| Name | Type | Description |
|---|---|---|
merged_grid |
Any
|
The merged grid, a READ-ONLY numpy array in the wire dtype of the
run: |
value_divisor |
int
|
|
valid |
ndarray or None
|
|
polygon |
dict
|
The source GeoJSON polygon. |
analysis_type |
str
|
Which analysis type was run. |
grid_shape |
tuple[int, int]
|
(num_rows, num_cols) of the merged grid. |
bounds |
tuple[float, float, float, float] | None
|
Geographic extent of |
failed_jobs |
list[str]
|
Job IDs where the job status was Failed. |
skipped_jobs |
list[str]
|
Job IDs where download failed (succeeded job but network error), or jobs that were still pending/running when merge was called. |
total_jobs |
int
|
Total number of jobs. |
succeeded_jobs |
int
|
Number of jobs that succeeded. |
min_legend, max_legend |
float or None
|
The exact value range measured over |
legend |
list[str] or None
|
The class labels of a categorical result (wind-comfort classes),
sorted and indexed by the class codes in |
failed_tiles |
list[TileFailure]
|
Per-tile failure records classified by |
to_dict
to_dict() -> dict
Serialise to a plain dict.
merged_grid holds the PHYSICAL values as a nested list (None
for no value), as before 1.0.0: a dict reader needs no divisor.
value_dtype and value_divisor record the wire dtype, so
from_dict() gives back the same dtype and the same values.
Returns:
| Type | Description |
|---|---|
dict
|
A JSON-compatible dict that |
from_dict
classmethod
from_dict(data: dict) -> AreaResult
Reconstruct from a dict produced by to_dict().
Unknown keys are silently ignored for forward compatibility.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
dict
|
A dict produced by |
required |
Returns:
| Type | Description |
|---|---|
AreaResult
|
The reconstructed result. |
Raises:
| Type | Description |
|---|---|
KeyError
|
If a required key ( |
AreaSchedule
dataclass
Schedule of submitted jobs for an area analysis.
Produced by run_area() and consumed by check_area_state(),
merge_area_jobs(), and run_area_and_wait(). Use to_dict() and
from_dict() to persist a schedule and resume it later.
Attributes:
| Name | Type | Description |
|---|---|---|
jobs |
dict[str, str]
|
Mapping of tile_id to job_id. |
polygon |
dict
|
The source GeoJSON polygon. |
analysis_type |
str
|
Which analysis type was run. |
config_hash |
str
|
SHA-256 hash of the payload's config-relevant fields. |
tile_positions |
dict[str, tuple[int, int]]
|
Mapping of tile_id to (row, col) grid position. |
grid_shape |
tuple[int, int]
|
(num_rows, num_cols) of the tile grid. |
webhook_url |
str or None
|
Webhook URL used for this submission. |
webhook_events |
tuple[str, ...] or None
|
Webhook events subscribed to. |
failed_submissions |
tuple[str, ...]
|
Tile IDs where job submission failed in a way that is SAFE to retry -- the server either never saw the request or answered with a definitive rejection. |
uncertain_submissions |
tuple[str, ...]
|
Tile IDs whose submission outcome is UNKNOWN: the request may
already have been accepted and queued server-side (a lost/timed-out
response, or a 2xx reply whose body didn't parse into a job).
Deliberately a SEPARATE bucket from |
config |
TilingConfig or None
|
The tiling configuration (tile size, step and context margins) the tiles were built with. |
submission_abort_status |
int or None
|
HTTP status that fail-fasted the submission batch, or
|
surface_fields |
bool
|
|
buildings_hash |
str or None
|
Fingerprint of the buildings/geometries map that produced this
schedule. Geometry drives sub-tile batch boundaries but is not part of
|
terrain_context_margin_m |
float or None
|
The terrain reach these tiles were sliced to, in metres — the FLOORED
value actually used ( |
max_sensors_per_job |
float or None
|
The facade per-job cap that planned this schedule. Its unit depends on
|
batching_policy_version |
int or None
|
Facade batching policy that planned the batches: 2 is the exact
retained-sensor policy (it requires complete |
batch_count_contract_version |
int or None
|
Version of the sensor-counting rules the batch sensor counts were computed under. A retry of a schedule counted under an older version is refused by name. |
batch_membership |
dict[str, tuple[str, ...]] or None
|
Building IDs in each facade batch, keyed by batch key
( |
batch_sensor_counts |
dict[str, int] or None
|
Retained sensor count of each facade batch, keyed by batch key.
|
transport |
str or None
|
Transport the jobs were submitted with ( |
wire_version |
int or None
|
Binary wire version of the submission ( |
binary_acknowledgements |
dict[str, dict] or None
|
The server's acknowledgement of each binary submission, keyed by
schedule key (tile ID or batch key). |
weather_identity |
str or None
|
The weather these tiles submitted — the columns, the payload
latitude and longitude and the window — as a digest, or |
schedule_contract_version |
int or None
|
Version of this client-side record; 4 is the run identity described
under |
site_identity |
str or None
|
Digest of the raw site inputs (buildings with their per-building
overrides, trees, ground materials, context and terrain geometry).
Guarded on retry and |
run_id |
str or None
|
Random ID made once per schedule and kept across every retry of it. Client-side only; never sent. |
attempts |
dict[str, int] or None
|
Attempt number of the current job or submission of each schedule key; a missing key is attempt 1. Client-side only; never sent. |
merge
merge(other: AreaSchedule) -> AreaSchedule
Merge another schedule into this one (e.g. after retry).
Validates that both schedules refer to the same polygon (via fingerprint), analysis_type, and config_hash. Overlapping tile_ids in other override this schedule's jobs. Failures that are now covered by other are removed.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
other
|
AreaSchedule
|
The retry schedule to merge in. |
required |
Returns:
| Type | Description |
|---|---|
AreaSchedule
|
A new merged schedule. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If polygon, analysis_type, or config_hash do not match. |
to_dict
to_dict() -> dict
Serialise to a plain dict for persistence.
Tuple fields are converted to lists for JSON compatibility.
Returns:
| Type | Description |
|---|---|
dict
|
A JSON-compatible dict that |
from_dict
classmethod
from_dict(data: dict) -> AreaSchedule
Reconstruct from a dict produced by to_dict().
Unknown keys are silently ignored for forward compatibility.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
dict
|
A dict produced by |
required |
Returns:
| Type | Description |
|---|---|
AreaSchedule
|
The reconstructed schedule. |
Raises:
| Type | Description |
|---|---|
KeyError
|
If a required key ( |
ValueError
|
If the saved batch records are inconsistent. |
AreaState
dataclass
Snapshot of area-level job status.
Produced by check_area_state() and consumed by
run_area_and_wait() callbacks.
Attributes:
| Name | Type | Description |
|---|---|---|
status |
str
|
Derived status: |
job_states |
dict[str, JobStatus]
|
Mapping of job_id to its current status. |
succeeded |
int
|
Count of succeeded jobs. |
failed |
int
|
Count of failed jobs. |
running |
int
|
Count of running jobs. |
pending |
int
|
Count of pending jobs. |
total |
int
|
Total number of jobs. |
is_complete |
bool
|
True when all jobs are in a terminal state. Also True when the schedule has no job but has uncertain tiles: nothing is in flight and an uncertain tile is never resubmitted, so waiting cannot change the state. The merge then reports each uncertain tile. |
uncertain |
int
|
Count of tiles whose submission outcome is unknown: the SDK
has no job id to poll for them. The merge reports each as a
|
from_job_states
classmethod
from_job_states(
job_states: Dict[str, JobStatus], *, uncertain: int = 0
) -> AreaState
Compute an AreaState from a mapping of job_id to JobStatus.
Status priority:
1. If no jobs -> "empty" (distinct from "completed"; submission
may have failed wholesale or been short-circuited)
2. If all jobs pending -> "pending"
3. If any non-terminal job exists (pending or running) -> "running"
4. If all terminal and all succeeded -> "completed", or
"partial" when a submission is uncertain
5. If all terminal and all failed -> "failed"
6. If all terminal with mixed results -> "partial"
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
job_states
|
dict[str, JobStatus]
|
Mapping of job_id to its current status. |
required |
uncertain
|
int
|
Number of tiles whose submission outcome is unknown. Default 0. |
0
|
Returns:
| Type | Description |
|---|---|
AreaState
|
The derived snapshot. |
AreaTimeoutError
Bases: Exception
Raised when run_area_and_wait exceeds its area_timeout.
Attributes:
| Name | Type | Description |
|---|---|---|
area_state |
AreaState
|
The state snapshot at the time of timeout. |
message |
str
|
Human-readable timeout message. |
TileGrid
dataclass
Immutable wrapper around a 2-D grid of tiles.
Produced by tile generation for a polygon and consumed by
downstream composable methods (run_area, get_by_tiles).
Tile IDs are deterministic UUIDs derived from the polygon geometry and grid position — the same polygon always produces the same IDs.
Attributes:
| Name | Type | Description |
|---|---|---|
tiles |
list[list[Tile]]
|
2-D grid where |
num_rows |
int
|
Number of rows in the grid. |
num_cols |
int
|
Number of columns in the grid. |
polygon |
dict
|
The source GeoJSON polygon used to generate this grid. |
config |
TilingConfig or None
|
The tiling configuration (tile size, step and context margins) the grid was generated with. |
non_empty_tiles
property
non_empty_tiles: List[Tuple[int, int, Tile]]
Return non-empty tiles with their grid positions.
Returns:
| Type | Description |
|---|---|
list[tuple[int, int, Tile]]
|
Each element is |
TiledResult
dataclass
Bases: _PhysicalGridMixin
Aggregated result from a tiled analysis run.
Attributes:
| Name | Type | Description |
|---|---|---|
merged_grid |
Any
|
Merged, blended, clipped grid: a READ-ONLY numpy array in the wire
dtype of the run ( |
value_divisor |
int
|
|
valid |
ndarray or None
|
|
polygon |
dict
|
Original input GeoJSON polygon. |
tile_count |
int
|
Number of tiles that were executed. |
grid_shape |
tuple[int, int]
|
(rows, cols) of the merged grid. |
failed_tiles |
list[TileFailure]
|
Tiles that failed after all retries. |
skipped_tiles |
list[str]
|
Tile IDs that were skipped. |
execution_time |
float
|
Total wall-clock seconds for the tiled run. |
per_tile_results |
list[TileResult]
|
Raw per-tile results. |
analysis_type |
str
|
Which analysis type was run. |
min_legend, max_legend |
float or None
|
The exact value range measured over |
legend |
list[str] or None
|
The class labels of a categorical result (wind-comfort classes),
sorted and indexed by the class codes in |
TileResult
dataclass
Raw result from a single analysis tile.
Attributes:
| Name | Type | Description |
|---|---|---|
tile_id |
str
|
Unique identifier of the tile. |
row |
int
|
Row index in the tile grid. |
col |
int
|
Column index in the tile grid. |
data |
dict or None
|
The raw result payload for the tile, or |