Source code for eocrops.tasks.vegetation_indices

import math
from eolearn.core import FeatureType, EOTask
import numpy as np
from eolearn.core import AddFeatureTask, RemoveFeatureTask


[docs]class VegetationIndicesVHRS(EOTask): """Compute vegetation indices for VHRS data (only 4 bands)""" def __init__(self, feature_name): self.feature_name = feature_name
[docs] def calcul_ratio_vegetation_indices(self): self.NDVI = (self.B4 - self.B3) / (self.B4 + self.B3) self.NDWI = (self.B2 - self.B4) / (self.B2 + self.B4) self.VARI = (self.B2 - self.B3) / (self.B2 + self.B3 - self.B1)
def execute(self, eopatch, **kwargs): arr0 = eopatch.data[self.feature_name] # Raw data self.B1 = arr0[..., 0] self.B2 = arr0[..., 1] self.B3 = arr0[..., 2] self.B4 = arr0[..., 3] # VIS self.calcul_ratio_vegetation_indices() add_NDVI = AddFeatureTask((FeatureType.DATA, "NDVI")) add_NDVI.execute(eopatch=eopatch, data=self.NDVI[..., np.newaxis]) add_NDWI = AddFeatureTask((FeatureType.DATA, "NDWI")) add_NDWI.execute(eopatch=eopatch, data=self.NDWI[..., np.newaxis]) add_VARI = AddFeatureTask((FeatureType.DATA, "VARI")) add_VARI.execute(eopatch=eopatch, data=self.VARI[..., np.newaxis]) return eopatch
[docs]class BiophysicalParameters: def __init__( self, B03, B04, B05, B06, B07, B8A, B11, B12, viewZenithMean, sunZenithAngles, viewAzimuthMean, sunAzimuthAngles, ): """ Compute biophysical parameters in Sentinel-2 data using the code available in SNAP biophysical processor. Parameters ---------- B03-B12 : np.array Band from S2 image (4-d format T*H*W*1) Illumination properties: Band from S2 image (4-d format T*H*W*1) """ self.B03 = B03 self.B04 = B04 self.B05 = B05 self.B06 = B06 self.B07 = B07 self.B8A = B8A self.B11 = B11 self.B12 = B12 self.viewZenithMean = viewZenithMean self.sunZenithAngles = sunZenithAngles self.viewAzimuthMean = viewAzimuthMean self.sunAzimuthAngles = sunAzimuthAngles @staticmethod def _normalize(unnormalized, mini, maxi): """Normalize inputs Neural Network""" return 2 * (unnormalized - mini) / (maxi - mini) - 1 @staticmethod def _denormalize(normalized, mini, maxi): """Denormalize output Neural Network""" return 0.5 * (normalized + 1) * (maxi - mini) + mini @staticmethod def _funccos(t): return np.vectorize(lambda t: math.cos(t)) @staticmethod def _neuron( cste, w_b03, w_b04, w_b05, w_b06, w_b07, w_b8A, w_b11, w_b12, w_viewZen_norm, w_sunZen_norm, w_relAzim_norm, b03_norm, b04_norm, b05_norm, b06_norm, b07_norm, b8a_norm, b11_norm, b12_norm, viewZen_norm, sunZen_norm, relAzim_norm, ): def tansig(input_neuron): """Activation function neural network""" funcexp = np.vectorize(lambda t: math.exp(t)) return 2 / (1 + funcexp(-2 * input_neuron)) - 1 """Define the neuron, which is a linear combination of the metadata of sentinel2 images""" var_sum = ( cste + w_b03 * b03_norm + w_b04 * b04_norm + w_b05 * b05_norm + w_b06 * b06_norm ) var_sum += ( w_b07 * b07_norm + w_b8A * b8a_norm + w_b11 * b11_norm + w_b12 * b12_norm ) var_sum += ( w_viewZen_norm * viewZen_norm + w_sunZen_norm * sunZen_norm + w_relAzim_norm * relAzim_norm ) return tansig(var_sum) @staticmethod def _layer2( cste, w_n1, neuron1, w_n2, neuron2, w_n3, neuron3, w_n4, neuron4, w_n5, neuron5 ): """Define the second layer, which is a linear combination of the neurons => inputs of the activation function""" return ( cste + w_n1 * neuron1 + w_n2 * neuron2 + w_n3 * neuron3 + w_n4 * neuron4 + w_n5 * neuron5 )
[docs] def apply_normalize(self): #https://github.com/senbox-org/s2tbx/blob/master/s2tbx-biophysical/src/main/resources/auxdata/2_1/FCOVER/FCOVER_Normalisation self.b03_norm = self._normalize(self.B03, 0, 0.253061520471542) self.b04_norm = self._normalize(self.B04, 0, 0.290393577911328) self.b05_norm = self._normalize(self.B05, 0, 0.305398915248555) self.b06_norm = self._normalize(self.B06, 0.006637972542253, 0.608900395797889) self.b07_norm = self._normalize(self.B07, 0.013972727018939, 0.753827384322927) self.b8a_norm = self._normalize(self.B8A, 0.026690138082061, 0.782011770669178) self.b11_norm = self._normalize(self.B11, 0.016388074192258, 0.493761397883092) self.b12_norm = self._normalize(self.B12, 0, 0.493025984460231) degToRad = math.pi / 180 funccos = np.vectorize(lambda t: math.cos(t)) self.viewZen_norm = self._normalize( funccos(self.viewZenithMean * degToRad), 0.918595400582046, 1 ) self.sunZen_norm = self._normalize( funccos(self.sunZenithAngles * degToRad), 0.342022871159208, 0.936206429175402, ) self.relAzim_norm = funccos( (self.sunAzimuthAngles - self.viewAzimuthMean) * degToRad )
[docs] def get_lai(self): """Define biophysical vegetation index Leaf Area Index, computed from a trained neural network which has as inputs the metadata of sentinel2 images""" n1 = self._neuron( 4.96238030555279, #bias of neuron 1 https://github.com/senbox-org/s2tbx/blob/master/s2tbx-biophysical/src/main/resources/auxdata/2_1/LAI/LAI_Weights_Layer1_Bias -0.023406878966470, # neuron https://github.com/senbox-org/s2tbx/blob/master/s2tbx-biophysical/src/main/resources/auxdata/2_1/LAI/LAI_Weights_Layer1_Neurons +0.921655164636366, 0.135576544080099, -1.938331472397950, -3.342495816122680, 0.902277648009576, 0.205363538258614, -0.040607844721716, -0.083196409727092, 0.260029270773809, 0.284761567218845, self.b03_norm, self.b04_norm, self.b05_norm, self.b06_norm, self.b07_norm, self.b8a_norm, self.b11_norm, self.b12_norm, self.viewZen_norm, self.sunZen_norm, self.relAzim_norm, ) n2 = self._neuron( 1.416008443981500, -0.132555480856684, -0.139574837333540, -1.014606016898920, -1.330890038649270, 0.031730624503341, -1.433583541317050, -0.959637898574699, +1.133115706551000, 0.216603876541632, 0.410652303762839, 0.064760155543506, self.b03_norm, self.b04_norm, self.b05_norm, self.b06_norm, self.b07_norm, self.b8a_norm, self.b11_norm, self.b12_norm, self.viewZen_norm, self.sunZen_norm, self.relAzim_norm, ) n3 = self._neuron( 1.075897047213310, 0.086015977724868, 0.616648776881434, 0.678003876446556, 0.141102398644968, -0.096682206883546, -1.128832638862200, 0.302189102741375, 0.434494937299725, -0.021903699490589, -0.228492476802263, -0.039460537589826, self.b03_norm, self.b04_norm, self.b05_norm, self.b06_norm, self.b07_norm, self.b8a_norm, self.b11_norm, self.b12_norm, self.viewZen_norm, self.sunZen_norm, self.relAzim_norm, ) n4 = self._neuron( 1.533988264655420, -0.109366593670404, -0.071046262972729, +0.064582411478320, 2.906325236823160, -0.673873108979163, -3.838051868280840, 1.695979344531530, 0.046950296081713, -0.049709652688365, 0.021829545430994, 0.057483827104091, self.b03_norm, self.b04_norm, self.b05_norm, self.b06_norm, self.b07_norm, self.b8a_norm, self.b11_norm, self.b12_norm, self.viewZen_norm, self.sunZen_norm, self.relAzim_norm, ) n5 = self._neuron( 3.024115930757230, -0.089939416159969, 0.175395483106147, -0.081847329172620, 2.219895367487790, 1.713873975136850, 0.713069186099534, 0.138970813499201, -0.060771761518025, 0.124263341255473, 0.210086140404351, -0.183878138700341, self.b03_norm, self.b04_norm, self.b05_norm, self.b06_norm, self.b07_norm, self.b8a_norm, self.b11_norm, self.b12_norm, self.viewZen_norm, self.sunZen_norm, self.relAzim_norm, ) l2 = self._layer2( 1.096963107077220, -1.500135489728730, n1, -0.096283269121503, n2, -0.194935930577094, n3, -0.352305895755591, n4, 0.075107415847473, n5, ) return self._denormalize(l2, 0.000319182538301, 14.4675094548151)
[docs] def get_cab(self): """Define biochemical vegetation index Chloro a+b, computed from a trained neural network which has as inputs the metadata of sentinel2 images""" n1 = self._neuron( 4.242299670155190, 0.400396555256580, 0.607936279259404, 0.137468650780226, -2.955866573461640, -3.186746687729570, 2.206800751246430, -0.313784336139636, +0.256063547510639, -0.071613219805105, 0.510113504210111, 0.142813982138661, self.b03_norm, self.b04_norm, self.b05_norm, self.b06_norm, self.b07_norm, self.b8a_norm, self.b11_norm, self.b12_norm, self.viewZen_norm, self.sunZen_norm, self.relAzim_norm, ) n2 = self._neuron( -0.259569088225796, -0.250781102414872, 0.439086302920381, -1.160590937522300, -1.861935250269610, 0.981359868451638, 1.634230834254840, -0.872527934645577, 0.448240475035072, 0.037078083501217, 0.030044189670404, 0.005956686619403, self.b03_norm, self.b04_norm, self.b05_norm, self.b06_norm, self.b07_norm, self.b8a_norm, self.b11_norm, self.b12_norm, self.viewZen_norm, self.sunZen_norm, self.relAzim_norm, ) n3 = self._neuron( 3.130392627338360, 0.552080132568747, -0.502919673166901, 6.105041924966230, -1.294386119140800, -1.059956388352800, -1.394092902418820, 0.324752732710706, -1.758871822827680, -0.036663679860328, -0.183105291400739, -0.038145312117381, self.b03_norm, self.b04_norm, self.b05_norm, self.b06_norm, self.b07_norm, self.b8a_norm, self.b11_norm, self.b12_norm, self.viewZen_norm, self.sunZen_norm, self.relAzim_norm, ) n4 = self._neuron( 0.774423577181620, 0.211591184882422, -0.248788896074327, 0.887151598039092, 1.143675895571410, -0.753968830338323, -1.185456953076760, 0.541897860471577, -0.252685834607768, -0.023414901078143, -0.046022503549557, -0.006570284080657, self.b03_norm, self.b04_norm, self.b05_norm, self.b06_norm, self.b07_norm, self.b8a_norm, self.b11_norm, self.b12_norm, self.viewZen_norm, self.sunZen_norm, self.relAzim_norm, ) n5 = self._neuron( 2.584276648534610, 0.254790234231378, -0.724968611431065, 0.731872806026834, 2.303453821021270, -0.849907966921912, -6.425315500537270, 2.238844558459030, -0.199937574297990, 0.097303331714567, 0.334528254938326, 0.113075306591838, self.b03_norm, self.b04_norm, self.b05_norm, self.b06_norm, self.b07_norm, self.b8a_norm, self.b11_norm, self.b12_norm, self.viewZen_norm, self.sunZen_norm, self.relAzim_norm, ) l2 = self._layer2( 0.463426463933822, -0.352760040599190, n1, -0.603407399151276, n2, 0.135099379384275, n3, -1.735673123851930, n4, -0.147546813318256, n5, ) return self._denormalize(l2, 0.007426692959872, 873.908222110306)
[docs] def get_fapar(self): """Define biophysical vegetation index Fraction of Absorbed Photosynthetically Active Radiation, computed from a trained neural network which has as inputs the metadata of sentinel2 images""" n1 = self._neuron( -0.887068364040280, 0.268714454733421, -0.205473108029835, 0.281765694196018, 1.337443412255980, 0.390319212938497, -3.612714342203350, 0.222530960987244, 0.821790549667255, -0.093664567310731, 0.019290146147447, 0.037364446377188, self.b03_norm, self.b04_norm, self.b05_norm, self.b06_norm, self.b07_norm, self.b8a_norm, self.b11_norm, self.b12_norm, self.viewZen_norm, self.sunZen_norm, self.relAzim_norm, ) n2 = self._neuron( 0.320126471197199, -0.248998054599707, -0.571461305473124, -0.369957603466673, 0.246031694650909, 0.332536215252841, 0.438269896208887, 0.819000551890450, -0.934931499059310, 0.082716247651866, -0.286978634108328, -0.035890968351662, self.b03_norm, self.b04_norm, self.b05_norm, self.b06_norm, self.b07_norm, self.b8a_norm, self.b11_norm, self.b12_norm, self.viewZen_norm, self.sunZen_norm, self.relAzim_norm, ) n3 = self._neuron( 0.610523702500117, -0.164063575315880, -0.126303285737763, -0.253670784366822, -0.321162835049381, 0.067082287973580, 2.029832288655260, -0.023141228827722, -0.553176625657559, 0.059285451897783, -0.034334454541432, -0.031776704097009, self.b03_norm, self.b04_norm, self.b05_norm, self.b06_norm, self.b07_norm, self.b8a_norm, self.b11_norm, self.b12_norm, self.viewZen_norm, self.sunZen_norm, self.relAzim_norm, ) n4 = self._neuron( -0.379156190833946, 0.130240753003835, 0.236781035723321, 0.131811664093253, -0.250181799267664, -0.011364149953286, -1.857573214633520, -0.146860751013916, 0.528008831372352, -0.046230769098303, -0.034509608392235, 0.031884395036004, self.b03_norm, self.b04_norm, self.b05_norm, self.b06_norm, self.b07_norm, self.b8a_norm, self.b11_norm, self.b12_norm, self.viewZen_norm, self.sunZen_norm, self.relAzim_norm, ) n5 = self._neuron( 1.353023396690570, -0.029929946166941, 0.795804414040809, 0.348025317624568, 0.943567007518504, -0.276341670431501, -2.946594180142590, 0.289483073507500, 1.044006950440180, -0.000413031960419, 0.403331114840215, 0.068427130526696, self.b03_norm, self.b04_norm, self.b05_norm, self.b06_norm, self.b07_norm, self.b8a_norm, self.b11_norm, self.b12_norm, self.viewZen_norm, self.sunZen_norm, self.relAzim_norm, ) l2 = self._layer2( -0.336431283973339, 2.126038811064490, n1, -0.632044932794919, n2, 5.598995787206250, n3, 1.770444140578970, n4, -0.267879583604849, n5, ) return self._denormalize(l2, 0.000153013463222, 0.977135096979553)
[docs] def get_fcover(self): """Define biophysical vegetation index Leaf Area Index, computed from a trained neural network which has as inputs the metadata of sentinel2 images""" n1 = self._neuron( -1.45261652206, -0.156854264841, 0.124234528462, +0.235625516229, -1.8323910258, -0.217188969888, +5.06933958064, -0.887578008155, -1.0808468167, -0.0323167041864, -0.224476137359, -0.195523962947, self.b03_norm, self.b04_norm, self.b05_norm, self.b06_norm, self.b07_norm, self.b8a_norm, self.b11_norm, self.b12_norm, self.viewZen_norm, self.sunZen_norm, self.relAzim_norm, ) n2 = self._neuron( -1.70417477557, -0.220824927842, +1.28595395487, +0.703139486363, -1.34481216665, -1.96881267559, -1.45444681639, +1.02737560043, -0.12494641532, +0.0802762437265, -0.198705918577, +0.108527100527, self.b03_norm, self.b04_norm, self.b05_norm, self.b06_norm, self.b07_norm, self.b8a_norm, self.b11_norm, self.b12_norm, self.viewZen_norm, self.sunZen_norm, self.relAzim_norm, ) n3 = self._neuron( 1.02168965849, -0.409688743281, +1.08858884766, +0.36284522554, +0.0369390509705, -0.348012590003, -2.0035261881, +0.0410357601757, +1.22373853174, +-0.0124082778287, -0.282223364524, +0.0994993117557, self.b03_norm, self.b04_norm, self.b05_norm, self.b06_norm, self.b07_norm, self.b8a_norm, self.b11_norm, self.b12_norm, self.viewZen_norm, self.sunZen_norm, self.relAzim_norm, ) n4 = self._neuron( -0.498002810205, -0.188970957866, -0.0358621840833, +0.00551248528107, +1.35391570802, -0.739689896116, -2.21719530107, +0.313216124198, +1.5020168915, +1.21530490195, -0.421938358618, +1.48852484547, self.b03_norm, self.b04_norm, self.b05_norm, self.b06_norm, self.b07_norm, self.b8a_norm, self.b11_norm, self.b12_norm, self.viewZen_norm, self.sunZen_norm, self.relAzim_norm, ) n5 = self._neuron( -3.88922154789, +2.49293993709, -4.40511331388, -1.91062012624, -0.703174115575, -0.215104721138, -0.972151494818, -0.930752241278, +1.2143441876, -0.521665460192, -0.445755955598, +0.344111873777, self.b03_norm, self.b04_norm, self.b05_norm, self.b06_norm, self.b07_norm, self.b8a_norm, self.b11_norm, self.b12_norm, self.viewZen_norm, self.sunZen_norm, self.relAzim_norm, ) l2 = self._layer2( -0.0967998147811, +0.23080586765, n1, -0.333655484884, n2, -0.499418292325, n3, +0.0472484396749, n4, -0.0798516540739, n5, ) return self._denormalize(l2, 0.000181230723879, 0.999638214715)
[docs] def get_cw(self): """Define biophysical vegetation index Fraction of Absorbed Photosynthetically Active Radiation, computed from a trained neural network which has as inputs the metadata of sentinel2 images""" n1 = self._neuron( -2.1064083686, 0.146378710426, 1.18979928187, -0.906235139963, -0.808337508767, -0.97333491783, -1.42591277646, -0.00561253629588, -0.634520356267, -0.117226059989, -0.0602700912102, 0.229407587132, self.b03_norm, self.b04_norm, self.b05_norm, self.b06_norm, self.b07_norm, self.b8a_norm, self.b11_norm, self.b12_norm, self.viewZen_norm, self.sunZen_norm, self.relAzim_norm, ) n2 = self._neuron( -1.69022094794, 0.283319173374, 0.149342023041, 1.08480588387, -0.138658791035, -0.455759407329, 0.420571438078, -1.7372949037, -0.704286287226, 0.0190953782358, -0.0393971316513, -0.00750241581744, self.b03_norm, self.b04_norm, self.b05_norm, self.b06_norm, self.b07_norm, self.b8a_norm, self.b11_norm, self.b12_norm, self.viewZen_norm, self.sunZen_norm, self.relAzim_norm, ) n3 = self._neuron( 3.10117655255, -0.197487427943, -0.105460325978, 0.158347670681, 2.14912426654, -0.970716842916, -4.92725317909, 1.42034301781, 1.45316917226, 0.0227257053609, 0.269298650421, 0.0849047657715, self.b03_norm, self.b04_norm, self.b05_norm, self.b06_norm, self.b07_norm, self.b8a_norm, self.b11_norm, self.b12_norm, self.viewZen_norm, self.sunZen_norm, self.relAzim_norm, ) n4 = self._neuron( -1.31231626496, 0.141405799763, 0.33386260328, 0.356218929123, -0.545942267639, 0.0891043076856, 0.919298362929, -1.8520892625, -0.427539590779, 0.00791385646467, 0.0148333201478, -0.00153786769736, self.b03_norm, self.b04_norm, self.b05_norm, self.b06_norm, self.b07_norm, self.b8a_norm, self.b11_norm, self.b12_norm, self.viewZen_norm, self.sunZen_norm, self.relAzim_norm, ) n5 = self._neuron( 1.01131930348, -0.186781083395, -0.549163704901, -0.181287638772, 0.96864043656, -0.470442559117, -1.24859725244, 2.67014942338, 0.49009062438, -0.00144931939526, 0.00314829369692, 0.0206517883893, self.b03_norm, self.b04_norm, self.b05_norm, self.b06_norm, self.b07_norm, self.b8a_norm, self.b11_norm, self.b12_norm, self.viewZen_norm, self.sunZen_norm, self.relAzim_norm, ) l2 = self._layer2( -0.197591709977, -0.0775555890347, n1, -0.86411786119, n2, -0.199212415374, n3, 1.98730461219, n4, 0.458926743489, n5, ) return self._denormalize(l2, 3.85066859366e-06, 0.522417054645)
[docs]class VegetationIndicesS2(EOTask): """Define a class of vegetation indices, which are computed from the metadata of sentinel2 images extracted""" def __init__(self, feature_name, mask_data=True): self.feature_name = feature_name self.mask_data = mask_data
[docs] def get_vegetation_indices(self): """Define vegetation indices which are simply ratio of spectral bands""" self.NDVI = (self.B8A - self.B04) / (self.B8A + self.B04) self.NDWI = (self.B8A - self.B11) / (self.B8A + self.B11) self.GNDVI = (self.B8A - self.B03) / (self.B8A + self.B03) self.NDVIre = (self.B8A - self.B05) / (self.B8A + self.B05)
[docs] def get_biophysical_parameters(self): biopysicial_parameters = BiophysicalParameters( self.B03, self.B04, self.B05, self.B06, self.B07, self.B8A, self.B11, self.B12, self.viewZenithMean, self.sunZenithAngles, self.viewAzimuthMean, self.sunAzimuthAngles, ) # Normalized bands biopysicial_parameters.apply_normalize() self.fapar = biopysicial_parameters.get_fapar() self.LAI = biopysicial_parameters.get_lai() self.CCC = biopysicial_parameters.get_cab() self.Cab = self.CCC / self.LAI self.CCW = biopysicial_parameters.get_cw() self.CW = self.CCW / self.LAI self.fcover = biopysicial_parameters.get_fcover()
[docs] def mask_pixels(self, eopatch): bands_array = eopatch.data[self.feature_name] valid_data_mask = ( eopatch.mask["VALID_DATA"] if self.mask_data else eopatch.mask["IS_DATA"] ) if "polygon_mask" in list(eopatch.mask_timeless.keys()): bands_array = np.ma.array( bands_array, dtype=np.float32, mask=np.logical_or( ~valid_data_mask.astype(bool), np.isnan(bands_array) ), fill_value=np.nan, ) bands_array = bands_array.filled() return bands_array
def execute(self, eopatch): """Add those vegeation indices to the eo-patch for futur use""" bands_array = self.mask_pixels(eopatch) illumination_array = eopatch.data["ILLUMINATION"] # Raw data self.B02 = bands_array[..., 0] self.B03 = bands_array[..., 1] self.B04 = bands_array[..., 2] self.B05 = bands_array[..., 3] self.B06 = bands_array[..., 4] self.B07 = bands_array[..., 5] self.B08 = bands_array[..., 6] self.B8A = bands_array[..., 7] self.B11 = bands_array[..., 8] self.B12 = bands_array[..., 9] self.viewZenithMean = illumination_array[..., 0] self.sunZenithAngles = illumination_array[..., 1] self.viewAzimuthMean = illumination_array[..., 2] self.sunAzimuthAngles = illumination_array[..., 3] self.get_vegetation_indices() self.get_biophysical_parameters() add_feat = AddFeatureTask((FeatureType.DATA, "fapar")) add_feat.execute(eopatch=eopatch, data=self.fapar[..., np.newaxis]) add_feat = AddFeatureTask((FeatureType.DATA, "LAI")) add_feat.execute(eopatch=eopatch, data=self.LAI[..., np.newaxis]) add_feat = AddFeatureTask((FeatureType.DATA, "CCC")) add_feat.execute(eopatch=eopatch, data=self.CCC[..., np.newaxis]) add_feat = AddFeatureTask((FeatureType.DATA, "Cab")) add_feat.execute(eopatch=eopatch, data=self.Cab[..., np.newaxis]) add_feat = AddFeatureTask((FeatureType.DATA, "CCW")) add_feat.execute(eopatch=eopatch, data=self.CCW[..., np.newaxis]) add_feat = AddFeatureTask((FeatureType.DATA, "CW")) add_feat.execute(eopatch=eopatch, data=self.CW[..., np.newaxis]) add_feat = AddFeatureTask((FeatureType.DATA, "fcover")) add_feat.execute(eopatch=eopatch, data=self.fcover[..., np.newaxis]) add_NDVI = AddFeatureTask((FeatureType.DATA, "NDVI")) add_NDVI.execute(eopatch=eopatch, data=self.NDVI[..., np.newaxis]) add_NDWI = AddFeatureTask((FeatureType.DATA, "NDWI")) add_NDWI.execute(eopatch=eopatch, data=self.NDWI[..., np.newaxis]) add_GNDVI = AddFeatureTask((FeatureType.DATA, "GNDVI")) add_GNDVI.execute(eopatch=eopatch, data=self.GNDVI[..., np.newaxis]) add_NDVIre = AddFeatureTask((FeatureType.DATA, "NDVIre")) add_NDVIre.execute(eopatch=eopatch, data=self.NDVIre[..., np.newaxis]) if "ILLUMINATION" in eopatch.data.keys(): remove_task = RemoveFeatureTask((FeatureType.DATA, "ILLUMINATION")) remove_task.execute(eopatch) return eopatch
[docs]class EuclideanNorm(EOTask): """ The tasks calculates Euclidian Norm of all bands within an array: norm = sqrt(sum_i Bi**2), where Bi are the individual bands within user-specified feature array. """ def __init__(self, feature_name, in_feature_name): self.feature_name = feature_name self.in_feature_name = in_feature_name def execute(self, eopatch): arr = eopatch.data[self.in_feature_name] norm = np.sqrt(np.sum(arr**2, axis=-1)) add_ecnorm = AddFeatureTask((FeatureType.DATA, self.feature_name)) return add_ecnorm.execute(eopatch=eopatch, data=norm[..., np.newaxis])