Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1# -*- coding: utf-8 -*- 

2 

3# gms_preprocessing, spatial and spectral homogenization of satellite remote sensing data 

4# 

5# Copyright (C) 2020 Daniel Scheffler (GFZ Potsdam, daniel.scheffler@gfz-potsdam.de) 

6# 

7# This software was developed within the context of the GeoMultiSens project funded 

8# by the German Federal Ministry of Education and Research 

9# (project grant code: 01 IS 14 010 A-C). 

10# 

11# This program is free software: you can redistribute it and/or modify it under 

12# the terms of the GNU General Public License as published by the Free Software 

13# Foundation, either version 3 of the License, or (at your option) any later version. 

14# Please note the following exception: `gms_preprocessing` depends on tqdm, which 

15# is distributed under the Mozilla Public Licence (MPL) v2.0 except for the files 

16# "tqdm/_tqdm.py", "setup.py", "README.rst", "MANIFEST.in" and ".gitignore". 

17# Details can be found here: https://github.com/tqdm/tqdm/blob/master/LICENCE. 

18# 

19# This program is distributed in the hope that it will be useful, but WITHOUT 

20# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 

21# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 

22# details. 

23# 

24# You should have received a copy of the GNU Lesser General Public License along 

25# with this program. If not, see <http://www.gnu.org/licenses/>. 

26 

27"""Level 2C Processor: Quality layers""" 

28 

29import numpy as np 

30from collections import OrderedDict 

31 

32from geoarray import GeoArray 

33 

34from ..misc.definition_dicts import bandslist_all_errors, get_outFillZeroSaturated 

35from .L2B_P import L2B_object 

36from ..options.config import GMS_config as CFG 

37 

38__author__ = 'Daniel Scheffler' 

39 

40 

41class L2C_object(L2B_object): 

42 def __init__(self, L2B_obj=None): 

43 super(L2C_object, self).__init__() 

44 

45 if L2B_obj: 

46 # populate attributes 

47 [setattr(self, key, value) for key, value in L2B_obj.__dict__.items()] 

48 

49 self.proc_level = 'L2C' 

50 self.proc_status = 'initialized' 

51 

52 

53class AccuracyCube(GeoArray): 

54 def __init__(self, GMS_obj): 

55 self._GMS_obj = GMS_obj 

56 

57 # privates 

58 self._layers = None 

59 

60 if self.layers: 

61 GMS_obj.logger.info('Generating combined accuracy layers array..') 

62 super(AccuracyCube, self).__init__(self.generate_array(), 

63 geotransform=list(self.layers.values())[0].gt, 

64 projection=list(self.layers.values())[0].prj, 

65 bandnames=self.get_bandnames(), 

66 nodata=get_outFillZeroSaturated('int16')[0]) 

67 

68 else: 

69 raise ValueError('The given GMS_object contains no accuracy layers for combination.') 

70 

71 @property 

72 def layers(self): 

73 # type: () -> OrderedDict 

74 if not self._layers: 

75 errs = OrderedDict((band, getattr(self._GMS_obj, band)) for band in bandslist_all_errors) 

76 self._layers = \ 

77 OrderedDict((band, err) for band, err in errs.items() if isinstance(err, (np.ndarray, GeoArray))) 

78 

79 return self._layers 

80 

81 def get_bandnames(self): 

82 bandnames = [] 

83 for errArrName, errArr in self.layers.items(): 

84 if errArrName == 'ac_errors': 

85 if CFG.ac_bandwise_accuracy: 

86 bandnames.extend(['AC errors %s' % bN for bN in errArr.bandnames]) 

87 else: 

88 bandnames.append('median of AC errors') 

89 

90 elif errArrName == 'mask_clouds_confidence': 

91 bandnames.append('confidence of cloud mask') 

92 

93 elif errArrName == 'spat_homo_errors': 

94 bandnames.append('shift reliability percentage') 

95 

96 elif errArrName == 'spec_homo_errors': 

97 if CFG.spechomo_bandwise_accuracy: 

98 bandnames.extend(['error of spectral homogenization %s' % bN for bN in errArr.bandnames]) 

99 else: 

100 bandnames.append('median error of spectral homogenization') 

101 

102 else: 

103 raise RuntimeError('Error setting bandnames for %s.' % errArrName) 

104 

105 return bandnames 

106 

107 def generate_array(self): 

108 err_layers = self.layers.copy() # copy OrdDict, otherwise attributes of GMS_object are overwritten 

109 

110 # validate dimensionality of ac_errors array 

111 if 'ac_errors' in err_layers and not CFG.ac_bandwise_accuracy: 

112 assert err_layers['ac_errors'].ndim == 2, "Received a 3D 'ac_errors' array although CFG.ac_bandwise " \ 

113 "accuracy is False." 

114 

115 # # validate dimensionality of spec_homo_errors array 

116 if 'spec_homo_errors' in err_layers and not CFG.spechomo_bandwise_accuracy: 

117 assert err_layers['spec_homo_errors'].ndim == 2, "Received a 3D 'spec_homo_errors' array although " \ 

118 "CFG.spechomo_bandwise_accuracy is False." 

119 

120 # stack all accuracy layers together 

121 accArr = np.dstack(list(err_layers.values())).astype('int16') 

122 

123 # apply int16 nodata value 

124 accArr[self._GMS_obj.arr.mask_nodata.astype(np.int8) == 0] = get_outFillZeroSaturated('int16')[0] 

125 

126 return accArr