spyndex

Awesome Spectral Indices in Python.

https://github.com/awesome-spectral-indices/spyndex

Science Score: 57.0%

This score indicates how likely this project is to be science-related based on various indicators:

  • CITATION.cff file
    Found CITATION.cff file
  • codemeta.json file
    Found codemeta.json file
  • .zenodo.json file
    Found .zenodo.json file
  • DOI references
    Found 6 DOI reference(s) in README
  • Academic publication links
  • Committers with academic emails
  • Institutional organization owner
  • JOSS paper metadata
  • Scientific vocabulary similarity
    Low similarity (8.3%) to scientific vocabulary

Keywords

earth-engine google-earth-engine numpy pandas python python3 remote-sensing satellite-imagery spectral spectral-data spectral-index spectral-indices xarray
Last synced: 6 months ago · JSON representation ·

Repository

Awesome Spectral Indices in Python.

Basic Info
Statistics
  • Stars: 222
  • Watchers: 7
  • Forks: 26
  • Open Issues: 2
  • Releases: 13
Topics
earth-engine google-earth-engine numpy pandas python python3 remote-sensing satellite-imagery spectral spectral-data spectral-index spectral-indices xarray
Created over 4 years ago · Last pushed 7 months ago
Metadata Files
Readme Contributing Funding License Citation

README.md

spyndex

Awesome Spectral Indices in Python:

Numpy | Pandas | GeoPandas | Xarray | Earth Engine | Planetary Computer | Dask

PyPI conda-forge Documentation Status Tests Awesome Spectral Indices License GitHub Sponsors Buy me a coffee Ko-fi Twitter Black isort


GitHub: https://github.com/davemlz/spyndex

Documentation: https://spyndex.readthedocs.io/

Paper: https://doi.org/10.1038/s41597-023-02096-0

PyPI: https://pypi.org/project/spyndex/

Conda-forge: https://anaconda.org/conda-forge/spyndex

Tutorials: https://spyndex.readthedocs.io/en/latest/tutorials.html


Citation

If you use this work, please consider citing the following paper:

bibtex @article{montero2023standardized, title={A standardized catalogue of spectral indices to advance the use of remote sensing in Earth system research}, author={Montero, David and Aybar, C{\'e}sar and Mahecha, Miguel D and Martinuzzi, Francesco and S{\"o}chting, Maximilian and Wieneke, Sebastian}, journal={Scientific Data}, volume={10}, number={1}, pages={197}, year={2023}, publisher={Nature Publishing Group UK London} }

Overview

The Awesome Spectral Indices is a standardized ready-to-use curated list of spectral indices that can be used as expressions for computing spectral indices in remote sensing applications. The list was born initially to supply spectral indices for Google Earth Engine through eemont and spectral, but given the necessity to compute spectral indices for other object classes outside the Earth Engine ecosystem, a new package was required.

Spyndex is a python package that uses the spectral indices from the Awesome Spectral Indices list and creates an expression evaluation method that is compatible with python object classes that support overloaded operators (e.g. numpy.ndarray, pandas.Series, xarray.DataArray).

Some of the spyndex features are listed here:

  • Access to Spectral Indices from the Awesome Spectral Indices list.
  • Multiple Spectral Indices computation.
  • Kernel Indices computation.
  • Parallel processing.
  • Compatibility with a lot of python objects!

Check the simple usage of spyndex here:

```python import spyndex import numpy as np import xarray as xr

N = np.random.normal(0.6,0.10,10000) R = np.random.normal(0.1,0.05,10000)

da = xr.DataArray( np.array([N,R]).reshape(2,100,100), dims = ("band","x","y"), coords = {"band": ["NIR","Red"]} )

idx = spyndex.computeIndex( index = ["NDVI","SAVI"], params = { "N": da.sel(band = "NIR"), "R": da.sel(band = "Red"), "L": 0.5 } ) ```

Bands can also be passed as keywords arguments:

python idx = spyndex.computeIndex( index = ["NDVI","SAVI"], N = da.sel(band = "NIR"), R = da.sel(band = "Red"), L = 0.5 )

And indices can be computed from their class:

python idx = spyndex.indices.NDVI.compute( N = da.sel(band = "NIR"), R = da.sel(band = "Red"), )

How does it work?

Any python object class that supports overloaded operators can be used with spyndex methods.


"Hey... what do you mean by 'overloaded operators'?"


That's the million dollars' question! An object class that supports overloaded operators is the one that allows you to compute mathematical operations using common operators (+, -, /, *, **) like a + b, a + b * c or (a - b) / (a + b). You know the last one, right? That's the formula of the famous NDVI.

So, if you can use the overloaded operators with an object class, you can use that class with spyndex!

BE CAREFUL! Not all overloaded operators work as mathematical operators. In a list object class, the addition operator (+) concatenates two objects instead of performing an addition operation! So you must convert the list into a numpy.ndarray before using spyndex!

Here is a little list of object classes that support mathematical overloaded operators:

And wait, there is more! If objects that support overloaded operatores can be used in spyndex, that means that you can work in parallel with dask!

Here is the list of the dask objects that you can use with spyndex:

  • dask.Array (with dask)
  • dask.Series (with dask)

This means that you can actually use spyndex in a lot of processes! For example, you can download a Sentinel-2 image with sentinelsat, open and read it with rasterio and then compute the desired spectral indices with spyndex. Or you can search through the Landsat-8 STAC in the Planetary Computer ecosystem using pystac-client, convert it to an xarray.DataArray with stackstac and then compute spectral indices using spyndex in parallel with dask! Amazing, right!?

Installation

Install the latest version from PyPI:

pip install spyndex

Upgrade spyndex by running:

pip install -U spyndex

Install the latest version from conda-forge:

conda install -c conda-forge spyndex

Install the latest dev version from GitHub by running:

pip install git+https://github.com/davemlz/spyndex

Features

Exploring Spectral Indices

Spectral Indices from the Awesome Spectral Indices list can be accessed through spyndex.indices. This is a Box object where each one of the indices in the list can be accessed as well as their attributes:

```python import spyndex

All indices

spyndex.indices

NDVI index

spyndex.indices["NDVI"]

Or with dot notation

spyndex.indices.NDVI

Formula of the NDVI

spyndex.indices["NDVI"]["formula"]

Or with dot notation

spyndex.indices.NDVI.formula

Reference of the NDVI

spyndex.indices["NDVI"]["reference"]

Or with dot notation

spyndex.indices.NDVI.reference ```

Default Values

Some Spectral Indices require constant values in order to be computed. Default values can be accessed through spyndex.constants. This is a Box object where each one of the constants can be accessed:

```python import spyndex

All constants

spyndex.constants

Canopy Background Adjustment

spyndex.constants["L"]

Or with dot notation

spyndex.constants.L

Default value

spyndex.constants["L"]["default"]

Or with dot notation

spyndex.constants.L.default ```

Band Parameters

The standard band parameters description can be accessed through spyndex.bands. This is a Box object where each one of the bands can be accessed:

```python import spyndex

All bands

spyndex.bands

Blue band

spyndex.bands["B"]

Or with dot notation

spyndex.bands.B ```

One (or more) Spectral Indices Computation

Use the computeIndex() method to compute as many spectral indices as you want! The index parameter receives the spectral index or a list of spectral indices to compute, while the params parameter receives a dictionary with the required parameters for the spectral indices computation.

```python import spyndex import xarray as xr import matplotlib.pyplot as plt from rasterio import plot

Open a dataset (in this case a xarray.DataArray)

snt = spyndex.datasets.open("sentinel")

Scale the data (remember that the valid domain for reflectance is [0,1])

snt = snt / 10000

Compute the desired spectral indices

idx = spyndex.computeIndex( index = ["NDVI","GNDVI","SAVI"], params = { "N": snt.sel(band = "B08"), "R": snt.sel(band = "B04"), "G": snt.sel(band = "B03"), "L": 0.5 } )

Plot the indices (and the RGB image for comparison)

fig, ax = plt.subplots(2,2,figsize = (10,10)) plot.show(snt.sel(band = ["B04","B03","B02"]).data / 0.3,ax = ax[0,0],title = "RGB") plot.show(idx.sel(index = "NDVI").data,ax = ax[0,1],title = "NDVI") plot.show(idx.sel(index = "GNDVI").data,ax = ax[1,0],title = "GNDVI") plot.show(idx.sel(index = "SAVI").data,ax = ax[1,1],title = "SAVI") ```

sentinel spectral indices

Kernel Indices Computation

Use the computeKernel() method to compute the required kernel for kernel indices like the kNDVI! The kernel parameter receives the kernel to compute, while the params parameter receives a dictionary with the required parameters for the kernel computation (e.g., a, b and sigma for the RBF kernel).

```python import spyndex import xarray as xr import matplotlib.pyplot as plt from rasterio import plot

Open a dataset (in this case a xarray.DataArray)

snt = spyndex.datasets.open("sentinel")

Scale the data (remember that the valid domain for reflectance is [0,1])

snt = snt / 10000

Compute the kNDVI and the NDVI for comparison

idx = spyndex.computeIndex( index = ["NDVI","kNDVI"], params = { # Parameters required for NDVI "N": snt.sel(band = "B08"), "R": snt.sel(band = "B04"), # Parameters required for kNDVI "kNN" : 1.0, "kNR" : spyndex.computeKernel( kernel = "RBF", params = { "a": snt.sel(band = "B08"), "b": snt.sel(band = "B04"), "sigma": snt.sel(band = ["B08","B04"]).mean("band") }), } )

Plot the indices (and the RGB image for comparison)

fig, ax = plt.subplots(1,3,figsize = (15,15)) plot.show(snt.sel(band = ["B04","B03","B02"]).data / 0.3,ax = ax[0],title = "RGB") plot.show(idx.sel(index = "NDVI").data,ax = ax[1],title = "NDVI") plot.show(idx.sel(index = "kNDVI").data,ax = ax[2],title = "kNDVI") ```

sentinel kNDVI

A pandas.DataFrame? Sure!

No matter what kind of python object you're working with, it can be used with spyndex as long as it supports mathematical overloaded operators!

```python import spyndex import pandas as pd import seaborn as sns import matplotlib.pyplot as plt

Open a dataset (in this case a pandas.DataFrame)

df = spyndex.datasets.open("spectral")

Compute the desired spectral indices

idx = spyndex.computeIndex( index = ["NDVI","NDWI","NDBI"], params = { "N": df["SRB5"], "R": df["SRB4"], "G": df["SRB3"], "S1": df["SRB6"] } )

Add the land cover column to the result

idx["Land Cover"] = df["class"]

Create a color palette for plotting

colors = ["#E33F62","#3FDDE3","#4CBA4B"]

Plot a pairplot to check the indices behaviour

plt.figure(figsize = (15,15)) g = sns.PairGrid(idx,hue = "Land Cover",palette = sns.colorpalette(colors)) g.maplower(sns.scatterplot) g.mapupper(sns.kdeplot,fill = True,alpha = .5) g.mapdiag(sns.kdeplot,fill = True) g.add_legend() plt.show() ```

landsat spectral indices

Parallel Processing

Parallel processing is possible with spyndex and dask! You can use dask.array or dask.dataframe objects to compute spectral indices with spyndex! If you're using xarray, you can also define a chunk size and work in parallel!

```python import spyndex import numpy as np import dask.array as da

Define the array shape

array_shape = (10000,10000)

Define the chunk size

chunk_size = (1000,1000)

Create a dask.array object

daskarray = da.array([ da.random.normal(0.6,0.10,arrayshape,chunks = chunksize), da.random.normal(0.1,0.05,arrayshape,chunks = chunk_size) ])

"Compute" the desired spectral indices

idx = spyndex.computeIndex( index = ["NDVI","SAVI"], params = { "N": daskarray[0], "R": daskarray[1], "L": 0.5 } )

Since dask works in lazy mode,

you have to tell it that you want to compute the indices!

idx.compute() ```

Plotting Spectral Indices

All posible values of a spectral index can be visualized using spyndex.plot.heatmap()! This is a module that doesn't require data, just specify the index, the bands, and BOOM! Heatmap of all the possible values of the index!

```python import spyndex import matplotlib.pyplot as plt import seaborn as sns

Define subplots grid

fig, ax = plt.subplots(1,2,figsize = (20,8))

Plot the NDVI with the Red values on the x-axis and the NIR on the y-axis

ax[0].set_title("NDVI heatmap with default parameters") spyndex.plot.heatmap("NDVI","R","N",ax = ax[0])

Keywords arguments can be passed for sns.heatmap()

ax[1].set_title("NDVI heatmap with seaborn keywords arguments") spyndex.plot.heatmap("NDVI","R","N",annot = True,cmap = "Spectral",ax = ax[1])

plt.show() ```

heatmap

License

The project is licensed under the MIT license.

Contributing

Check the contributing page.

Owner

  • Name: Awesome Spectral Indices
  • Login: awesome-spectral-indices
  • Kind: organization

Awesome Spectral Indices Ecosystem Organization

Citation (CITATION.bib)

@article{montero2023standardized,
  title={A standardized catalogue of spectral indices to advance the use of remote sensing in Earth system research},
  author={Montero, David and Aybar, C{\'e}sar and Mahecha, Miguel D and Martinuzzi, Francesco and S{\"o}chting, Maximilian and Wieneke, Sebastian},
  journal={Scientific Data},
  volume={10},
  number={1},
  pages={197},
  year={2023},
  publisher={Nature Publishing Group UK London}
}

GitHub Events

Total
  • Issues event: 3
  • Watch event: 36
  • Issue comment event: 6
  • Push event: 8
  • Pull request review event: 1
  • Pull request event: 6
  • Fork event: 3
  • Create event: 1
Last Year
  • Issues event: 3
  • Watch event: 36
  • Issue comment event: 6
  • Push event: 8
  • Pull request review event: 1
  • Pull request event: 6
  • Fork event: 3
  • Create event: 1

Committers

Last synced: 9 months ago

All Time
  • Total Commits: 208
  • Total Committers: 4
  • Avg Commits per committer: 52.0
  • Development Distribution Score (DDS): 0.26
Past Year
  • Commits: 10
  • Committers: 3
  • Avg Commits per committer: 3.333
  • Development Distribution Score (DDS): 0.6
Top Committers
Name Email Commits
davemlz d****t@g****m 154
GitHub Action a****n@g****m 49
konstntokas k****s@b****e 4
MartinuzziFrancesco m****o@g****m 1
Committer Domains (Top 20 + Academic)

Issues and Pull Requests

Last synced: 6 months ago

All Time
  • Total issues: 23
  • Total pull requests: 6
  • Average time to close issues: about 2 months
  • Average time to close pull requests: 1 day
  • Total issue authors: 13
  • Total pull request authors: 4
  • Average comments per issue: 1.91
  • Average comments per pull request: 1.67
  • Merged pull requests: 4
  • Bot issues: 0
  • Bot pull requests: 0
Past Year
  • Issues: 0
  • Pull requests: 2
  • Average time to close issues: N/A
  • Average time to close pull requests: 4 days
  • Issue authors: 0
  • Pull request authors: 1
  • Average comments per issue: 0
  • Average comments per pull request: 0.5
  • Merged pull requests: 1
  • Bot issues: 0
  • Bot pull requests: 0
Top Authors
Issue Authors
  • davemlz (8)
  • remi-braun (3)
  • seuriously (1)
  • abreufilho (1)
  • cdgriffith (1)
  • Raziehgithub (1)
  • LaurentBerder (1)
  • szwiep (1)
  • julianblue (1)
  • Aca-Ali (1)
  • bastiencyr (1)
  • simonreise (1)
  • maawoo (1)
  • vsilva89 (1)
Pull Request Authors
  • konstntokas (4)
  • simonreise (3)
  • bastiencyr (1)
  • MartinuzziFrancesco (1)
Top Labels
Issue Labels
enhancement (12) bug (4) question (1)
Pull Request Labels

Packages

  • Total packages: 2
  • Total downloads:
    • pypi 4,248 last-month
  • Total dependent packages: 6
    (may contain duplicates)
  • Total dependent repositories: 8
    (may contain duplicates)
  • Total versions: 20
  • Total maintainers: 1
pypi.org: spyndex

Awesome Spectral Indices in Python

  • Versions: 13
  • Dependent Packages: 5
  • Dependent Repositories: 6
  • Downloads: 4,248 Last month
Rankings
Dependent packages count: 2.1%
Stargazers count: 5.9%
Average: 5.9%
Dependent repos count: 6.1%
Downloads: 6.4%
Forks count: 9.1%
Maintainers (1)
Last synced: 6 months ago
conda-forge.org: spyndex
  • Versions: 7
  • Dependent Packages: 1
  • Dependent Repositories: 2
Rankings
Dependent repos count: 20.3%
Dependent packages count: 29.0%
Average: 31.0%
Stargazers count: 32.0%
Forks count: 42.7%
Last synced: 6 months ago

Dependencies

docs/docs-requirements.txt pypi
  • google-auth <2.0dev
  • ipython *
  • nbsphinx *
  • protobuf <3.18.0,>=3.12.0
  • pydata-sphinx-theme *
  • recommonmark *
  • sphinx >=1.4,
  • sphinx-copybutton *
  • sphinx-material *
  • sphinxcontrib-autoprogram *
requirements.txt pypi
  • dask *
  • earthengine-api *
  • eemont *
  • matplotlib *
  • numpy *
  • pandas *
  • python-box *
  • requests *
  • seaborn *
  • xarray *
setup.py pypi
  • dask >=2021.9.1
  • earthengine-api *
  • eemont >=0.2.5
  • matplotlib *
  • numpy *
  • pandas *
  • python-box *
  • requests *
  • seaborn *
  • xarray *
.github/workflows/tests.yml actions
  • actions/checkout v2 composite
  • actions/setup-python v2 composite
.github/workflows/update_awesome_spectral_indices.yml actions
  • actions/checkout v2 composite
  • actions/setup-python v2 composite
  • ad-m/github-push-action v0.6.0 composite