diff --git a/assets/changelog/2026-08-26-sentinel1-cloud-reveal.gif b/assets/changelog/2026-08-26-sentinel1-cloud-reveal.gif new file mode 100644 index 0000000..f9a8673 Binary files /dev/null and b/assets/changelog/2026-08-26-sentinel1-cloud-reveal.gif differ diff --git a/assets/changelog/2026-08-27-dashboard.png b/assets/changelog/2026-08-27-dashboard.png new file mode 100644 index 0000000..334929f Binary files /dev/null and b/assets/changelog/2026-08-27-dashboard.png differ diff --git a/assets/guides/datasets/sentinel1-vv-venice.webp b/assets/guides/datasets/sentinel1-vv-venice.webp new file mode 100644 index 0000000..1a190ff Binary files /dev/null and b/assets/guides/datasets/sentinel1-vv-venice.webp differ diff --git a/assets/guides/datasets/sentinel2-rgb-sandwich-harbour.webp b/assets/guides/datasets/sentinel2-rgb-sandwich-harbour.webp new file mode 100644 index 0000000..c984ee7 Binary files /dev/null and b/assets/guides/datasets/sentinel2-rgb-sandwich-harbour.webp differ diff --git a/assets/guides/sentinel2/sandwich-harbour-true-color.webp b/assets/guides/sentinel2/sandwich-harbour-true-color.webp deleted file mode 100644 index b7ae626..0000000 Binary files a/assets/guides/sentinel2/sandwich-harbour-true-color.webp and /dev/null differ diff --git a/changelog.mdx b/changelog.mdx index 6cf00d2..a149102 100644 --- a/changelog.mdx +++ b/changelog.mdx @@ -5,6 +5,42 @@ icon: rss mode: center --- + + ## Your workflow operations, at a glance + + + Tilebox Console Dashboard Page + + + The new Tilebox Console Dashboard puts workflow health front and center. See queue pressure, recent job outcomes, workflow logs, workspace activity, and usage in one operational view, then drill directly into the jobs and logs that need attention. + + + + Monitor your workflows and investigate issues. + + + + + + ## Sentinel-1 radar imagery, ready day or night + + + Cloud-covered Sentinel-2 optical imagery of Venice transitioning to Sentinel-1 radar imagery captured on the same day + + + The new `open_data.aws_earth.sentinel1` dataset provides credentials-free access to global Sentinel-1 Level-1 Ground Range Detected (GRD) scenes and their public AWS assets. Unlike optical sensors, Sentinel-1 uses synthetic aperture radar (SAR) to observe the surface through clouds and without sunlight, so you can keep analyzing conditions when optical imagery is unavailable. + + Query scenes by time, location, or satellite platform, then open the available polarization measurements as Cloud Optimized GeoTIFFs (COGs). Each datapoint also includes acquisition and orbit details, SAR metadata, a preview image, and the product, calibration, noise, and SAFE manifest files needed for further processing. + + These consistent, all-weather observations are well suited to flood and disaster mapping, sea-ice and maritime monitoring, forest disturbance detection, and tracking changes in crops, soil moisture, and infrastructure. You can move from a spatial query to a focused pixel read in one workflow, without configuring separate AWS credentials or downloading a complete scene first. + + + + Query a GRD scene and render a monochrome image from its public VV measurement. + + + + ## Understand and debug workflow jobs faster @@ -39,8 +75,8 @@ mode: center This makes it practical to move from catalog search to image processing in one workflow: find a low-cloud scene, select a band, crop it to a geographic region, and pass the resulting data into your analysis without first downloading an entire scene. - - Query a Sentinel-2 scene, read RGB band windows, and display a true-color image. + + Query a cloud-free scene and combine its red, green, and blue COG assets. diff --git a/datasets/assets-and-storage/read-and-download.mdx b/datasets/assets-and-storage/read-and-download.mdx index 8e57781..1ace1ff 100644 --- a/datasets/assets-and-storage/read-and-download.mdx +++ b/datasets/assets-and-storage/read-and-download.mdx @@ -148,8 +148,8 @@ Asset locations can reference authentication metadata. The storage client curren ## Next steps - - Query Sentinel-2, read RGB band windows, and display a true-color image. + + Query Sentinel-2 and combine three image bands over a selected region. Attach file references to datapoints you ingest. diff --git a/docs.json b/docs.json index 2cde75d..46a1fc5 100644 --- a/docs.json +++ b/docs.json @@ -159,6 +159,7 @@ "pages": [ "guides/datasets/query-satellite-data", "guides/datasets/access-sentinel2-data", + "guides/datasets/access-sentinel1-data", "guides/datasets/build-spatiotemporal-catalog", "guides/datasets/ingest-into-spatiotemporal-catalog", "guides/datasets/ingest-format" diff --git a/guides/cookbook.mdx b/guides/cookbook.mdx index 37fd55b..cd3b9e6 100644 --- a/guides/cookbook.mdx +++ b/guides/cookbook.mdx @@ -21,13 +21,22 @@ export const cookbookSections = [ tags: ["Open data", "Sentinel-2", "Metadata queries", "Spatial filters"], }, { - title: "Visualize Sentinel-2 imagery", + title: "Create a Sentinel-2 RGB image", href: "/guides/datasets/access-sentinel2-data", - description: "Query a Sentinel-2 scene, read its RGB bands, and display a true-color image.", + description: "Combine three public Sentinel-2 COG assets into a cloud-free RGB image.", icon: "magnifying-glass-location", level: "Beginner", time: "10 min", - tags: ["Assets", "COG", "Sentinel-2", "True color"], + tags: ["Assets", "COG", "Sentinel-2", "RGB"], + }, + { + title: "Create a Sentinel-1 radar image", + href: "/guides/datasets/access-sentinel1-data", + description: "Render a north-up monochrome image from a public Sentinel-1 GRD measurement COG.", + icon: "radar", + level: "Intermediate", + time: "15 min", + tags: ["Assets", "COG", "Sentinel-1", "SAR"], }, { title: "Build a spatio-temporal catalog", diff --git a/guides/datasets/access-sentinel1-data.mdx b/guides/datasets/access-sentinel1-data.mdx new file mode 100644 index 0000000..c2a0ca9 --- /dev/null +++ b/guides/datasets/access-sentinel1-data.mdx @@ -0,0 +1,120 @@ +--- +title: Create a Sentinel-1 radar image +description: Query a Sentinel-1 GRD scene and render a monochrome image from its public SAR measurement COG. +icon: radar +--- + +Tilebox indexes global Sentinel-1 Ground Range Detected (GRD) scenes and their public AWS assets in the `open_data.aws_earth.sentinel1` dataset. In this guide, you query a scene over Venice, read its VV polarization measurement, and create a north-up monochrome radar image. + +## Prerequisites + +- You have a [Tilebox API key](/authentication). +- You have Python 3.11 or newer. + +```bash +uv add tilebox shapely numpy pillow rasterio +``` + +## Select a Sentinel-1 scene + +Define an area around Venice, then query a dual-polarization Sentinel-1C scene from October 4, 2025: + +```python Python +from shapely import box +from tilebox.datasets import Client + +# west, south, east, north +area = box(12.3, 45.385, 12.49, 45.466) # Venice + +collection = Client().dataset("open_data.aws_earth.sentinel1").collection("GRD") +scenes = collection.query( + temporal_extent=("2025-10-04", "2025-10-05"), + spatial_extent=area, +) + +datapoint = scenes.isel(time=0) +print(datapoint.stac_id.item()) +``` + +## Resolve the VV measurement + +Each datapoint provides measurement COGs for its available polarizations, alongside product, calibration, noise, manifest, and preview assets. Select the VV measurement and resolve its public HTTPS location: + +```python Python +from tilebox.datasets.assets import AssetCollection +from tilebox.storage.aio import AssetAccessPolicy, Client as StorageClient + +assets = AssetCollection.from_datapoint(datapoint) +vv = assets["vv"] + +storage = StorageClient( + policy=AssetAccessPolicy(preferred_schemes=("https",)), +) +resolved = storage.resolve(vv) +``` + +No AWS credentials or requester-pays configuration is required for this asset. + +## Read a north-up image window + +Sentinel-1 GRD measurement COGs store geolocation as ground control points. Use a `WarpedVRT` to apply that geolocation, project the image, and read a bounded north-up window without downloading the complete scene: + +```python Python +import numpy as np +import rasterio +from rasterio.enums import Resampling +from rasterio.vrt import WarpedVRT +from rasterio.warp import transform_bounds +from rasterio.windows import from_bounds + +with rasterio.open(resolved.href) as source: + with WarpedVRT(source, crs="EPSG:3857") as geotiff: + projected_bounds = transform_bounds( + "EPSG:4326", + geotiff.crs, + *area.bounds, + ) + window = from_bounds(*projected_bounds, transform=geotiff.transform) + vv_pixels = geotiff.read( + 1, + window=window, + out_shape=(675, 1200), + resampling=Resampling.bilinear, + ).astype(np.float32) +``` + +## Render the radar image + +Stretch the central 96% of valid pixel values across a gray display range, then save the result: + +```python Python +from PIL import Image + +valid = vv_pixels[vv_pixels > 0] +low, high = np.percentile(valid, (2, 98)) +grayscale = np.clip((vv_pixels - low) / (high - low), 0, 1) + +image = Image.fromarray((grayscale * 255).astype(np.uint8), mode="L") +image.save("sentinel1-venice.png") +``` + + + Monochrome Sentinel-1 VV radar image of Venice and the surrounding lagoon + + +Smooth water appears dark because it reflects little radar energy back toward the sensor, while dense buildings appear bright because their geometry produces strong returns. + + + This percentile stretch creates a visual image from the stored measurement values. Calibrate the measurement and account for acquisition geometry before using pixel values in quantitative SAR analysis. + + +## Next steps + + + + Build a cloud-free optical RGB image from three spectral bands. + + + Understand how dataset metadata connects queries to files in object storage. + + diff --git a/guides/datasets/access-sentinel2-data.mdx b/guides/datasets/access-sentinel2-data.mdx index c9529e1..1b3a7e7 100644 --- a/guides/datasets/access-sentinel2-data.mdx +++ b/guides/datasets/access-sentinel2-data.mdx @@ -1,10 +1,10 @@ --- -title: Visualize Sentinel-2 imagery -description: Query a Sentinel-2 scene, read its RGB bands, and display a true-color image. +title: Create a Sentinel-2 RGB image +description: Query a cloud-free Sentinel-2 scene and render an RGB image from its public COG assets. icon: satellite --- -Tilebox indexes Sentinel-2 metadata and asset locations in the `open_data.aws_earth.sentinel2` dataset. In this guide, you query a low-cloud scene over Sandwich Harbour in Namibia, read its RGB bands, and display a true-color image. +Tilebox indexes Sentinel-2 metadata and public asset locations in the `open_data.aws_earth.sentinel2` dataset. In this guide, you query a cloud-free scene over Sandwich Harbour in Namibia, read a small window from its red, green, and blue Cloud Optimized GeoTIFFs (COGs), and combine the bands into an RGB image. Asset collections and the storage client are currently available in the Python SDK. @@ -13,26 +13,24 @@ Tilebox indexes Sentinel-2 metadata and asset locations in the `open_data.aws_ea ## Prerequisites - You have a [Tilebox API key](/authentication). -- You have installed the [Python SDK](/sdks/python/install) with Python 3.11 or newer. +- You have Python 3.11 or newer. ```bash -uv add tilebox shapely numpy matplotlib +uv add tilebox shapely numpy pillow ``` -## Select a Sentinel-2 datapoint +## Select a cloud-free scene -Define a small area around the Sandwich Harbour lagoon and dune coast. Query Level-2A observations from a known clear period, sort them by scene-level cloud cover, and select the clearest result: +Define a small area around Sandwich Harbour and query Sentinel-2 Level-2A scenes from June 17, 2024. Select the result with the least cloud cover. ```python Python from shapely import box from tilebox.datasets import Client, field -area_bounds = (14.42, -23.43, 14.58, -23.25) # west, south, east, north -area = box(*area_bounds) - -datasets = Client() -collection = datasets.dataset("open_data.aws_earth.sentinel2").collection("L2A") +# west, south, east, north +area = box(14.42, -23.43, 14.58, -23.25) # Sandwich Harbour, Namibia +collection = Client().dataset("open_data.aws_earth.sentinel2").collection("L2A") scenes = collection.query( temporal_extent=("2024-06-17", "2024-06-18"), spatial_extent=area, @@ -43,26 +41,21 @@ datapoint = scenes.sortby("cloud_cover").isel(time=0) print(datapoint.stac_id.item(), datapoint.cloud_cover.item()) ``` -The selected observation is `S2B_T33KVQ_20240617T090616_L2A`, acquired on June 17, 2024, with `0.008524` percent scene-level cloud cover. The cloud-cover value describes the complete Sentinel-2 tile, not only the area of interest. - -See [Query open data metadata](/guides/datasets/query-satellite-data) for more query patterns. +See [Query open data metadata](/guides/datasets/query-satellite-data) for broader temporal, spatial, and field-filtering patterns. ## Resolve the RGB assets -Turn the selected datapoint into an asset collection, then resolve its 10-meter red, green, and blue COGs: +Convert the datapoint into an asset collection: ```python Python from tilebox.datasets.assets import AssetCollection assets = AssetCollection.from_datapoint(datapoint) -red = assets["red"] -green = assets["green"] -blue = assets["blue"] ``` -## Read the COG windows +## Read and combine the bands -Use the storage client to read the area of interest from each COG: +Open the three COGs and read only the window that covers the area of interest. The bands share the same pixel grid, so you can fetch them concurrently and stack them directly. ```python Python import asyncio @@ -73,52 +66,57 @@ from tilebox.storage.geotiff import window_from_bounds async def read_rgb(): storage = StorageClient() - bands = [] - for asset in (red, green, blue): + async def read_band(key): + asset = assets[key] geotiff = await storage.open_geotiff(asset) - window = window_from_bounds(geotiff, area_bounds, crs="EPSG:4326") + window = window_from_bounds(geotiff, area.bounds, crs="EPSG:4326") raster = await geotiff.read(window=window) - bands.append(raster.data[0]) + pixels = raster.data[0].astype(np.float32) + return pixels * asset.raster.scale + asset.raster.offset - return np.stack(bands, axis=-1).astype(np.float32) + red, green, blue = await asyncio.gather( + read_band("red"), + read_band("green"), + read_band("blue"), + ) + return np.stack((red, green, blue), axis=-1) rgb = asyncio.run(read_rgb()) ``` -`window_from_bounds` converts the longitude and latitude bounds to the COG's pixel grid. Each read returns a `(2000, 1643)` array of `uint16` values; stacking the bands creates a `(2000, 1643, 3)` RGB array. +The asset metadata supplies the scale and offset that convert stored pixel values to surface reflectance. -## Display the true-color image +## Render the RGB image -Apply one contrast stretch across all three channels to preserve their relative color balance, then display the image: +Apply a display stretch, gamma correction, and a small contrast clip, then save the array as a PNG: ```python Python -import matplotlib.pyplot as plt +from PIL import Image, ImageOps -low, high = np.percentile(rgb, (2, 98)) -display_rgb = np.clip((rgb - low) / (high - low), 0, 1) -display_rgb = display_rgb ** (1 / 1.1) - -fig, ax = plt.subplots(figsize=(8, 10)) -ax.imshow(display_rgb) -ax.set_axis_off() -plt.tight_layout(pad=0) -plt.show() +display_rgb = np.power(np.clip(rgb / 0.3, 0, 1), 1 / 2.2) +image = Image.fromarray((display_rgb * 255).astype(np.uint8)) +image = ImageOps.autocontrast(image, cutoff=0.5) +image.save("sentinel2-sandwich-harbour.png") ``` -The percentile stretch and gamma correction bring out the coastline, lagoon, and dune textures in a beautiful true-color visualization. + +`ImageOps.autocontrast` is only intended for visualization. Keep the original reflectance values when calculating indices or running quantitative analysis. + - - Sentinel-2 true-color view of the Atlantic Ocean, Sandwich Harbour lagoon, and orange dunes of the Namib Sand Sea + + Cloud-free Sentinel-2 RGB image of Sandwich Harbour and the Namib dune coast + + ## Next steps + + Render an all-weather SAR observation over Venice. + Learn about streaming, downloads, GeoTIFF access, and location selection. - - Understand how asset metadata connects dataset queries to file storage. - diff --git a/guides/datasets/query-satellite-data.mdx b/guides/datasets/query-satellite-data.mdx index 1926443..95e4f8b 100644 --- a/guides/datasets/query-satellite-data.mdx +++ b/guides/datasets/query-satellite-data.mdx @@ -60,8 +60,8 @@ print(latest.cloud_cover.item()) ## Next steps - - Read RGB band windows and display a true-color image. + + Read three COG windows and combine them into an RGB image. Learn more dataset query patterns.