Skip to main content

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.

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.8.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.8-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.8-cp312-cp312-macosx_11_0_arm64.whl (307.6 kB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

spires-0.2.8-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.8-cp311-cp311-macosx_11_0_arm64.whl (307.3 kB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

spires-0.2.8-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.8-cp310-cp310-macosx_11_0_arm64.whl (307.3 kB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

spires-0.2.8-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.8-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.8.tar.gz.

File metadata

  • Download URL: spires-0.2.8.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.8.tar.gz
Algorithm Hash digest
SHA256 a2ec014fc5bd3cf1eca2620cc9b6fea65334ed68d410483bd71227d0e00d256c
MD5 a16fb3f6f0bc65445fadf5a7affa3a65
BLAKE2b-256 f64d9f425b1073d18a8412da0c1bd5ea6424a39ff727da761fe736bd114cfc41

See more details on using hashes here.

Provenance

The following attestation bundles were made for spires-0.2.8.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.8-cp312-cp312-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for spires-0.2.8-cp312-cp312-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 c1b1397cf6886e52a32fad827ca93da8b75b606d489b2c265459bd50e2091e9d
MD5 9b414a44c9b39eaa6b6724b3c5ab68d3
BLAKE2b-256 2cc30c374bc1b78f41629b50c0705e4dd5eb003018a37473b0540ac5cb6b587a

See more details on using hashes here.

Provenance

The following attestation bundles were made for spires-0.2.8-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.8-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for spires-0.2.8-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 960869d7c60efb8d83ec4dec7e6d3086ccaef00ac0e285fe940a08234f62c1d8
MD5 3e249fd8d2530fc55af2a99a50e0889e
BLAKE2b-256 a45b13d0a01303773b3370db7d2d737f0b9c64f090ba05f1667ac281acc0a169

See more details on using hashes here.

Provenance

The following attestation bundles were made for spires-0.2.8-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.8-cp311-cp311-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for spires-0.2.8-cp311-cp311-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 e544a42128a429b52d06c2126fad596545dbe842f3913a1fb1ab49c7cc8f6d91
MD5 4fd564f4958cad6781ff4b1ba858a2b3
BLAKE2b-256 24d72a25c7457d1d9f02c676d1afe6e1781c61fc788f6d6f0e079bff6da6cfca

See more details on using hashes here.

Provenance

The following attestation bundles were made for spires-0.2.8-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.8-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for spires-0.2.8-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 7921d6b4a63abfee99016bd28eedec2358b8b987fa8f9eeffe55846b51a9cba6
MD5 5d7a375eb592e10126530a3bed9565d4
BLAKE2b-256 f82179bfbdc42f8f27919e915adc2946ee91e74936ea6feaf6459e9b1803880f

See more details on using hashes here.

Provenance

The following attestation bundles were made for spires-0.2.8-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.8-cp310-cp310-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for spires-0.2.8-cp310-cp310-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 d17c6ff24e6b1596745865e0782490632b3e1df26dcf4722d2aff042ef219bbc
MD5 4c247c76ce66239e74a13d9a8199ef92
BLAKE2b-256 f5d301a5113ef6851affd686a9478f48c65639dd36b17f3eabce73bebaf6a680

See more details on using hashes here.

Provenance

The following attestation bundles were made for spires-0.2.8-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.8-cp310-cp310-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for spires-0.2.8-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 ac43a0d6978823d8b90304bf168142f3c5acbfd53eee4056b649d348e0d495ea
MD5 3c2ca6c839fee6f8704169b3f8622dac
BLAKE2b-256 d01091ab894d376cd1d69d81252ee71fc533e88f3914a7853210e1ce2cbf0eb1

See more details on using hashes here.

Provenance

The following attestation bundles were made for spires-0.2.8-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.8-cp39-cp39-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for spires-0.2.8-cp39-cp39-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 997785fff71726a579733995530eb0f4be4a6e38935b4ba77c25ca677698d29c
MD5 87ff59cbca4417b5c936f28dc20f5d00
BLAKE2b-256 073620517d03bd0ef4e386a782bd24557579782753baff61c4956b51a75ec1eb

See more details on using hashes here.

Provenance

The following attestation bundles were made for spires-0.2.8-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.8-cp39-cp39-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for spires-0.2.8-cp39-cp39-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 4008cdce60505890f5961ec2916a4ccbb90a2c4db99ab9deef912343c1bbd5ca
MD5 ccdc805c72498abb9915cf025ebad42d
BLAKE2b-256 fba16a47589ca0489486717a5792f9b753102c2b7c45a684ad1f7e08570577fd

See more details on using hashes here.

Provenance

The following attestation bundles were made for spires-0.2.8-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.

Release history Release notifications | RSS feed

This release

0.2.8 This release

9 files

0.2.5

9 files

0.2.4

9 files

0.2.2

9 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page