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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
95516fef7c6b9566d307e4c2e09ca6d607494958ef7ce616ea010800772c8b12
|
|
| MD5 |
bb8d822dfe98f10cf879a7ecaf39dab9
|
|
| BLAKE2b-256 |
2f36fba59e08ff41827f39a4967b47310686797bab1c7e59b4f3f8a1f27e4906
|
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5cc852d52c7fb486c15a908a9da9ec3dee12deb5d5ab541230772cfe8637a802
|
|
| MD5 |
be2acc272ee84107cdae47ce8a2afcd1
|
|
| BLAKE2b-256 |
0084b2dcea02b15f57ea30ab81bd6c8056135f13bbee1553ff66c02a2504b9f2
|