Skip to content

Processing

cdse.processing

Post-download processing utilities for CDSE products.

This module provides functions for cropping, reprojecting, extracting bands, and previewing downloaded Sentinel products. These operations help users work with data centered on their area of interest rather than full tiles.

Key features: - Extract specific bands from SAFE/ZIP products - Crop to bounding box (city, AOI) - Stack bands into multi-band GeoTIFF - Generate RGB preview images (PNG/JPEG) - Display interactive previews in Jupyter notebooks - Calculate vegetation indices (NDVI)

Requires: rasterio (install with: pip install cdse-client[processing])

crop_to_bbox(input_path: Union[str, Path], bbox: list[float], output_path: Optional[Union[str, Path]] = None, bands: Optional[list[str]] = None) -> Path

Crop a raster file to a bounding box.

Parameters:

Name Type Description Default
input_path Union[str, Path]

Path to input raster file (GeoTIFF or JP2)

required
bbox list[float]

Bounding box [min_lon, min_lat, max_lon, max_lat] in WGS84

required
output_path Optional[Union[str, Path]]

Output path (default: input_cropped.tif)

None
bands Optional[list[str]]

List of band indices to extract (1-based), None for all

None

Returns:

Type Description
Path

Path to cropped output file

Raises:

Type Description
ValidationError

If input is invalid

ImportError

If rasterio is not installed

Example

cropped = crop_to_bbox( ... "S2A_MSIL2A.../B04.jp2", ... bbox=[9.15, 45.45, 9.20, 45.50], # Milan center ... )

extract_bands_from_safe(safe_path: Union[str, Path], bands: list[str], output_dir: Optional[Union[str, Path]] = None, resolution: int = 10) -> dict[str, Path]

Extract specific bands from a Sentinel-2 SAFE folder or ZIP.

Parameters:

Name Type Description Default
safe_path Union[str, Path]

Path to .SAFE folder or .zip file

required
bands list[str]

List of band names (e.g., ["B02", "B03", "B04", "B08"])

required
output_dir Optional[Union[str, Path]]

Output directory (default: same as input)

None
resolution int

Target resolution in meters (10, 20, or 60)

10

Returns:

Type Description
dict[str, Path]

Dictionary mapping band names to extracted file paths

Example

bands = extract_bands_from_safe( ... "S2A_MSIL2A_20240115.zip", ... bands=["B04", "B03", "B02"], # RGB ... resolution=10 ... )

stack_bands(band_paths: dict[str, Path], output_path: Union[str, Path], band_order: Optional[list[str]] = None) -> Path

Stack multiple bands into a single multi-band GeoTIFF.

Parameters:

Name Type Description Default
band_paths dict[str, Path]

Dictionary mapping band names to file paths

required
output_path Union[str, Path]

Output GeoTIFF path

required
band_order Optional[list[str]]

Order of bands in output (default: sorted keys)

None

Returns:

Type Description
Path

Path to output stacked GeoTIFF

Example

stacked = stack_bands( ... {"B04": "red.jp2", "B03": "green.jp2", "B02": "blue.jp2"}, ... "rgb_stack.tif", ... band_order=["B04", "B03", "B02"] ... )

crop_and_stack(safe_path: Union[str, Path], bbox: list[float], bands: Optional[list[str]] = None, output_path: Optional[Union[str, Path]] = None, resolution: int = 10) -> Path

Extract bands, crop to bbox, and stack into single GeoTIFF.

This is a convenience function combining extract, crop, and stack operations.

Parameters:

Name Type Description Default
safe_path Union[str, Path]

Path to .SAFE folder or .zip file

required
bbox list[float]

Bounding box [min_lon, min_lat, max_lon, max_lat]

required
bands Optional[list[str]]

Band names (default: true color B04, B03, B02)

None
output_path Optional[Union[str, Path]]

Output path (default: auto-generated)

None
resolution int

Target resolution in meters

10

Returns:

Type Description
Path

Path to output cropped and stacked GeoTIFF

Example

result = crop_and_stack( ... "S2A_MSIL2A_20240115.zip", ... bbox=[9.15, 45.45, 9.25, 45.55], # Milan ... bands=["B04", "B03", "B02", "B08"], # RGB + NIR ... )

calculate_ndvi(nir_path: Union[str, Path], red_path: Union[str, Path], output_path: Union[str, Path]) -> Path

Calculate NDVI (Normalized Difference Vegetation Index).

NDVI = (NIR - Red) / (NIR + Red)

Parameters:

Name Type Description Default
nir_path Union[str, Path]

Path to NIR band (B08 for Sentinel-2)

required
red_path Union[str, Path]

Path to Red band (B04 for Sentinel-2)

required
output_path Union[str, Path]

Output GeoTIFF path

required

Returns:

Type Description
Path

Path to NDVI output file (values -1 to 1)

get_bounds_from_raster(raster_path: Union[str, Path]) -> tuple[list[float], str]

Get bounding box and CRS from a raster file.

Parameters:

Name Type Description Default
raster_path Union[str, Path]

Path to raster file

required

Returns:

Type Description
tuple[list[float], str]

Tuple of (bbox in WGS84 [min_lon, min_lat, max_lon, max_lat], original CRS string)

reproject(input_path: Union[str, Path], output_path: Union[str, Path], target_crs: str = 'EPSG:4326', resolution: Optional[float] = None) -> Path

Reproject a raster to a different CRS.

Parameters:

Name Type Description Default
input_path Union[str, Path]

Input raster path

required
output_path Union[str, Path]

Output raster path

required
target_crs str

Target CRS (default: WGS84)

'EPSG:4326'
resolution Optional[float]

Target resolution (default: preserve original)

None

Returns:

Type Description
Path

Path to reprojected raster

create_rgb_preview(input_path: Union[str, Path], output_path: Optional[Union[str, Path]] = None, bands: tuple[int, int, int] = (1, 2, 3), percentile_stretch: tuple[float, float] = (2, 98), size: Optional[tuple[int, int]] = None, format: str = 'PNG') -> Path

Create an RGB preview image from a multi-band raster.

Generates a color-balanced preview image suitable for visual inspection. Applies percentile stretching to enhance contrast.

Parameters:

Name Type Description Default
input_path Union[str, Path]

Path to multi-band raster (GeoTIFF)

required
output_path Optional[Union[str, Path]]

Output image path (default: input_preview.png)

None
bands tuple[int, int, int]

Tuple of band indices for R, G, B (1-based, default: 1, 2, 3)

(1, 2, 3)
percentile_stretch tuple[float, float]

Low and high percentiles for contrast stretch

(2, 98)
size Optional[tuple[int, int]]

Output size (width, height) or None for original size

None
format str

Output format ("PNG" or "JPEG")

'PNG'

Returns:

Type Description
Path

Path to preview image

Example

preview = create_rgb_preview( ... "milan_rgb.tif", ... bands=(1, 2, 3), # R, G, B order ... percentile_stretch=(2, 98) ... )

preview_product(safe_path: Union[str, Path], bbox: Optional[list[float]] = None, bands: Optional[list[str]] = None, resolution: int = 10, output_path: Optional[Union[str, Path]] = None, display: bool = True, size: tuple[int, int] = (800, 800)) -> dict[str, Any]

Generate and optionally display a preview of a Sentinel product.

This is a convenience function that extracts RGB bands, optionally crops to a bounding box, and generates a preview image. When run in Jupyter, it can display the preview inline.

Parameters:

Name Type Description Default
safe_path Union[str, Path]

Path to .SAFE folder or .zip file

required
bbox Optional[list[float]]

Optional bounding box to crop [min_lon, min_lat, max_lon, max_lat]

None
bands Optional[list[str]]

Band names for RGB (default: ["B04", "B03", "B02"] for true color)

None
resolution int

Resolution in meters (10, 20, or 60)

10
output_path Optional[Union[str, Path]]

Where to save the preview (default: auto-generated)

None
display bool

Whether to display in Jupyter (default: True)

True
size tuple[int, int]

Preview size (width, height)

(800, 800)

Returns:

Type Description
dict[str, Any]

Dictionary with:

dict[str, Any]
  • preview_path: Path to generated preview image
dict[str, Any]
  • tiff_path: Path to cropped GeoTIFF (if bbox provided)
dict[str, Any]
  • bounds: Geographic bounds of the preview
dict[str, Any]
  • size_pixels: Size in pixels (width, height)
dict[str, Any]
  • image: PIL Image object (for programmatic use)
Example

result = preview_product( ... "S2A_MSIL2A_20240115.zip", ... bbox=[9.15, 45.45, 9.25, 45.55], # Milan ... display=True ... ) print(f"Preview saved to: {result['preview_path']}")

quick_preview(tiff_path: Union[str, Path], bands: tuple[int, int, int] = (1, 2, 3), figsize: tuple[int, int] = (10, 10), title: Optional[str] = None) -> Any

Quick preview using matplotlib (for Jupyter notebooks).

Simpler alternative to preview_product when you already have a processed GeoTIFF and want a quick visualization.

Parameters:

Name Type Description Default
tiff_path Union[str, Path]

Path to GeoTIFF file

required
bands tuple[int, int, int]

Band indices for RGB (1-based)

(1, 2, 3)
figsize tuple[int, int]

Figure size in inches

(10, 10)
title Optional[str]

Optional title for the plot

None

Returns:

Type Description
Any

matplotlib figure object

Example

fig = quick_preview("milan_rgb.tif", title="Milan - Sentinel-2")

create_thumbnail(input_path: Union[str, Path], output_path: Optional[Union[str, Path]] = None, size: tuple[int, int] = (256, 256), bands: tuple[int, int, int] = (1, 2, 3)) -> Path

Create a small thumbnail from a raster.

Parameters:

Name Type Description Default
input_path Union[str, Path]

Path to input raster

required
output_path Optional[Union[str, Path]]

Output thumbnail path

None
size tuple[int, int]

Thumbnail size (width, height)

(256, 256)
bands tuple[int, int, int]

Band indices for RGB

(1, 2, 3)

Returns:

Type Description
Path

Path to thumbnail

Example

thumb = create_thumbnail("milan_rgb.tif", size=(128, 128))

compare_previews(paths: list[Union[str, Path]], titles: Optional[list[str]] = None, figsize: tuple[int, int] = (15, 5)) -> Any

Display multiple previews side by side for comparison.

Parameters:

Name Type Description Default
paths list[Union[str, Path]]

List of GeoTIFF paths to compare

required
titles Optional[list[str]]

Optional titles for each image

None
figsize tuple[int, int]

Figure size

(15, 5)

Returns:

Type Description
Any

matplotlib figure

Example

compare_previews( ... ["before.tif", "after.tif"], ... titles=["Before", "After"] ... )