Metadata-Version: 2.4
Name: geoahsi
Version: 1.2.4
Summary: Hyperspectral spectral analysis, expert-rule computation, and process visualization (USGS Tetracorder algorithm)
Author: GeoAHSI Team
License: MIT License
        
        Copyright (c) 2026 GeoAHSI Team
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
        
Keywords: GeoAHSI,Tetracorder,EMIT,hyperspectral,mineral,USGS,remote sensing
Classifier: Development Status :: 5 - Production/Stable
Classifier: License :: OSI Approved :: MIT License
Classifier: Intended Audience :: Science/Research
Classifier: Topic :: Scientific/Engineering :: GIS
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Operating System :: Microsoft :: Windows
Classifier: Operating System :: POSIX :: Linux
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: numpy>=1.20
Requires-Dist: pandas>=1.3
Requires-Dist: netCDF4>=1.6
Requires-Dist: pyproj>=3.0
Requires-Dist: pyresample>=1.25
Requires-Dist: threadpoolctl>=3.0
Provides-Extra: viz
Requires-Dist: matplotlib>=3.5; extra == "viz"
Provides-Extra: dev
Requires-Dist: pytest; extra == "dev"
Requires-Dist: matplotlib>=3.5; extra == "dev"
Requires-Dist: build; extra == "dev"
Requires-Dist: twine; extra == "dev"
Provides-Extra: gdal
Dynamic: license-file

# geoahsi

**Hyperspectral spectral analysis · expert-rule computation · process visualization** — an end-to-end engine that turns spectra into mineral identification with a fully transparent, publication-ready rendering of every expert-rule decision. Based on the USGS Tetracorder algorithm, it ships with a built-in 77-mineral expert rule library and the USGS splib06b spectral library, classifies hyperspectral imagery or individual spectra per pixel, and renders each expert-rule gate as a Nature-style PDF.

```
Spectral analysis ─► Expert-rule computation ─► Process visualization
continuum removal + least-squares fit   3-layer rule gating + weighted verdict   per-feature curves + every gate PASS/FAIL
```

## Core features

### 1. Spectral analysis
- **Continuum removal**: normalize reference and unknown spectra by feature endpoints
- **Closed-form 2×2 least-squares fit**: each feature yields `k0 / k1 / R² / absorption depth` (with `det==0` singularity guard — no iterations)
- **Reference resampling**: Gaussian resampling of USGS splib06b to target band FWHM, aligned band-by-band with the input
- Two entry points: full-scene cube (per-pixel parallel) and single spectrum

### 2. Expert-rule computation
Built-in **77 mineral expert rules** (pure end-members + mixtures); each rule passes through three gating layers:
1. **Continuum constraints** (left/mean/right/ratio min/max — 8 checks)
2. **Diagnostic + non-feature exclusion** (`not_absolute` / `not_relative`: absorptions that must be absent)
3. **Weighted constraints** (`min_weighted_fit` / `min·max_weighted_depth` / `min_fit_depth_product`)
- Optional **depth-ratio constraint** (`max_depth_ratio_feat1_over_feat0`)
- Per-pixel outputs: best mineral, weighted fit, absorption depth, fit×depth confidence (fd), muscovite 2.2 µm absorption center
- Match a single mineral by key — returns accept/fit/fd plus which gate rejected it

### 3. Process visualization (Nature-style PDF, requires `geoahsi[viz]`)
- **Top-N PDF**: one page per candidate mineral — all diagnostic/non-feature continuum-removed curves + k0/k1/R²/depth + constraint ranges + not-feature reference keys
- **Single-mineral match PDF**: per-feature curves + **every expert-rule gate's PASS/FAIL verdict** + final fit/depth/fd + ACCEPT/REJECT — shows exactly why a match is accepted or rejected
- Okabe-Ito colorblind-safe palette, adaptive y-axes, panel letters, shared legend, fixed GridSpec layout

## Installation

```bash
pip install geoahsi                  # core: spectral analysis + expert rules + GeoTIFF
pip install 'geoahsi[viz]'           # + PDF process visualization
conda install -c conda-forge gdal    # GDAL for GeoTIFF output (install via conda)
```

> Input: supports **EMIT L2A NetCDF** (auto-removes water-vapor bad bands, 285 → 244). The library bundles every resource it needs — spectral library and rule library are built-in, no external data required.

Command line:
```bash
geoahsi -i EMIT_xxx.nc -o output/                 # full scene → 3 GeoTIFFs
geoahsi -i EMIT_xxx.nc -o output/ --raw            # also emit mus_center + fd
```

## Quick start

### Full scene: spectral analysis + expert rules → GeoTIFF

```python
from geoahsi import MicaEngine

engine = MicaEngine()                                    # zero-arg, all resources built-in
spectrum, lon, lat, w, bp = engine.load_emit("EMIT_xxx.nc")   # bad bands removed
orth, color, mus = engine.spectrum_analysis(
    spectrum, w, bp, n_workers=8,
)
engine.write_tiff("result", lon, lat, orth, color, mus)
# → result_mapping_orth.tiff        mineral classification
# → result_color_enhanced_orth.tiff depth-modulated color
# → result_mus_orth.tiff            muscovite thematic map
```

### Single spectrum: Top-N identification + process PDF

```python
pixel = spectrum[row, col, :]                           # already valid bands
top = engine.classify_spectrum(pixel, w, bp, top_n=10,
                               pdf_path="topN_features.pdf")
# [{"name": "calcite.8+montmorilloniteNa.2_mix_intimate", "fit": 0.9457, "fd": 0.0659}, ...]
```

### Single spectrum vs. a single reference spectrum

```python
r = engine.match_reference(pixel, w, bp,
                           mineral_key="calcite",        # a key from rf.json
                           pdf_path="match.pdf")          # optional process PDF
# {"name": "calcite", "fit": 0.4007, "fd": 0.0194, "accept": False}
# PDF shows: weighted: fit>=0.64 → FAIL 0.4007 (rejection reason at a glance)
```

## Main API

| Method | Description |
|---|---|
| `MicaEngine.load_emit(path)` | Load imagery + bad-band removal → `spectrum, lon, lat, w, bp` |
| `MicaEngine.spectrum_analysis(spectrum, w, bp, n_workers, raw)` | Full-scene spectral analysis + expert rules + rendering |
| `MicaEngine.classify_spectrum(pixel, w, bp, top_n, pdf_path)` | Single-spectrum Top-N identification (+ optional PDF) |
| `MicaEngine.match_reference(pixel, w, bp, mineral_key, pdf_path)` | Single spectrum vs. a specified reference (+ optional process PDF) |
| `MicaEngine.write_tiff(prefix, lon, lat, orth, color, mus)` | Write 3 GeoTIFFs (UTM projection) |
| `MicaClassifier.classify / classify_spectrum / get_resample` | Low-level three-component API (custom pipelines) |
| `ResultRenderer.render / write_tiff / plot_features_pdf / plot_rule_match_pdf` | Rendering + GeoTIFF + PDF |

## Built-in resources & algorithm

- **USGS splib06b spectral library** (21 MB), **77-mineral expert rule library** `rf.json`, mineral RGB color table, muscovite 10-step color table — all built-in; `MicaEngine()` works with zero arguments
- Algorithm: continuum removal + closed-form 2×2 least-squares (R² + absorption depth) → 3-layer rule gating → weighted verdict; parabolic fit for the muscovite 2.2 µm absorption center
- Parallelism: mineral-level multiprocessing + read-only memmap sharing

## Performance

Measured on a 1280×1242 EMIT scene: ~75–95 s with 8 workers, ~99.8% pixels classified; output is bit-identical to the reference Tetracorder implementation.

## Acknowledgements

- USGS Tetracorder algorithm and the splib06b spectral library
- NASA EMIT hyperspectral imagery

## License

MIT License (see [LICENSE](LICENSE)).
