Skip to main content

Sentinel-2 L2A downloader with STAC, Fortran-backed validation, spectral indices, and Plotly visualisation

Project description

sentinel-processor

Sentinel-2 L2A downloader and processing toolkit built on the Element84 STAC API.

Downloads spectral bands, quality layers, and visual overviews for any coordinate. Validation, spectral index computation, convolution filters, and pansharpening are all backed by compiled Fortran kernels — Python handles I/O and orchestration, Fortran handles the pixels.

CI codecov PyPI Python License: AGPL-3.0


Features

Module What it does
Downloader STAC search → parallel band fetch → validation → save .tif / .nc
Validation SCL cloud/snow analysis, radiometry check, dimension check (Fortran)
Indices 10 spectral indices: NDVI, EVI, SAVI, NDWI, MNDWI, NDBI, NBR, NDSI, CIG, ARVI (Fortran)
Filters 14 convolution and morphological filters: Gaussian, bilateral, Sobel, Laplacian, unsharp mask, median, erosion, dilation, top-hat, arbitrary kernel (Fortran)
Pansharpening Gram-Schmidt, IHS, Wavelet — inject PAN detail into MS bands (Fortran)
Visualisation Interactive Plotly figures: band heatmap, RGB composite, grid, SCL mask

Installation

pip install sentinel-processor

For NetCDF output:

pip install "sentinel-processor[netcdf]"

All optional extras:

pip install "sentinel-processor[all]"

Fortran libraries

The Fortran kernels must be compiled once before validation, indices, filters, and pansharpening are available. Without them, set validate=False and skip compute_indices / apply_filter — the downloader works normally regardless.

Linux / macOS

gfortran -O2 -shared -fPIC \
  -o sentinel_processor/validation/fortran/libsentinel_validation.so \
  sentinel_processor/validation/fortran/validation.f90

gfortran -O2 -shared -fPIC \
  -o sentinel_processor/indices/fortran/libsentinel_indices.so \
  sentinel_processor/indices/fortran/indices_mod.f90

gfortran -O2 -shared -fPIC \
  -o sentinel_processor/processing/fortran/libsentinel_raster_ops.so \
  sentinel_processor/processing/fortran/raster_ops.f90

gfortran -O2 -shared -fPIC \
  -o sentinel_processor/processing/fortran/libsentinel_processing.so \
  sentinel_processor/processing/fortran/pansharpening.f90

gfortran -O2 -shared -fPIC \
  -o sentinel_processor/filters/fortran/libsentinel_filters.so \
  sentinel_processor/filters/fortran/filters.f90

Windows (MSYS2 UCRT64 — do not use -static-libgfortran on GCC 16+)

gfortran -O2 -shared -o sentinel_processor\validation\fortran\libsentinel_validation.dll sentinel_processor\validation\fortran\validation.f90
gfortran -O2 -shared -o sentinel_processor\indices\fortran\libsentinel_indices.dll sentinel_processor\indices\fortran\indices_mod.f90
gfortran -O2 -shared -o sentinel_processor\processing\fortran\libsentinel_raster_ops.dll sentinel_processor\processing\fortran\raster_ops.f90
gfortran -O2 -shared -o sentinel_processor\processing\fortran\libsentinel_processing.dll sentinel_processor\processing\fortran\pansharpening.f90
gfortran -O2 -shared -o sentinel_processor\filters\fortran\libsentinel_filters.dll sentinel_processor\filters\fortran\filters.f90

After compiling on Windows, copy the MSYS2 runtime DLLs next to each .dll:

for %d in (validation indices processing filters) do (
  copy C:\msys64\ucrt64\bin\libgfortran-5.dll    sentinel_processor\%d\fortran\
  copy C:\msys64\ucrt64\bin\libgcc_s_seh-1.dll   sentinel_processor\%d\fortran\
  copy C:\msys64\ucrt64\bin\libwinpthread-1.dll   sentinel_processor\%d\fortran\
)

Quick start

import sentinel_processor as sp
from sentinel_processor.indices.compute import compute_indices
from sentinel_processor.filters import apply_filter
from sentinel_processor.visualisation.plot import plot_band, plot_rgb, plot_grid, plot_mask

# 1. Download
results = sp.download_sentinel2(
    [sp.LocationSpec(lat=47.56, lon=19.17, name="budapest")],
)

scene = "data/spectral/budapest_20260526T095725.nc"
vis   = "data/visual/vis_budapest_20260526T095725.nc"
scl   = "data/technical/scl_budapest_20260526T095725.nc"

# 2. Spectral indices
idx = compute_indices(scene, ["ndvi", "ndwi", "ndbi"])

# 3. Filters
import rioxarray
nir = rioxarray.open_rasterio(scene).sel(band="nir").squeeze().values
nir_smooth  = apply_filter(nir, "bilateral",     sigma_s=2.0, sigma_r=0.08)
nir_edges   = apply_filter(nir, "sobel_magnitude")
nir_sharp   = apply_filter(nir, "unsharp_mask",  sigma=1.5, amount=1.2)

# 4. Visualise
plot_rgb(vis).show()
plot_band(idx["ndvi"], colorscale="RdYlGn").show()
plot_mask(scl).show()
plot_grid([
    {"file": scene,       "band": "nir", "label": "NIR"},
    {"file": idx["ndvi"],                "label": "NDVI", "colorscale": "RdYlGn"},
    {"file": idx["ndwi"],                "label": "NDWI", "colorscale": "Blues"},
], ncols=3).show()

Modules

Module Description Docs
sentinel_processor Download, STAC search, validation DOWNLOADER.md
sentinel_processor.validation SCL + radiometry quality checks (Fortran) VALIDATION.md
sentinel_processor.indices Spectral index computation (Fortran) INDICES.md
sentinel_processor.filters Convolution and morphological filters (Fortran) FILTERS.md
sentinel_processor.processing Pansharpening + raster ops (Fortran) PANSHARPENING.md · RASTER_OPS.md
sentinel_processor.visualisation Interactive Plotly figures VISUALISATION.md

Usage

Download with defaults

import sentinel_processor as sp

results = sp.download_sentinel2(
    [sp.LocationSpec(lat=47.56, lon=19.17, name="my_field")],
)

Downloads the 10 most recent cloud-free scenes within ~5 km of the point. Saves to data/spectral/, data/technical/, data/visual/.

Custom download config

import datetime, sentinel_processor as sp

cfg = sp.DownloadConfig(
    bands               = sp.SpectralBands.VEGETATION,
    tech_bands          = sp.TechnicalLayers.SCL,
    visual              = False,
    output_dir          = "/mnt/sentinel",
    start_date          = datetime.datetime(2025, 3, 1, tzinfo=datetime.UTC),
    end_date            = datetime.datetime(2025, 6, 1, tzinfo=datetime.UTC),
    keep_items          = 3,
    max_cloud_threshold = 0.15,
    min_confidence      = 0.75,
)
results = sp.download_sentinel2(
    [sp.LocationSpec(lat=47.56, lon=19.17, name="budapest")],
    cfg=cfg,
)

Spectral indices

from sentinel_processor.indices.compute import compute_indices, list_indices

for name, info in list_indices().items():
    print(f"{name:8s}  {info['bands_required']}")

results = compute_indices(
    source="data/spectral/scene.nc",
    indices=["ndvi", "evi", "ndwi", "ndbi", "nbr"],
    output_dir="data/indices",
)
# {"ndvi": "data/indices/indices_scene_ndvi.tif", ...}

Supported: ndvi, evi, savi, ndwi, mndwi, ndbi, nbr, ndsi, cig, arvi.

Filters

import numpy as np
from sentinel_processor.filters import apply_filter, apply_filter_da, list_filters

band   = np.random.rand(512, 512)
smooth = apply_filter(band, "gaussian",       sigma=1.5)
clean  = apply_filter(band, "median",         radius=2)
edges  = apply_filter(band, "sobel_magnitude")
sharp  = apply_filter(band, "unsharp_mask",   sigma=1.5, amount=1.2)
feats  = apply_filter(band, "top_hat_white",  radius=5)
custom = apply_filter(band, "convolve",       kernel=np.ones((3, 3)) / 9)

# xarray DataArray — preserves CRS and coordinates
result_da = apply_filter_da(da, "bilateral", sigma_s=3.0, sigma_r=0.08)

# Multi-band (n_bands, rows, cols) — applied per band
ms = np.random.rand(4, 256, 256)
ms_smooth = apply_filter(ms, "gaussian", sigma=1.0)

Available: gaussian, bilateral, median, sobel_magnitude, sobel_direction, laplacian, unsharp_mask, erode, dilate, open, close, top_hat_white, top_hat_black, convolve.

Pansharpening

import sentinel_processor as sp

results = sp.download_sentinel2(
    [sp.LocationSpec(lat=47.56, lon=19.17, name="budapest")],
    cfg=sp.DownloadConfig(
        bands                = sp.SpectralBands.RGB_NIR,
        pansharpen_algorithm = "gram_schmidt",  # "ihs" (RGB only) | "wavelet"
    ),
)

Validate an SCL file

from sentinel_processor import validate_file

report = validate_file(
    "data/technical/scl_budapest_20260526T095725.tif",
    max_cloud_threshold=0.30,
    min_confidence=0.50,
)
print(report["passed"])            # True
print(report["cloud_ratio"])       # 0.04
print(report["confidence_score"])  # 1.0

Visualise

from sentinel_processor.visualisation.plot import plot_band, plot_rgb, plot_grid, plot_mask

plot_band("data/spectral/scene.nc",      band="nir",   colorscale="Plasma").show()
plot_rgb("data/visual/vis_scene.nc").show()
plot_rgb("data/spectral/scene.nc",       "nir", "red", "green").show()  # false colour
plot_mask("data/technical/scl_scene.nc", bad_classes=[8, 9, 10]).show()
plot_grid([
    {"file": "data/spectral/scene.nc", "band": "red",  "label": "Red"},
    {"file": "data/spectral/scene.nc", "band": "nir",  "label": "NIR"},
    {"file": "data/indices/scene_ndvi.tif",             "label": "NDVI", "colorscale": "RdYlGn"},
], ncols=3).show()

Output structure

<output_dir>/
├── spectral/
│   ├── <name>_<timestamp>.tif
│   ├── <name>_<timestamp>.nc            ← requires [netcdf]
│   ├── <name>_<timestamp>_report.json
│   └── indices/
│       └── indices_<name>_<timestamp>_<index>.tif
├── technical/
│   ├── scl_<name>_<timestamp>.tif/.nc
│   ├── aot_<name>_<timestamp>.tif/.nc
│   └── wvp_<name>_<timestamp>.tif/.nc
└── visual/
    └── vis_<name>_<timestamp>.tif/.nc

Band presets

Preset Bands
SpectralBands.RGB blue, green, red
SpectralBands.RGB_NIR blue, green, red, NIR
SpectralBands.VEGETATION red, NIR, rededge 1-2-3
SpectralBands.AGRICULTURE blue, green, red, NIR, rededge1, SWIR1, SWIR2
SpectralBands.ALL_10M blue, green, red, NIR
SpectralBands.ALL_20M rededge 1-3, NIR narrow, SWIR 1-2
SpectralBands.ALL all 10 m + 20 m bands
TechnicalLayers.SCL Scene Classification Layer
TechnicalLayers.ALL SCL + AOT + WVP

Custom list: DownloadConfig(bands=["red", "nir", "swir16"])


Project layout

sentinel_processor/
├── __init__.py
├── config.py
├── filters/
│   ├── __init__.py
│   ├── _filters_bridge.py
│   ├── compute.py
│   └── fortran/filters.f90
├── indices/
│   ├── __init__.py
│   ├── _indices_bridge.py
│   ├── compute.py
│   └── fortran/indices_mod.f90
├── input/
│   └── downloader.py
├── processing/
│   ├── _fortran_bridge.py
│   ├── _raster_ops_bridge.py
│   └── fortran/pansharpening.f90 · raster_ops.f90
├── utils/
│   └── data_utils.py
├── validation/
│   ├── _fortran_bridge.py
│   └── fortran/validation.f90
└── visualisation/
    └── plot.py

tests/
├── conftest.py
├── test_validation.py
├── test_indices.py
├── test_filters.py
├── test_processing.py
└── test_visualisation.py

docs/
├── DOWNLOADER.md
├── VALIDATION.md
├── INDICES.md
├── FILTERS.md
├── PANSHARPENING.md
├── RASTER_OPS.md
└── VISUALISATION.md

Development

git clone https://github.com/niki8885/sentinel-processor
cd sentinel-processor
pip install -e ".[dev,netcdf]"
pytest tests/ -v

See CONTRIBUTING.md for full contribution guidelines.


Requirements

  • Python ≥ 3.10
  • pystac-client, rioxarray, xarray, numpy, rasterio, plotly
  • netCDF4 or h5netcdf for .nc output (optional)
  • gfortran ≥ 9 to build the Fortran kernels

Maintainer

Nikita Manaenkov — nick.maanenkov@gmail.com · @niki8885

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

sentinel_processor-0.1.0.tar.gz (267.5 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

sentinel_processor-0.1.0-py3-none-any.whl (5.6 MB view details)

Uploaded Python 3

sentinel_processor-0.1.0-cp312-cp312-win_amd64.whl (5.1 MB view details)

Uploaded CPython 3.12Windows x86-64

sentinel_processor-0.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.1 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ x86-64

sentinel_processor-0.1.0-cp312-cp312-macosx_11_0_arm64.whl (70.9 kB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

sentinel_processor-0.1.0-cp311-cp311-win_amd64.whl (5.1 MB view details)

Uploaded CPython 3.11Windows x86-64

sentinel_processor-0.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.1 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ x86-64

sentinel_processor-0.1.0-cp311-cp311-macosx_11_0_arm64.whl (70.9 kB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

sentinel_processor-0.1.0-cp310-cp310-win_amd64.whl (5.1 MB view details)

Uploaded CPython 3.10Windows x86-64

sentinel_processor-0.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.1 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ x86-64

sentinel_processor-0.1.0-cp310-cp310-macosx_11_0_arm64.whl (70.9 kB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

File details

Details for the file sentinel_processor-0.1.0.tar.gz.

File metadata

  • Download URL: sentinel_processor-0.1.0.tar.gz
  • Upload date:
  • Size: 267.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.1

File hashes

Hashes for sentinel_processor-0.1.0.tar.gz
Algorithm Hash digest
SHA256 c567a46a9c7c96a2b1b797bf4c79453b50a62096d37098e07af572cffdf6362c
MD5 01c0eb7c837948a5d6b12ae8f438a37e
BLAKE2b-256 79e33defe5cc4e838d531c060204023a21d8f767f81db27a1496c7a9a9e97526

See more details on using hashes here.

File details

Details for the file sentinel_processor-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for sentinel_processor-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 25d55c08bb72f5d99002a7bc9350db348d9ad11c81d84926906b6b3b2593d99e
MD5 32cefdf26aff33cb8044509d52c58f69
BLAKE2b-256 64690143fc3531908dfd16a0ee6434293840fc41618c8c768b4d92aa94ecef85

See more details on using hashes here.

File details

Details for the file sentinel_processor-0.1.0-cp312-cp312-win_amd64.whl.

File metadata

File hashes

Hashes for sentinel_processor-0.1.0-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 3ea69a882468896bf3f3969fa3178c3017ed551b0c620afac2c118950e37cbef
MD5 7680c5d2e433b457a5c2c1e0682355c9
BLAKE2b-256 1c51e46b638c9d8cd40b4dd6c4a069d4fc065ccb884d8a2f936a6a57ce09d25a

See more details on using hashes here.

Provenance

The following attestation bundles were made for sentinel_processor-0.1.0-cp312-cp312-win_amd64.whl:

Publisher: build_wheels.yml on niki8885/sentinel_processor_project

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file sentinel_processor-0.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for sentinel_processor-0.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 0a14291505a75bc886f757c9836efa861a4c4c5bc4311de72db158df10706af3
MD5 3ed408fe485eb6599439bc52032ddeee
BLAKE2b-256 541f288092f0f71f297791c55ce24bd963ac4b0208b9f54ef69139b34477955b

See more details on using hashes here.

Provenance

The following attestation bundles were made for sentinel_processor-0.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: build_wheels.yml on niki8885/sentinel_processor_project

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file sentinel_processor-0.1.0-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for sentinel_processor-0.1.0-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 88089abcaae544d3cb5cd0a24ae908d4bb68658ba54574371ad7de5b99e81c66
MD5 b3376b54d118599be4778ccf197515d3
BLAKE2b-256 20b65082efd4f00f2c8f5339bd52bc1015682b339a9f33405a59c997d63b9325

See more details on using hashes here.

Provenance

The following attestation bundles were made for sentinel_processor-0.1.0-cp312-cp312-macosx_11_0_arm64.whl:

Publisher: build_wheels.yml on niki8885/sentinel_processor_project

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file sentinel_processor-0.1.0-cp311-cp311-win_amd64.whl.

File metadata

File hashes

Hashes for sentinel_processor-0.1.0-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 6337b0fbe93415aa328c9fadce95d3e24de11c020311172b7bf624f25ba6ba9d
MD5 eb463ed72fa6be3966969a136856bf09
BLAKE2b-256 9ebe1cd5422c7d0c6ec698cb351080ab866fef2d298fd661d3d8b72ad1f5e82a

See more details on using hashes here.

Provenance

The following attestation bundles were made for sentinel_processor-0.1.0-cp311-cp311-win_amd64.whl:

Publisher: build_wheels.yml on niki8885/sentinel_processor_project

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file sentinel_processor-0.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for sentinel_processor-0.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 ffc20d2cfabea3d403bdefda730626aada052731a7a4db01af7ee427ca1063bf
MD5 1777757d3687c249c89b4a5d8dc67377
BLAKE2b-256 a7e41d28d65eb7083d703a1ab7a65c913e9280160816d2f0cb4468e685fa1e39

See more details on using hashes here.

Provenance

The following attestation bundles were made for sentinel_processor-0.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: build_wheels.yml on niki8885/sentinel_processor_project

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file sentinel_processor-0.1.0-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for sentinel_processor-0.1.0-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 70b3ad2c5824573f9cdfcee0a7e124da2a9be727be2f60d8b76174d97513a096
MD5 2ec11d24f21bc816de6a77057dcefc24
BLAKE2b-256 f2b75ae4722197bfb3247f98e7f231ebd70d14fdec4bba078dcbe5d5a6c5ba81

See more details on using hashes here.

Provenance

The following attestation bundles were made for sentinel_processor-0.1.0-cp311-cp311-macosx_11_0_arm64.whl:

Publisher: build_wheels.yml on niki8885/sentinel_processor_project

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file sentinel_processor-0.1.0-cp310-cp310-win_amd64.whl.

File metadata

File hashes

Hashes for sentinel_processor-0.1.0-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 85e7fa54bb14ad4eee5d754013840ecfdee6074b8a0fa554b47eab98cb6fa45d
MD5 7ed8ab98a3737d1e05a839abcf4e969c
BLAKE2b-256 ada16fb6342e7b4bc858775587cd140d33209d2097dc44f191fa1a743a42ed7a

See more details on using hashes here.

Provenance

The following attestation bundles were made for sentinel_processor-0.1.0-cp310-cp310-win_amd64.whl:

Publisher: build_wheels.yml on niki8885/sentinel_processor_project

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file sentinel_processor-0.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for sentinel_processor-0.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 88bd0a6196d296755f020bfb85242024a935589c7c95e2b56e1b31e5f7f2db7d
MD5 21f4c41e6b0f4270a03bf3635949307f
BLAKE2b-256 d81909198b0270ba6ee3e66387a7011089c6a3eefaa582f838b10ede7b6c619a

See more details on using hashes here.

Provenance

The following attestation bundles were made for sentinel_processor-0.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: build_wheels.yml on niki8885/sentinel_processor_project

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file sentinel_processor-0.1.0-cp310-cp310-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for sentinel_processor-0.1.0-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 8ce976a2139e7791e80ab65c002c412c5ad5776dc72b88fa4557869be4caf771
MD5 d6e7b5d6b7fd34c32109d8f80302768a
BLAKE2b-256 de59b2b6b01c3e7534982b81603ed85cc86f08e3d7a7c8a6a9129293ccf9c97b

See more details on using hashes here.

Provenance

The following attestation bundles were made for sentinel_processor-0.1.0-cp310-cp310-macosx_11_0_arm64.whl:

Publisher: build_wheels.yml on niki8885/sentinel_processor_project

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page