Metadata-Version: 2.4
Name: asterra
Version: 0.1.3
Summary: Support-aware machine learning for Earth observation
Requires-Python: >=3.11
License-Expression: BSD-3-Clause
License-File: LICENSE
Author: Asterra Contributors
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: BSD License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: GIS
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Requires-Dist: numpy>=1.26
Requires-Dist: scipy>=1.11
Requires-Dist: scikit-learn>=1.3
Provides-Extra: geo
Requires-Dist: pyproj>=3.6; extra == "geo"
Requires-Dist: shapely>=2.0; extra == "geo"
Provides-Extra: dev
Requires-Dist: build>=1.2; extra == "dev"
Requires-Dist: pytest>=7.4; extra == "dev"
Requires-Dist: pytest-cov>=4.1; extra == "dev"
Requires-Dist: ruff>=0.5.0; extra == "dev"
Project-URL: Homepage, https://github.com/ArnaBannonymus/asterra
Project-URL: Issues, https://github.com/ArnaBannonymus/asterra/issues
Project-URL: Changelog, https://github.com/ArnaBannonymus/asterra/blob/main/CHANGELOG.md
Description-Content-Type: text/markdown

# asterra

Support-aware machine learning for Earth observation.

## Motivation

Earth observation (EO) machine learning workflows routinely mix data sources and label types with **mismatched
spatial supports**:

- sensors with different pixel sizes (e.g., Sentinel-2 vs PlanetScope)
- labels defined on parcels/fields, tiles, scenes, or time windows (not per-pixel)
- coarse-to-fine (and fine-to-coarse) supervision
- patch overlap leakage and neighborhood dependence in evaluation

Ignoring these mismatches often leads to:
- biased features/labels due to incorrect aggregation
- silent leakage (overlapping patches, neighboring pixels, same-tile same-date)
- metrics that do not correspond to the true label support

## What Asterra does

Asterra is a **NumPy-first**, **scikit-learn-compatible** package for building *support-aware* pipelines.

The core abstraction is a sparse, overlap-based **`SupportMatrix`** that maps one support to another. It powers:

- mixed-resolution aggregation and projection (grid ↔ grid, samples → groups)
- support-aware feature and label projection
- leakage-safe splitting utilities (buffers, tile/time grouping)
- support-aware metrics

## Installation

```bash
# Once published to PyPI:
# python -m pip install asterra

# Install from source (GitHub):
python -m pip install "asterra @ git+https://github.com/ArnaBannonymus/asterra.git@main"
```

Optional geospatial extras (not required for pixel-space workflows):

```bash
python -m pip install "asterra[geo] @ git+https://github.com/ArnaBannonymus/asterra.git@main"
```

## Quickstart

```python
import numpy as np
from asterra.data import EOData
from asterra.io import sensors
from asterra.support import SupportMatrix

# Synthetic Sentinel-2-like grid (H, W, B)
arr_s2 = np.random.RandomState(0).randn(32, 32, 4).astype("float32")
e_s2 = EOData.from_array(
    arr_s2,
    band_schema=sensors.sentinel2_rgbn(),
    support={"kind": "grid", "resolution": (10.0, 10.0), "origin": (0.0, 0.0)},
)

# Synthetic PlanetScope-like grid on a different resolution
arr_ps = np.random.RandomState(1).randn(64, 64, 4).astype("float32")
e_ps = EOData.from_array(
    arr_ps,
    band_schema=sensors.planetscope_4band(),
    support={"kind": "grid", "resolution": (5.0, 5.0), "origin": (0.0, 0.0)},
)

# Map PlanetScope pixels (source) onto Sentinel-2 pixels (target)
M = SupportMatrix.from_grid_to_grid(source=e_ps.support, target=e_s2.support)
X_ps_on_s2 = M.project_features(e_ps.as_samples())
print(X_ps_on_s2.shape)  # (32*32, 4)
```

## Visual proofs (local datasets)

Asterra is NumPy-first and does not ship heavy geospatial file I/O. For GeoTIFF/SAFE/NetCDF products you
typically read data with tools like `rasterio`/`xarray` and then construct `EOData` with a `BandSchema` and
`SupportSpec`.

The figures below are generated from **local** datasets (not included in this repo) to sanity-check the
support-aware operators on non-synthetic inputs:

**Planet (3m PF-SR) NDVI → Sentinel-2 (10m) NDVI window (SupportMatrix overlap projection + sparse structure view)**

![Planet→Sentinel-2 NDVI projection sanity check](https://raw.githubusercontent.com/ArnaBannonymus/asterra/v0.1.3/docs/assets/planet_to_s2_ndvi_window.png)

**Sentinel-1 VV/VH (dB) window + label map (leakage-aware spatial CV demo data)**

![Sentinel-1 VV/VH and label map window](https://raw.githubusercontent.com/ArnaBannonymus/asterra/v0.1.3/docs/assets/sentinel1_vv_vh_labelmap.png)

**complex SAR patch example (HH/HV magnitudes)**

![CVDL complex SAR patch example](https://raw.githubusercontent.com/ArnaBannonymus/asterra/v0.1.3/docs/assets/cvdl_hh_hv_patch.png)

To regenerate these visuals on your machine (with your own file paths):

```bash
python scripts/generate_readme_visuals.py \
  --planet-pf-sr /path/to/planet_pf_sr.tif \
  --s2-lr-ndvi /path/to/s2_lr_ndvi.tif \
  --s1-vv /path/to/s1_vv.tif \
  --s1-vh /path/to/s1_vh.tif \
  --label-map /path/to/label_map.tif \
  --cvdl-city-dir /path/to/S1SLC_CVDL/City
```

## Supported inputs

- `.npy` arrays with shapes `(H, W, B)`, `(T, H, W, B)`, `(N, B)`
- generic EO arrays with user-provided metadata:
  - `band_names`
  - georeferencing (`resolution`/`origin` or affine `transform`/`crs`) when available
  - pixel-space coordinates when georeferencing is not available
  - explicit group identifiers for parcel/tile/time supports

## Built-in sensor presets

Sensor helpers are convenience presets; the core library is sensor-agnostic.

- Sentinel-2 (common optical bands)
- Sentinel-1 (VV/VH-style SAR schema)
- PlanetScope (4-band and 8-band styles)
- NISAR-style configurable SAR schemas

## Architecture

The project is organized to keep EO-specific functionality separate from potentially generic sparse support logic:

- `asterra.data`: EO data model (array + band schema + support metadata)
- `asterra.support`: sparse support operators (SupportMatrix, projection)
- `asterra.preprocessing`: reshape/masking and band-aware transformers
- `asterra.model_selection`: leakage-aware splitters/utilities
- `asterra.metrics`: support-aware metrics
- `asterra.io`: `.npy` loader + sensor presets

See `DESIGN_BOUNDARIES.md` and `UPSTREAMING.md` for boundary notes and candidate generic components.

## Release status

`0.1.x` is an early, focused release line. The API is intentionally narrow and may evolve based on user feedback
and scientific validation.

## Roadmap (high level)

- richer support specifications (polygons/parcels via optional geo extras)
- additional support-aware scorers and splitters
- integration examples with local EO stacks (while keeping the core sensor-agnostic)
