Skip to main content

fundayao

A Python library for processing remote sensing imagery, developed for educational use in courses on the basic principles of remote sensing and its applications.

Data from different sensors is imported into a common, self-describing format (GeoTIFF + XML metadata), so that all processing steps work the same way regardless of the data source. The format supports both geocoded products (map geometry) and sensor-geometry products (image coordinates + RPC model) and is specified in docs/file-format.md. Guidance for AI coding agents working on this repository lives in AGENTS.md.

Features

  • Import: Sentinel-2 L1C (SAFE), SuperView Neo-1 L1B (PAN + MUX, with RPCs) and WH-1 / LJ-3 L1A (PAN + MSS, with RPCs) → fundayao products (one GeoTIFF per resolution group + XML metadata with geometry, calibration, angles, provenance)
  • Radiometry: DN → TOA reflectance/radiance, sun-elevation correction, DOS atmospheric correction (TOA → BOA) — each formula is an explicit, inspectable processing step recorded in the product provenance
  • Spectral indices: NDVI, NDWI, MNDWI, NDBI, NDMI, SAVI, EVI — bands are selected from the metadata by central wavelength, not hardcoded band names, so the same code works across sensors
  • Band math: custom index formulas over wavelength-addressed bands (e.g. "(nir - red) / (nir + red)")
  • AOI subsetting: windowed crops for geocoded products; sensor-geometry products get freshly re-estimated RPCs (via rpcfit) so the geometry model stays exact after cropping
  • Statistics: per-band statistics (min/max/mean/std/percentiles), raw or calibrated
  • Visualization: true-color and false-color (CIR) composites with percentile stretch, band/index maps with map coordinates, histograms, spectral profiles (reflectance vs wavelength at chosen points), band scatterplots (e.g. red–NIR)
  • Segmentation: SAM-based automatic segmentation via samgeo (segment-geospatial), producing an L3 index mask product with optional unique segment IDs or a binary foreground mask, and optional vector output
  • Unsupervised classification: classic k-means and ISODATA clustering (train on a pixel sample, classify the whole scene block-wise) producing an L3 product with uint8 class labels
  • Supervised classification: nearest neighbour (minimum distance), box (parallelepiped), maximum likelihood, spectral angle mapper (SAM) and random forest (scikit-learn, with per-band feature importances in the provenance), trained from vector labels (any geopandas-readable format, e.g. Shapefile, GeoPackage, GeoJSON) on the grid of a chosen band resolution (10 m or 20 m for Sentinel-2); produces an L3 product whose XML records the label → class-name mapping
  • Accuracy assessment: confusion matrix, overall/producer's/user's accuracy and Cohen's kappa of a supervised product against independent reference polygons (fundayao accuracy)
  • Provenance & metadata: every processing step is recorded in the product XML; the radiometric state (DN / TOA / BOA / index) is explicit and checked by every consumer

Installation

python3 -m venv .venv
.venv/bin/pip install -e ".[dev]"

Requires Python ≥ 3.10. Main dependencies: rasterio, numpy, matplotlib, rpcfit, geopandas (supervised classification training labels), scikit-learn (random forest). The SAM segmentation feature is optional: install it with pip install -e ".[sam]" (requires segment-geospatial, which pulls in PyTorch and downloads a ~2 GB model checkpoint on first use).

Usage

Command line

# import sensor data
fundayao import-s2 S2C_MSIL1C_....SAFE products/
fundayao import-svn1 SVN1-01_..._01/ products/
fundayao import-wh1 /path/to/WH-1/ products/

# radiometric correction chain
fundayao toa products/S2C_T36RUU_20260815_L2 products/ --quantity reflectance
fundayao dos products/S2C_T36RUU_20260815_L2_TOA products/ --percentile 1

# indices and custom formulas
fundayao index ndvi products/S2C_T36RUU_20260815_L2 products/
fundayao band-math --name ndwi \
    --formula "(green - nir) / (green + nir)" \
    --band green=560 --band nir=842 \
    products/S2C_T36RUU_20260815_L2 products/

# subset an area of interest (map coords, or pixel coords for RPC products)
fundayao subset products/S2C_T36RUU_20260815_L2 products/ \
    --bbox 300000 3350000 320000 3370000
fundayao subset products/SVN101_20241203_MUX1_L1 products/ \
    --bbox 0 0 2000 2000 --coords pixel

# statistics and quicklooks
fundayao stats products/S2C_T36RUU_20260815_L2 --calibrated
fundayao quicklook products/S2C_T36RUU_20260815_L2 rgb.png
fundayao quicklook products/S2C_T36RUU_20260815_L2 cir.png --cir
fundayao quicklook products/S2C_T36RUU_20260815_L2_NDVI ndvi.png --band NDVI

# SAM segmentation (requires fundayao[sam])
fundayao segment-sam products/S2C_T36RUU_20260815_L2 products/
fundayao segment-sam products/S2C_T36RUU_20260815_L2 products/ --binary --scale 2
fundayao segment-sam products/S2C_T36RUU_20260815_L2 products/ \
    --model vit_l --device cuda --vector segments.geojson

# unsupervised classification
fundayao classify kmeans products/S2C_T36RUU_20260815_L2 products/ --clusters 6
fundayao classify isodata products/S2C_T36RUU_20260815_L2 products/ \
    --clusters 8 --max-clusters 16 --max-std 0.02 --min-distance 0.05

# supervised classification (training labels from a vector file)
fundayao classify nearest-neighbour products/S2C_T36RUU_20260815_L2 products/ \
    --labels training_polygons.shp --field label
fundayao classify box products/S2C_T36RUU_20260815_L2 products/ \
    --labels training_polygons.geojson --resolution 20 --box-std 2.0
fundayao classify max-likelihood products/S2C_T36RUU_20260815_L2 products/ \
    --labels training_polygons.gpkg --max-per-class 5000
fundayao classify sam products/S2C_T36RUU_20260815_L2 products/ \
    --labels training_polygons.shp
fundayao classify rf products/S2C_T36RUU_20260815_L2 products/ \
    --labels training_polygons.shp --trees 200 --depth 20

# accuracy assessment against independent reference polygons
fundayao accuracy products/S2C_T36RUU_20260815_L2_ML \
    --labels validation_polygons.shp

Python API

from fundayao.io import (
    import_sentinel2_l1c, import_superview_neo1, import_wh1)
from fundayao.radiometry import toa_reflectance, dos
from fundayao.indices import ndvi, mndwi, band_math
from fundayao.segment import sam_segment
from fundayao.classify import (kmeans, isodata, nearest_neighbour, box,
                               maximum_likelihood, spectral_angle_mapper,
                               random_forest, accuracy_assessment)
from fundayao.subset import subset
from fundayao.stats import band_statistics
from fundayao.visualize import (
    rgb_composite, plot_band, spectral_profile, band_scatter)

product = import_sentinel2_l1c("S2C_MSIL1C_....SAFE", "products")
boa = dos(toa_reflectance(product, "products"), "products")
ndvi_product = ndvi(boa, "products")

table = band_statistics(product, apply_calibration=True)
sam_mask = sam_segment(product, "products", unique=False, scale=2)
classes = kmeans(product, "products", n_clusters=6)
classes = isodata(product, "products", n_clusters=8, max_clusters=16)
# supervised: train on polygons from any geopandas-readable vector file
classes = nearest_neighbour(product, "products", "training_polygons.shp")
classes = box(product, "products", "training_polygons.shp", box_std=2.0)
classes = maximum_likelihood(product, "products", "training_polygons.shp",
                             resolution=20)
classes = spectral_angle_mapper(product, "products", "training_polygons.shp")
classes = random_forest(product, "products", "training_polygons.shp",
                        n_estimators=200)
# accuracy assessment against independent reference polygons
report = accuracy_assessment(classes, "validation_polygons.shp")
print(report["overall"], report["kappa"])
fig = rgb_composite(product, out_path="rgb.png")
fig = plot_band(ndvi_product, "NDVI", cmap="RdYlGn", out_path="ndvi.png")
fig = spectral_profile(product, [(305100.0, 3356200.0)], out_path="profile.png")
fig = band_scatter(product, 665, 842, out_path="red_nir.png")

# sensor-geometry data (SuperView Neo-1 / WH-1): pixel-coordinate subset, RPCs refit
svn_products = import_superview_neo1("SVN1-01_..._01/", "products")
sub = subset(svn_products[0], "products", (0, 0, 2000, 2000), coords="pixel")
wh1_products = import_wh1("/path/to/WH-1/", "products")
sub = subset(wh1_products[0], "products", (0, 0, 2000, 2000), coords="pixel")

Project layout

├── docs/file-format.md      # fundayao product format specification
├── src/fundayao/
│   ├── cli.py               # command line interface (thin wrapper)
│   ├── io/
│   │   ├── sentinel2.py     # Sentinel-2 L1C importer
│   │   ├── superview.py     # SuperView Neo-1 L1B importer
│   │   └── wh1.py           # WH-1 / LJ-3 L1A importer
│   ├── radiometry.py        # TOA / sun-elevation / DOS corrections
│   ├── indices.py           # spectral indices + band math
│   ├── subset.py            # AOI subsetting (+ RPC re-estimation)
│   ├── segment.py           # SAM segmentation via segment-geospatial
│   ├── classify.py          # classification: kmeans/isodata (unsupervised),
│   │                        # nearest_neighbour/box/maximum_likelihood/
│   │                        # spectral_angle_mapper/random_forest
│   │                        # (supervised) + accuracy_assessment
│   ├── stats.py             # per-band statistics
│   ├── visualize.py         # composites, maps, profiles, scatterplots
│   └── _rgb.py              # internal RGB GeoTIFF builder
└── tests/                   # pytest suite (synthetic fixtures + integration)

Testing

.venv/bin/python -m pytest

The unit tests run on small synthetic products. Additional integration tests run against real data when pointed at it via environment variables:

FUNDAO_S2_TEST_DATA=/path/to/S2 \
FUNDAO_SVN1_TEST_DATA=/path/to/SVN1 \
FUNDAO_WH1_TEST_DATA=/path/to/WH-1 \
FUNDAO_SEGMENT_SAM_TEST_DATA=/path/to/fundayao/product \
FUNDAO_S2_CLASSIFY_PRODUCT=/path/to/imported/fundayao/product \
FUNDAO_S2_CLASSIFY_LABELS=/path/to/labels.shp \
.venv/bin/python -m pytest

AI-generated code disclaimer

This repository was created by AI vibe-coding tools. The code, documentation, and other materials are provided without any warranty and may contain errors. No guarantee is made that the contents are free of third-party intellectual-property rights, including copyright. Use this software entirely at your own risk; verify its correctness and legal status for your jurisdiction before relying on it.

License

Unlicense (public domain dedication) — see LICENSE.

Download files

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

Source Distribution

fundayao-0.2.0.tar.gz (103.0 kB view details)

Uploaded Source

Built Distribution

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

fundayao-0.2.0-py3-none-any.whl (74.7 kB view details)

Uploaded Python 3

File details

Details for the file fundayao-0.2.0.tar.gz.

File metadata

  • Download URL: fundayao-0.2.0.tar.gz
  • Upload date:
  • Size: 103.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.12.13

File hashes

Hashes for fundayao-0.2.0.tar.gz
Algorithm Hash digest
SHA256 95516fef7c6b9566d307e4c2e09ca6d607494958ef7ce616ea010800772c8b12
MD5 bb8d822dfe98f10cf879a7ecaf39dab9
BLAKE2b-256 2f36fba59e08ff41827f39a4967b47310686797bab1c7e59b4f3f8a1f27e4906

See more details on using hashes here.

File details

Details for the file fundayao-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: fundayao-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 74.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.12.13

File hashes

Hashes for fundayao-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 5cc852d52c7fb486c15a908a9da9ec3dee12deb5d5ab541230772cfe8637a802
MD5 be2acc272ee84107cdae47ce8a2afcd1
BLAKE2b-256 0084b2dcea02b15f57ea30ab81bd6c8056135f13bbee1553ff66c02a2504b9f2

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page