options_schema.py 10.3 KB
Newer Older
1
2
# -*- coding: utf-8

3
# EnPT, EnMAP Processing Tool - A Python package for pre-processing of EnMAP Level-1B data
4
#
Daniel Scheffler's avatar
Daniel Scheffler committed
5
# Copyright (C) 2018-2021 Karl Segl (GFZ Potsdam, segl@gfz-potsdam.de), Daniel Scheffler
6
7
# (GFZ Potsdam, danschef@gfz-potsdam.de), Niklas Bohn (GFZ Potsdam, nbohn@gfz-potsdam.de),
# Stéphane Guillaso (GFZ Potsdam, stephane.guillaso@gfz-potsdam.de)
8
9
10
11
12
13
14
#
# This software was developed within the context of the EnMAP project supported
# by the DLR Space Administration with funds of the German Federal Ministry of
# Economic Affairs and Energy (on the basis of a decision by the German Bundestag:
# 50 EE 1529) and contributions from DLR, GFZ and OHB System AG.
#
# This program is free software: you can redistribute it and/or modify it under
15
16
17
18
19
20
# the terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version. Please note the following exception: `EnPT` depends on tqdm, which
# is distributed under the Mozilla Public Licence (MPL) v2.0 except for the files
# "tqdm/_tqdm.py", "setup.py", "README.rst", "MANIFEST.in" and ".gitignore".
# Details can be found here: https://github.com/tqdm/tqdm/blob/master/LICENCE.
21
22
23
24
25
26
27
28
29
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# You should have received a copy of the GNU Lesser General Public License along
# with this program.  If not, see <http://www.gnu.org/licenses/>.

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


33
34
35
36
37
38
39
enpt_schema_input = dict(

    general_opts=dict(
        type='dict', required=False,
        schema=dict(
            CPUs=dict(type='integer', required=False, nullable=True),
            log_level=dict(type='string', required=False, allowed=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL']),
40
            create_logfile=dict(type='boolean', required=False),
41
42
            path_l1b_enmap_image=dict(type='string', required=False),
            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
54
55
56
        )),

    output=dict(
        type='dict', required=False,
        schema=dict(
            output_dir=dict(type='string', required=False),
57
58
            output_format=dict(type='string', required=False, allowed=['GTiff', 'ENVI']),
            output_interleave=dict(type='string', required=False, allowed=['band', 'line', 'pixel'])
59
60
61
62
63
64
65
66
67
68
69
        )),

    processors=dict(
        type='dict', required=False,
        schema=dict(

            toa_ref=dict(
                type='dict', required=False,
                schema=dict(
                    path_earthSunDist=dict(type='string', required=False),
                    path_solar_irr=dict(type='string', required=False),
70
                    scale_factor_toa_ref=dict(type='integer', required=False, min=1),
71
72
73
74
75
76
77
                )),

            geometry=dict(
                type='dict', required=False,
                schema=dict(
                    enable_keystone_correction=dict(type='boolean', required=False),
                    enable_vnir_swir_coreg=dict(type='boolean', required=False),
78
                    enable_absolute_coreg=dict(type='boolean', required=False),
79
                    path_reference_image=dict(type='string', required=False),
80
81
82
83
84
                )),

            atmospheric_correction=dict(
                type='dict', required=False,
                schema=dict(
Brenner Silva's avatar
Brenner Silva committed
85
                    polymer_root=dict(type='string', required=False),
86
                    enable_ac=dict(type='boolean', required=False),
87
                    mode_ac=dict(type='string', required=False, allowed=['land', 'water', 'combined']),
88
                    auto_download_ecmwf=dict(type='boolean', required=False),
89
                    scale_factor_boa_ref=dict(type='integer', required=False, min=1),
Brenner Silva's avatar
Brenner Silva committed
90
                    threads=dict(type='integer', required=False),
bsilva's avatar
bsilva committed
91
92
                    blocksize=dict(type='integer', required=False),

93
94
95
96
97
98
99
100
101
102
103
104
                )),

            smile=dict(
                type='dict', required=False,
                schema=dict(
                    run_processor=dict(type='boolean', required=False),
                )),

            dead_pixel=dict(
                type='dict', required=False,
                schema=dict(
                    run_processor=dict(type='boolean', required=False),
105
                    algorithm=dict(type='string', required=False, allowed=['spectral', 'spatial']),
106
107
108
109
                    interp_method_spectral=dict(type='string', required=False,
                                                allowed=['linear', 'nearest', 'zero', 'slinear', 'quadratic', 'cubic']),
                    interp_method_spatial=dict(type='string', required=False,
                                               allowed=['linear', 'nearest', 'zero', 'slinear', 'quadratic', 'cubic']),
110
111
112
113
114
                )),

            orthorectification=dict(
                type='dict', required=False,
                schema=dict(
115
                    resamp_alg=dict(type='string', required=False, allowed=['nearest', 'bilinear', 'gauss']),
116
117
                    vswir_overlap_algorithm=dict(type='string', required=False,
                                                 allowed=['order_by_wvl', 'average', 'vnir_only', 'swir_only']),
118
119
120
                    target_projection_type=dict(type='string', required=False, allowed=['UTM', 'Geographic']),
                    target_epsg=dict(type='integer', required=False, nullable=True, min=0, forbidden=[0]),
                    target_coord_grid=dict(type='list', required=False, nullable=True, minlength=4, maxlength=4)
121
122
123
                ))
        ))
)
124
125
126
127
128
129


parameter_mapping = dict(
    # general opts
    CPUs=('general_opts', 'CPUs'),
    log_level=('general_opts', 'log_level'),
130
    create_logfile=('general_opts', 'create_logfile'),
131
132
    path_l1b_enmap_image=('general_opts', 'path_l1b_enmap_image'),
    path_l1b_enmap_image_gapfill=('general_opts', 'path_l1b_enmap_image_gapfill'),
133
    path_dem=('general_opts', 'path_dem'),
134
    is_dummy_dataformat=('general_opts', 'is_dummy_dataformat'),
135
    average_elevation=('general_opts', 'average_elevation'),
136
    path_l1b_snr_model=('general_opts', 'path_l1b_snr_model'),
137
    working_dir=('general_opts', 'working_dir'),
138
    n_lines_to_append=('general_opts', 'n_lines_to_append'),
139
    drop_bad_bands=('general_opts', 'drop_bad_bands'),
140
    disable_progress_bars=('general_opts', 'disable_progress_bars'),
141
142
143

    # output
    output_dir=('output', 'output_dir'),
144
    output_format=('output', 'output_format'),
145
    output_interleave=('output', 'output_interleave'),
146
147
148
149

    # processors > toa_ref
    path_earthSunDist=('processors', 'toa_ref', 'path_earthSunDist'),
    path_solar_irr=('processors', 'toa_ref', 'path_solar_irr'),
150
    scale_factor_toa_ref=('processors', 'toa_ref', 'scale_factor_toa_ref'),
151
152
153
154

    # processors > geometry
    enable_keystone_correction=('processors', 'geometry', 'enable_keystone_correction'),
    enable_vnir_swir_coreg=('processors', 'geometry', 'enable_vnir_swir_coreg'),
155
    enable_absolute_coreg=('processors', 'geometry', 'enable_absolute_coreg'),
156
    path_reference_image=('processors', 'geometry', 'path_reference_image'),
157
158

    # processors > atmospheric_correction
Brenner Silva's avatar
Brenner Silva committed
159
    polymer_root=('processors', 'atmospheric_correction', 'polymer_root'),
160
    enable_ac=('processors', 'atmospheric_correction', 'enable_ac'),
161
    mode_ac=('processors', 'atmospheric_correction', 'mode_ac'),
162
    auto_download_ecmwf=('processors', 'atmospheric_correction', 'auto_download_ecmwf'),
163
    scale_factor_boa_ref=('processors', 'atmospheric_correction', 'scale_factor_boa_ref'),
Brenner Silva's avatar
Brenner Silva committed
164
    threads=('processors', 'atmospheric_correction', 'threads'),
bsilva's avatar
bsilva committed
165
    blocksize=('processors', 'atmospheric_correction', 'blocksize'),
166
167
168
169
170
171

    # processors > smile
    run_smile_P=('processors', 'smile', 'run_processor'),

    # processors > dead_pixel
    run_deadpix_P=('processors', 'dead_pixel', 'run_processor'),
172
    deadpix_P_algorithm=('processors', 'dead_pixel', 'algorithm'),
173
174
    deadpix_P_interp_spectral=('processors', 'dead_pixel', 'interp_method_spectral'),
    deadpix_P_interp_spatial=('processors', 'dead_pixel', 'interp_method_spatial'),
175
176
177

    # processors > orthorectification
    ortho_resampAlg=('processors', 'orthorectification', 'resamp_alg'),
178
    vswir_overlap_algorithm=('processors', 'orthorectification', 'vswir_overlap_algorithm'),
179
180
181
    target_projection_type=('processors', 'orthorectification', 'target_projection_type'),
    target_epsg=('processors', 'orthorectification', 'target_epsg'),
    target_coord_grid=('processors', 'orthorectification', 'target_coord_grid'),
182
183
184
185
186
)


def get_updated_schema(source_schema, key2update, new_value):
    def deep_update(schema, key2upd, new_val):
Daniel Scheffler's avatar
Daniel Scheffler committed
187
        """Return true if update, else false."""
188
189
190
191
192
193
194
195
196
197
        for key in schema:
            if key == key2upd:
                schema[key] = new_val
            elif isinstance(schema[key], dict):
                deep_update(schema[key], key2upd, new_val)

        return schema

    from copy import deepcopy
    tgt_schema = deepcopy(source_schema)
198
199
200
201

    tgt_schema['processors']['schema']['orthorectification']['schema']['target_coord_grid'] = \
        dict(type='dict', required=False, nullable=True)

202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
    return deep_update(tgt_schema, key2update, new_value)


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


def get_param_from_json_config(paramname, json_config):
    keymap = parameter_mapping[paramname]  # tuple

    dict2search = json_config
    for i, k in enumerate(keymap):
        if i < len(keymap) - 1:
            # not the last element of the tuple -> contains a sub-dictionary
            dict2search = dict2search[k]
        elif isinstance(k, list):
            return [dict2search[sk] for sk in k]
        else:
            return dict2search[k]