Skip to main content

Python implementation of SPIRES (SPectral Inversion of REflectance from Snow) for retrieving snow properties from satellite imagery

Project description

SpiPy

PyPI version Documentation Status Build and Test Python 3.9-3.14 License: MIT

📦 View Source on GitHub | 📖 Documentation | 🐛 Report Issues

SpiPy is a Python implementation of SPIRES (Snow Property Inversion From Remote Sensing), originally implemented in MATLAB (SPIRES GitHub repository).

Overview

SPIRES retrieves snow properties (grain size, dust concentration, fractional snow-covered area) from satellite multispectral imagery by inverting reflectance spectra using lookup tables generated from Mie-scattering theory.

Key features:

  • Hybrid Python/C++ implementation for performance (3000x speedup over pure Python)
  • Support for MODIS, Sentinel-2, and Landsat data
  • SWIG bindings for optimized interpolation and optimization routines
  • NLopt-based nonlinear optimization

Installation

Quick Install (PyPI)

pip install spires

Note: Pre-built binary wheels are available for Linux and macOS (Python 3.9-3.14). For other platforms or to build from source, see below.

Install from Source

Important: Use conda-forge for all dependencies. The apt version of nlopt does not include required C++ headers.

# Install build tools and nlopt (required)
conda install -c conda-forge swig gxx gcc nlopt

# Install all dependencies (recommended)
conda install -c conda-forge numpy h5py scipy xarray netCDF4 gdal geopandas matplotlib tox sphinx dask jupyterlab pyproj

Git LFS

This repository uses Git LFS for test data. Install Git LFS before cloning:

# macOS
brew install git-lfs

# Linux
sudo apt install git-lfs

# Initialize
git lfs install

Build and Install

# Build SWIG extensions
python3 setup.py build_ext --inplace

# Install package
pip install .

# Or install with optional dependencies
pip install ".[dev,test,docs]"

Usage

See the examples/ folder for Jupyter notebooks with detailed use cases.

Basic usage:

import spires

# Load lookup table
interpolator = spires.LutInterpolator(
    lut_file='tests/data/lut_sentinel2b_b2to12_3um_dust.mat'
)

# Process imagery to get fractional snow-covered area
fsca = spires.get_fsca(...)

Development

Building Wheels

Build a wheel for the active Python interpreter:

pip install build
python -m build --wheel

Build wheels for multiple Python versions using tox:

tox -e py39,py310,py311,py312

Note: When using pyenv, wheels for Python 3.9 may incorrectly build for x86 instead of arm64 on M1 Macs. Use a conda environment to build correctly.

Building C++ Extensions Manually

The setuptools build process handles SWIG bindings automatically. To build manually:

cd spires
make

Or specify paths explicitly:

NUMPY_INCLUDE=$(python -c "import numpy; print(numpy.get_include())")
g++ -shared -o spires_module.so spires.cpp -I$NUMPY_INCLUDE

Testing

Run doctests:

pytest --doctest-modules

Documentation

Install documentation dependencies:

pip install ".[docs]"

Build documentation:

cd doc/
make html

Lookup Tables and Test Data

Lookup Tables

Simulated Mie-scattering snow reflectance lookup tables are available on Zenodo:

DOI

  • MODIS: LUT_MODIS.mat (537 MB)
  • Sentinel-2: lut_sentinel2b_b2to12_3um_dust.mat (70 MB)

Download using the helper script:

python scripts/download_test_data.py --luts

Or download directly:

curl -L -o LUT_MODIS.mat https://zenodo.org/records/18701286/files/LUT_MODIS.mat
curl -L -o lut_sentinel2b_b2to12_3um_dust.mat https://zenodo.org/records/18701286/files/lut_sentinel2b_b2to12_3um_dust.mat

Note: The Sentinel-2 LUT is also included in the repository via Git LFS. Landsat lookup tables are planned.

Test Data

Full-resolution test imagery for validation is available on Zenodo:

DOI

  • Sentinel-2 reflectance: sentinel_r.nc (1.4 GB, 921×1347 pixels)
  • Background reflectance: sentinel_r0.nc (705 MB)

Small subsets suitable for CI/testing are included in the repository via Git LFS. See tests/data/README.md for details.

Performance

The C++ optimizations provide significant speedups over pure Python:

Interpolation: 3000x faster (1.07 ms → 309 ns)

  • Pure Python RegularGridInterpolator: 1.07 ms
  • Vectorized Python: 143 μs
  • SWIG C++ (vectorized): 5.58 μs
  • SWIG C++ (index lookup): 309 ns

Spectrum Difference: 1000x faster (1.1 ms → 1 μs)

  • Pure Python: 1.1 ms
  • With optimized interpolator: 3.8 μs
  • C++ implementation: 1 μs

Full Optimization: 3000x faster (165 ms → 43 μs)

  • Scipy optimization: 165 ms
  • With optimized interpolator: 4.94 ms
  • With C++ spectrum difference: 3.5 ms
  • NLopt in C++: 43 μs

Known Issues

  • SLSQP solver doesn't work in the C++ implementation; using COBYLA instead
  • SWIG interpolator and scipy's RegularGridInterpolator behave differently when coordinates aren't linspace
  • COBYLA in scipy can't set rhobeg per dimension individually, requiring problem scaling

Roadmap

  • Optimize inversion for single location over multiple timesteps (keep R_0 constant)
  • Support xarray inputs for interpolator and spectra
  • Add Landsat lookup tables
  • Improve cloud masking workflows

License

See LICENSE file for details.

Citation

If you use this software, please cite the algorithm paper, software implementation, and any datasets you use:

Algorithm:

@article{bair2021spires,
  title={Snow Property Inversion From Remote Sensing (SPIReS): A Generalized Multispectral Unmixing Approach With Examples From MODIS and Landsat 8 OLI},
  author={Bair, E. H. and Stillinger, T. and Dozier, J.},
  journal={IEEE Transactions on Geoscience and Remote Sensing},
  volume={59},
  number={9},
  pages={7270--7284},
  year={2021},
  doi={10.1109/TGRS.2020.3040328}
}

Software:

@software{bair2026spipy,
  title={SpiPy: Python implementation of SPIRES snow property inversion},
  author={Bair, Edward H. and Griessbaum, Niklas},
  year={2026},
  url={https://github.com/NiklasPhabian/SpiPy},
  version={0.2.2},
  doi={10.5281/zenodo.XXXXXXX},
  note={DOI will be updated after Zenodo release. See CITATION.cff for full metadata}
}

Lookup Tables (if used):

@dataset{bair2026spires_luts,
  author       = {Bair, Edward and Dozier, Jeff},
  title        = {{SPIRES} Snow Reflectance Lookup Tables},
  year         = 2026,
  publisher    = {Zenodo},
  doi          = {10.5281/zenodo.18701286},
  url          = {https://doi.org/10.5281/zenodo.18701286}
}

Test Data (if used):

@dataset{griessbaum2026sentinel2_testdata,
  author       = {Griessbaum, Niklas},
  title        = {Sentinel-2 reflectance data for testing the {SpiPy} implementation of the {SPIRES} algorithm},
  year         = 2026,
  publisher    = {Zenodo},
  doi          = {10.5281/zenodo.18704072},
  url          = {https://doi.org/10.5281/zenodo.18704072}
}

Alternatively, see CITATION.cff or use GitHub's "Cite this repository" feature.

Funding

Development of this software was supported by:

Contract: W913E523C0002 Program: "Climate and natural hazards, snow-covered and mountain environment sensing research" Sponsor: Broad Agency Announcement Program, Cold Regions Research and Engineering Laboratory Monitored by: U.S. Army Engineer Research and Development Center, Hanover, NH 03755

Distribution Statement: Approved for public release; distribution is unlimited.

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

spires-0.2.4.tar.gz (62.5 kB view details)

Uploaded Source

Built Distributions

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

spires-0.2.4-cp312-cp312-manylinux_2_28_x86_64.whl (1.0 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.28+ x86-64

spires-0.2.4-cp312-cp312-macosx_11_0_arm64.whl (307.6 kB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

spires-0.2.4-cp311-cp311-manylinux_2_28_x86_64.whl (965.7 kB view details)

Uploaded CPython 3.11manylinux: glibc 2.28+ x86-64

spires-0.2.4-cp311-cp311-macosx_11_0_arm64.whl (307.3 kB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

spires-0.2.4-cp310-cp310-manylinux_2_28_x86_64.whl (957.1 kB view details)

Uploaded CPython 3.10manylinux: glibc 2.28+ x86-64

spires-0.2.4-cp310-cp310-macosx_11_0_arm64.whl (307.3 kB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

spires-0.2.4-cp39-cp39-manylinux_2_28_x86_64.whl (953.9 kB view details)

Uploaded CPython 3.9manylinux: glibc 2.28+ x86-64

spires-0.2.4-cp39-cp39-macosx_11_0_arm64.whl (305.2 kB view details)

Uploaded CPython 3.9macOS 11.0+ ARM64

File details

Details for the file spires-0.2.4.tar.gz.

File metadata

  • Download URL: spires-0.2.4.tar.gz
  • Upload date:
  • Size: 62.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for spires-0.2.4.tar.gz
Algorithm Hash digest
SHA256 c7b4c1ce6b88bbb900b0523a3c574d98f4967ce1ff7db87dd80a399521467da1
MD5 b3cd0715f781a9d3b2070eb67ed4f5bb
BLAKE2b-256 31b491e92c3826f2a0e7c3bede8421643f25d1f366ec3b4bb59c9b9a1f029931

See more details on using hashes here.

Provenance

The following attestation bundles were made for spires-0.2.4.tar.gz:

Publisher: publish-pypi.yml on NiklasPhabian/SpiPy

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

File details

Details for the file spires-0.2.4-cp312-cp312-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for spires-0.2.4-cp312-cp312-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 ec19eed6ed29bf777a13a02123e3eeaf5e27c81f264207aaa303a42cf0aa0d49
MD5 9f0d6b9cb9b73c13b2eecb315af38991
BLAKE2b-256 66782811a405315188615106a37c470d72d80f0c4cb032eea8c6dd42218b7e1b

See more details on using hashes here.

Provenance

The following attestation bundles were made for spires-0.2.4-cp312-cp312-manylinux_2_28_x86_64.whl:

Publisher: publish-pypi.yml on NiklasPhabian/SpiPy

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

File details

Details for the file spires-0.2.4-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for spires-0.2.4-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 8fdd0b94c4771b28f4e3073dd6df1bbcd21c8a35d49f20d47539939cdc435fdf
MD5 219209268a0b31d17efcb20efa61b95e
BLAKE2b-256 69e6abaa5d8c211d1aa9e352f6347686a31b0c55276de7573266167525a0b2fc

See more details on using hashes here.

Provenance

The following attestation bundles were made for spires-0.2.4-cp312-cp312-macosx_11_0_arm64.whl:

Publisher: publish-pypi.yml on NiklasPhabian/SpiPy

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

File details

Details for the file spires-0.2.4-cp311-cp311-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for spires-0.2.4-cp311-cp311-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 a417abde0794b6f4dc4b5d969b15bfcebfd59fa3df3f632dfc3209d000c39ad8
MD5 071581cf14ebc26de82b4122fd203a19
BLAKE2b-256 8de2447f275bd96a3e3f672594829353b2e56359e0df2605c34280147607855c

See more details on using hashes here.

Provenance

The following attestation bundles were made for spires-0.2.4-cp311-cp311-manylinux_2_28_x86_64.whl:

Publisher: publish-pypi.yml on NiklasPhabian/SpiPy

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

File details

Details for the file spires-0.2.4-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for spires-0.2.4-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 42918f31f53aaf0e564504a42aa06b04abeaa11bc359f12f4136331d451cb267
MD5 e0914019e80647f282fd0762e759e384
BLAKE2b-256 a54c4c44bc83c33642b5af5a91c3ca016ca45d8ceb42f85f5803ed1a9bba6a01

See more details on using hashes here.

Provenance

The following attestation bundles were made for spires-0.2.4-cp311-cp311-macosx_11_0_arm64.whl:

Publisher: publish-pypi.yml on NiklasPhabian/SpiPy

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

File details

Details for the file spires-0.2.4-cp310-cp310-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for spires-0.2.4-cp310-cp310-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 5e49555901db24a0b479b4404cbe3ebe9270e0439f4bf5bfd43f225c0ffed405
MD5 890af02ce222f2043e0b1451a03d0a38
BLAKE2b-256 a7097b147efdddca91ca84c6c27c39a79668f8583fc8bbd1620e0872963a49f2

See more details on using hashes here.

Provenance

The following attestation bundles were made for spires-0.2.4-cp310-cp310-manylinux_2_28_x86_64.whl:

Publisher: publish-pypi.yml on NiklasPhabian/SpiPy

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

File details

Details for the file spires-0.2.4-cp310-cp310-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for spires-0.2.4-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 1cd39a64f22b610f92e9ebc18d3a2073c1adae38f5c803d130bd697cded2a048
MD5 1537fca8b71f7b0b832775202e2f0d90
BLAKE2b-256 f472afcfc485f534a842af9bb1e96b6f4c632e8d6293c575e0dfdb622121074c

See more details on using hashes here.

Provenance

The following attestation bundles were made for spires-0.2.4-cp310-cp310-macosx_11_0_arm64.whl:

Publisher: publish-pypi.yml on NiklasPhabian/SpiPy

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

File details

Details for the file spires-0.2.4-cp39-cp39-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for spires-0.2.4-cp39-cp39-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 2265134963361387ae75f23c593064380b7f54ba3b45b0c39df88b6d0687d273
MD5 b51c6f833239d23d894b6cb28c744aba
BLAKE2b-256 1608873a246f54de1ad46985a0fc44a8474a3cffcd4f2698b0cd3674c222d37e

See more details on using hashes here.

Provenance

The following attestation bundles were made for spires-0.2.4-cp39-cp39-manylinux_2_28_x86_64.whl:

Publisher: publish-pypi.yml on NiklasPhabian/SpiPy

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

File details

Details for the file spires-0.2.4-cp39-cp39-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for spires-0.2.4-cp39-cp39-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 e1206a233bf23bebc8b773c2bd92b7fa8167e80b1e49c39ffe323c0509810678
MD5 65b44f27de863b2624695ba61adba1e1
BLAKE2b-256 504b669235b03b31051317ade18173c07dcdf4bd45cd486cf33b5cd9dcf617da

See more details on using hashes here.

Provenance

The following attestation bundles were made for spires-0.2.4-cp39-cp39-macosx_11_0_arm64.whl:

Publisher: publish-pypi.yml on NiklasPhabian/SpiPy

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