diff --git a/docs/spectral_index.md b/docs/spectral_index.md index 726dde35a..d4814c868 100644 --- a/docs/spectral_index.md +++ b/docs/spectral_index.md @@ -201,21 +201,45 @@ Index range: -1, 1 Calculates the Green Difference Vegetation Index using reflectance values ([Sripada et al., 2006](#references)): ``` -GDVI = (NIR - GREEN) / (NIR + GREEN) +GDVI = (NIR - GREEN) ``` Here, we use ~R800 for NIR and ~R550 for GREEN: ``` -GDVI = (R800 - R550) / (R800 + R550) +GDVI = (R800 - R550) ``` -Index range: -2.0, 2.0 +Index range: -1.0, 1.0 **plantcv.spectral_index.gdvi**(*hsi, distance=20*) **returns** calculated index array (instance of the `Spectral_data` class) +- **Parameters:** + - hsi - Hyperspectral image object, an instance of the `Spectral_data` class in plantcv (read in using [pcv.readimage](read_image.md) with `mode='envi'`) + - distance - Amount of flexibility (in nanometers) regarding the bands used to calculate an index. + +### GNDVI + +Calculates the Green Normalized Difference Vegetation Index using reflectance values ([Gitelson et al., 1996](#references)): + +``` +GNDVI = (NIR - GREEN) / (NIR + GREEN) +``` + +Here, we use ~R800 for NIR and ~R550 for GREEN: + +``` +GNDVI = (R800 - R550) / (R800 + R550) +``` + +Index range: -1.0, 1.0 + +**plantcv.spectral_index.gndvi**(*hsi, distance=20*) + +**returns** calculated index array (instance of the `Spectral_data` class) + - **Parameters:** - hsi - Hyperspectral image object, an instance of the `Spectral_data` class in plantcv (read in using [pcv.readimage](read_image.md) with `mode='envi'`) - distance - Amount of flexibility (in nanometers) regarding the bands used to calculate an index. @@ -721,6 +745,9 @@ ndvi_array = pcv.spectral_index.ndvi(hsi=spectral_data, distance=20) # Extract GDVI index from the datacube gdvi_array = pcv.spectral_index.gdvi(hsi=spectral_data, distance=20) +# Extract GNDVI index from the datacube +gndvi_array = pcv.spectral_index.gndvi(hsi=spectral_data, distance=20) + # Extract SAVI index from the datacube savi_array = pcv.spectral_index.savi(hsi=spectral_data, distance=20) @@ -859,6 +886,8 @@ DOI: [10.1080/0143116042000274015](https://doi.org/10.1080/0143116042000274015). Gamon JA, Surfus JS. 1999. Assessing leaf pigment content and activity with a reflectometer. The New Phytologist 143:105–117. DOI: [10.1046/j.1469-8137.1999.00424.x](https://doi.org/10.1046/j.1469-8137.1999.00424.x). +Gitelson AA, Kaufman YJ, & Merzlyak MN. (1996). Use of a green channel in remote sensing of global vegetation from EOS-MODIS. Remote sensing of Environment, 58(3), 289-298. DOI: [10.1016/S0034-4257(96)00072-7](https://doi.org/10.1016/S0034-4257(96)00072-7) + Gitelson AA, Zur Y, Chivkunova OB, Merzlyak MN. 2002. Assessing carotenoid content in plant leaves with reflectance spectroscopy. Photochemistry and Photobiology 75:272–281. DOI: [10.1562/0031-8655(2002)0750272ACCIPL2.0.CO2](https://doi.org/10.1562/0031-8655(2002)0750272ACCIPL2.0.CO2). diff --git a/docs/updating.md b/docs/updating.md index 2821645ca..c01bb1426 100644 --- a/docs/updating.md +++ b/docs/updating.md @@ -1239,6 +1239,10 @@ pages for more details on the input and output variable types. * post v3.8: array = **plantcv.spectral_index.gdvi**(*hsi, distance=20*) +#### plantcv.spectral_index.gndvi + +* post v5.0: array = **plantcv.spectral_index.gndvi**(*hsi, distance=20*) + #### plantcv.spectral_index.gli * post v4.4: array = **plantcv.spectral_index.gli**(*img, distance=20*) diff --git a/plantcv/plantcv/spectral_index/__init__.py b/plantcv/plantcv/spectral_index/__init__.py index bc5469ab4..fc0e256ca 100644 --- a/plantcv/plantcv/spectral_index/__init__.py +++ b/plantcv/plantcv/spectral_index/__init__.py @@ -1,5 +1,6 @@ from plantcv.plantcv.spectral_index.spectral_index import ndvi from plantcv.plantcv.spectral_index.spectral_index import gdvi +from plantcv.plantcv.spectral_index.spectral_index import gndvi from plantcv.plantcv.spectral_index.spectral_index import savi from plantcv.plantcv.spectral_index.spectral_index import pri from plantcv.plantcv.spectral_index.spectral_index import ari @@ -35,6 +36,8 @@ # add new functions to end of lists -__all__ = ["ndvi", "gdvi", "savi", "pri", "ari", "ci_rededge", "cri550", "cri700", "egi", "evi", "gli", "sci", "bgr", "bgi", - "mari", "mcari", "mtci", "ndre", "npci", "psnd_chla", "psnd_chlb", "psnd_car", "psri", "pssr_chla", "pssr_chlb", - "pssr_car", "rgri", "rvsi", "sipi", "sr", "vari", "vi_green", "wi", "ndci"] +__all__ = ["ndvi", "gdvi", "gndvi", "savi", "pri", "ari", "ci_rededge", "cri550", + "cri700", "egi", "evi", "gli", "sci", "bgr", "bgi", "mari", "mcari", + "mtci", "ndre", "npci", "psnd_chla", "psnd_chlb", "psnd_car", "psri", + "pssr_chla", "pssr_chlb", "pssr_car", "rgri", "rvsi", "sipi", "sr", "vari", + "vi_green", "wi", "ndci"] diff --git a/plantcv/plantcv/spectral_index/spectral_index.py b/plantcv/plantcv/spectral_index/spectral_index.py index e969e72d4..e0fcd72d2 100644 --- a/plantcv/plantcv/spectral_index/spectral_index.py +++ b/plantcv/plantcv/spectral_index/spectral_index.py @@ -73,6 +73,36 @@ def gdvi(hsi, distance=20): return None +def gndvi(hsi, distance=20): + """Green Normalized Difference Vegetation Index. + + GNDVI = (R800 - R550) / (R800 + R550) + + The theoretical range for GNDVI is [-1.0, 1.0]. + + Inputs: + hsi = hyperspectral image (PlantCV Spectral_data instance) + distance = how lenient to be if the required wavelengths are not available + + Returns: + index_array = Index data as a Spectral_data instance + + :param hsi: __main__.Spectral_data + :param distance: int + :return index_array: __main__.Spectral_data + """ + if (float(hsi.max_wavelength) + distance) >= 800 and (float(hsi.min_wavelength) - distance) <= 550: + r800_index = _find_closest(np.array([float(i) for i in hsi.wavelength_dict.keys()]), 800) + r550_index = _find_closest(np.array([float(i) for i in hsi.wavelength_dict.keys()]), 550) + r800 = (hsi.array_data[:, :, r800_index]) + r550 = (hsi.array_data[:, :, r550_index]) + # Naturally ranges from -1 to 1 + index_array_raw = (r800 - r550) / (r800 + r550) + return _package_index(hsi=hsi, raw_index=index_array_raw, method="GNDVI") + warn("Available wavelengths are not suitable for calculating GNDVI. Try increasing distance.") + return None + + def savi(hsi, distance=20): """Soil Adjusted Vegetation Index. diff --git a/tests/plantcv/spectral_index/test_spectral_index.py b/tests/plantcv/spectral_index/test_spectral_index.py index 6089a8fa7..c04c50011 100644 --- a/tests/plantcv/spectral_index/test_spectral_index.py +++ b/tests/plantcv/spectral_index/test_spectral_index.py @@ -27,6 +27,18 @@ def test_gdvi_bad_input(spectral_index_test_data): assert spectral_index.gdvi(hsi=index_array, distance=20) is None +def test_gndvi(spectral_index_test_data): + """Test for PlantCV.""" + index_array = spectral_index.gndvi(spectral_index_test_data.load_hsi(), distance=20) + assert np.shape(index_array.array_data) == (1, 1600) and np.nanmax(index_array.pseudo_rgb) == 255 + + +def test_gndvi_bad_input(spectral_index_test_data): + """Test for PlantCV.""" + index_array = spectral_index.gndvi(spectral_index_test_data.load_hsi(), distance=20) + assert spectral_index.gndvi(hsi=index_array, distance=20) is None + + def test_savi(spectral_index_test_data): """Test for PlantCV.""" index_array = spectral_index.savi(spectral_index_test_data.load_hsi(), distance=20)