Coverage for enpt/options/options_schema.py: 96%

25 statements  

« prev     ^ index     » next       coverage.py v7.4.1, created at 2024-03-07 11:39 +0000

1# -*- coding: utf-8 

2 

3# EnPT, EnMAP Processing Tool - A Python package for pre-processing of EnMAP Level-1B data 

4# 

5# Copyright (C) 2018-2024 Karl Segl (GFZ Potsdam, segl@gfz-potsdam.de), Daniel Scheffler 

6# (GFZ Potsdam, danschef@gfz-potsdam.de), Niklas Bohn (GFZ Potsdam, nbohn@gfz-potsdam.de), 

7# Stéphane Guillaso (GFZ Potsdam, stephane.guillaso@gfz-potsdam.de) 

8# 

9# This software was developed within the context of the EnMAP project supported 

10# by the DLR Space Administration with funds of the German Federal Ministry of 

11# Economic Affairs and Energy (on the basis of a decision by the German Bundestag: 

12# 50 EE 1529) and contributions from DLR, GFZ and OHB System AG. 

13# 

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

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

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

17# version. Please note the following exception: `EnPT` depends on tqdm, which 

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

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

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

21# 

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

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

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

25# details. 

26# 

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

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

29 

30"""Definition of EnPT options schema (as used by cerberus library).""" 

31 

32 

33enpt_schema_input = dict( 

34 

35 general_opts=dict( 

36 type='dict', required=False, 

37 schema=dict( 

38 CPUs=dict(type='integer', required=False, nullable=True), 

39 log_level=dict(type='string', required=False, allowed=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL']), 

40 create_logfile=dict(type='boolean', required=False), 

41 path_l1b_enmap_image=dict(type='string', required=False), 

42 path_l1b_enmap_image_gapfill=dict(type='string', required=False), 

43 path_dem=dict(type='string', required=False), 

44 is_dummy_dataformat=dict(type='boolean', required=False), 

45 average_elevation=dict(type='integer', required=False), 

46 path_l1b_snr_model=dict(type='string', required=False), 

47 working_dir=dict(type='string', required=False, nullable=True), 

48 n_lines_to_append=dict(type='integer', required=False, nullable=True, min=0), 

49 drop_bad_bands=dict(type='boolean', required=False), 

50 disable_progress_bars=dict(type='boolean', required=False, nullable=True), 

51 )), 

52 

53 output=dict( 

54 type='dict', required=False, 

55 schema=dict( 

56 output_dir=dict(type='string', required=False), 

57 output_format=dict(type='string', required=False, allowed=['GTiff', 'ENVI']), 

58 output_interleave=dict(type='string', required=False, allowed=['band', 'line', 'pixel']), 

59 output_nodata_value=dict(type='integer', required=False, min=-32768, max=32767) 

60 )), 

61 

62 processors=dict( 

63 type='dict', required=False, 

64 schema=dict( 

65 

66 toa_ref=dict( 

67 type='dict', required=False, 

68 schema=dict( 

69 path_earthSunDist=dict(type='string', required=False), 

70 path_solar_irr=dict(type='string', required=False), 

71 scale_factor_toa_ref=dict(type='integer', required=False, min=1), 

72 )), 

73 

74 geometry=dict( 

75 type='dict', required=False, 

76 schema=dict( 

77 enable_keystone_correction=dict(type='boolean', required=False), 

78 enable_vnir_swir_coreg=dict(type='boolean', required=False), 

79 enable_absolute_coreg=dict(type='boolean', required=False), 

80 path_reference_image=dict(type='string', required=False), 

81 )), 

82 

83 atmospheric_correction=dict( 

84 type='dict', required=False, 

85 schema=dict( 

86 polymer_root=dict(type='string', required=False), 

87 enable_ac=dict(type='boolean', required=False), 

88 mode_ac=dict(type='string', required=False, allowed=['land', 'water', 'combined']), 

89 polymer_additional_results=dict(type='boolean', required=False), 

90 auto_download_ecmwf=dict(type='boolean', required=False), 

91 scale_factor_boa_ref=dict(type='integer', required=False, min=1), 

92 threads=dict(type='integer', required=False), 

93 blocksize=dict(type='integer', required=False), 

94 

95 )), 

96 

97 smile=dict( 

98 type='dict', required=False, 

99 schema=dict( 

100 run_processor=dict(type='boolean', required=False), 

101 )), 

102 

103 dead_pixel=dict( 

104 type='dict', required=False, 

105 schema=dict( 

106 run_processor=dict(type='boolean', required=False), 

107 algorithm=dict(type='string', required=False, allowed=['spectral', 'spatial']), 

108 interp_method_spectral=dict(type='string', required=False, 

109 allowed=['linear', 'quadratic', 'cubic']), 

110 interp_method_spatial=dict(type='string', required=False, 

111 allowed=['linear', 'nearest', 'zero', 'slinear', 'quadratic', 'cubic']), 

112 )), 

113 

114 orthorectification=dict( 

115 type='dict', required=False, 

116 schema=dict( 

117 resamp_alg=dict(type='string', required=False, allowed=['nearest', 'bilinear', 'gauss', 'cubic', 

118 'cubic_spline', 'lanczos', 'average', 

119 'mode', 'max', 'min', 'med', 'q1', 'q3']), 

120 vswir_overlap_algorithm=dict(type='string', required=False, 

121 allowed=['order_by_wvl', 'average', 'vnir_only', 'swir_only']), 

122 target_projection_type=dict(type='string', required=False, allowed=['UTM', 'Geographic']), 

123 target_epsg=dict(type='integer', required=False, nullable=True, min=0, forbidden=[0]), 

124 target_coord_grid=dict(type='list', required=False, nullable=True, minlength=4, maxlength=4) 

125 )) 

126 )) 

127) 

128 

129 

130parameter_mapping = dict( 

131 # general opts 

132 CPUs=('general_opts', 'CPUs'), 

133 log_level=('general_opts', 'log_level'), 

134 create_logfile=('general_opts', 'create_logfile'), 

135 path_l1b_enmap_image=('general_opts', 'path_l1b_enmap_image'), 

136 path_l1b_enmap_image_gapfill=('general_opts', 'path_l1b_enmap_image_gapfill'), 

137 path_dem=('general_opts', 'path_dem'), 

138 is_dummy_dataformat=('general_opts', 'is_dummy_dataformat'), 

139 average_elevation=('general_opts', 'average_elevation'), 

140 path_l1b_snr_model=('general_opts', 'path_l1b_snr_model'), 

141 working_dir=('general_opts', 'working_dir'), 

142 n_lines_to_append=('general_opts', 'n_lines_to_append'), 

143 drop_bad_bands=('general_opts', 'drop_bad_bands'), 

144 disable_progress_bars=('general_opts', 'disable_progress_bars'), 

145 

146 # output 

147 output_dir=('output', 'output_dir'), 

148 output_format=('output', 'output_format'), 

149 output_interleave=('output', 'output_interleave'), 

150 output_nodata_value=('output', 'output_nodata_value'), 

151 

152 # processors > toa_ref 

153 path_earthSunDist=('processors', 'toa_ref', 'path_earthSunDist'), 

154 path_solar_irr=('processors', 'toa_ref', 'path_solar_irr'), 

155 scale_factor_toa_ref=('processors', 'toa_ref', 'scale_factor_toa_ref'), 

156 

157 # processors > geometry 

158 enable_keystone_correction=('processors', 'geometry', 'enable_keystone_correction'), 

159 enable_vnir_swir_coreg=('processors', 'geometry', 'enable_vnir_swir_coreg'), 

160 enable_absolute_coreg=('processors', 'geometry', 'enable_absolute_coreg'), 

161 path_reference_image=('processors', 'geometry', 'path_reference_image'), 

162 

163 # processors > atmospheric_correction 

164 polymer_root=('processors', 'atmospheric_correction', 'polymer_root'), 

165 enable_ac=('processors', 'atmospheric_correction', 'enable_ac'), 

166 mode_ac=('processors', 'atmospheric_correction', 'mode_ac'), 

167 polymer_additional_results=('processors', 'atmospheric_correction', 'polymer_additional_results'), 

168 auto_download_ecmwf=('processors', 'atmospheric_correction', 'auto_download_ecmwf'), 

169 scale_factor_boa_ref=('processors', 'atmospheric_correction', 'scale_factor_boa_ref'), 

170 threads=('processors', 'atmospheric_correction', 'threads'), 

171 blocksize=('processors', 'atmospheric_correction', 'blocksize'), 

172 

173 # processors > smile 

174 run_smile_P=('processors', 'smile', 'run_processor'), 

175 

176 # processors > dead_pixel 

177 run_deadpix_P=('processors', 'dead_pixel', 'run_processor'), 

178 deadpix_P_algorithm=('processors', 'dead_pixel', 'algorithm'), 

179 deadpix_P_interp_spectral=('processors', 'dead_pixel', 'interp_method_spectral'), 

180 deadpix_P_interp_spatial=('processors', 'dead_pixel', 'interp_method_spatial'), 

181 

182 # processors > orthorectification 

183 ortho_resampAlg=('processors', 'orthorectification', 'resamp_alg'), 

184 vswir_overlap_algorithm=('processors', 'orthorectification', 'vswir_overlap_algorithm'), 

185 target_projection_type=('processors', 'orthorectification', 'target_projection_type'), 

186 target_epsg=('processors', 'orthorectification', 'target_epsg'), 

187 target_coord_grid=('processors', 'orthorectification', 'target_coord_grid'), 

188) 

189 

190 

191def get_updated_schema(source_schema, key2update, new_value): 

192 def deep_update(schema, key2upd, new_val): 

193 """Return true if update, else false.""" 

194 for key in schema: 

195 if key == key2upd: 

196 schema[key] = new_val 

197 elif isinstance(schema[key], dict): 

198 deep_update(schema[key], key2upd, new_val) 

199 

200 return schema 

201 

202 from copy import deepcopy 

203 tgt_schema = deepcopy(source_schema) 

204 

205 tgt_schema['processors']['schema']['orthorectification']['schema']['target_coord_grid'] = \ 

206 dict(type='dict', required=False, nullable=True) 

207 

208 return deep_update(tgt_schema, key2update, new_value) 

209 

210 

211enpt_schema_config_output = get_updated_schema(enpt_schema_input, key2update='required', new_value=True) 

212 

213 

214def get_param_from_json_config(paramname, json_config): 

215 keymap = parameter_mapping[paramname] # tuple 

216 

217 dict2search = json_config 

218 for i, k in enumerate(keymap): 

219 if i < len(keymap) - 1: 

220 # not the last element of the tuple -> contains a sub-dictionary 

221 dict2search = dict2search[k] 

222 elif isinstance(k, list): 

223 return [dict2search[sk] for sk in k] 

224 else: 

225 return dict2search[k]