GroundMaterialsServiceError

Bases: Exception

A ground-material operation failed in a way the caller must see.

LocalGroundMaterialCleaner

Clean ground-material layers in-process.

The Local in the name is historical; the name is kept because it is published API.

clean() takes a dict and returns one. A bulk caller should use clean_json, or merge_and_clean_json when the input is still the per-tile documents: both take and return JSON bytes, so no intermediate layer tree is built as Python objects.

z_step=None uses the default of 0.05 m.

clean

Python
clean(
layers: Dict[str, Any],
*,
latitude: float,
longitude: float,
distance: float,
default_layer: str,
z_step: Optional[float] = None,
) -> Dict[str, Any]

Clean a layer dict and return the cleaned layer dict.

Parameters:

NameTypeDescriptionDefault
layersdict{layer_name: FeatureCollection}.required
latitudefloatLatitude of the clean circle's centre, in degrees.required
longitudefloatLongitude of the clean circle's centre, in degrees.required
distancefloatRadius of the clean circle, in metres.required
default_layerstrName of the default material layer, used for the backdrop.required
z_stepfloatPer-layer z spacing in metres (default 0.05).None

Returns:

TypeDescription
dictThe cleaned {layer_name: FeatureCollection}.

Raises:

TypeDescription
GroundMaterialsServiceErrorIf layers is not a dict or the cleaning fails.

clean_json

Python
clean_json(
layers_json: bytes,
*,
latitude: float,
longitude: float,
distance: float,
default_layer: str,
z_step: Optional[float] = None,
) -> bytes

Clean a JSON layer document, bytes in and bytes out.

Nothing here builds a Python object tree.

Parameters:

NameTypeDescriptionDefault
layers_jsonbytes{layer: FeatureCollection} as a JSON document.required
latitudefloatLatitude of the clean circle's centre, in degrees.required
longitudefloatLongitude of the clean circle's centre, in degrees.required
distancefloatRadius of the clean circle, in metres.required
default_layerstrName of the default material layer, used for the backdrop.required
z_stepfloatPer-layer z spacing in metres (default 0.05).None

Returns:

TypeDescription
bytesThe cleaned layers as a UTF-8 JSON document.

Raises:

TypeDescription
GroundMaterialsServiceErrorIf the cleaning fails.

merge_and_clean_json

Python
merge_and_clean_json(
tile_layers_json: bytes,
*,
latitude: float,
longitude: float,
distance: float,
default_layer: str,
z_step: Optional[float] = None,
) -> bytes

Merge per-tile layer documents and clean them in one step.

The merged layer tree never becomes Python objects between the two steps.

Parameters:

NameTypeDescriptionDefault
tile_layers_jsonbytesA JSON array of per-tile {layer: FeatureCollection} documents.required
latitudefloatLatitude of the clean circle's centre, in degrees.required
longitudefloatLongitude of the clean circle's centre, in degrees.required
distancefloatRadius of the clean circle, in metres.required
default_layerstrName of the default material layer, used for the backdrop.required
z_stepfloatPer-layer z spacing in metres (default 0.05).None

Returns:

TypeDescription
bytesThe merged and cleaned layers as a JSON document.

Raises:

TypeDescription
GroundMaterialsServiceErrorIf the merge or the cleaning fails.

Notes

An empty merge returns b"{}" and is not cleaned: no layers, no default backdrop.

GroundMaterialsServiceClient

Bases: ScrubbedSessionState

Client for ground-material layers.

api_key, base_url, gateway_base_url and telemetry are accepted for construction compatibility with the other service clients and are unused: this client sends no request of its own since the utilities routes were removed. The public data reads go through the range reader of each worker.

logger instance-attribute

Python
logger: Logger = logger

Logger the client reports progress to.

base_url instance-attribute

Python
base_url: str = base_url

Base URL accepted for construction compatibility; never contacted.

close

Python
close() -> None

Release the client's resources. Kept for API compatibility.

get_area

Python
get_area(
polygon: dict,
*,
max_workers: int = 10,
default_material: str = "asphalt",
timeout: int = 60,
total_timeout: int = 600,
on_progress: Optional[Callable[[TileProgress], None]] = None,
max_tiles_override: Optional[int] = None,
z_step: Optional[float] = None,
overture_release: Optional[str] = None,
analysis_type: Optional[str] = None,
acquisition: Any = REMOVED,
cleaner: Any = REMOVED,
) -> AreaGroundMaterials

Read, deduplicate, and clean ground materials for a polygon area.

The site is read once: as a single rectangle up to 4 km2, and above that as a grid of roughly 2 x 2 km read chunks, at most two in flight. Nothing is composed per simulation tile.

There is no partial answer. A chunk that fails raises TiledRunError, whose failed_tiles names the failed chunks and whose __cause__ is the first underlying error.

The returned AreaGroundMaterials can be reused across multiple run_area() calls (tile assignment happens at submission).

Parameters:

NameTypeDescriptionDefault
polygondictGeoJSON Polygon.required
max_workersintRead chunks in flight. A CEILING of 2 applies, so this can only ask for FEWER: 1 reads the chunks one at a time. Raising it does nothing — the memory bound of the site read is "at most two chunks resident".10
default_materialstrDefault material layer name for the clean step (default "asphalt").'asphalt'
timeoutintPer-REQUEST budget in seconds (default 60), trimmed to what is left of total_timeout.60
total_timeoutintWall-clock deadline over the whole site read, in seconds (default 600). Checked between chunks and before each read.600
on_progresscallableProgress callback (TileProgress) -> None, once per read CHUNK. tile_id is the chunk id and total_count the chunk count.None
max_tiles_overrideintOverride the default maximum number of non-empty tiles.None
z_stepfloatPer-layer z spacing in metres (default 0.05).None
overture_releasestrPin the Overture collections to one immutable release. The resolved release is reported on the result.None
analysis_typestrThe analysis this acquisition is for. It decides the read margin (363 m for wind-speed / pedestrian-wind-comfort and 544 m for every other analysis) and the tile grid the read rectangles are centred on. Omit it and the read uses the widest margin, valid for every analysis.None
acquisitionobjectRemoved. Passing a value raises TypeError.REMOVED
cleanerobjectRemoved. Passing a value raises TypeError.REMOVED

Returns:

TypeDescription
AreaGroundMaterialsCleaned material layers for the whole polygon. failed_tiles is empty: a read that could not cover the polygon raises instead of answering.

Raises:

TypeDescription
PolygonValidationErrorIf polygon is not a valid GeoJSON Polygon, if the grid it needs exceeds the tile ceiling, or if max_tiles_override is not a non-negative integer.
TiledRunErrorIf a read chunk fails or total_timeout expires.
GeodataDependencyErrorIf the optional [geodata] extra is not installed.
GroundMaterialsServiceErrorIf the merged and cleaned layers cannot be produced.
TypeErrorIf the removed acquisition or cleaner argument is passed.

AreaGroundMaterials dataclass

Result of ground-material fetch for a polygon area.

layers instance-attribute

Python
layers: Dict[str, dict]

Material layers keyed by name (e.g. 'vegetation', 'water', 'asphalt'), each a GeoJSON FeatureCollection.

polygon instance-attribute

Python
polygon: dict

The input GeoJSON polygon.

total_features instance-attribute

Python
total_features: int

Total features across all layers after dedup.

execution_time instance-attribute

Python
execution_time: float

Wall-clock seconds for the full pipeline.

overture_release class-attribute instance-attribute

Python
overture_release: Optional[str] = None

Overture Maps release the layers were read from. The public index pointer moves daily, so the same polygon can otherwise return different ground layers on two days with no signal to the caller; pass the value back as overture_release= to pin the run. Several releases are joined with ", " on the rare run that straddles a refresh.

failed_tiles class-attribute instance-attribute

Python
failed_tiles: List[Dict[str, Any]] = field(default_factory=list)

Tiles that failed every retry, as {"tile_id", "row", "col", "error"}, the same shape AreaVegetation.failed_tiles carries. A partial read is otherwise invisible: the layers simply cover less ground than the polygon, which reads as "there is nothing there". Empty means every tile was read.

read_margin_m class-attribute instance-attribute

Python
read_margin_m: Optional[float] = None

Half extent, in metres, of the read rectangle every tile was fetched with: 363 m for the wind analyses, 544 m otherwise. run_area refuses a run whose analysis needs more than this.

analysis_type class-attribute instance-attribute

Python
analysis_type: Optional[str] = None

The analysis type the read margin was taken from. None on layers built by hand, which make no claim and are never refused.