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
« prev ^ index » next coverage.py v7.4.1, created at 2024-03-07 11:39 +0000
1# -*- coding: utf-8
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/>.
30"""Definition of EnPT options schema (as used by cerberus library)."""
33enpt_schema_input = dict(
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 )),
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 )),
62 processors=dict(
63 type='dict', required=False,
64 schema=dict(
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 )),
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 )),
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),
95 )),
97 smile=dict(
98 type='dict', required=False,
99 schema=dict(
100 run_processor=dict(type='boolean', required=False),
101 )),
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 )),
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)
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'),
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'),
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'),
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'),
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'),
173 # processors > smile
174 run_smile_P=('processors', 'smile', 'run_processor'),
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'),
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)
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)
200 return schema
202 from copy import deepcopy
203 tgt_schema = deepcopy(source_schema)
205 tgt_schema['processors']['schema']['orthorectification']['schema']['target_coord_grid'] = \
206 dict(type='dict', required=False, nullable=True)
208 return deep_update(tgt_schema, key2update, new_value)
211enpt_schema_config_output = get_updated_schema(enpt_schema_input, key2update='required', new_value=True)
214def get_param_from_json_config(paramname, json_config):
215 keymap = parameter_mapping[paramname] # tuple
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]