Skip to content

API reference

Generated from the docstrings of the package.

Client

Async functions over :mod:copernicus_ems.catalogue and :mod:copernicus_ems.events.

They take your httpx.AsyncClient: timeouts, retries and pooling stay yours, and HTTP errors propagate. :class:RapidMapping wraps them for callers who would rather not bring one: it opens (and closes) its own, which retries network errors and 429/502/503/504 (the dashboard API answers 502 now and then).

Layers are saved as .geojson in a directory, which is also the cache: a layer's URL carries its version (_v1), so a file already there is the same layer and is read from disk, not downloaded again. The activation list and details are always asked: new monitoring products appear in them. Files are written to .part and renamed, so a file that exists is whole.

Send module-attribute

Send = Callable[[httpx.Request], Awaitable[httpx.Response]]

ENV_DATA_DIR module-attribute

ENV_DATA_DIR = 'COPERNICUS_EMS_DATA_DIR'

RapidMapping

The functions above, with a client and a directory of their own.

Give it no client and it opens one that retries (see :class:RetryTransport); use it as an async context manager, or call :meth:aclose, to close it. directory defaults to :func:default_directory, read when a layer is fetched.

send, an async (httpx.Request) -> httpx.Response callable, routes every request (Rapid Mapping, layers, STAC search) through the caller instead, e.g. an application's shared client with its own retry policy; no :class:RetryTransport is installed then.

aclose async

aclose() -> None

Close the HTTP client if this instance opened it.

activations async

activations(*, country: str | None = None, categories: Iterable[str] | None = None, since: date | datetime | None = None, until: date | datetime | None = None) -> list[Activation]

Public activations, oldest first, filtered as :func:select_activations does.

products async

products(code: str) -> list[Product]

The products of one activation (EMSR762).

scenes async

scenes(product: Product, *, collections: Iterable[str] = ('sentinel-1-grd',), within: timedelta = timedelta(days=3), max_cloud_cover: float | None = None) -> list[SceneMatch]

Open Sentinel scenes near the product, nearest first: see :func:find_scenes.

search_scenes async

search_scenes(geometry: dict[str, Any], start: datetime, end: datetime, *, collections: Iterable[str] = ('sentinel-1-grd',)) -> list[Scene]

Open scenes over geometry from start to end: see :func:fetch_scenes.

layer async

layer(product: Product, kind: str) -> dict[str, Any] | None

One vector layer as GeoJSON, cached; None if the product has none of that kind.

observed_events async

observed_events(code: str, *, event_types: Iterable[str] | None = (FLOOD_EVENT_TYPE,), notations: Iterable[str] | None = FLOOD_NOTATIONS, concurrency: int = 4) -> list[ProductEvents]

The observed events of every product of an activation (floods by default).

ProductEvents dataclass

The selected features of one product's layer, with the product they come from.

RetryTransport

Bases: AsyncBaseTransport

Retry network errors and 429/502/503/504, waiting backoff_s, doubled each time.

SendTransport

Bases: AsyncBaseTransport

Hands every request to send (the caller's retry, rate limit, shared client).

No retry of its own: with send, retrying is the caller's job.

default_directory

default_directory() -> Path

Where layers are saved when no directory is given.

COPERNICUS_EMS_DATA_DIR if set, else copernicus-ems in the user cache ($XDG_CACHE_HOME, or ~/.cache).

layer_path

layer_path(product: Product, layer: Layer, directory: Path) -> Path

directory/EMSR762/EMSR762_AOI01_DEL_PRODUCT_observedEventA_v1.geojson.

fetch_activations async

fetch_activations(client: AsyncClient, *, page_size: int = 500) -> list[Activation]

Every public activation, following the pages.

fetch_products async

fetch_products(client: AsyncClient, code: str) -> list[Product]

The products of one activation (EMSR762).

fetch_layer async

fetch_layer(client: AsyncClient, product: Product, kind: str, *, directory: Path | None = None) -> dict[str, Any] | None

One vector layer of a product as GeoJSON; None if the product has none of that kind.

The layer is saved under directory (default :func:default_directory) and read from there on the next call.

fetch_observed_events async

fetch_observed_events(client: AsyncClient, code: str, *, event_types: Iterable[str] | None = (FLOOD_EVENT_TYPE,), notations: Iterable[str] | None = FLOOD_NOTATIONS, directory: Path | None = None, concurrency: int = 4) -> list[ProductEvents]

The observed events of every product of an activation (floods by default).

Products without an observedEventA layer, and products where no feature passes the filter, are left out. Layers are cached as in :func:fetch_layer, and downloaded concurrency at a time; the result keeps the order of the products.

Catalogue

Activations and products of Copernicus EMS Rapid Mapping.

The public dashboard API needs no credentials:

  • public-activations-info/ lists every activation, paginated (count / next), newest first;
  • public-activations/?code=EMSR762 details one: its areas of interest (AOI), and for each AOI the products (delineation DEL, grading GRA, first estimate FEP; monitoringNumber 0 for the first product, then 1, 2, ... for each monitoring update), the satellite images each product was made from, and its layers.

Every vector layer of a product is published on its own as GeoJSON (the json URL of a vt layer), from tens of kilobytes to tens of megabytes. There is no need for the product package, which is a ~100 MB zip of zips holding the ortho imagery, and which for some activations answers 403 (EMSR664) while its GeoJSON layers are open.

Two things the API does not say:

  • the category describes the cause, not the effect: many Italian floods are filed as Storm. Filter on the features' event_type instead;
  • the list gives countries as strings, the detail as {"name": ...}.

Activation dataclass

One activation, as listed.

Layer dataclass

A vector layer of a product, published as GeoJSON.

Image dataclass

A satellite image a product was made from.

Often a commercial sensor (PAZ, COSMO-SkyMed, RADARSAT-2, Pléiades…), not an open Sentinel one: see :mod:copernicus_ems.scenes for the nearest open acquisitions.

Product dataclass

One map product of one AOI.

label property

label: str

AOI01_DEL_PRODUCT, AOI02_DEL_MONIT01: the product's own name.

observed_time property

observed_time: datetime | None

The earliest image the product was made from: when the satellite saw it.

aoi_extent property

aoi_extent: dict[str, Any] | None

The observation mask as a GeoJSON geometry (lon/lat), from :attr:aoi_extent_wkt.

wkt_to_geojson

wkt_to_geojson(wkt: str) -> dict[str, Any]

A WKT POLYGON or MULTIPOLYGON as a GeoJSON geometry.

Those are the only shapes Rapid Mapping uses for an AOI; anything else raises :class:EmsError. Z and M values are dropped.

parse_time

parse_time(raw: Any) -> datetime | None

An ISO time from the API, as aware UTC (the API omits the zone).

parse_activations

parse_activations(body: bytes | str) -> ActivationsPage

One page of the activation list. Rows without a usable event time are skipped.

select_activations

select_activations(activations: Iterable[Activation], *, country: str | None = None, categories: Iterable[str] | None = None, since: date | datetime | None = None, until: date | datetime | None = None) -> list[Activation]

Activations in country and categories (case-insensitive), oldest first.

since and until bound the event time, both included; a date means that whole day (UTC), a naive datetime is taken as UTC.

parse_detail

parse_detail(body: bytes | str) -> list[Product]

Every product of an activation, with its vector layers.

Events

Observed event layers: what the satellite actually saw under water.

The flooded extent is the observedEventA layer, not the AOI. On EMSR762 AOI01 the AOI covers ~1,850 km² and the observed flood 1.19 km²: taking the AOI as the event would call hundreds of dry square kilometres flooded. The AOI is the observation mask instead: inside it, the absence of a flood polygon is an observed "not flooded"; outside it, nothing was observed.

A flood activation also maps the landslides the same rain triggered (event_type 6-Mass Movement). Keep 5-Flood, with the notations "Flooded area" and "Flood trace" (ground the water left marks on).

parse_layer

parse_layer(body: bytes | str) -> dict[str, Any]

A GeoJSON FeatureCollection (CRS84, i.e. lon/lat WGS84).

select_features

select_features(collection: dict[str, Any], *, event_types: Iterable[str] | None = (FLOOD_EVENT_TYPE,), notations: Iterable[str] | None = FLOOD_NOTATIONS) -> list[dict[str, Any]]

The features of the given event types and notations (None keeps all).

Open imagery (Sentinel scenes)

Open Sentinel scenes near a product: imagery to pair with the labels.

Rapid Mapping products are often made from commercial images (PAZ, COSMO-SkyMed, RADARSAT-2, Pléiades… see :attr:Product.images), which are not open. To train or test a model on open data, pair each product with the nearest open acquisition over its AOI: Sentinel-1 (radar, sees through clouds, the usual choice for floods) or Sentinel-2 (optical).

The scenes come from the public STAC catalogue of the Copernicus Data Space Ecosystem: searching needs no account, downloading does (a free account on https://dataspace.copernicus.eu). Every match carries its time gap to the product's observed_time: water moves, and a scene a day later can show a different flood.

Scene dataclass

One scene of the Copernicus Data Space catalogue.

download_url property

download_url: str | None

The zipped product on the Data Space (needs an account token).

SceneMatch dataclass

A scene near a product, and how far apart they are in time.

ScenePass dataclass

The scenes of one pass of a satellite over a product's AOI.

A catalogue scene is a slice (a Sentinel-1 slice, a Sentinel-2 tile): one pass often needs several to cover an AOI.

geometry property

geometry: dict[str, Any]

The footprints, as a GeoJSON GeometryCollection (lon/lat).

cloud_cover property

cloud_cover: float | None

The cloudiest scene of the pass (None for radar).

passes

passes(matches: Iterable[SceneMatch]) -> list[ScenePass]

Group scene matches by pass (datatake), nearest pass first.

scene_search_body

scene_search_body(geometry: dict[str, Any], start: datetime, end: datetime, *, collections: Iterable[str] = (SENTINEL_1_GRD,), limit: int = 100) -> dict[str, Any]

The STAC /search request for scenes intersecting geometry (lon/lat GeoJSON).

parse_scenes

parse_scenes(body: bytes | str) -> tuple[list[Scene], dict[str, Any] | None]

One page of a STAC search: the scenes, and the next link if there is one.

fetch_scenes async

fetch_scenes(client: AsyncClient, geometry: dict[str, Any], start: datetime, end: datetime, *, collections: Iterable[str] = (SENTINEL_1_GRD,), url: str = STAC_SEARCH_URL) -> list[Scene]

Every scene intersecting geometry between start and end, following pages.

find_scenes async

find_scenes(client: AsyncClient, product: Product, *, collections: Iterable[str] = (SENTINEL_1_GRD,), within: timedelta = timedelta(days=3), max_cloud_cover: float | None = None, url: str = STAC_SEARCH_URL) -> list[SceneMatch]

Open scenes over the product's AOI within within of its observed time, nearest first.

max_cloud_cover (0-100) drops cloudier optical scenes; radar scenes have no cloud cover and are always kept.

Files (GeoJSON, GeoParquet)

Observed events as files: GeoJSON (core) or GeoParquet (parquet extra).

Every feature is tagged with where it comes from (activation, product, aoi_name, observed_time); the observation masks are features too, one per product, with the same tags. GeoParquet follows the GeoParquet 1.1 <https://geoparquet.org/releases/v1.1.0/>_ specification (WKB geometry, lon/lat CRS84), and opens in GeoPandas, DuckDB and QGIS.

tags

tags(event: ProductEvents) -> dict[str, Any]

Where an event comes from, as feature properties.

tagged_features

tagged_features(events: Iterable[ProductEvents]) -> list[dict[str, Any]]

Every feature of the events, its properties extended with :func:tags.

mask_features

mask_features(events: Iterable[ProductEvents]) -> list[dict[str, Any]]

One feature per product: its observation mask (AOI), with :func:tags.

write_geojson

write_geojson(path: Path, features: list[dict[str, Any]]) -> Path

A GeoJSON FeatureCollection, written whole (.part then renamed).

write_geoparquet

write_geoparquet(path: Path, features: list[dict[str, Any]]) -> Path

A GeoParquet 1.1 file: one row per feature, a WKB geometry column.

Needs the parquet extra (pyarrow, shapely). Property columns are typed when their values agree, else stored as text; observed_time is a UTC timestamp.

write_features

write_features(path: Path, features: list[dict[str, Any]]) -> Path

GeoParquet for .parquet / .geoparquet, GeoJSON otherwise.

Sentinel-1 backscatter ([cdse] extra)

Sentinel-1 backscatter from the Copernicus Data Space, on the grid of the labels.

Needs the cdse extra (pip install 'copernicus-ems[cdse]') and a free account on https://dataspace.copernicus.eu with an OAuth client (Dashboard → User Settings → OAuth clients → Create). The Sentinel Hub Process API then returns analysis-ready backscatter (calibrated, orthorectified, optionally speckle-filtered) cut to exactly the :class:~copernicus_ems.ml.Grid of a label raster, so image and labels line up pixel for pixel: no 1 GB GRD archive, no SNAP.

Files are written to the data directory (COPERNICUS_EMS_DATA_DIR, a Docker volume in a container), next to the layers, and read from there on the next call; nothing is stored in a bucket.

Credentials come from the environment, never from code:

  • CDSE_CLIENT_ID and CDSE_CLIENT_SECRET, or
  • CDSE_CREDENTIALS_FILE: a JSON file {"client_id": ..., "client_secret": ...} (e.g. a Docker secret in /run/secrets).

Every request costs processing units (PU) of the account's monthly quota (10,000 for a general user): :func:estimate_pu says how many before anything is sent, and budget_pu refuses requests above it.

Credentials dataclass

An OAuth client of the Copernicus Data Space. The secret never shows in repr.

from_env classmethod

from_env(environ: Mapping[str, str] | None = None) -> Credentials

CDSE_CLIENT_ID + CDSE_CLIENT_SECRET, or the file in CDSE_CREDENTIALS_FILE.

SentinelHub

An authenticated Process API client; reuses its token until it expires.

Give it no client and it opens one that retries (see :class:~copernicus_ems.RetryTransport); use it as an async context manager. With send (async (httpx.Request) -> httpx.Response) the token and Process API requests go through the caller instead, with no retry here.

process async

process(request: dict[str, Any], *, pu: float = 0.0) -> bytes

POST one Process API request; the GeoTIFF bytes.

Backscatter dataclass

A Sentinel-1 backscatter GeoTIFF on a label grid, and how it was made.

PairPlan dataclass

What :func:make_pair would do for one product, and what it would cost.

ReferencePlan dataclass

A pre-event pass for change detection, and what it would cost.

parse_token

parse_token(status_code: int, body: bytes | str, *, now: float) -> Token

The token from the identity server's answer; :class:EmsError if refused.

estimate_pu

estimate_pu(width: int, height: int, *, bands: int = 2, float32: bool = True, samples: int = 1, orthorectify: bool = True, terrain_correction: bool = False, speckle_filter: bool = False) -> float

Processing units of one Process API request, by the CDSE formula.

1 PU is 512 x 512 pixels, 3 bands, 16 bits; factors multiply: area, bands / 3 (dataMask not counted), 2 for FLOAT32, samples, and for Sentinel-1 2 for orthorectification, 2.5 for terrain correction (GAMMA0_TERRAIN), 2 for speckle filtering. At least 0.005.

tiles

tiles(grid: Grid, max_pixels: int = MAX_PIXELS) -> list[tuple[int, int, Grid]]

(row, col, window) covering grid with windows of at most max_pixels a side.

evalscript

evalscript(polarizations: Sequence[str] = ('VV', 'VH')) -> str

Linear backscatter of each polarization, then dataMask, as FLOAT32 bands.

backscatter_request

backscatter_request(grid: Grid, start: datetime, end: datetime, *, polarizations: Sequence[str] = ('VV', 'VH'), back_coeff: BackCoeff = 'GAMMA0_ELLIPSOID', orthorectify: bool = True, speckle_filter: bool = False, orbit_direction: str | None = None) -> dict[str, Any]

The Process API request for Sentinel-1 GRD backscatter on exactly grid.

The bounding box is the grid's extent and the size its pixels, so each output pixel is one grid pixel.

fetch_backscatter async

fetch_backscatter(hub: SentinelHub, grid: Grid, start: datetime, end: datetime, *, path: Path, polarizations: Sequence[str] = ('VV', 'VH'), back_coeff: BackCoeff = 'GAMMA0_ELLIPSOID', orthorectify: bool = True, speckle_filter: bool = False, orbit_direction: str | None = None, budget_pu: float | None = None, max_pixels: int = MAX_PIXELS, tags: Mapping[str, Any] | None = None) -> Backscatter

Sentinel-1 backscatter on grid between start and end, as one GeoTIFF.

Bands: each polarization (linear power), then dataMask (1 data, 0 no data). Read from path if it is already there; otherwise the grid is asked in tiles of at most max_pixels a side and mosaicked. Raises :class:EmsError before any request if the estimate exceeds budget_pu.

backscatter_path

backscatter_path(grid: Grid, start: datetime, end: datetime, *, activation: str, directory: Path | None = None, **options: Any) -> Path

<data dir>/<activation>/sentinel-1/S1_<time>_<res>m_<key>.tif.

The name depends on the grid, the time range and the options, not on the product: two products of one AOI seen by the same pass share it.

pass_window

pass_window(time: datetime, minutes: float = 10.0) -> tuple[datetime, datetime]

A time range around one satellite pass, narrow enough to exclude the next one.

plan_pair async

plan_pair(ems: RapidMapping, event: ProductEvents, *, resolution_m: float = 20.0, within: timedelta = timedelta(days=2), min_coverage: float = 0.9, max_gap: timedelta = timedelta(hours=24), directory: Path | None = None) -> PairPlan

Choose the Sentinel-1 pass nearest in time among those covering min_coverage of the AOI within max_gap, and price it on the labels' grid. No PU is spent.

Every feature of event becomes the flooded label: pass events selected for floods (the default of observed_events), not event_types=None, which would label landslides as water.

pu_to_spend

pu_to_spend(plans: Sequence[PairPlan], references: Sequence[ReferencePlan | None] = ()) -> float

PU that :func:make_pair would spend on these plans (and references), all told.

Images already in the data directory cost nothing, and an image shared by several products (one pass, one grid) is counted once: check this against a budget before calling :func:make_pair.

plan_reference async

plan_reference(ems: RapidMapping, plan: PairPlan, *, before: datetime | None = None, lookback: timedelta = 3 * REPEAT_CYCLE, min_coverage: float = 0.9, directory: Path | None = None) -> ReferencePlan

The latest Sentinel-1 pass of the same relative orbit as the plan's pass, acquired before before, priced on the same grid. No PU is spent.

Same orbit means same viewing geometry: the difference between the two images is change on the ground (water came), not a change of incidence angle. before should be the start of the flood (an activation's event_time); by default it is one repeat cycle before the event pass, which is right only for floods that rose within those days.

make_pair async

make_pair(hub: SentinelHub, plan: PairPlan, *, reference: ReferencePlan | None = None, budget_pu: float | None = None) -> tuple[Backscatter, Path]

The backscatter GeoTIFF of the plan's pass and the label GeoTIFF on the same grid.

With a reference that found a pass, its image is fetched too (same grid, same options) and named in the manifest under "reference".

Training dataset ([ml] extra)

A training dataset from the image-label pairs of copernicus-ems pairs.

Needs the ml extra (numpy, rasterio). It reads the pairs already in the data directory (<data dir>/<code>/sentinel-1/*_pair.json), so it spends no processing units and works offline, and writes::

dataset/
├── images/<id>.tif     Sentinel-1 VV, VH, dataMask (float32, linear power);
│                       VV, VH, VV_pre, VH_pre, dataMask with ``reference=True``
├── labels/<id>.tif     1 flooded, 0 dry, 255 ignore (uint8)
├── index.csv           one row per chip: split, provenance, shares, bounds
└── dataset.json        bands, label values, splits, statistics, credits

Two rules keep the dataset honest:

  • a label pixel where the image has no data (dataMask 0) becomes 255: there is nothing to learn from;
  • train / val / test are assigned by area (activation + AOI), never by chip: the products of one AOI overlap in space, and splitting their chips at random would put the same ground in training and in test.

Pair dataclass

One image-label pair written by :func:copernicus_ems.sentinelhub.make_pair.

aoi property

aoi: str

AOI01 from AOI01_DEL_MONIT02.

reference property

reference: Path | None

The pre-event image (pairs --reference), if it was fetched.

group property

group: str

The unit the splits are made of: one area of interest of one activation.

find_pairs

find_pairs(directory: Path, codes: Iterable[str] | None = None) -> list[Pair]

Every pair under directory/<code>/sentinel-1/, codes only if given.

split_groups

split_groups(sizes: dict[str, int], ratios: Sequence[float] = (0.7, 0.15, 0.15), *, seed: int = 0) -> dict[str, str]

Assign each group to a split so that chip counts approach ratios.

Deterministic for a seed: groups are taken in a seeded hash order, largest first among equals, each to the split furthest below its target. With fewer groups than splits, the last splits stay empty.

build_dataset

build_dataset(pairs: Sequence[Pair], directory: Path, *, size: int = 256, stride: int | None = None, min_observed: float = 0.5, min_flooded: float = 0.0, min_valid: float = 0.9, ratios: Sequence[float] = (0.7, 0.15, 0.15), seed: int = 0, reference: bool = False) -> DatasetSummary

Cut every pair into aligned chips, assign splits by area, write the dataset.

A chip is kept when min_observed of its pixels are observed (label 0 or 1), min_flooded of those are flooded, and the image has data on min_valid of the observed ones.

With reference=True only pairs with a pre-event image are used, and each image chip has five bands: VV, VH, VV_pre, VH_pre, dataMask, where dataMask is 1 only where both acquisitions have data.

Geometry ([geo] extra)

Geometry over observed events: flooded, observed dry, areas in km².

Needs the geo extra (pip install copernicus-ems[geo]: shapely and pyproj). Areas are geodesic, on the WGS84 ellipsoid, so they do not depend on a projection. A product splits the map in three:

  • inside a feature: observed flooded (:func:flooded);
  • inside the AOI, outside every feature: observed dry (:func:observed_dry);
  • outside the AOI: not observed.

ProductSummary dataclass

The numbers of one product: what was looked at, and what was found.

flooded_share property

flooded_share: float

Flooded fraction of the observed area (0 when nothing was observed).

mask

mask(event: ProductEvents) -> BaseGeometry

The observation mask (the AOI) of the event's product.

flooded

flooded(event: ProductEvents) -> BaseGeometry

The union of the event's features, clipped to the observation mask.

observed_dry

observed_dry(event: ProductEvents) -> BaseGeometry

Inside the AOI, outside every feature: where "not flooded" was observed.

area_km2

area_km2(geometry: BaseGeometry | dict[str, Any]) -> float

Geodesic area of a lon/lat geometry (or GeoJSON geometry), in km².

coverage

coverage(footprint: dict[str, Any] | BaseGeometry, event: ProductEvents) -> float

Share of the event's AOI inside footprint, from 0 to 1.

footprint is lon/lat: Scene.geometry, or ScenePass.geometry for every slice of one pass together.

summarize

summarize(event: ProductEvents) -> ProductSummary

The :class:ProductSummary of one product.

summary

summary(events: Iterable[ProductEvents]) -> list[ProductSummary]

One :class:ProductSummary per product, in the order given.

Labels and scores ([ml] extra)

Label rasters and mask-aware scores for flood models.

Needs the ml extra (pip install copernicus-ems[ml]: numpy, shapely, pyproj). A product becomes a tri-state label raster:

======== ========== ===================================== value meaning where ======== ========== ===================================== 1 flooded inside an observedEventA feature 0 dry inside the AOI, outside every feature 255 ignore outside the AOI: nobody looked ======== ========== =====================================

255 is meant for ignore_index in a training loss, and :func:evaluate leaves it out of the contingency table: a prediction where nobody looked is reported (:attr:Scores.unobserved_predicted), never counted as a false alarm. That is the whole point of the observation mask.

Rasters are in a metric CRS, by default the UTM zone of the AOI centre; pixels are labelled by their centre.

Grid dataclass

A north-up pixel grid: width by height pixels of resolution_m.

x0, y0 are the top-left corner in crs (e.g. EPSG:32632).

transform property

transform: tuple[float, float, float, float, float, float]

The GDAL-style affine transform, as rasterio's Affine takes it.

from_transform classmethod

from_transform(crs: Any, transform: Sequence[float], width: int, height: int) -> Grid

The grid of a raster, e.g. Grid.from_transform(src.crs, src.transform, src.width, src.height) for a rasterio dataset: north-up, square pixels.

window

window(row: int, col: int, height: int, width: int) -> Grid

The sub-grid starting at pixel (row, col).

LabelRaster dataclass

A tri-state label raster (uint8, rows by columns) and its grid.

to_geotiff

to_geotiff(path: Path) -> Path

A single-band uint8 GeoTIFF (deflate, tiled), 255 as nodata, the provenance (activation, product, observed time, credit) as tags.

from_geotiff classmethod

from_geotiff(path: Path) -> LabelRaster

A label raster written by :meth:to_geotiff (or any north-up uint8 band).

Scores dataclass

Contingency table of a binary flood prediction, inside the observation mask.

Ratios are nan when undefined (e.g. :attr:far with no predicted flood). Scores add up: sum(per_product, Scores.zero()) pools pixels.

csi property

csi: float

Critical success index, hits / (hits + misses + false alarms); the IoU of flood.

iou property

iou: float

Intersection over union of the flooded class: the same number as :attr:csi.

pod property

pod: float

Probability of detection (recall), hits / (hits + misses).

far property

far: float

False alarm ratio, false alarms / (hits + false alarms).

bias property

bias: float

Frequency bias, predicted over observed flood: above 1 over-predicts.

unobserved_predicted_km2 property

unobserved_predicted_km2: float

Predicted flood outside the AOI: not an error, nobody looked.

Chip dataclass

A square tile of a :class:LabelRaster, for training.

flooded_share property

flooded_share: float

Flooded fraction of the observed pixels of the chip.

save

save(directory: Path, *, file_format: Literal['npy', 'tif'] = 'npy') -> Path

The chip as .npy + .json sidecar (grid, provenance), or as a GeoTIFF (file_format="tif", provenance in its tags); the file's path.

utm_crs

utm_crs(lon: float, lat: float) -> str

The UTM zone of a point, as EPSG:326xx (north) or EPSG:327xx (south).

grid_for

grid_for(event: ProductEvents, resolution_m: float = 20.0, *, crs: str | None = None) -> Grid

The grid covering the event's AOI, snapped to resolution_m.

burn

burn(geometry: BaseGeometry | dict[str, Any], grid: Grid) -> npt.NDArray[np.bool_]

True where a pixel centre falls in geometry (lon/lat, or GeoJSON).

rasterize

rasterize(event: ProductEvents, resolution_m: float = 20.0, *, grid: Grid | None = None, crs: str | None = None) -> LabelRaster

The tri-state :class:LabelRaster of one product (see the module docs).

evaluate

evaluate(predicted: ArrayLike, truth: LabelRaster) -> Scores

Score a flood prediction on truth's grid, inside the observation mask.

predicted is a boolean (or 0/1) array with the shape of truth.labels.

evaluate_geometry

evaluate_geometry(predicted: BaseGeometry | dict[str, Any], event: ProductEvents, resolution_m: float = 20.0) -> Scores

Score a predicted flood extent (lon/lat geometry, GeoJSON geometry or FeatureCollection) against one product, rasterized at resolution_m.

chips

chips(raster: LabelRaster, size: int = 256, *, stride: int | None = None, min_observed: float = 0.5, min_flooded: float = 0.0) -> Iterator[Chip]

Square tiles of raster, skipping the ones mostly outside the AOI.

A chip is kept when at least min_observed of its pixels are observed and at least min_flooded of the observed ones are flooded. Edge tiles are padded with :data:IGNORE.

MCP server ([mcp] extra)

Copernicus EMS Rapid Mapping as an MCP server, for LLM agents.

Needs the mcp extra (pip install 'copernicus-ems[mcp]'), then:

copernicus-ems mcp                       # stdio, for Claude Desktop / Claude Code
claude mcp add copernicus-ems -- copernicus-ems mcp
copernicus-ems-mcp --transport streamable-http --host 0.0.0.0 --port 8768

Over HTTP the MCP endpoint is /mcp and GET /health answers {"status": "ok"} for container healthchecks. Every option also reads an environment variable (COPERNICUS_EMS_MCP_TRANSPORT, _HOST, _PORT, _ALLOWED_HOSTS; the data directory from COPERNICUS_EMS_DATA_DIR), so a compose file needs no command line.

The tools answer with facts and file paths, never raw geometry: an activation can hold thousands of polygons, which help no model reason. Every number is computed here, from the published layers; the model only chooses the calls and writes the prose. Layers are cached on disk as everywhere else in the library, so repeated questions cost nothing.

ATTRIBUTION module-attribute

ATTRIBUTION = 'Contains modified Copernicus Emergency Management Service information, © European Union.'

build_server

build_server(client: AsyncClient | None = None, *, directory: Path | None = None) -> MCPServer[Any]

The MCP server; client and directory as for :class:RapidMapping.

list_activations async

list_activations(ems: RapidMapping, *, country: str | None = None, categories: list[str] | None = None, since: str | None = None, until: str | None = None, limit: int = 50) -> ActivationList

Activations, newest first, at most limit.

activation_summary async

activation_summary(ems: RapidMapping, code: str, *, hazard: Hazard = 'flood') -> ActivationSummary

Per product and per AOI: what was observed, how large, when.

compare_products async

compare_products(ems: RapidMapping, code: str, aoi_number: int, *, hazard: Hazard = 'flood') -> AoiTimeline

The products of one AOI in time order, with the change from one to the next.

export_observed_events async

export_observed_events(ems: RapidMapping, code: str, *, hazard: Hazard = 'flood', with_masks: bool = True, file_format: Literal['geojson', 'geoparquet'] = 'geojson', directory: Path | None = None) -> Export

Write the events (and the observation masks) of an activation as files.

Errors

copernicus_ems.errors.EmsError

Bases: Exception

The Rapid Mapping service answered with something that is not what was asked.