Skip to content

project

Builders for GeoLibre project (.geolibre.json) dicts and their layers.

The shapes here mirror the TypeScript interfaces in packages/core/src/types.ts and packages/core/src/project.ts. Keeping the Python builders faithful to those interfaces is what lets the embedded app load a project produced entirely from Python.

LIDAR_SOURCE_KIND module-attribute

LIDAR_SOURCE_KIND = 'lidar-url'

metadata.sourceKind of a LiDAR point cloud the app streams from a URL.

POINT_CLOUD_ANNOTATION_PLUGIN_ID module-attribute

POINT_CLOUD_ANNOTATION_PLUGIN_ID = 'geolibre-point-cloud-annotation'

Plugin id under which the app saves point cloud labels and 3D boxes.

MAX_POINT_LABEL_NODE_BYTES module-attribute

MAX_POINT_LABEL_NODE_BYTES = 16 * 1024 * 1024

Largest inflated size of one node's saved labels (mirrors the app's cap).

MAX_POINT_LABEL_BYTES module-attribute

MAX_POINT_LABEL_BYTES = 256 * 1024 * 1024

Largest total inflated size of all saved labels in one project.

MAX_POINT_LABEL_EDITS module-attribute

MAX_POINT_LABEL_EDITS = 20000000

Most decoded label entries across a project; bounds Python memory, since a dict entry costs far more than the two inflated bytes behind it.

CUSTOM_CLASS_MIN module-attribute

CUSTOM_CLASS_MIN = 19

Lowest code a custom class may use (ASPRS reserves 19-63, 64-255 are user).

CUSTOM_CLASS_MAX module-attribute

CUSTOM_CLASS_MAX = 255

Highest code a custom class may use (the LAS classification byte).

CESIUM_ION_SOURCE_KIND module-attribute

CESIUM_ION_SOURCE_KIND = 'cesium-ion'

metadata.sourceKind of a layer that references a Cesium Ion asset.

CZML_SOURCE_KIND module-attribute

CZML_SOURCE_KIND = 'czml'

metadata.sourceKind of a layer that references a CZML dynamic scene.

redact_url

redact_url(url: str) -> str

Return a URL with its userinfo and credential parameters stripped.

The public entry point to the sweep redact_credentials applies to every URL it finds, for the single-value reads (Map.basemap) that hand one back rather than writing a whole project out.

redact_layer_field

redact_layer_field(value: Any) -> Any

Return one of a layer's config fields, detached and swept.

The single-field counterpart to redact_layer, for a read that wants only source and should not pay to copy an inlined GeoJSON blob first.

redact_layer

redact_layer(layer: dict[str, Any]) -> dict[str, Any]

Return a detached copy of one layer, safe to display or hand to others.

The same sweep redact_credentials applies to every layer, for the single-layer reads (Layer.source, Layer.data) that hand a layer record back to a caller rather than writing a whole project out.

redact_credentials

redact_credentials(project: dict[str, Any]) -> dict[str, Any]

Return a detached project safe to publish, export, or hand to others.

default_map_view

default_map_view() -> dict[str, Any]

Return the app's default camera (createDefaultMapView in project.ts).

build_empty_project

build_empty_project(name: str = 'Untitled Project', *, center: list[float] | tuple[float, float] | None = None, zoom: float | None = None, basemap_url: str | None = None, renderer: str = 'maplibre') -> dict[str, Any]

Build an empty GeoLibre project dict.

Parameters:

Name Type Description Default
name str

Project display name.

'Untitled Project'
center list[float] | tuple[float, float] | None

Optional [lng, lat] map center.

None
zoom float | None

Optional initial zoom level.

None
basemap_url str | None

Optional MapLibre style URL; defaults to the app default.

None
renderer str

"maplibre" (default), "cesium", "mapbox", or "arcgis".

'maplibre'

Returns:

Type Description
dict[str, Any]

A project dict ready to be assigned to the widget's project trait.

normalize_hex_color

normalize_hex_color(value: str) -> str | None

Return value as #rrggbb, or None if it is not a hex color.

Mirrors normalizeHexColor in packages/core/src/color-ramp.ts, which is what the marker sprite baker runs a markerColor through: a value it rejects silently draws the default blue.

Parameters:

Name Type Description Default
value str

A color token such as "#f00", "FF0000", or "red".

required

Returns:

Type Description
str | None

The canonical #rrggbb form, or None for a non-hex token.

popup_field

popup_field(field: str, *, label: str | None = None, kind: str = 'auto', hover: bool | None = None, decimals: int | None = None, thousands: bool | None = None, date_format: str | None = None, prefix: str | None = None, suffix: str | None = None, link_label: str | None = None) -> dict[str, Any]

Build one entry of a layer popup's field list.

Parameters:

Name Type Description Default
field str

The feature property key to show.

required
label str | None

Heading printed instead of the raw property name.

None
kind str

How the value renders: "auto", "text", "number", "date", "link" (an http(s) URL becomes an anchor), or "image" (an http(s) URL or inline base64 raster data URL becomes a thumbnail).

'auto'
hover bool | None

Include this field in the hover tooltip's short subset.

None
decimals int | None

Fixed decimal places for a "number" field.

None
thousands bool | None

Group thousands for a "number" field.

None
date_format str | None

One of POPUP_DATE_FORMATS for a "date" field.

None
prefix str | None

Text placed before the formatted value.

None
suffix str | None

Text placed after the formatted value, e.g. a unit.

None
link_label str | None

Anchor text for a "link" field; defaults to the value.

None

Returns:

Type Description
dict[str, Any]

A PopupFieldConfig dict.

Raises:

Type Description
ValueError

If field is blank, or kind/date_format/ decimals is outside the range the app understands.

popup_config

popup_config(fields: Any = None, *, click: bool | None = None, hover: bool | None = None, title: str | None = None, title_expression: str | None = None, body_expression: str | None = None, show_feature_id: bool | None = None, max_width: int | None = None, image_height: int | None = None) -> dict[str, Any]

Build a layer's LayerPopupConfig.

Parameters:

Name Type Description Default
fields Any

The fields to show and their order: a single property name, or a sequence of property names and/or popup_field mappings. None keeps the default, which shows every visible property in the feature's own key order.

None
click bool | None

False suppresses the click popup entirely.

None
hover bool | None

True shows a hover tooltip built from the fields flagged hover.

None
title str | None

Property whose value titles the popup instead of the layer name.

None
title_expression str | None

MapLibre expression source (JSON text) producing the title; wins over title and falls back to it when it fails.

None
body_expression str | None

MapLibre expression source producing the whole popup body as one block of text instead of the field rows.

None
show_feature_id bool | None

False drops the synthetic id row.

None
max_width int | None

Widest the click popup may draw, in CSS pixels (POPUP_MAX_WIDTH_RANGE). The viewport still caps it, so a popup never covers the whole map on a small screen.

None
image_height int | None

Tallest an "image" field's thumbnail may draw inside the popup, in CSS pixels (POPUP_IMAGE_HEIGHT_RANGE). A thumbnail keeps its aspect ratio, so raise max_width too for a landscape photo to use the extra height.

None

Returns:

Type Description
dict[str, Any]

A LayerPopupConfig dict, empty when nothing was configured.

Raises:

Type Description
ValueError

If a field entry is not a name or a valid field mapping, or a size falls outside the range the app renders.

apply_tooltip

apply_tooltip(config: dict[str, Any], tooltip: Any) -> dict[str, Any]

Fold a tooltip= shorthand into a popup config, in place.

The app's hover tooltip needs two things: hover on the config, and at least one field flagged hover (or a configured title) to put in it -- createHoverTooltipElement returns nothing otherwise. This raises the field flags, then checks the finished config through _assert_tooltip_can_render so a tooltip that could never appear is an error however hover was switched on.

Parameters:

Name Type Description Default
config dict[str, Any]

The popup config being built (mutated in place).

required
tooltip Any

True/False to flag every configured field or turn the tooltip off, or a property name or sequence of names to flag. An empty sequence means the same as False. Note that naming a field here adds it to fields, and a non-empty fields is also what the click popup shows -- so a tooltip field on a popup that had no field list narrows the click popup to it.

required

Returns:

Type Description
dict[str, Any]

The same config.

Raises:

Type Description
ValueError

If a tooltip field name is blank, or the finished config leaves the tooltip on with nothing to show.

normalize_popup

normalize_popup(popup: Any = None, tooltip: Any = None, *, max_width: Any = None, image_height: Any = None) -> dict[str, Any] | None

Coerce the popup=/tooltip= arguments to a LayerPopupConfig.

popup accepts, in rising order of control: True/False to turn the click popup on or off, a property name, a sequence of property names and/or popup_field mappings, or a full config mapping whose keys are the arguments of popup_config (fields, click, hover, title, title_expression, body_expression, show_feature_id, max_width, image_height, tooltip) in either snake_case or camelCase.

Parameters:

Name Type Description Default
popup Any

The popup specification, or None for no popup config.

None
tooltip Any

Hover-tooltip shorthand; see apply_tooltip. Wins over a tooltip key inside popup.

None
max_width Any

popup_max_width= shorthand, in CSS pixels. Wins over a max_width key inside popup, and configures a popup on its own -- popup_max_width=480 alone still widens the default popup, which is the point of the shorthand.

None
image_height Any

popup_image_height= shorthand, in CSS pixels; the same precedence as max_width.

None

Returns:

Type Description
dict[str, Any] | None

A LayerPopupConfig dict, or None when neither argument

dict[str, Any] | None

configured anything.

Raises:

Type Description
ValueError

If the specification carries an unknown key or an unusable field entry.

is_valid_metadata_date

is_valid_metadata_date(value: str) -> bool

Whether a string is an ISO 8601 date or date-time naming a real instant.

Accepts YYYY-MM-DD and YYYY-MM-DDTHH:MM[:SS[.fff]][Z|+HH:MM], the same forms the app's Metadata dialog accepts.

Parameters:

Name Type Description Default
value str

The candidate date.

required

Returns:

Type Description
bool

True when the value is a valid date or date-time.

normalize_layer_metadata

normalize_layer_metadata(value: Any) -> dict[str, Any] | None

Clean a raw descriptive-metadata mapping the way the app does on load.

Keeps only string fields, trims them, drops blank fields, blank or duplicate (case-insensitive) keywords, and links without an href. Values are not validated -- see layer_metadata for the checked builder.

Parameters:

Name Type Description Default
value Any

A descriptiveMetadata mapping (camelCase keys), or anything.

required

Returns:

Type Description
dict[str, Any] | None

The cleaned mapping, or None when nothing is left, so an empty block

dict[str, Any] | None

is never written to a project.

layer_metadata

layer_metadata(*, title: str | None = None, abstract: str | None = None, keywords: str | list[str] | None = None, license: str | None = None, attribution: str | None = None, contact: dict[str, str] | None = None, lineage: str | None = None, temporal_extent: tuple[str | None, str | None] | dict[str, str] | None = None, links: list[str | dict[str, str]] | None = None) -> dict[str, Any] | None

Build a layer's descriptiveMetadata block, validated like the app.

This is the catalog description shown and edited in the app's layer Metadata dialog and exported as a STAC Item.

Parameters:

Name Type Description Default
title str | None

Human-readable title.

None
abstract str | None

Free-text summary of the data.

None
keywords str | list[str] | None

Keywords, as a list or one comma-separated string.

None
license str | None

SPDX license identifier (e.g. "CC-BY-4.0") or free text.

None
attribution str | None

Credit line for the data's producers.

None
contact dict[str, str] | None

Mapping with any of name, email, organization.

None
lineage str | None

How the data was produced (sources, processing steps).

None
temporal_extent tuple[str | None, str | None] | dict[str, str] | None

(start, end) ISO 8601 dates or date-times (either may be None), or a mapping with start/end.

None
links list[str | dict[str, str]] | None

URLs, or mappings with href plus optional rel and title.

None

Returns:

Type Description
dict[str, Any] | None

The cleaned block, or None when every field is blank.

Raises:

Type Description
ValueError

If the contact email, a temporal-extent date, or a link URL is malformed, or the extent ends before it starts.

marker_style

marker_style(*, color: str | None = None, opacity: float | None = None, radius: float | None = None, stroke_color: str | None = None, stroke_width: float | None = None, shape: str | None = None, size: float | None = None, icon: str | None = None) -> dict[str, Any]

Translate friendly marker arguments into layer style keys.

A point layer draws one of two ways. By default it is a MapLibre circle sized by radius and filled with color. Passing shape, size or icon switches it to a baked marker sprite instead, sized by size and colored by color; radius no longer applies to it.

Parameters:

Name Type Description Default
color str | None

Marker color. Applied to both the circle fill and the sprite, so it takes effect either way.

None
opacity float | None

Circle fill opacity in [0, 1].

None
radius float | None

Circle radius in pixels (circle rendering only).

None
stroke_color str | None

Outline color.

None
stroke_width float | None

Outline width in pixels.

None
shape str | None

One of MARKER_SHAPES. Switches to sprite rendering.

None
size float | None

Sprite size in pixels. Switches to sprite rendering.

None
icon str | None

Raw SVG markup, or a data/https URL to an SVG, PNG, JPEG, or GIF image, for a "custom" sprite. Only SVG takes color. Switches to sprite rendering and implies shape="custom".

None

Returns:

Type Description
dict[str, Any]

A dict of camelCase layer style keys, empty when nothing was passed.

Raises:

Type Description
ValueError

If shape is not a known shape, a numeric argument is out of range, shape="custom" is asked for without icon, or sprite rendering is requested with a non-hex color.

geojson_layer

geojson_layer(name: str, data: dict[str, Any], *, source_url: str | None = None, **style: Any) -> dict[str, Any]

Build a GeoJSON layer with an inlined FeatureCollection.

Parameters:

Name Type Description Default
name str

Layer display name.

required
data dict[str, Any]

A GeoJSON FeatureCollection dict.

required
source_url str | None

Optional URL the data originated from (recorded on the source for restore/refresh).

None
**style Any

Style overrides merged into the default layer style (e.g. fillColor="#ff0000").

{}

Returns:

Type Description
dict[str, Any]

A layer dict for the project's layers array.

tile_layer

tile_layer(name: str, url: str, *, tile_size: int = 256, attribution: str | None = None, bounds: list[float] | None = None, **style: Any) -> dict[str, Any]

Build a raster XYZ tile layer (e.g. an {z}/{x}/{y} template).

Parameters:

Name Type Description Default
name str

Layer display name.

required
url str

The XYZ tile URL template.

required
tile_size int

Tile size in pixels (typically 256).

256
attribution str | None

Optional attribution string.

None
bounds list[float] | None

Optional [west, south, east, north] request bounds.

None
**style Any

Style overrides merged into the default layer style.

{}

Returns:

Type Description
dict[str, Any]

A layer dict for the project's layers array.

cog_layer

cog_layer(name: str, url: str, *, bands: list[int] | None = None, colormap: str | None = None, rescale: list[list[float]] | None = None, **style: Any) -> dict[str, Any]

Build a Cloud Optimized GeoTIFF (COG) layer.

The shape matches what restoreRasterLayers replays from a saved project (see packages/plugins/src/plugins/raster-layer-sync.ts), so the app rebuilds the deck.gl raster overlay on load.

Parameters:

Name Type Description Default
name str

Layer display name.

required
url str

URL of the COG / GeoTIFF.

required
bands list[int] | None

Optional 1-based band indices to render (e.g. [1, 2, 3]).

None
colormap str | None

Optional colormap name for single-band rendering.

None
rescale list[list[float]] | None

Optional list of [min, max] ranges, one per rendered band.

None
**style Any

Style overrides merged into the default layer style.

{}

Returns:

Type Description
dict[str, Any]

A layer dict for the project's layers array.

wms_layer

wms_layer(name: str, endpoint: str, layers: str, *, styles: str = '', image_format: str = 'image/png', transparent: bool = True, tile_size: int = 256, version: str | None = '1.1.1', crs: str | None = None, bounds: list[float] | None = None, **style: Any) -> dict[str, Any]

Build a WMS layer rendered as tiled raster (a WMS GetMap request).

The GetMap tile template is built exactly as createWmsTileUrl in the Add Data dialog, so the core raster sync renders it identically to a layer added through the UI. The {bbox-epsg-3857} placeholder is substituted per tile.

Parameters:

Name Type Description Default
name str

Layer display name.

required
endpoint str

WMS service endpoint (the GetMap base URL).

required
layers str

Comma-separated WMS layer name(s).

required
styles str

Comma-separated WMS style name(s) (empty for the default).

''
image_format str

WMS image format (e.g. "image/png").

'image/png'
transparent bool

Whether to request transparent tiles.

True
tile_size int

Tile size in pixels.

256
version str | None

WMS protocol version, "1.1.1" (default) or "1.3.0". Version 1.3.0 sends CRS instead of SRS; some servers accept only one version. EPSG:3857 keeps its axis order in both, so the BBOX template is unchanged. None falls back to "1.1.1".

'1.1.1'
crs str | None

The CRS tiles are requested in: "EPSG:3857" (None, the default) or, for a server that does not offer Web Mercator, a CRS it does list in its capabilities: a geographic one ("EPSG:4326", "EPSG:4258", "EPSG:6706", "CRS:84") or a projected "EPSG:<code>" such as "EPSG:25832". The desktop app requests each tile's extent in that CRS and redraws or warps it into Web Mercator; the web build still sends the Web Mercator BBOX, which such a server rejects.

None
bounds list[float] | None

Optional [west, south, east, north] request bounds, in WGS84. Take them from the service's EX_GeographicBoundingBox, which is always lon/lat, rather than a 1.3.0 BoundingBox CRS="EPSG:4326", whose axis order servers often get wrong.

None
**style Any

Style overrides merged into the default layer style.

{}

Returns:

Type Description
dict[str, Any]

A layer dict for the project's layers array.

Raises:

Type Description
ValueError

If bounds is not four finite numbers with valid latitudes, crs is neither one of WMS_CRS nor an EPSG:<code>, or crs is "CRS:84" with a version other than 1.3.0.

wmts_layer

wmts_layer(name: str, url: str, *, tile_size: int = 256, bounds: list[float] | None = None, **style: Any) -> dict[str, Any]

Build a WMTS layer from a tile URL template.

Parameters:

Name Type Description Default
name str

Layer display name.

required
url str

A WMTS tile URL template in WMTS REST {z}/{y}/{x} order (row before column — unlike XYZ templates in tile_layer/add_tile_layer, which use {z}/{x}/{y}).

required
tile_size int

Tile size in pixels.

256
bounds list[float] | None

Optional [west, south, east, north] request bounds, in WGS84. WMTS capabilities carry it as ows:WGS84BoundingBox (EX_GeographicBoundingBox is a WMS element and is absent here).

None
**style Any

Style overrides merged into the default layer style.

{}

Returns:

Type Description
dict[str, Any]

A layer dict for the project's layers array.

Raises:

Type Description
ValueError

If bounds is not four finite numbers with valid latitudes.

wfs_getfeature_url

wfs_getfeature_url(endpoint: str, type_name: str, *, version: str = '2.0.0', output_format: str = 'application/json', srs_name: str = 'EPSG:4326', max_features: int | None = None) -> str

Build a WFS GetFeature URL, mirroring createWfsGetFeatureUrl.

WFS 2.x uses typeNames/count while WFS 1.x uses typeName/maxFeatures. The endpoint is expected to return GeoJSON when output_format is application/json so the result can be inlined as a GeoJSON layer.

Parameters:

Name Type Description Default
endpoint str

WFS service endpoint.

required
type_name str

WFS feature type name (e.g. "topp:states").

required
version str

WFS protocol version (e.g. "2.0.0" or "1.1.0").

'2.0.0'
output_format str

Requested output format.

'application/json'
srs_name str

Spatial reference of the response.

'EPSG:4326'
max_features int | None

Optional cap on the number of returned features.

None

Returns:

Type Description
str

The fully-formed GetFeature request URL.

vector_layer

vector_layer(name: str, url: str, *, render_mode: str = 'geojson', data_format: str | None = None, source_layer: str | None = None, picker: bool | None = None, ingest_mode: str | None = None, **style: Any) -> dict[str, Any]

Build a vector layer backed by the maplibre-gl-vector control.

Covers any GDAL-readable vector served from a URL (GeoParquet, FlatGeobuf, zipped Shapefile, GeoJSON, ...). The shape matches what restoreVectorLayers replays from a saved project: it reads source.url and the persisted metadata.vectorState and re-runs VectorControl.addData on load, so the in-browser DuckDB-backed control fetches and renders the data.

Parameters:

Name Type Description Default
name str

Layer display name.

required
url str

URL of the vector dataset.

required
render_mode str

"geojson" (load into a GeoJSON source) or "tiles" (stream as vector tiles).

'geojson'
data_format str | None

Optional GDAL format hint (e.g. "parquet", "flatgeobuf"); the control auto-detects when omitted.

None
source_layer str | None

Optional source/container layer name for multi-layer files.

None
picker bool | None

Optional toggle for the control's feature-inspection popup.

None
ingest_mode str | None

Optional ingest strategy, "table" or "stream".

None
**style Any

Style overrides merged into the default layer style.

{}

Returns:

Type Description
dict[str, Any]

A layer dict for the project's layers array.

Raises:

Type Description
ValueError

If render_mode or ingest_mode is not a valid value.

vector_tiles_layer

vector_tiles_layer(name: str, url: str, *, source_layers: list[str] | None = None, source_layer: str | None = None, **style: Any) -> dict[str, Any]

Build a vector tile layer from a TileJSON endpoint.

Rendered directly by the core layer sync (no control), which reads source.url as a TileJSON URL and styles each named source layer.

Parameters:

Name Type Description Default
name str

Layer display name.

required
url str

TileJSON endpoint for the vector tileset.

required
source_layers list[str] | None

Source-layer names to render (for multi-layer tilesets).

None
source_layer str | None

A single source-layer name (convenience for the common single-layer case).

None
**style Any

Style overrides merged into the default layer style.

{}

Returns:

Type Description
dict[str, Any]

A layer dict for the project's layers array.

pmtiles_layer

pmtiles_layer(name: str, url: str, *, tile_type: str = 'vector', source_layers: list[str] | None = None, **style: Any) -> dict[str, Any]

Build a PMTiles layer from a .pmtiles URL.

The core sync registers the pmtiles:// protocol and prepends it to the URL automatically, so a plain https:// URL is accepted here.

Parameters:

Name Type Description Default
name str

Layer display name.

required
url str

URL of the .pmtiles archive.

required
tile_type str

"vector" or "raster".

'vector'
source_layers list[str] | None

Vector source-layer names to render (vector tiles only).

None
**style Any

Style overrides merged into the default layer style.

{}

Returns:

Type Description
dict[str, Any]

A layer dict for the project's layers array.

Raises:

Type Description
ValueError

If tile_type is not "vector" or "raster".

three_d_tiles_layer

three_d_tiles_layer(name: str, url: str | None = None, *, ion_asset_id: int | None = None, altitude_offset: float = 0, request_headers: dict[str, str] | None = None, **style: Any) -> dict[str, Any]

Build a 3D Tiles layer from a tileset.json URL or a Cesium Ion asset.

A URL layer matches what restoreThreeDTilesLayers replays from a saved project, so the deck.gl 3D-tiles overlay is rebuilt on load. An Ion asset (ion_asset_id) renders only on the 3D globe, which loads it with the app's Cesium Ion token; the token itself is never written to the project.

Parameters:

Name Type Description Default
name str

Layer display name.

required
url str | None

URL of the 3D Tiles tileset.json. Omit for an Ion asset.

None
ion_asset_id int | None

A Cesium Ion asset id (for example 96188, Cesium OSM Buildings). Mutually exclusive with url.

None
altitude_offset float

Vertical offset applied to the tileset, in meters.

0
request_headers dict[str, str] | None

Optional request headers (e.g. an auth token). Stored in the project file, so avoid persisting secrets you do not want saved.

None
**style Any

Style overrides merged into the default layer style.

{}

Returns:

Type Description
dict[str, Any]

A layer dict for the project's layers array.

Raises:

Type Description
ValueError

If neither or both of url and ion_asset_id are given, the asset id is not a positive integer, or request_headers are combined with an Ion asset (Ion requests carry the token instead).

lidar_layer

lidar_layer(name: str, url: str, **style: Any) -> dict[str, Any]

Build a LiDAR point cloud layer from a LAS, LAZ, COPC or EPT URL.

The layer matches what the app's LiDAR control writes, so a saved project re-streams the point cloud when it opens (COPC and EPT by level of detail, LAS/LAZ as a whole download).

Parameters:

Name Type Description Default
name str

Layer display name.

required
url str

HTTP(S) URL of a .las, .laz, .copc.laz file or an EPT ept.json.

required
**style Any

Style overrides merged into the default layer style.

{}

Returns:

Type Description
dict[str, Any]

A layer dict for the project's layers array.

Raises:

Type Description
ValueError

If url is not an HTTP(S) URL.

decode_point_label_node

decode_point_label_node(text: str, limit: int = MAX_POINT_LABEL_NODE_BYTES) -> dict[int, int]

Decode one node's saved point labels.

The app stores a node's edits as raw-DEFLATE compressed pairs of (delta-varint point index, class byte), base64 encoded.

Parameters:

Name Type Description Default
text str

The base64 string from the project.

required
limit int

Maximum inflated size in bytes; a larger record is rejected without being inflated in full (a crafted decompression bomb).

MAX_POINT_LABEL_NODE_BYTES

Returns:

Type Description
dict[int, int]

Point index within the node -> ASPRS class code.

Raises:

Type Description
ValueError

If the record is truncated, not valid DEFLATE, or inflates past limit.

point_cloud_annotations

point_cloud_annotations(project: dict[str, Any]) -> dict[str, Any]

Read the point labels and 3D boxes the annotator saved in a project.

Labels are keyed by each point's stable identity: the source node key (a COPC/EPT octree key such as "2-1-0-1", or "file" for a LAS/LAZ loaded whole) and the point's index within that node.

Parameters:

Name Type Description Default
project dict[str, Any]

A project dict (e.g. Map.project or a loaded file).

required

Returns:

Type Description
dict[str, Any]

``{"labels": {url: {node_key: {index: class}}}, "instances": {url:

dict[str, Any]

{node_key: {index: instance_id}}}, "boxes": [...], "vectors": [...],

dict[str, Any]

"classes": [...]}.vectors`` are the 3D polylines, polygons and

dict[str, Any]

keypoints (see _point_cloud_vectors).

dict[str, Any]

classes is the project's custom class schema (see

dict[str, Any]

point_cloud_class_schema), and each box is ``{"url", "id",

dict[str, Any]

"class_code", "center", "size", "yaw", "status", "attributes"}``:

dict[str, Any]

center is [lng, lat, elevation_m], size ``[length, width,

dict[str, Any]

height]in metres,yaw`` radians counter-clockwise from east,

dict[str, Any]

status one of "new", "reviewed" or "flagged", and

dict[str, Any]

attributes the box's free-form string name/value pairs.

point_cloud_class_schema

point_cloud_class_schema(classes: Any, *, strict: bool = True) -> list[dict[str, Any]]

Validate custom point classes for the annotator (its label schema).

Custom classes extend the ASPRS standard classes 0-18 with user codes the annotator can assign, drawn in their own colour and named in the LiDAR legend.

Parameters:

Name Type Description Default
classes Any

A list of {"code", "name", "color"} dicts; code an integer 19-255, name non-empty text (clipped to 64 UTF-16 units, as the app does), color "#rrggbb" or (r, g, b).

required
strict bool

Raise on an invalid entry (authoring) instead of skipping it (reading a saved project).

True

Returns:

Type Description
list[dict[str, Any]]

The classes as {"code", "name", "color": "#rrggbb"}, ascending by

list[dict[str, Any]]

code; a repeated code keeps its last definition.

Raises:

Type Description
ValueError

With strict, for a malformed list or entry.

apply_point_labels

apply_point_labels(classification: Any, nodes: dict[str, dict[int, int]]) -> int

Apply saved labels to the classification of a LAS/LAZ loaded whole.

Labels on a whole-file source are keyed "file" with the point's index in file order, so they map straight onto e.g. laspy's las.classification. COPC/EPT labels are keyed by octree node and need the node's point order; export those from the app as LAS/LAZ instead.

Parameters:

Name Type Description Default
classification Any

A mutable sequence or NumPy array of class codes in file order (modified in place).

required
nodes dict[str, dict[int, int]]

One source's labels, as returned in point_cloud_annotations(project)["labels"][url].

required

Returns:

Type Description
int

The number of points whose class changed.

Raises:

Type Description
ValueError

If the labels are keyed by COPC/EPT node, or an index is past the end of classification.

cesium_ion_layer

cesium_ion_layer(name: str, asset_id: int, *, kind: str = '3d-tiles', altitude_offset: float = 0, **style: Any) -> dict[str, Any]

Build a layer that references a Cesium Ion asset by id.

The shape matches createCesiumIonLayer in @geolibre/core: a 3d-tiles layer for a tileset, a raster layer for imagery, both marked external so the 2D map leaves them alone and badges them "3D only". The globe loads the asset with the app's Cesium Ion token.

Parameters:

Name Type Description Default
name str

Layer display name.

required
asset_id int

The Cesium Ion asset id (a positive integer).

required
kind str

"3d-tiles" for a tileset or "imagery" for an imagery asset.

'3d-tiles'
altitude_offset float

Vertical offset applied to a tileset, in meters.

0
**style Any

Style overrides merged into the default layer style.

{}

Returns:

Type Description
dict[str, Any]

A layer dict for the project's layers array.

Raises:

Type Description
ValueError

If kind is unknown or asset_id is not a positive integer.

czml_layer

czml_layer(name: str, *, url: str | None = None, data: list[dict[str, Any]] | dict[str, Any] | None = None, source_path: str | None = None, **style: Any) -> dict[str, Any]

Build a layer that loads a CZML (Cesium Language) dynamic 3D scene.

The shape matches createCzmlLayer in @geolibre/core: a 3d-tiles layer marked external so the 2D map leaves it alone and badges it "3D only". The globe renders dynamic orbits, vehicle paths, and time-varying scenes from CZML packets with clock synchronization.

Parameters:

Name Type Description Default
name str

Layer display name.

required
url str | None

URL endpoint serving the CZML document.

None
data list[dict[str, Any]] | dict[str, Any] | None

Inline parsed CZML document (packets array or packet object).

None
source_path str | None

Optional local file path when loaded from disk.

None
**style Any

Style overrides merged into the default layer style.

{}

Returns:

Type Description
dict[str, Any]

A layer dict for the project's layers array.

Raises:

Type Description
ValueError

If neither url nor a non-empty data is provided.

cesium_kml_layer

cesium_kml_layer(name: str, *, url: str | None = None, data: str | None = None, source_path: str | None = None, **style: Any) -> dict[str, Any]

Build a native globe KML/KMZ layer preserving document styling.

Supply a URL, inline KML XML, or a KMZ data URL. Package local resources inside KMZ archives so they remain available when sharing the project.

video_layer

video_layer(name: str, urls: list[str], coordinates: list[list[float]], **style: Any) -> dict[str, Any]

Build a georeferenced video layer.

Parameters:

Name Type Description Default
name str

Layer display name.

required
urls list[str]

One or more video URLs (format fallbacks, e.g. MP4 then WebM).

required
coordinates list[list[float]]

Four [lng, lat] corners in top-left, top-right, bottom-right, bottom-left order.

required
**style Any

Style overrides merged into the default layer style.

{}

Returns:

Type Description
dict[str, Any]

A layer dict for the project's layers array.

Raises:

Type Description
ValueError

If urls is empty, any URL is not https:// (the browser's media-src CSP blocks http://), or coordinates is not four [lng, lat] pairs.

load_featurecollection

load_featurecollection(data: Any) -> dict[str, Any]

Coerce assorted inputs into a GeoJSON FeatureCollection dict.

Accepts a FeatureCollection/Feature/geometry dict, a file path or URL to a GeoJSON file, a JSON string, or any object exposing __geo_interface__ (e.g. a GeoPandas GeoDataFrame/GeoSeries or a Shapely geometry).

Parameters:

Name Type Description Default
data Any

The input geometry/collection in one of the supported forms.

required

Returns:

Type Description
dict[str, Any]

A GeoJSON FeatureCollection dict.

Raises:

Type Description
ValueError

If the input cannot be interpreted as GeoJSON.

ensure_plugins_block

ensure_plugins_block(project: dict[str, Any]) -> dict[str, Any]

Return the project's plugins block, creating it if absent.

Mirrors normalizeProjectPlugins in packages/core/src/project.ts: the block always carries manifestUrls, activePluginIds, mapControlPositions, and settings. A freshly created block is seeded with DEFAULT_ACTIVE_PLUGIN_IDS so adding a control from Python does not deactivate the app's default plugins (an existing block is left as-is, honouring whatever the user/app already chose).

Parameters:

Name Type Description Default
project dict[str, Any]

The project dict to read/extend in place.

required

Returns:

Type Description
dict[str, Any]

The (possibly newly created) plugins block dict.

set_plugin_state

set_plugin_state(project: dict[str, Any], plugin_id: str, settings: dict[str, Any], *, position: str | None = None, activate: bool = True) -> None

Store a map-control plugin's project state in place, optionally activating.

Writes the settings blob and records the control corner; with activate=True it also adds plugin_id to activePluginIds. The Components plugin (legend/colorbar) restores from its settings alone, so it passes activate=False to avoid mounting the full Components toolbar.

Parameters:

Name Type Description Default
project dict[str, Any]

The project dict to mutate.

required
plugin_id str

The plugin id (e.g. "maplibre-gl-swipe").

required
settings dict[str, Any]

The plugin's project-state settings blob.

required
position str | None

Optional control corner; one of CONTROL_POSITIONS.

None
activate bool

Whether to add plugin_id to activePluginIds.

True

swipe_state

swipe_state(*, left_layers: list[str], right_layers: list[str], orientation: str = 'vertical', position: float = 50) -> dict[str, Any]

Build the Layer Swipe plugin state (SwipeState in maplibre-swipe.ts).

Parameters:

Name Type Description Default
left_layers list[str]

Layer ids shown on the left/top of the slider. The string "__basemap__" selects the basemap.

required
right_layers list[str]

Layer ids shown on the right/bottom of the slider.

required
orientation str

"vertical" or "horizontal".

'vertical'
position float

Slider position as a percentage in [0, 100].

50

Returns:

Type Description
dict[str, Any]

A swipe-state dict for the project's plugin settings.

legend_gui_entry

legend_gui_entry(title: str, items: list[dict[str, Any]], position: str) -> dict[str, Any]

Build one legend entry (ComponentLegendGuiEntryState).

legend_gui_state

legend_gui_state(entry: dict[str, Any], *, existing: dict[str, Any] | None = None) -> dict[str, Any]

Build the Legend control state, appending entry to any existing one.

The control renders one on-map legend per item in its legends array (see LegendGuiControl.setState in maplibre-gl-components), so each call appends rather than replaces, and the top-level fields mirror the latest entry for the editing form.

Parameters:

Name Type Description Default
entry dict[str, Any]

A legend entry from legend_gui_entry.

required
existing dict[str, Any] | None

The current legend state to append to, if any.

None

Returns:

Type Description
dict[str, Any]

A ComponentLegendGuiState dict.

colorbar_gui_entry

colorbar_gui_entry(*, mode: str, colormap: str, custom_colors: str, vmin: float, vmax: float, label: str, units: str, orientation: str, position: str) -> dict[str, Any]

Build one colorbar entry (ComponentColorbarGuiEntryState).

colorbar_gui_state

colorbar_gui_state(entry: dict[str, Any], *, existing: dict[str, Any] | None = None) -> dict[str, Any]

Build the Colorbar control state, appending entry to any existing one.

Like legend_gui_state, the control renders one colorbar per item in its colorbars array, so calls accumulate.

Parameters:

Name Type Description Default
entry dict[str, Any]

A colorbar entry from colorbar_gui_entry.

required
existing dict[str, Any] | None

The current colorbar state to append to, if any.

None

Returns:

Type Description
dict[str, Any]

A ComponentColorbarGuiState dict.

filter_expression

filter_expression(expression: Any) -> list[Any]

Build a layer's persistent filterExpression.

Parameters:

Name Type Description Default
expression Any

A boolean MapLibre expression, as a list or a JSON string, e.g. [">=", ["get", "population"], 100000].

required

Returns:

Type Description
list[Any]

The expression as a list, ready for the layer's filterExpression.

Raises:

Type Description
ValueError

If the expression is not an array, or its operator cannot produce a boolean.

parse_level_value

parse_level_value(raw: Any) -> list[tuple[str, float | None]]

Parse one level attribute into the floors it names.

Mirrors parseLevelValue in packages/core/src/level-filter.ts: numbers are taken as they are; text is split on ; (OpenStreetMap's list separator) and each part read as a number, an integer span such as 0-2 (every floor it covers), or a named floor such as G.

Parameters:

Name Type Description Default
raw Any

The attribute value.

required

Returns:

Type Description
list[tuple[str, float | None]]

(label, ordinal) pairs; ordinal is None for a named floor.

level_value_matches

level_value_matches(raw: Any, level: str, mode: str) -> bool

Whether a feature's level attribute falls on the chosen floor.

Parameters:

Name Type Description Default
raw Any

The feature's level attribute.

required
level str

The chosen floor's label, e.g. "0".

required
mode str

"only" for that floor, "below" for it and every numbered floor under it, "all" for everything.

required

Returns:

Type Description
bool

True when the feature is drawn.

level_filter

level_filter(field: str, level: Any = None, *, mode: str | None = None, features: Iterable[dict[str, Any]] | None = None) -> dict[str, Any]

Build a layer's floor picker link (levelFilter).

Parameters:

Name Type Description Default
field str

The feature property holding the floor, e.g. "level".

required
level Any

The floor to show ("0", -1), or None for every floor.

None
mode str | None

"only" (the default once a level is given) or "below" to also show the floors under it.

None
features Iterable[dict[str, Any]] | None

The layer's features, used to resolve the raw values that match. Without them the link is saved unresolved and the app resolves it once it has the layer's features (a local file it re-reads); a layer whose features the app never holds (vector tiles) is not narrowed.

None

Returns:

Type Description
dict[str, Any]

The levelFilter record.

Raises:

Type Description
ValueError

If the field is blank or the mode is unknown.

label_style

label_style(field: str | None = None, *, expression: Any = None, enabled: bool | None = None, base: dict[str, Any] | None = None, **options: Any) -> dict[str, Any]

Build a layer's style.labels object (LabelStyle in types.ts).

Parameters:

Name Type Description Default
field str | None

Attribute whose value becomes the label text.

None
expression Any

A MapLibre expression (list or JSON string) for the label text; overrides field when set, e.g. ["concat", ["get", "name"], " (", ["get", "pop"], ")"]. Pass "" to clear an existing one.

None
enabled bool | None

Whether labels are shown. False keeps the configuration but hides the labels. None keeps base's value, or turns labels on when there is no base.

None
base dict[str, Any] | None

An existing labels object to update; unspecified options keep its values. Defaults to DEFAULT_LABEL_STYLE.

None
**options Any

Any of LABEL_OPTION_NAMES -- placement ("point"/"line"), size, color, halo_color, halo_width, min_zoom, max_zoom, allow_overlap, anchor, offset_x, offset_y, rotation, max_width, transform, number_format, number_decimals, number_locale, dedupe, and the data-defined size_expression, color_expression, opacity_expression, visibility_expression, priority_expression. None values are skipped. Expressions are checked for shape only (a JSON array with an operator), not for their result type; the app reports a mistyped one when it renders.

{}

Returns:

Type Description
dict[str, Any]

A complete labels object.

Raises:

Type Description
ValueError

If an option is unknown or invalid, or labels are enabled with neither a field nor an expression to draw.

json_compatible

json_compatible(value: Any, what: str) -> Any

Return a deep copy of value after checking it is plain JSON.

Mirrors isJsonCompatible in project.ts, which drops a plugin's settings on load when they are not.

Parameters:

Name Type Description Default
value Any

The value to check.

required
what str

The argument name, for error messages.

required

Returns:

Type Description
Any

A deep copy of the value.

Raises:

Type Description
ValueError

If the value holds something JSON cannot represent.

story_map_settings

story_map_settings(**settings: Any) -> dict[str, Any]

Validate story map presentation settings and map them to project keys.

Parameters:

Name Type Description Default
**settings Any

Any of STORY_SETTING_NAMES. None values are skipped.

{}

Returns:

Type Description
dict[str, Any]

The settings keyed as StoryMap stores them (showMarkers, ...).

Raises:

Type Description
ValueError

If a setting is unknown or has a value the app rejects.

story_chapter

story_chapter(title: str, *, center: tuple[float, float] | list[float], zoom: float, pitch: float = 0, bearing: float = 0, description: str = '', image: str | None = None, alignment: str = 'left', hidden: bool = False, map_animation: str = 'flyTo', rotate_animation: bool = False, on_enter: Any = None, on_exit: Any = None, chapter_id: str | None = None) -> dict[str, Any]

Build one story map chapter (StoryChapter in types.ts).

Values are stored the way normalizeStoryChapter in project.ts leaves them, so the app loads the chapter unchanged: the bearing is wrapped into 0-360, and out-of-range coordinates, zooms, and pitches are refused rather than silently clamped.

Parameters:

Name Type Description Default
title str

Chapter heading.

required
center tuple[float, float] | list[float]

Camera target as (lng, lat).

required
zoom float

Camera zoom, 0-24.

required
pitch float

Camera tilt in degrees, 0-85.

0
bearing float

Camera rotation in degrees.

0
description str

Chapter body text.

''
image str | None

Optional image URL (or data URI) shown in the chapter panel.

None
alignment str

Text panel position: "left", "center", "right", or "full".

'left'
hidden bool

Hide the text panel while still moving the map.

False
map_animation str

"flyTo", "easeTo", or "jumpTo".

'flyTo'
rotate_animation bool

Slowly rotate the camera once the move settles.

False
on_enter Any

Layer opacity changes applied on entering the chapter, as {"layer": <id>, "opacity": 0-1, "duration": ms} entries.

None
on_exit Any

Layer opacity changes applied on leaving the chapter.

None
chapter_id str | None

Explicit chapter id; a UUID by default.

None

Returns:

Type Description
dict[str, Any]

A chapter dict.

Raises:

Type Description
ValueError

If any value is out of range or not in its vocabulary.

bookmark_folder

bookmark_folder(name: str, *, collapsed: bool = False, folder_id: str | None = None) -> dict[str, Any]

Build one Bookmarks panel folder (ProjectBookmarkGroup in types.ts).

Parameters:

Name Type Description Default
name str

Folder name shown in the panel.

required
collapsed bool

Start with the folder collapsed.

False
folder_id str | None

Explicit folder id; a UUID by default.

None

Returns:

Type Description
dict[str, Any]

A folder dict.

Raises:

Type Description
ValueError

If name is blank or collapsed is not a bool.

bookmark

bookmark(name: str, *, center: tuple[float, float] | list[float], zoom: float, pitch: float = 0, bearing: float = 0, group_id: str | None = None, visible_layer_ids: list[str] | None = None, bookmark_id: str | None = None, created_at: int | None = None) -> dict[str, Any]

Build one saved map view for the Bookmarks panel (ProjectBookmark).

Values are stored the way normalizeBookmarks in project.ts leaves them, so the app loads the bookmark unchanged: the bearing is wrapped into 0-360, and out-of-range coordinates, zooms, and pitches are refused rather than silently clamped.

Parameters:

Name Type Description Default
name str

Bookmark name shown in the panel.

required
center tuple[float, float] | list[float]

Camera target as (lng, lat).

required
zoom float

Camera zoom, 0-24.

required
pitch float

Camera tilt in degrees, 0-85.

0
bearing float

Camera rotation in degrees.

0
group_id str | None

Id of the folder it belongs to; ungrouped when omitted.

None
visible_layer_ids list[str] | None

Layer ids to show when the bookmark is opened (all others are hidden). Omit to leave layer visibility alone.

None
bookmark_id str | None

Explicit bookmark id; a UUID by default.

None
created_at int | None

Creation time in milliseconds since the epoch; now by default.

None

Returns:

Type Description
dict[str, Any]

A bookmark dict.

Raises:

Type Description
ValueError

If any value is out of range or of the wrong type.