Sentinel AOI Quality Report avatar

Sentinel AOI Quality Report

Pricing

$0.05 / complete observed aoi report

Go to Apify Store
Sentinel AOI Quality Report

Sentinel AOI Quality Report

Experimental single-scene Sentinel-2 classification and coverage statistics for a small public area.

Pricing

$0.05 / complete observed aoi report

Rating

0.0

(0)

Developer

L3Digital

L3Digital

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

a day ago

Last modified

Share

Sentinel-2 AOI Quality Report

Get native Sentinel-2 scene-classification counts for one small rectangular area from one Earth Search Collection 1 L2A scene. The report distinguishes observed pixels, missing classification and centres outside the scene footprint, so a caller can assess the actual sampled coverage rather than using whole-tile cloud metadata.

This is an experimental TRYOUT. One hundred offline tests and four private owner QA runs passed; three geometries from one public scene matched an independent reference. Customer demand, workflow savings and population reliability remain unvalidated. This unofficial Actor is not affiliated with Copernicus, ESA, Element 84 or AWS.

Use from an AI agent through MCP

Add this URL to a client that supports remote HTTP MCP, then authorize with your own Apify account using the Apify MCP setup guide:

https://mcp.apify.com/?tools=l3digital/sentinel-aoi-quality

This configuration selects the Actor directly. Availability still depends on Apify account and Actor eligibility. Call l3digital/sentinel-aoi-quality with the example input below; the pricing and input restrictions on this page apply.

When using call-actor, its response contains run status and storage IDs. If the run is still active, check that run with get-actor-run. After success, retrieve the report with get-dataset-items using the returned dataset ID (defaultDatasetId in the run API). These retrieval tools load with the Actor. Retrieve the existing result instead of starting another run. Inspect the report status and the coverage or refusal fields described below before using its values.

Input

The default {} runs a deterministic illustrative demo with no upstream requests. It still writes one Apify dataset result and incurs no useful-report event.

Scene example (identity and AOI frozen before any raster inspection):

{
"mode": "scene",
"sceneId": "S2A_T18TWL_20250602T154709_L2A",
"bbox": [-74.01, 40.7, -74.0, 40.71]
}

sceneId and bbox are required in scene mode. Bbox is [west,south,east,north] in WGS84 degrees, with finite ordered values, latitude from −80 through 84 and each axis span at most 0.05 degrees. Crossing the antimeridian is unsupported. West/south edges include centres; east/north edges exclude them. The platform form uses a flat JSON array editor; runtime validates the conditional/geometric rules. Only mode, sceneId and bbox are accepted. The Actor does not search or rank scenes, query dates, accept polygons/uploads/arbitrary URLs, or resample pixels.

Output and denominators

Each invocation attempts exactly one dataset result. status is complete, demo, no_observation, below_resolution, unsupported, source_failure, incomplete or invalid_input. computationComplete means the admitted grid was fully computed, including any missing coverage. useful is true only for a non-demo complete scene with at least one observed pixel. Failure results have no metrics and make no complete-quality claim. illustrative labels the demo.

metrics.classCounts has string keys "0" through "11", counting only centres inside the raster footprint. The other integer fields satisfy:

inFootprintCount = sum(classCounts)
observedCount = sum(classCounts[1..11])
noDataCount = classCounts[0]
requestedCount = inFootprintCount + outsideCount
missingCount = outsideCount + noDataCount
requestedCount = observedCount + missingCount

A requested sample is a native grid pixel centre inside the caller's rectangle, including extrapolated positions beyond the raster extent. Outside samples are counted separately, never filled with SCL0. Coverage is sampled-grid coverage, not a continuous geographic area ratio. All five coverage fractions (inFootprintFraction, observedFraction, outsideFraction, noDataFraction, missingFraction) divide their matching counts by requestedCount.

Quality fractions use observedCount: cloudFraction counts classes 8+9+10, cloudShadowFraction class 3, and snowIceFraction class 11. Class 2 is cast shadow, not class 3 cloud-shadow. Class 1 defective and class 7 unclassified stay visible and remain in the observed denominator. A zero denominator yields JSON null. A bbox without sampled centres is below_resolution; an admitted grid with no observed pixels is no_observation. Both are uncharged outcomes.

provenance carries collection, scene ID, acquisition datetime, processing baseline, exact Item/asset URLs, application payload itemBytes/rasterBytes, native 20 m resolution and raster EPSG. HTTP framing/headers are excluded from payload accounting. These are SCL classification statistics, not ground-truth cloud-free percentages or a clear-quality score; no cloud-free guarantee is made. If the worker is terminated without a receipt, payload byte counts are null because completed transfers cannot be recovered honestly from that process.

Resource and failure bounds

One fixed Earth Search Item GET (at most 1 MiB) and one supported Collection 1 S3 SCL GET (at most 32 MiB) are allowed; no redirects, retries or alternate source. Complete compressed data is downloaded to ephemeral local storage before GDAL opens it; there are no hidden remote GDAL range reads. Missing-length streams that reach the exact byte ceiling are conservatively refused because an extra EOF probe would exceed that ceiling. Known HTTP-length streams can use the ceiling.

Only one uint8 band, north-up unrotated 20 m UTM and dimensions at most 6000×6000 are supported. Actual candidate envelope size, including a two-cell halo, must be at most 262,144 before allocation or read. Geographic edges use 255 densification points; each candidate centre is transformed back to WGS84 for inclusion. This finite numerical bound has denser independent synthetic controls; it is not a formal mathematical projection guarantee.

Each request has a 30-second deadline. Acquisition and native computation run in one subprocess with a 120-second total deadline; timeout kills and waits for that process, then removes all temporary files. Source failures/refusals produce explicit uncharged results. Initial hosted settings are 512 MiB and 180 seconds; The four private runs peaked below 114 million bytes; worst-case hosted memory and cost remain unmeasured. Compressed bytes do not bound decoded blocks; source dimension, candidate and GDAL cache bounds also apply.

Useful-report pricing

The initial event is report-produced at $0.05 per persisted complete useful scene report. This code does not configure platform pricing. It checks the effective event price in a PPE run, persists the single dataset result first, then requests at most one event and checks accepted count equals one. Demo, refusal, source failure, incomplete, zero observation and below resolution never emit this event. Unpriced runs persist results without an event. Storage failure prevents charging; charge failure fails the run after retaining its result. The persisted payload does not assert billing success. The public offer charges only this event, with no separate platform-usage charge to the customer.

Source attribution

Reports contain modified Copernicus Sentinel data. The source year is the year of provenance.datetime; the supplied example contains modified Copernicus Sentinel data 2025. Preserve the notice “Contains modified Copernicus Sentinel data [Year]”, substituting that acquisition year, when redistributing results. Source classification is supplied without a quality or fitness warranty; see the Copernicus Sentinel data notice.

Development and independent comparison

Python 3.13 and the committed uv lock are required. The pinned Rasterio wheel supports glibc Linux; no Alpine/musl compatibility is claimed. Run the four gates from the repository root through rexec as recorded in VALIDATION.md. Deployment/build/source acquisition and hosting are owned by the parent job.

The offline oracle accepts a local raster, the frozen receipt and one JSON result:

rexec -- uv run --directory actors/sentinel-aoi-quality --locked python scripts/validate_public_sample.py \
--receipt ../../research/evidence/2026-09-29-sentinel-public-sample.json \
--raster /path/to/local-scl.tif --report /path/to/actor-result.json \
--output /path/to/comparison.json

Inputs must exist on the worker; use repository-relative private evidence paths and explicit --pull paths when retrieving artifacts. The oracle makes no requests, imports no production metric/window/model helpers, enumerates the full native source blockwise, and independently adds same-grid exterior centres using 4097 edge samples plus eight cells of slack. It compares integer counts exactly, fractions within absolute 1e-9, nulls exactly, and checks receipt/source identity. Every compared metric key must exist, including explicit null fractions. The --report input has a --result compatibility alias; --output writes comparison JSON only after successful comparison, while stdout also displays that JSON. Public outcomes are not part of local synthetic acceptance.

Source documentation: Earth Search, Sentinel COG registry, Rasterio warp API.