コード例 #1
0
ファイル: spectral_index.py プロジェクト: sapuppogit/plantcv
def gdvi(hsi, distance=20):
    """Green Difference Vegetation Index.

    GDVI = R800 - R550

    The theoretical range for GDVI 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
        return _package_index(hsi=hsi, raw_index=index_array_raw, method="GDVI")
    else:
        fatal_error("Available wavelengths are not suitable for calculating GDVI. Try increasing distance.")
コード例 #2
0
ファイル: spectral_index.py プロジェクト: sapuppogit/plantcv
def wi(hsi, distance=20):
    """Water Index.

    WI = R900 / R970

    The theoretical range for WI is [0.0, Inf).

    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) >= 970 and (float(hsi.min_wavelength) - distance) <= 900:
        r900_index = _find_closest(np.array([float(i) for i in hsi.wavelength_dict.keys()]), 900)
        r970_index = _find_closest(np.array([float(i) for i in hsi.wavelength_dict.keys()]), 970)
        r900 = (hsi.array_data[:, :, r900_index])
        r970 = (hsi.array_data[:, :, r970_index])
        # Naturally ranges from 0 to Inf
        index_array_raw = r900 / r970
        return _package_index(hsi=hsi, raw_index=index_array_raw, method="WI")
    else:
        fatal_error("Available wavelengths are not suitable for calculating WBI. Try increasing distance.")
コード例 #3
0
ファイル: spectral_index.py プロジェクト: sapuppogit/plantcv
def rvsi(hsi, distance=20):
    """Red-Edge Vegetation Stress Index.

    RVSI = ((R714 + R752) / 2) - R733

    The theoretical range for RVSI 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) >= 752 and (float(hsi.min_wavelength) - distance) <= 714:
        r714_index = _find_closest(np.array([float(i) for i in hsi.wavelength_dict.keys()]), 714)
        r733_index = _find_closest(np.array([float(i) for i in hsi.wavelength_dict.keys()]), 733)
        r752_index = _find_closest(np.array([float(i) for i in hsi.wavelength_dict.keys()]), 752)
        r714 = (hsi.array_data[:, :, r714_index])
        r733 = (hsi.array_data[:, :, r733_index])
        r752 = (hsi.array_data[:, :, r752_index])
        # Naturally ranges from -1 to 1
        index_array_raw = ((r714 + r752) / 2) - r733
        return _package_index(hsi=hsi, raw_index=index_array_raw, method="RVSI")
    else:
        fatal_error("Available wavelengths are not suitable for calculating RVSI. Try increasing distance.")
コード例 #4
0
ファイル: spectral_index.py プロジェクト: sapuppogit/plantcv
def pssr_chlb(hsi, distance=20):
    """Pigment Specific Simple Ratio for Chlorophyll b.

    PSSR_CHLB = R800 / R635

    The theoretical range for PSSR_CHLB is [0.0, Inf).

    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) <= 635:
        r800_index = _find_closest(np.array([float(i) for i in hsi.wavelength_dict.keys()]), 800)
        r635_index = _find_closest(np.array([float(i) for i in hsi.wavelength_dict.keys()]), 635)
        r800 = (hsi.array_data[:, :, r800_index])
        r635 = (hsi.array_data[:, :, r635_index])
        # Naturally ranges from 0 to inf
        index_array_raw = r800 / r635
        return _package_index(hsi=hsi, raw_index=index_array_raw, method="PSSR_CHLB")
    else:
        fatal_error("Available wavelengths are not suitable for calculating PSSR_CHLB. Try increasing distance.")
コード例 #5
0
ファイル: spectral_index.py プロジェクト: sapuppogit/plantcv
def rgri(hsi, distance=20):
    """Red/green ratio index (Gamon and Surfus, 1999)
    The theoretical range for RGRI is [0.0, Inf).

    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) >= 670 and (float(hsi.min_wavelength) - distance) <= 560:
        r670_index = _find_closest(np.array([float(i) for i in hsi.wavelength_dict.keys()]), 670)
        r560_index = _find_closest(np.array([float(i) for i in hsi.wavelength_dict.keys()]), 560)
        r670 = (hsi.array_data[:, :, r670_index])
        r560 = (hsi.array_data[:, :, r560_index])
        # Naturally ranges from 0 to inf
        index_array_raw = r670 / r560
        return _package_index(hsi=hsi, raw_index=index_array_raw, method="RGRI")
    else:
        fatal_error("Available wavelengths are not suitable for calculating RGRI. Try increasing distance.")
コード例 #6
0
ファイル: spectral_index.py プロジェクト: sapuppogit/plantcv
def pri(hsi, distance=20):
    """Photochemical Reflectance Index.

    PRI = (R531 - R570) / (R531 + R570)

    The theoretical range for PRI 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) >= 570 and (float(hsi.min_wavelength) - distance) <= 531:
        # Obtain index that best approximates 570 and 531 nm bands
        r570_index = _find_closest(np.array([float(i) for i in hsi.wavelength_dict.keys()]), 570)
        r531_index = _find_closest(np.array([float(i) for i in hsi.wavelength_dict.keys()]), 531)
        r570 = (hsi.array_data[:, :, r570_index])
        r531 = (hsi.array_data[:, :, r531_index])
        index_array_raw = (r531 - r570) / (r531 + r570)
        return _package_index(hsi=hsi, raw_index=index_array_raw, method="PRI")
    else:
        fatal_error("Available wavelengths are not suitable for calculating PRI. Try increasing distance.")
コード例 #7
0
ファイル: spectral_index.py プロジェクト: sapuppogit/plantcv
def psri(hsi, distance=20):
    """Plant Senescence Reflectance Index.

    PSRI = (R678 - R500) / R750

    The theoretical range for PSRI is (-Inf, Inf).

    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) >= 750 and (float(hsi.min_wavelength) - distance) <= 500:
        r500_index = _find_closest(np.array([float(i) for i in hsi.wavelength_dict.keys()]), 500)
        r678_index = _find_closest(np.array([float(i) for i in hsi.wavelength_dict.keys()]), 678)
        r750_index = _find_closest(np.array([float(i) for i in hsi.wavelength_dict.keys()]), 750)
        r500 = (hsi.array_data[:, :, r500_index])
        r678 = (hsi.array_data[:, :, r678_index])
        r750 = (hsi.array_data[:, :, r750_index])
        # Naturally ranges from -inf to inf
        index_array_raw = (r678 - r500) / r750
        return _package_index(hsi=hsi, raw_index=index_array_raw, method="PSRI")
    else:
        fatal_error("Available wavelengths are not suitable for calculating PSRI. Try increasing distance.")
コード例 #8
0
ファイル: spectral_index.py プロジェクト: sapuppogit/plantcv
def sr(hsi, distance=20):
    """Simple Ratio.

    SR = R800 / R670

    The theoretical range for SR is [0.0, Inf).

    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) <= 670:
        r670_index = _find_closest(np.array([float(i) for i in hsi.wavelength_dict.keys()]), 670)
        r800_index = _find_closest(np.array([float(i) for i in hsi.wavelength_dict.keys()]), 800)
        r670 = (hsi.array_data[:, :, r670_index])
        r800 = (hsi.array_data[:, :, r800_index])
        # Naturally ranges from 0 to inf
        index_array_raw = r800 / r670
        return _package_index(hsi=hsi, raw_index=index_array_raw, method="SR")
    else:
        fatal_error("Available wavelengths are not suitable for calculating SR. Try increasing distance.")
コード例 #9
0
ファイル: spectral_index.py プロジェクト: sapuppogit/plantcv
def vi_green(hsi, distance=20):
    """Vegetation Index using green bands.

    VIgreen = (R550 - R670) / (R550 + R670)

    The theoretical range for VI_GREEN 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) >= 670 and (float(hsi.min_wavelength) - distance) <= 550:
        r670_index = _find_closest(np.array([float(i) for i in hsi.wavelength_dict.keys()]), 670)
        r550_index = _find_closest(np.array([float(i) for i in hsi.wavelength_dict.keys()]), 550)
        r670 = (hsi.array_data[:, :, r670_index])
        r550 = (hsi.array_data[:, :, r550_index])
        # Naturally ranges from -1 to 1
        index_array_raw = (r550 - r670) / (r550 + r670)
        return _package_index(hsi=hsi, raw_index=index_array_raw, method="VI_GREEN")
    else:
        fatal_error("Available wavelengths are not suitable for calculating VI_GREEN. Try increasing distance.")
コード例 #10
0
ファイル: spectral_index.py プロジェクト: sapuppogit/plantcv
def mcari(hsi, distance=20):
    """Modified Chlorophyll Absorption in Reflectance Index.

    MCARI = ((R700 - R670) - 0.2 * (R700 - R550)) * (R700 / R670)

    The theoretical range for MCARI is (-Inf, Inf).

    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) >= 700 and (float(hsi.min_wavelength) - distance) <= 550:
        r550_index = _find_closest(np.array([float(i) for i in hsi.wavelength_dict.keys()]), 550)
        r670_index = _find_closest(np.array([float(i) for i in hsi.wavelength_dict.keys()]), 670)
        r700_index = _find_closest(np.array([float(i) for i in hsi.wavelength_dict.keys()]), 700)
        r550 = (hsi.array_data[:, :, r550_index])
        r670 = (hsi.array_data[:, :, r670_index])
        r700 = (hsi.array_data[:, :, r700_index])
        # Naturally ranges from -inf to inf
        index_array_raw = ((r700 - r670) - 0.2 * (r700 - r550)) * (r700 / r670)
        return _package_index(hsi=hsi, raw_index=index_array_raw, method="MCARI")
    else:
        fatal_error("Available wavelengths are not suitable for calculating MCARI. Try increasing distance.")
コード例 #11
0
ファイル: spectral_index.py プロジェクト: sapuppogit/plantcv
def mtci(hsi, distance=20):
    """MERIS Terrestrial Chlorophyll Index.

    MTCI = (R753.75 - R708.75) / (R708.75 - R681.25)

    The theoretical range for MTCI is (-Inf, Inf).

    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) >= 753.75 and (float(hsi.min_wavelength) - distance) <= 681.25:
        r681_index = _find_closest(np.array([float(i) for i in hsi.wavelength_dict.keys()]), 681.25)
        r708_index = _find_closest(np.array([float(i) for i in hsi.wavelength_dict.keys()]), 708.75)
        r753_index = _find_closest(np.array([float(i) for i in hsi.wavelength_dict.keys()]), 753.75)
        r681 = (hsi.array_data[:, :, r681_index])
        r708 = (hsi.array_data[:, :, r708_index])
        r753 = (hsi.array_data[:, :, r753_index])
        # Naturally ranges from -inf to inf
        index_array_raw = (r753 - r708) / (r708 - r681)
        return _package_index(hsi=hsi, raw_index=index_array_raw, method="MTCI")
    else:
        fatal_error("Available wavelengths are not suitable for calculating MTCI. Try increasing distance.")
コード例 #12
0
ファイル: spectral_index.py プロジェクト: sapuppogit/plantcv
def cri700(hsi, distance=20):
    """Carotenoid Reflectance Index 700.

    CRI700 = (1 / R510) - (1 / R700)

    The theoretical range for CRI700 is (-Inf, Inf).

    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) >= 700 and (float(hsi.min_wavelength) - distance) <= 510:
        r510_index = _find_closest(np.array([float(i) for i in hsi.wavelength_dict.keys()]), 510)
        r700_index = _find_closest(np.array([float(i) for i in hsi.wavelength_dict.keys()]), 700)
        r510 = (hsi.array_data[:, :, r510_index])
        r700 = (hsi.array_data[:, :, r700_index])
        # Naturally ranges from -inf to inf
        index_array_raw = (1 / r510) - (1 / r700)
        return _package_index(hsi=hsi, raw_index=index_array_raw, method="CRI700")
    else:
        fatal_error("Available wavelengths are not suitable for calculating CRI700. Try increasing distance.")
コード例 #13
0
ファイル: spectral_index.py プロジェクト: sapuppogit/plantcv
def evi(hsi, distance=20):
    """Enhanced Vegetation index.

    EVI = (2.5 * (R800 - R670)) / (1 + R800 + (6 * R670) - (7.5 * R480))

    The theoretical range for EVI is (-Inf, Inf).

    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) <= 480:
        r480_index = _find_closest(np.array([float(i) for i in hsi.wavelength_dict.keys()]), 480)
        r670_index = _find_closest(np.array([float(i) for i in hsi.wavelength_dict.keys()]), 670)
        r800_index = _find_closest(np.array([float(i) for i in hsi.wavelength_dict.keys()]), 800)
        r480 = (hsi.array_data[:, :, r480_index])
        r670 = (hsi.array_data[:, :, r670_index])
        r800 = (hsi.array_data[:, :, r800_index])
        # Naturally ranges from -inf to inf
        index_array_raw = (2.5 * (r800 - r670)) / (1 + r800 + (6 * r670) - (7.5 * r480))
        return _package_index(hsi=hsi, raw_index=index_array_raw, method="EVI")
    else:
        fatal_error("Available wavelengths are not suitable for calculating EVI. Try increasing distance.")
コード例 #14
0
ファイル: spectral_index.py プロジェクト: sapuppogit/plantcv
def ci_rededge(hsi, distance=20):
    """Chlorophyll Index Red Edge.

    CI_REDEDGE = (R800 / R700) - 1

    The theoretical range for CI_REDEDGE is [-1.0, Inf).

    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) <= 700:
        r700_index = _find_closest(np.array([float(i) for i in hsi.wavelength_dict.keys()]), 700)
        r800_index = _find_closest(np.array([float(i) for i in hsi.wavelength_dict.keys()]), 800)
        r700 = (hsi.array_data[:, :, r700_index])
        r800 = (hsi.array_data[:, :, r800_index])
        # Naturally ranges from -1 to inf
        index_array_raw = (r800 / r700) - 1
        return _package_index(hsi=hsi, raw_index=index_array_raw, method="CI_REDEDGE")
    else:
        fatal_error("Available wavelengths are not suitable for calculating CI_REDEDGE. Try increasing distance.")
コード例 #15
0
ファイル: spectral_index.py プロジェクト: sapuppogit/plantcv
def ari(hsi, distance=20):
    """Anthocyanin Reflectance Index.

    ARI = (1 / R550) - (1 / R700)

    The theoretical range for ARI is (-Inf, Inf).

    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) >= 700 and (float(hsi.min_wavelength) - distance) <= 550:
        r550_index = _find_closest(np.array([float(i) for i in hsi.wavelength_dict.keys()]), 550)
        r700_index = _find_closest(np.array([float(i) for i in hsi.wavelength_dict.keys()]), 700)
        r550 = (hsi.array_data[:, :, r550_index])
        r700 = (hsi.array_data[:, :, r700_index])
        index_array_raw = (1 / r550) - (1 / r700)
        return _package_index(hsi=hsi, raw_index=index_array_raw, method="ARI")
    else:
        fatal_error("Available wavelengths are not suitable for calculating ARI. Try increasing distance.")
コード例 #16
0
ファイル: spectral_index.py プロジェクト: sapuppogit/plantcv
def ndvi(hsi, distance=20):
    """Normalized Difference Vegetation Index.

    NDVI = (R800 - R670) / (R800 + R670)

    The theoretical range for NDVI 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) <= 670:
        # Obtain index that best represents NIR and red bands
        r800_index = _find_closest(np.array([float(i) for i in hsi.wavelength_dict.keys()]), 800)
        r670_index = _find_closest(np.array([float(i) for i in hsi.wavelength_dict.keys()]), 670)
        r800 = (hsi.array_data[:, :, r800_index])
        r670 = (hsi.array_data[:, :, r670_index])
        # Naturally ranges from -1 to 1
        index_array_raw = (r800 - r670) / (r800 + r670)
        return _package_index(hsi=hsi, raw_index=index_array_raw, method="NDVI")
    else:
        fatal_error("Available wavelengths are not suitable for calculating NDVI. Try increasing distance.")
コード例 #17
0
ファイル: spectral_index.py プロジェクト: sapuppogit/plantcv
def sipi(hsi, distance=20):
    """Structure-Independent Pigment Index.

    SIPI = (R800 - R670) / (R800 - R480)

    The theoretical range for SIPI is (-Inf, Inf).

    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) <= 480:
        r480_index = _find_closest(np.array([float(i) for i in hsi.wavelength_dict.keys()]), 480)
        r670_index = _find_closest(np.array([float(i) for i in hsi.wavelength_dict.keys()]), 670)
        r800_index = _find_closest(np.array([float(i) for i in hsi.wavelength_dict.keys()]), 800)
        r445 = (hsi.array_data[:, :, r480_index])
        r670 = (hsi.array_data[:, :, r670_index])
        r800 = (hsi.array_data[:, :, r800_index])
        # Naturally ranges from -inf to inf
        index_array_raw = (r800 - r670) / (r800 - r445)
        return _package_index(hsi=hsi, raw_index=index_array_raw, method="SIPI")
    else:
        fatal_error("Available wavelengths are not suitable for calculating SIPI. Try increasing distance.")
コード例 #18
0
ファイル: spectral_index.py プロジェクト: sapuppogit/plantcv
def ndre(hsi, distance=20):
    """Normalized Difference Red Edge.

    NDRE = (R790 - R720) / (R790 + R720)

    The theoretical range for NDRE 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) >= 790 and (float(hsi.min_wavelength) - distance) <= 720:
        r720_index = _find_closest(np.array([float(i) for i in hsi.wavelength_dict.keys()]), 720)
        r790_index = _find_closest(np.array([float(i) for i in hsi.wavelength_dict.keys()]), 790)
        r790 = (hsi.array_data[:, :, r790_index])
        r720 = (hsi.array_data[:, :, r720_index])
        # Naturally ranges from -1 to 1
        index_array_raw = (r790 - r720) / (r790 + r720)
        return _package_index(hsi=hsi, raw_index=index_array_raw, method="NDRE")
    else:
        fatal_error("Available wavelengths are not suitable for calculating NDRE. Try increasing distance.")
コード例 #19
0
ファイル: spectral_index.py プロジェクト: sapuppogit/plantcv
def savi(hsi, distance=20):
    """Soil Adjusted Vegetation Index.

    SAVI = (1.5 * (R800 - R680)) / (R800 + R680 + 0.5)

    The theoretical range for SAVI is [-1.2, 1.2].

    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) <= 680:
        r800_index = _find_closest(np.array([float(i) for i in hsi.wavelength_dict.keys()]), 800)
        r680_index = _find_closest(np.array([float(i) for i in hsi.wavelength_dict.keys()]), 680)
        r800 = (hsi.array_data[:, :, r800_index])
        r680 = (hsi.array_data[:, :, r680_index])
        # Naturally ranges from -1.2 to 1.2
        index_array_raw = (1.5 * (r800 - r680)) / (r800 + r680 + 0.5)
        return _package_index(hsi=hsi, raw_index=index_array_raw, method="SAVI")
    else:
        fatal_error("Available wavelengths are not suitable for calculating SAVI. Try increasing distance.")
コード例 #20
0
ファイル: spectral_index.py プロジェクト: sapuppogit/plantcv
def vari(hsi, distance=20):
    """Visible Atmospherically Resistant Index.

    VARI = (R550 - R670) / (R550 + R670 - R480)

    The theoretical range for VARI is (-Inf, Inf).

    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) >= 670 and (float(hsi.min_wavelength) - distance) <= 480:
        r670_index = _find_closest(np.array([float(i) for i in hsi.wavelength_dict.keys()]), 670)
        r550_index = _find_closest(np.array([float(i) for i in hsi.wavelength_dict.keys()]), 550)
        r480_index = _find_closest(np.array([float(i) for i in hsi.wavelength_dict.keys()]), 480)
        r670 = (hsi.array_data[:, :, r670_index])
        r550 = (hsi.array_data[:, :, r550_index])
        r480 = (hsi.array_data[:, :, r480_index])
        # Naturally ranges from -inf to inf
        index_array_raw = (r550 - r670) / (r550 + r670 - r480)
        return _package_index(hsi=hsi, raw_index=index_array_raw, method="VARI")
    else:
        fatal_error("Available wavelengths are not suitable for calculating VARI. Try increasing distance.")
コード例 #21
0
ファイル: spectral_index.py プロジェクト: sapuppogit/plantcv
def psnd_car(hsi, distance=20):
    """Pigment Specific Normalized Difference for Caroteniods.

    PSND_CAR = (R800 - R470) / (R800 + R470)

    The theoretical range for PSND_CAR 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) <= 470:
        r470_index = _find_closest(np.array([float(i) for i in hsi.wavelength_dict.keys()]), 470)
        r800_index = _find_closest(np.array([float(i) for i in hsi.wavelength_dict.keys()]), 800)
        r470 = (hsi.array_data[:, :, r470_index])
        r800 = (hsi.array_data[:, :, r800_index])
        # Naturally ranges from -1 to 1
        index_array_raw = (r800 - r470) / (r800 + r470)
        return _package_index(hsi=hsi, raw_index=index_array_raw, method="PSND_CAR")
    else:
        fatal_error("Available wavelengths are not suitable for calculating PSND_CAR. Try increasing distance.")
コード例 #22
0
def extract_index(array, index="NDVI", distance=20):
    """Pull out indices of interest from a hyperspectral datacube.

        Inputs:
        array = hyperspectral data instance
        index = index of interest, either "ndvi", "gdvi", or "savi"
        distance = how lenient to be if the required wavelengths are not available

        Returns:
        index_array    = Index data as a Spectral_data instance

        :param array: __main__.Spectral_data
        :param index: str
        :param distance: int
        :return index_array: __main__.Spectral_data
        """
    params.device += 1

    # Min and max available wavelength will be used to determine if an index can be extracted
    max_wavelength = float(array.max_wavelength)
    min_wavelength = float(array.min_wavelength)

    # Dictionary of wavelength and it's index in the list
    wavelength_dict = array.wavelength_dict.copy()
    array_data = array.array_data.copy()

    if index.upper() == "NDVI":
        if (max_wavelength + distance) >= 800 and (min_wavelength - distance) <= 670:
            # Obtain index that best represents NIR and red bands
            nir_index = _find_closest(np.array([float(i) for i in wavelength_dict.keys()]), 800)
            red_index = _find_closest(np.array([float(i) for i in wavelength_dict.keys()]), 670)
            nir = (array_data[:, :, [nir_index]])
            red = (array_data[:, :, [red_index]])
            # Naturally ranges from -1 to 1
            index_array_raw = (nir - red) / (nir + red)
        else:
            fatal_error("Available wavelengths are not suitable for calculating NDVI. Try increasing distance.")

    elif index.upper() == "GDVI":
        # Green Difference Vegetation Index [Sripada et al. (2006)]
        if (max_wavelength + distance) >= 800 and (min_wavelength - distance) <= 680:
            nir_index = _find_closest(np.array([float(i) for i in wavelength_dict.keys()]), 800)
            red_index = _find_closest(np.array([float(i) for i in wavelength_dict.keys()]), 680)
            nir = (array_data[:, :, [nir_index]])
            red = (array_data[:, :, [red_index]])
            # Naturally ranges from -2 to 2
            index_array_raw = nir - red
        else:
            fatal_error("Available wavelengths are not suitable for calculating GDVI. Try increasing distance.")

    elif index.upper() == "SAVI":
        # Soil Adjusted Vegetation Index [Huete et al. (1988)]
        if (max_wavelength + distance) >= 800 and (min_wavelength - distance) <= 680:
            nir_index = _find_closest(np.array([float(i) for i in wavelength_dict.keys()]), 800)
            red_index = _find_closest(np.array([float(i) for i in wavelength_dict.keys()]), 680)
            nir = (array_data[:, :, [nir_index]])
            red = (array_data[:, :, [red_index]])
            # Naturally ranges from -1.2 to 1.2
            index_array_raw = (1.5 * (nir - red)) / (red + nir + 0.5)
        else:
            fatal_error("Available wavelengths are not suitable for calculating SAVI. Try increasing distance.")

    elif index.upper() == "PRI":
        #  Photochemical Reflectance Index (https://doi.org/10.1111/j.1469-8137.1995.tb03064.x)
        if (max_wavelength + distance) >= 570 and (min_wavelength - distance) <= 531:
            # Obtain index that best approximates 570 and 531 nm bands
            pri570_index = _find_closest(np.array([float(i) for i in wavelength_dict.keys()]), 570)
            pri531_index = _find_closest(np.array([float(i) for i in wavelength_dict.keys()]), 531)
            pri570 = (array_data[:, :, [pri570_index]])
            pri531 = (array_data[:, :, [pri531_index]])
            # PRI = (R531− R570)/(R531+ R570))
            denominator = pri531 + pri570
            # Avoid dividing by zero
            index_array_raw = np.where(denominator == 0, 0, ((pri531 - pri570) / denominator))
        else:
            fatal_error("Available wavelengths are not suitable for calculating PRI. Try increasing distance.")

    elif index.upper() == "ACI":
        #  Van den Berg et al. 2005
        if (max_wavelength + distance) >= 800 and (min_wavelength - distance) <= 560:
            green_index = _find_closest(np.array([float(i) for i in wavelength_dict.keys()]), 560)
            nir_index   = _find_closest(np.array([float(i) for i in wavelength_dict.keys()]), 800)
            green = (array_data[:, :, [green_index]])
            nir   = (array_data[:, :, [nir_index]])
            # Naturally ranges from -1.0 to 1.0
            index_array_raw = green/nir
        else:
            fatal_error("Available wavelengths are not suitable for calculating ACI. Try increasing distance.")
    
    elif index.upper() == "ARI":
        # Gitelson et al., 2001
        if (max_wavelength + distance) >= 700 and (min_wavelength - distance) <= 550:
            ari550_indes = _find_closest(np.array([float(i) for i in wavelength_dict.keys()]), 550)
            ari700_index   = _find_closest(np.array([float(i) for i in wavelength_dict.keys()]), 700)
            ari550 = (array_data[:, :, [ari550_indes]])
            ari700 = (array_data[:, :, [ari700_index]])
            index_array_raw = (1/ari550)-(1/ari700)
        else:
            fatal_error("Available wavelengths are not suitable for calculating ARI. Try increasing distance.")
    else:
        fatal_error(index + " is not one of the currently available indices for this function. Please open an issue " +
                    "on the PlantCV GitHub account so we can add more handy indicies!")

    # Reshape array into hyperspectral datacube shape
    index_array_raw = np.transpose(np.transpose(index_array_raw)[0])

    # Store debug mode
    debug = params.debug
    params.debug = None

    # Resulting array is float 32 from varying natural ranges, transform into uint8 for plotting
    all_positive = np.add(index_array_raw, 2 * np.ones(np.shape(index_array_raw)))
    scaled = rescale(all_positive)

    # Find array min and max values
    obs_max_pixel = float(np.nanmax(index_array_raw))
    obs_min_pixel = float(np.nanmin(index_array_raw))

    index_array = Spectral_data(array_data=index_array_raw, max_wavelength=0,
                                min_wavelength=0, max_value=obs_max_pixel, min_value=obs_min_pixel, d_type=np.uint8,
                                wavelength_dict={}, samples=array.samples,
                                lines=array.lines, interleave=array.interleave,
                                wavelength_units=array.wavelength_units, array_type="index_" + index.lower(),
                                pseudo_rgb=scaled, filename=array.filename, default_bands=None)

    # Restore debug mode
    params.debug = debug

    if params.debug == "plot":
        plot_image(index_array.pseudo_rgb)
    elif params.debug == "print":
        print_image(index_array.pseudo_rgb,
                    os.path.join(params.debug_outdir, str(params.device) + index + "_index.png"))

    return index_array
コード例 #23
0
def extract_index(array, index="NDVI", distance=20):
    """Pull out indices of interest from a hyperspectral datacube.

        Inputs:
        array = hyperspectral data instance
        index = index of interest, "ndvi", "gdvi", "savi", "pri", "aci", "ari", "cari", "ci_rededge", "cri1", "cri2", "evi",
        "mari", "mcari", "mtci", "ndre", "psnd_chla", "psnd_chlb", "psnd_car", "psri", "pssr1", "pssr2", "pssr3", "rgri", "rvsi", "sipi",
        "sr", "vari", "vi_green", "wbi".
        distance = how lenient to be if the required wavelengths are not available

        Returns:
        index_array    = Index data as a Spectral_data instance

        :param array: __main__.Spectral_data
        :param index: str
        :param distance: int
        :return index_array: __main__.Spectral_data
        """
    params.device += 1

    # Min and max available wavelength will be used to determine if an index can be extracted
    max_wavelength = float(array.max_wavelength)
    min_wavelength = float(array.min_wavelength)

    # Dictionary of wavelength and it's index in the list
    wavelength_dict = array.wavelength_dict
    array_data = array.array_data

    if index.upper() == "NDVI":
        if (max_wavelength + distance) >= 800 and (min_wavelength -
                                                   distance) <= 670:
            # Obtain index that best represents NIR and red bands
            nir_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 800)
            red_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 670)
            nir = (array_data[:, :, [nir_index]])
            red = (array_data[:, :, [red_index]])
            # Naturally ranges from -1 to 1
            index_array_raw = (nir - red) / (nir + red)
        else:
            fatal_error(
                "Available wavelengths are not suitable for calculating NDVI. Try increasing distance."
            )

    elif index.upper() == "GDVI":
        # Green Difference Vegetation Index [Sripada et al. (2006)]
        if (max_wavelength + distance) >= 800 and (min_wavelength -
                                                   distance) <= 680:
            nir_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 800)
            red_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 680)
            nir = (array_data[:, :, [nir_index]])
            red = (array_data[:, :, [red_index]])
            # Naturally ranges from -2 to 2
            index_array_raw = nir - red
        else:
            fatal_error(
                "Available wavelengths are not suitable for calculating GDVI. Try increasing distance."
            )

    elif index.upper() == "SAVI":
        # Soil Adjusted Vegetation Index [Huete et al. (1988)]
        if (max_wavelength + distance) >= 800 and (min_wavelength -
                                                   distance) <= 680:
            nir_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 800)
            red_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 680)
            nir = (array_data[:, :, [nir_index]])
            red = (array_data[:, :, [red_index]])
            # Naturally ranges from -1.2 to 1.2
            index_array_raw = (1.5 * (nir - red)) / (red + nir + 0.5)
        else:
            fatal_error(
                "Available wavelengths are not suitable for calculating SAVI. Try increasing distance."
            )

    elif index.upper() == "PRI":
        #  Photochemical Reflectance Index (https://doi.org/10.1111/j.1469-8137.1995.tb03064.x)
        if (max_wavelength + distance) >= 570 and (min_wavelength -
                                                   distance) <= 531:
            # Obtain index that best approximates 570 and 531 nm bands
            pri570_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 570)
            pri531_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 531)
            pri570 = (array_data[:, :, [pri570_index]])
            pri531 = (array_data[:, :, [pri531_index]])
            # PRI = (R531- R570)/(R531+ R570))
            denominator = pri531 + pri570
            # Avoid dividing by zero
            index_array_raw = np.where(denominator == 0, 0,
                                       ((pri531 - pri570) / denominator))
        else:
            fatal_error(
                "Available wavelengths are not suitable for calculating PRI. Try increasing distance."
            )

    elif index.upper() == "ACI":
        #  Van den Berg et al. 2005
        if (max_wavelength + distance) >= 800 and (min_wavelength -
                                                   distance) <= 560:
            green_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 560)
            nir_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 800)
            green = (array_data[:, :, [green_index]])
            nir = (array_data[:, :, [nir_index]])
            # Naturally ranges from -1.0 to 1.0
            index_array_raw = green / nir
        else:
            fatal_error(
                "Available wavelengths are not suitable for calculating ACI. Try increasing distance."
            )

    elif index.upper() == "ARI":
        # Gitelson et al., 2001
        if (max_wavelength + distance) >= 700 and (min_wavelength -
                                                   distance) <= 550:
            ari550_indes = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 550)
            ari700_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 700)
            ari550 = (array_data[:, :, [ari550_indes]])
            ari700 = (array_data[:, :, [ari700_index]])
            index_array_raw = (1 / ari550) - (1 / ari700)
        else:
            fatal_error(
                "Available wavelengths are not suitable for calculating ARI. Try increasing distance."
            )

    elif index.upper() == 'CARI':
        # Chlorophyll absorption in reflectance index (Giteson et al., 2003a)
        if (max_wavelength + distance) >= 700 and (min_wavelength -
                                                   distance) <= 550:
            cari550_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 550)
            cari700_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 700)
            cari550 = (array_data[:, :, [cari550_index]])
            cari700 = (array_data[:, :, [cari700_index]])
            # Naturally ranges from -inf to inf
            index_array_raw = (1 / cari550) - (1 / cari700)
        else:
            fatal_error(
                "Available wavelengths are not suitable for calculating CARI. Try increasing distance."
            )

    elif index.upper() == 'CI_REDEDGE':
        # Chlorophyll index red edge (Giteson et al., 2003a)
        if (max_wavelength + distance) >= 800 and (min_wavelength -
                                                   distance) <= 750:
            rededge_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 750)
            nir_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 800)
            rededge = (array_data[:, :, [rededge_index]])
            nir = (array_data[:, :, [nir_index]])
            # Naturally ranges from -1 to inf
            index_array_raw = nir / rededge - 1
        else:
            fatal_error(
                "Available wavelengths are not suitable for calculating CI_rededge. Try increasing distance."
            )

    elif index.upper() == 'CRI1':
        # Carotenoid reflectance index (Gitelson et al., 2002b) (note: part 1 of 2)
        if (max_wavelength + distance) >= 550 and (min_wavelength -
                                                   distance) <= 510:
            cri1510_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 510)
            cri1550_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 550)
            cri1510 = (array_data[:, :, [cri1510_index]])
            cri1550 = (array_data[:, :, [cri1550_index]])
            # Naturally ranges from -inf to inf
            index_array_raw = 1 / cri1510 - 1 / cri1550
        else:
            fatal_error(
                "Available wavelengths are not suitable for calculating CRI1. Try increasing distance."
            )

    elif index.upper() == 'CRI2':
        # Carotenoid reflectance index (Gitelson et al., 2002b) (note: part 1 of 2)
        if (max_wavelength + distance) >= 700 and (min_wavelength -
                                                   distance) <= 510:
            cri1510_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 510)
            cri1700_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 700)
            cri1510 = (array_data[:, :, [cri1510_index]])
            cri1700 = (array_data[:, :, [cri1700_index]])
            # Naturally ranges from -inf to inf
            index_array_raw = 1 / cri1510 - 1 / cri1700
        else:
            fatal_error(
                "Available wavelengths are not suitable for calculating CRI2. Try increasing distance."
            )

    elif index.upper() == 'EVI':
        # Enhanced Vegetation index (Huete et al., 1997)
        if (max_wavelength + distance) >= 800 and (min_wavelength -
                                                   distance) <= 470:
            blue_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 470)
            red_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 670)
            nir_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 800)
            blue = (array_data[:, :, [blue_index]])
            red = (array_data[:, :, [red_index]])
            nir = (array_data[:, :, [nir_index]])
            # Naturally ranges from -inf to inf
            index_array_raw = 2.5 * (nir - red) / (nir + 6 * red - 7.5 * blue +
                                                   1)
        else:
            fatal_error(
                "Available wavelengths are not suitable for calculating EVI. Try increasing distance."
            )

    elif index.upper() == 'MARI':
        # Modified anthocyanin reflectance index (Gitelson et al., 2001)
        if (max_wavelength + distance) >= 800 and (min_wavelength -
                                                   distance) <= 550:
            mari550_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 550)
            mari700_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 700)
            nir_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 800)
            mari550 = (array_data[:, :, [mari550_index]])
            mari700 = (array_data[:, :, [mari700_index]])
            nir = (array_data[:, :, [nir_index]])
            # Naturally ranges from -inf to inf
            index_array_raw = ((1 / mari550) - (1 / mari700)) * nir
        else:
            fatal_error(
                "Available wavelengths are not suitable for calculating MARI. Try increasing distance."
            )

    elif index.upper() == 'MCARI':
        # Modified chlorophyll absorption in reflectance index (Daughtry et al., 2000)
        if (max_wavelength + distance) >= 700 and (min_wavelength -
                                                   distance) <= 550:
            mcari550_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 550)
            mcari670_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 670)
            mcari700_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 700)
            mcari550 = (array_data[:, :, [mcari550_index]])
            mcari670 = (array_data[:, :, [mcari670_index]])
            mcari700 = (array_data[:, :, [mcari700_index]])
            # Naturally ranges from -inf to inf
            index_array_raw = ((mcari700 - mcari670) - 0.2 *
                               (mcari700 - mcari550)) * (mcari700 / mcari670)
        else:
            fatal_error(
                "Available wavelengths are not suitable for calculating MCARI. Try increasing distance."
            )

    elif index.upper() == 'MTCI':
        # MERIS terrestrial chlorophyll index (Dash and Curran, 2004)
        if (max_wavelength + distance) >= 753.75 and (min_wavelength -
                                                      distance) <= 681.25:
            mtci68125_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 681.25)
            mtci70875_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 708.75)
            mtci75375_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 753.75)
            mtci68125 = (array_data[:, :, [mtci68125_index]])
            mtci70875 = (array_data[:, :, [mtci70875_index]])
            mtci75375 = (array_data[:, :, [mtci75375_index]])
            # Naturally ranges from -inf to inf
            index_array_raw = (mtci75375 - mtci70875) / (mtci70875 - mtci68125)
        else:
            fatal_error(
                "Available wavelengths are not suitable for calculating MTCI. Try increasing distance."
            )

    elif index.upper() == 'NDRE':
        # Normalized difference red edge (Barnes et al., 2000)
        if (max_wavelength + distance) >= 790 and (min_wavelength -
                                                   distance) <= 720:
            ndre720_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 720)
            ndre790_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 790)
            ndre790 = (array_data[:, :, [ndre790_index]])
            ndre720 = (array_data[:, :, [ndre720_index]])
            # Naturally ranges from -1 to 1
            index_array_raw = (ndre790 - ndre720) / (ndre790 + ndre720)
        else:
            fatal_error(
                "Available wavelengths are not suitable for calculating NDRE. Try increasing distance."
            )

    elif index.upper() == 'PSND_CHLA':
        # Pigment sensitive normalized difference (Blackburn, 1998) note: chl_a
        if (max_wavelength + distance) >= 800 and (min_wavelength -
                                                   distance) <= 675:
            psndchla675_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 675)
            psndchla800_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 800)
            psndchla675 = (array_data[:, :, [psndchla675_index]])
            psndchla800 = (array_data[:, :, [psndchla800_index]])
            # Naturally ranges from -1 to 1
            index_array_raw = (psndchla800 - psndchla675) / (psndchla800 +
                                                             psndchla675)
        else:
            fatal_error(
                "Available wavelengths are not suitable for calculating PSND_CHLA. Try increasing distance."
            )

    elif index.upper() == 'PSND_CHLB':
        # Pigment sensitive normalized difference (Blackburn, 1998) note: chl_b (part 1 of 3)
        if (max_wavelength + distance) >= 800 and (min_wavelength -
                                                   distance) <= 650:
            psndchlb650_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 650)
            psndchlb800_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 800)
            psndchlb650 = (array_data[:, :, [psndchlb650_index]])
            psndchlb800 = (array_data[:, :, [psndchlb800_index]])
            # Naturally ranges from -1 to 1
            index_array_raw = (psndchlb800 - psndchlb650) / (psndchlb800 +
                                                             psndchlb650)
        else:
            fatal_error(
                "Available wavelengths are not suitable for calculating PSND_CHLB. Try increasing distance."
            )

    elif index.upper() == 'PSND_CAR':
        # Pigment sensitive normalized difference (Blackburn, 1998) note: chl_b (part 1 of 3)
        if (max_wavelength + distance) >= 800 and (min_wavelength -
                                                   distance) <= 500:
            psndcar500_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 500)
            psndcar800_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 800)
            psndcar500 = (array_data[:, :, [psndcar500_index]])
            psndcar800 = (array_data[:, :, [psndcar800_index]])
            # Naturally ranges from -1 to 1
            index_array_raw = (psndcar800 - psndcar500) / (psndcar800 +
                                                           psndcar500)
        else:
            fatal_error(
                "Available wavelengths are not suitable for calculating PSND_CAR. Try increasing distance."
            )

    elif index.upper() == 'PSRI':
        # Plant senescence reflectance index (Merzlyak et al., 1999) note: car (part 1 of 3)
        if (max_wavelength + distance) >= 750 and (min_wavelength -
                                                   distance) <= 500:
            psri500_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 500)
            psri678_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 678)
            psri750_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 750)
            psri500 = (array_data[:, :, [psri500_index]])
            psri678 = (array_data[:, :, [psri678_index]])
            psri750 = (array_data[:, :, [psri750_index]])
            # Naturally ranges from -inf to inf
            index_array_raw = (psri678 - psri500) / psri750
        else:
            fatal_error(
                "Available wavelengths are not suitable for calculating PSRI. Try increasing distance."
            )

    elif index.upper() == 'PSSR1':
        # Pigment-specific spectral ration (Blackburn, 1998) note: part 1 of 3
        if (max_wavelength + distance) >= 800 and (min_wavelength -
                                                   distance) <= 675:
            pssr1_800_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 800)
            pssr1_675_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 675)
            pssr1_800 = (array_data[:, :, [pssr1_800_index]])
            pssr1_675 = (array_data[:, :, [pssr1_675_index]])
            # Naturally ranges from 0 to inf
            index_array_raw = pssr1_800 / pssr1_675
        else:
            fatal_error(
                "Available wavelengths are not suitable for calculating PSSR1. Try increasing distance."
            )

    elif index.upper() == 'PSSR2':
        # Pigment-specific spectral ration (Blackburn, 1998) note: part 2 of 3
        if (max_wavelength + distance) >= 800 and (min_wavelength -
                                                   distance) <= 650:
            pssr2_800_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 800)
            pssr2_650_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 650)
            pssr2_800 = (array_data[:, :, [pssr2_800_index]])
            pssr2_650 = (array_data[:, :, [pssr2_650_index]])
            # Naturally ranges from 0 to inf
            index_array_raw = pssr2_800 / pssr2_650
        else:
            fatal_error(
                "Available wavelengths are not suitable for calculating PSSR2. Try increasing distance."
            )

    elif index.upper() == 'PSSR3':
        # Pigment-specific spectral ration (Blackburn, 1998) note: part 3 of 3
        if (max_wavelength + distance) >= 800 and (min_wavelength -
                                                   distance) <= 500:
            pssr3_800_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 800)
            pssr3_500_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 500)
            pssr3_800 = (array_data[:, :, [pssr3_800_index]])
            pssr3_500 = (array_data[:, :, [pssr3_500_index]])
            # Naturally ranges from 0 to inf
            index_array_raw = pssr3_800 / pssr3_500
        else:
            fatal_error(
                "Available wavelengths are not suitable for calculating PSSR3. Try increasing distance."
            )

    elif index.upper() == 'RGRI':
        # Red/green ratio index (Gamon and Surfus, 1999)
        if (max_wavelength + distance) >= 670 and (min_wavelength -
                                                   distance) <= 560:
            red_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 670)
            green_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 560)
            red = (array_data[:, :, [red_index]])
            green = (array_data[:, :, [green_index]])
            # Naturally ranges from 0 to inf
            index_array_raw = red / green
        else:
            fatal_error(
                "Available wavelengths are not suitable for calculating RGRI. Try increasing distance."
            )

    elif index.upper() == 'RVSI':
        # Red-edge vegetation stress index (Metron and Huntington, 1999)
        if (max_wavelength + distance) >= 752 and (min_wavelength -
                                                   distance) <= 714:
            rvsi714_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 714)
            rvsi733_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 733)
            rvsi752_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 752)
            rvsi714 = (array_data[:, :, [rvsi714_index]])
            rvsi733 = (array_data[:, :, [rvsi733_index]])
            rvsi752 = (array_data[:, :, [rvsi752_index]])
            # Naturally ranges from -1 to 1
            index_array_raw = (rvsi714 + rvsi752) / 2 - rvsi733
        else:
            fatal_error(
                "Available wavelengths are not suitable for calculating RVSI. Try increasing distance."
            )

    elif index.upper() == 'SIPI':
        # Structure-intensitive pigment index (Penuelas et al., 1995)
        if (max_wavelength + distance) >= 800 and (min_wavelength -
                                                   distance) <= 445:
            sipi445_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 445)
            sipi680_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 680)
            sipi800_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 800)
            sipi445 = (array_data[:, :, [sipi445_index]])
            sipi680 = (array_data[:, :, [sipi680_index]])
            sipi800 = (array_data[:, :, [sipi800_index]])
            # Naturally ranges from -inf to inf
            index_array_raw = (sipi800 - sipi445) / (sipi800 - sipi680)
        else:
            fatal_error(
                "Available wavelengths are not suitable for calculating SIPI. Try increasing distance."
            )

    elif index.upper() == 'SR':
        # Simple ratio (Jordan, 1969)
        if (max_wavelength + distance) >= 800 and (min_wavelength -
                                                   distance) <= 675:
            sr675_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 675)
            sr800_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 800)
            sr675 = (array_data[:, :, [sr675_index]])
            sr800 = (array_data[:, :, [sr800_index]])
            # Naturally ranges from 0 to inf
            index_array_raw = sr800 / sr675
        else:
            fatal_error(
                "Available wavelengths are not suitable for calculating SR. Try increasing distance."
            )

    elif index.upper() == 'VARI':
        # Visible atmospherically resistant index (Gitelson et al., 2002a)
        if (max_wavelength + distance) >= 670 and (min_wavelength -
                                                   distance) <= 470:
            red_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 670)
            green_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 560)
            blue_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 470)
            red = (array_data[:, :, [red_index]])
            green = (array_data[:, :, [green_index]])
            blue = (array_data[:, :, [blue_index]])
            # Naturally ranges from -inf to inf
            index_array_raw = (green - red) / (green + red - blue)
        else:
            fatal_error(
                "Available wavelengths are not suitable for calculating VARI. Try increasing distance."
            )

    elif index.upper() == 'VI_GREEN':
        # Vegetation index using green band (Gitelson et al., 2002a)
        if (max_wavelength + distance) >= 670 and (min_wavelength -
                                                   distance) <= 560:
            red_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 670)
            green_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 560)
            red = (array_data[:, :, [red_index]])
            green = (array_data[:, :, [green_index]])
            # Naturally ranges from -1 to 1
            index_array_raw = (green - red) / (green + red)
        else:
            fatal_error(
                "Available wavelengths are not suitable for calculating VI_green. Try increasing distance."
            )

    elif index.upper() == 'WBI':
        # Water band index (Peñuelas et al., 1997)
        if (max_wavelength + distance) >= 800 and (min_wavelength -
                                                   distance) <= 675:
            red_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 670)
            green_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 560)
            red = (array_data[:, :, [red_index]])
            green = (array_data[:, :, [green_index]])
            # Naturally ranges from -1 to 1
            index_array_raw = (green - red) / (green + red)
        else:
            fatal_error(
                "Available wavelengths are not suitable for calculating VI_green. Try increasing distance."
            )

    else:
        fatal_error(
            index +
            " is not one of the currently available indices for this function. Please open an issue "
            +
            "on the PlantCV GitHub account so we can add more handy indicies!")

    # Reshape array into hyperspectral datacube shape
    index_array_raw = np.transpose(np.transpose(index_array_raw)[0])

    # Store debug mode
    debug = params.debug
    params.debug = None

    # Resulting array is float 32 from varying natural ranges, transform into uint8 for plotting
    all_positive = np.add(index_array_raw,
                          2 * np.ones(np.shape(index_array_raw)))
    scaled = rescale(all_positive)

    # Find array min and max values
    obs_max_pixel = float(np.nanmax(index_array_raw))
    obs_min_pixel = float(np.nanmin(index_array_raw))

    index_array = Spectral_data(array_data=index_array_raw,
                                max_wavelength=0,
                                min_wavelength=0,
                                max_value=obs_max_pixel,
                                min_value=obs_min_pixel,
                                d_type=np.uint8,
                                wavelength_dict={},
                                samples=array.samples,
                                lines=array.lines,
                                interleave=array.interleave,
                                wavelength_units=array.wavelength_units,
                                array_type="index_" + index.lower(),
                                pseudo_rgb=scaled,
                                filename=array.filename,
                                default_bands=None)

    # Restore debug mode
    params.debug = debug

    if params.debug == "plot":
        plot_image(index_array.pseudo_rgb)
    elif params.debug == "print":
        print_image(
            index_array.pseudo_rgb,
            os.path.join(params.debug_outdir,
                         str(params.device) + index + "_index.png"))

    return index_array
コード例 #24
0
def extract_index(array, index="NDVI", distance=20):
    """Pull out indices of interest from a hyperspectral datacube.

        Inputs:
        array = hyperspectral data instance
        index = index of interest, either "ndvi", "gdvi", or "savi"
        distance = how lenient to be if the required wavelengths are not available

        Returns:
        index_array    = Index data as a Spectral_data instance

        :param array: __main__.Spectral_data
        :param index: str
        :param distance: int
        :return index_array: __main__.Spectral_data
        """
    params.device += 1

    # Min and max available wavelength will be used to determine if an index can be extracted
    max_wavelength = float(array.max_wavelength)
    min_wavelength = float(array.min_wavelength)

    # Dictionary of wavelength and it's index in the list
    wavelength_dict = array.wavelength_dict.copy()
    array_data = array.array_data.copy()

    if index.upper() == "NDVI":
        if (max_wavelength + distance) >= 800 and (min_wavelength -
                                                   distance) <= 670:
            # Obtain index that best represents NIR and red bands
            nir_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 800)
            red_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 670)
            nir = (array_data[:, :, [nir_index]])
            red = (array_data[:, :, [red_index]])
            # Naturally ranges from -1 to 1
            index_array_raw = (nir - red) / (nir + red)
        else:
            fatal_error(
                "Available wavelengths are not suitable for calculating NDVI. Try increasing fudge factor."
            )

    elif index.upper() == "GDVI":
        # Green Difference Vegetation Index [Sripada et al. (2006)]
        if (max_wavelength + distance) >= 800 and (min_wavelength -
                                                   distance) <= 680:
            nir_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 800)
            red_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 680)
            nir = (array_data[:, :, [nir_index]])
            red = (array_data[:, :, [red_index]])
            # Naturally ranges from -2 to 2
            index_array_raw = nir - red
        else:
            fatal_error(
                "Available wavelengths are not suitable for calculating GDVI. Try increasing fudge factor."
            )

    elif index.upper() == "SAVI":
        # Soil Adjusted Vegetation Index [Huete et al. (1988)]
        if (max_wavelength + distance) >= 800 and (min_wavelength -
                                                   distance) <= 680:
            nir_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 800)
            red_index = _find_closest(
                np.array([float(i) for i in wavelength_dict.keys()]), 680)
            nir = (array_data[:, :, [nir_index]])
            red = (array_data[:, :, [red_index]])
            # Naturally ranges from -1.2 to 1.2
            index_array_raw = (1.5 * (nir - red)) / (red + nir + 0.5)
        else:
            fatal_error(
                "Available wavelengths are not suitable for calculating SAVI. Try increasing fudge factor."
            )

    else:
        fatal_error(
            index +
            " is not one of the currently available indices for this function."
        )

    # Reshape array into hyperspectral datacube shape
    index_array_raw = np.transpose(np.transpose(index_array_raw)[0])

    # Store debug mode
    debug = params.debug
    params.debug = None

    # Resulting array is float 32 from varying natural ranges, transform into uint8 for plotting
    all_positive = np.add(index_array_raw,
                          2 * np.ones(np.shape(index_array_raw)))
    scaled = rescale(all_positive)

    index_array = Spectral_data(array_data=index_array_raw,
                                max_wavelength=0,
                                min_wavelength=0,
                                d_type=np.uint8,
                                wavelength_dict={},
                                samples=array.samples,
                                lines=array.lines,
                                interleave=array.interleave,
                                wavelength_units=array.wavelength_units,
                                array_type="index_" + index.lower(),
                                pseudo_rgb=scaled,
                                filename=array.filename,
                                default_bands=None)

    # Restore debug mode
    params.debug = debug

    if params.debug == "plot":
        plot_image(index_array.pseudo_rgb)
    elif params.debug == "print":
        print_image(
            index_array.pseudo_rgb,
            os.path.join(params.debug_outdir,
                         str(params.device) + index + "_index.png"))

    return index_array