Source code for eolearn.features.ndi

"""
A collection of bands extraction EOTasks

Copyright (c) 2017- Sinergise and contributors
For the full list of contributors, see the CREDITS file in the root directory of this source tree.

This source code is licensed under the MIT license, see the LICENSE file in the root directory of this source tree.
"""

from __future__ import annotations

import numpy as np

from eolearn.core import MapFeatureTask
from eolearn.core.types import Feature


[docs]class NormalizedDifferenceIndexTask(MapFeatureTask): """The task calculates a Normalized Difference Index (NDI) between two bands A and B as: :math:`NDI = \\dfrac{A-B+c}{A+B+c}`, where c is provided as the *acorvi_constant* argument. For the reasoning behind using the acorvi_constant in the equation, check the article `Using NDVI with atmospherically corrected data <http://www.cesbio.ups-tlse.fr/multitemp/?p=12746>`_. """ def __init__( self, input_feature: Feature, output_feature: Feature, bands: tuple[int, int], acorvi_constant: float = 0, undefined_value: float = np.nan, ): """ :param input_feature: A source feature from which to take the bands. :param output_feature: An output feature to which to write the NDI. :param bands: A list of bands from which to calculate the NDI. :param acorvi_constant: A constant to be used in the NDI calculation. It is set to 0 by default. :param undefined_value: A value to override any calculation result that is not a finite value (e.g.: inf, nan). """ super().__init__(input_feature, output_feature) if not isinstance(bands, (list, tuple)) or len(bands) != 2 or not all(isinstance(x, int) for x in bands): raise ValueError("bands argument should be a list or tuple of two integers!") self.band_a, self.band_b = bands self.undefined_value = undefined_value self.acorvi_constant = acorvi_constant
[docs] def map_method(self, feature: np.ndarray) -> np.ndarray: """ :param feature: An eopatch on which to calculate the NDI. """ band_a, band_b = feature[..., self.band_a], feature[..., self.band_b] with np.errstate(divide="ignore", invalid="ignore"): ndi = (band_a - band_b + self.acorvi_constant) / (band_a + band_b + self.acorvi_constant) ndi[~np.isfinite(ndi)] = self.undefined_value return ndi[..., np.newaxis]