Skip to content

Commit

Permalink
Aanpassingen adhv review commentaar
Browse files Browse the repository at this point in the history
  • Loading branch information
DRIESSEB committed Nov 4, 2021
1 parent bdf8e0a commit a4679de
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 77 deletions.
10 changes: 1 addition & 9 deletions openeo/extra/spectral_indices/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,4 @@
The indices implemented have been derived from the eemont package created by davemlz:
https://github.com/davemlz/eemont/blob/master/eemont/data/spectral-indices-dict.json
and further supplemented with indices that were necessary for use cases
"""

class BaseOpenEoException(Exception):
pass

from openeo._version import __version__

def client_version() -> str:
return __version__
"""
89 changes: 33 additions & 56 deletions openeo/extra/spectral_indices/spectral_indices.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,64 +3,41 @@
import numpy as np

def _get_expression_map(cube: DataCube, x: ProcessBuilder):
collection_id = cube.graph["loadcollection1"]["arguments"]["id"]
collection_id = cube.metadata.get("id")
bands = [band.replace("0", "").upper() for band in cube.metadata.band_names]

def check_validity():
if not all(band in orig_bands for band in bands):
if not all(band in band_mapping.keys() for band in bands):
raise ValueError(
"The bands in your cube {} are not all Sentinel-2 bands (the following are: {})".format(bands,orig_bands))
"The bands in your cube {} are not all {} bands (the following are: {})".format(bands,collection_id,band_mapping.keys()))

def get_params():
lookup = dict(zip(orig_bands, norm_bands))
return {lookup[key]: x.array_element(i) for i, key in enumerate(bands)}

def lookupS2():
orig_bands = ["B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8", "B8A", "B9", "B11", "B12"]
norm_bands = ["A", "B", "G", "R", "RE1", "RE2", "RE3", "N", "RE4", "WV", "S1", "S2"]
return orig_bands, norm_bands

def lookupL8():
orig_bands = ["B1", "B2", "B3", "B4", "B5", "B6", "B7", "B10", "B11"]
norm_bands = ["A", "B", "G", "R", "N", "S1", "S2", "T1", "T2"]
return orig_bands, norm_bands

def lookupL457():
orig_bands = ["B1", "B2", "B3", "B4", "B5", "B6", "B7"]
norm_bands = ["B", "G", "R", "N", "S1", "T1", "S2"]
return orig_bands, norm_bands

def lookupModis():
orig_bands = ["B3", "B4", "B1", "B2", "B5", "B6", "B7"]
norm_bands = ["B", "G", "R", "N", np.nan, "S1", "S2"]
return orig_bands, norm_bands

def lookupProbav():
orig_bands = ["BLUE", "RED", "NIR", "SWIR"]
norm_bands = ["B", "R", "N", "S1"]
return orig_bands, norm_bands

lookupPlatform = {
"LANDSAT4-5_TM_L1": lookupL457,
"LANDSAT4-5_TM_L2": lookupL457,
"LANDSAT8_L1": lookupL8,
"LANDSAT8_L2": lookupL8,
"MODIS": lookupModis,
"PROBAV_L3_S5_TOC_100M": lookupProbav,
"PROBAV_L3_S10_TOC_333M": lookupProbav,
"SENTINEL2_L1C_SENTINELHUB": lookupS2,
"SENTINEL2_L2A_SENTINELHUB": lookupS2,
"TERRASCOPE_S2_TOC_V2": lookupS2,
}

if collection_id not in list(lookupPlatform.keys()):
raise Exception("Sorry, satellite platform not supported for index computation!")

orig_bands, norm_bands = lookupPlatform[collection_id]()
return {band_mapping[key]: x.array_element(i) for i, key in enumerate(bands)}

landsat457_mapping = {"B1":"B", "B2":"G", "B3":"R", "B4":"N", "B5":"S1", "B6":"T1", "B7":"S2"}
landsat8_mapping = {"B1":"A", "B2":"B", "B3":"G", "B4":"R", "B5":"N", "B6":"S1", "B7":"S2", "B10":"T1", "B11":"T2"}
modis_mapping = {"B3":"B", "B4":"G", "B1":"R", "B2":"N", "B5":np.nan, "B6":"S1", "B7":"S2"}
probav_mapping = {"BLUE":"B", "RED":"R", "NIR":"N", "SWIR":"S1"}
sentinel2_mapping = {"B1":"A", "B2":"B", "B3":"G", "B4":"R", "B5":"RE1", "B6":"RE2", "B7":"RE3", "B8":"N", "B8A":"RE4", "B9":"WV", "B11":"S1", "B12":"S2"}

if "LANDSAT8" in collection_id:
band_mapping = landsat8_mapping
elif "LANDSAT" in collection_id:
band_mapping = landsat457_mapping
elif "MODIS" in collection_id:
band_mapping = modis_mapping
elif "PROBAV" in collection_id:
band_mapping = probav_mapping
elif "TERRASCOPE_S2" in collection_id or "SENTINEL2" in collection_id:
band_mapping = sentinel2_mapping
else:
raise Exception("Sorry, satellite platform "+collection_id+" is not supported for index computation!")

check_validity()
return get_params()


def _callback(x: ProcessBuilder, index_list: list, datacube: DataCube, scaling_factor: int, index_specs) -> ProcessBuilder:
def _callback(x: ProcessBuilder, index_list: list, datacube: DataCube, uplim_rescale: int, index_specs) -> ProcessBuilder:
index_values = []
x_res = x

Expand All @@ -69,31 +46,31 @@ def _callback(x: ProcessBuilder, index_list: list, datacube: DataCube, scaling_f
if index_name not in index_specs.keys():
raise NotImplementedError("Index " + index_name + " has not been implemented.")
index_result = eval(index_specs[index_name]["formula"], params)
if scaling_factor is not None:
if uplim_rescale is not None:
if "range" not in index_specs[index_name].keys():
raise ValueError(
"You want to scale the " + index_name + ", however the range of this index has not been supplied in the indices json yet.")
index_result = index_result.linear_scale_range(*eval(index_specs[index_name]["range"]), 0, scaling_factor)
index_result = index_result.linear_scale_range(*eval(index_specs[index_name]["range"]), 0, uplim_rescale)
index_values.append(index_result)
if scaling_factor is not None:
x_res = x_res.linear_scale_range(0, 8000, 0, scaling_factor)
if uplim_rescale is not None:
x_res = x_res.linear_scale_range(0, 8000, 0, uplim_rescale)
return array_modify(data=x_res, values=index_values, index=len(datacube.metadata.band_names))


def compute_indices(datacube: DataCube, index_list: list, scaling_factor: int = None) -> DataCube:
def compute_indices(datacube: DataCube, index_list: list, uplim_rescale: int = None) -> DataCube:
"""
Computes a list of indices from a datacube
param datacube: an instance of openeo.rest.DataCube
param index_list: a list of indices. The indices that are implemented are derived from the eemont package created by davemlz:
https://github.com/davemlz/eemont/blob/master/eemont/data/spectral-indices-dict.json
param scaling_factor: the upper range to which you want to scale the value (the result after rescaling will be [0,scaling_factor])
param uplim_rescale: the upper range to which you want to scale the value (the result after rescaling will be [0,uplim_rescale])
return: the datacube with the indices attached as bands
"""
with open("resources/spectral-indices-dict.json") as f:
index_specs = eval(f.read())["SpectralIndices"]
return datacube.apply_dimension(dimension="bands",
process=lambda x: _callback(x, index_list, datacube, scaling_factor,
process=lambda x: _callback(x, index_list, datacube, uplim_rescale,
index_specs)).rename_labels('bands',
target=datacube.metadata.band_names + index_list)
33 changes: 21 additions & 12 deletions tests/test_spectral_indices.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
from unittest.mock import Mock
from openeo.extra.spectral_indices.spectral_indices import _callback, _get_expression_map
from processes import array_create
from unittest.mock import Mock, MagicMock
from extra.spectral_indices.spectral_indices import _callback, _get_expression_map
from openeo.rest.connection import Connection
from processes import array_create, ProcessBuilder
from tests.rest.datacube.conftest import con100

x = array_create([9,4,6,1,3,8,2,5,7,11,7,2])
cube = Mock()
cube.metadata.band_names = ["B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8", "B8A", "B9", "B11", "B12"]
cube.graph = {"loadcollection1": {"arguments": {"id": "TERRASCOPE_S2_TOC_V2"}}}
# cube = Mock()
# cube.metadata.band_names = ["B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8", "B8A", "B9", "B11", "B12"]
# cube.metadata.get = MagicMock(return_value="TERRASCOPE_S2_TOC_V2")
index_specs = {
"NDRE1": {
"bands": ["N","RE1"],
Expand All @@ -25,10 +26,18 @@
}


def test_get_expression_map():
assert _get_expression_map(cube, x)["A"] == array_create([9])
def test_get_expression_map(con100: Connection):
cube = con100.load_collection("S2",bands=["B02","B03","B04","B08"]).filter_bbox(*[3, 51, 4, 52])
cube.metadata.get = MagicMock(return_value="TERRASCOPE_S2_TOC_V2")
assert True
# assert _get_expression_map(cube, x)["B"] == array_create([9])

def test_callback():
index_list = ["NDRE1","NDGI","NDRE5"]
scaling_factor = None
assert _callback(x, index_list, cube, scaling_factor, index_specs)
index_name = "NDGI"
uplim_rescale = 250
index_result = eval(index_specs[index_name]["formula"], {"G": 5, "R": 2, "RE1": 3})
print(index_result)
index_result = index_result.linear_scale_range(*eval(index_specs[index_name]["range"]), 0, uplim_rescale)
print(index_result)
assert True

0 comments on commit a4679de

Please sign in to comment.