test_enpt_enmapboxapp.py 7.59 KB
Newer Older
Daniel Scheffler's avatar
Daniel Scheffler committed
1
2
3
#!/usr/bin/env python
# -*- coding: utf-8 -*-

4
5
# enpt_enmapboxapp, A QGIS EnMAPBox plugin providing a GUI for the EnMAP processing tools (EnPT)
#
6
# Copyright (C) 2018-2021 Daniel Scheffler (GFZ Potsdam, daniel.scheffler@gfz-potsdam.de)
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#
# 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
# the terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# 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/>.

Daniel Scheffler's avatar
Daniel Scheffler committed
26
27
"""Tests for `enpt_enmapboxapp` package."""

28
import os
29
30
from tempfile import TemporaryDirectory
import pickle
31

32
from unittest import TestCase, skipIf
33
from qgis.core import QgsProcessingAlgorithm, QgsProcessingContext, QgsProcessingFeedback, QgsProcessingProvider, NULL
Daniel Scheffler's avatar
Daniel Scheffler committed
34

Daniel Scheffler's avatar
Daniel Scheffler committed
35
from enmapbox.testing import initQgisApplication
36
37
38
from enpt_enmapboxapp.enpt_enmapboxapp import EnPTEnMAPBoxApp, EnMAPBoxApplication
from enpt_enmapboxapp.enpt_algorithm import EnPTAlgorithm
from enpt_enmapboxapp.enpt_external_algorithm import ExternalEnPTAlgorithm
39
# from enpt_enmapboxapp.enpt_enmapboxapp import ExampleAppGUI
Daniel Scheffler's avatar
Daniel Scheffler committed
40

Daniel Scheffler's avatar
Daniel Scheffler committed
41
42
# initialize the QGIS API + several background states
APP = initQgisApplication()
Daniel Scheffler's avatar
Daniel Scheffler committed
43

Daniel Scheffler's avatar
Daniel Scheffler committed
44
45
# set on True to show widgets and wait until a user closes them.
SHOW_GUI = True
Daniel Scheffler's avatar
Daniel Scheffler committed
46

47
48
# os.environ['QT_X11_NO_MITSHM'] = "1"

49
# FIXME replace hardcoded paths
50
enpt_test_parameters = dict(
51
    anaconda_root='',
52
53
54
55
56
    CPUs=12,
    auto_download_ecmwf=False,
    deadpix_P_algorithm='spectral',
    deadpix_P_interp_spectral='linear',
    deadpix_P_interp_spatial='linear',
57
    drop_bad_bands=True,
58
    disable_progress_bars=False,
59
    output_format='GTiff',
60
61
62
63
    enable_keystone_correction=False,
    enable_vnir_swir_coreg=False,
    json_config=None,
    n_lines_to_append=NULL,
64
    mode_ac='combined',
65
    ortho_resampAlg='bilinear',
66
    vswir_overlap_algorithm='vnir_only',
67
68
69
70
71
    output_dir='TEMPORARY_OUTPUT',
    path_earthSunDist=None,
    path_l1b_enmap_image='D:\\Daten\\Code\\python\\EnPT\\tests\\data\\EnMAP_Level_1B\\'
                         'ENMAP01-____L1B-DT000000987_20130205T105307Z_001_V000101_20190426T143700Z__rows0-99.zip',
    path_l1b_enmap_image_gapfill=None,
72
    path_dem='D:\\Daten\\Code\\python\\EnPT\\tests\\data\\DLR_L2A_DEM_UTM32.bsq',
73
74
75
76
77
78
79
    path_reference_image=None,
    path_solar_irr=None,
    run_deadpix_P=True,
    run_smile_P=False,
    scale_factor_boa_ref=10000,
    scale_factor_toa_ref=10000,
    sicor_cache_dir=None,
80
    target_projection_type='UTM',
81
82
    working_dir=None)

Daniel Scheffler's avatar
Daniel Scheffler committed
83

Daniel Scheffler's avatar
Daniel Scheffler committed
84
class TestExampleEnMAPBoxApp(TestCase):
Daniel Scheffler's avatar
Daniel Scheffler committed
85

86
87
88
89
90
91
92
93
94
95
96
97
98
    # def test_algorithms(self):
    #     """
    #     Test your core algorithms, which might not require any GUI or QGIS.
    #     """
    #
    #     args, kwds = exampleAlgorithm()
    #
    #     self.assertEqual(args, ())
    #     self.assertEqual(kwds, dict())
    #
    #     args, kwds = exampleAlgorithm(42, foo='bar')
    #     self.assertEqual(args[0], 42)
    #     self.assertEqual(kwds['foo'], 'bar')
Daniel Scheffler's avatar
Daniel Scheffler committed
99
100

    def test_processingAlgorithms(self):
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
        for algname, ALG in zip(['EnPTAlgorithm', 'ExternalEnPTAlgorith'],
                                [EnPTAlgorithm, ExternalEnPTAlgorithm]):

            with self.subTest(ALG=algname):
                try:
                    os.environ['IS_ENPT_GUI_TEST'] = '1'

                    alg = ALG()
                    self.assertIsInstance(alg, QgsProcessingAlgorithm)

                    alg2 = alg.createInstance()
                    self.assertIsInstance(alg2, QgsProcessingAlgorithm)

                    with TemporaryDirectory() as td:
                        params = enpt_test_parameters.copy()
                        params['output_dir'] = td
                        params['path_l1b_enmap_image'] = os.path.join('dummy', 'path', 'to', 'EnMAP_file.zip')
                        params['path_dem'] = os.path.join('dummy', 'path', 'to', 'DEM.bsq')

                        # call the EnPT_Controller with the above params, it will pickle.dump them to disk
                        outputs = alg.processAlgorithm(params,
                                                       QgsProcessingContext(),
                                                       QgsProcessingFeedback())

                        self.assertIsInstance(outputs, dict)
                        self.assertTrue(outputs['success'] is True,
                                        'EnPT could not be called or did not output the expected results.')

                        # unpickle the dumped args/kwargs and validate that EnPT received them correctly
                        content = None
                        try:
                            with open(os.path.join(td, 'received_args_kwargs.pkl'), 'rb') as inF:
                                content = pickle.load(inF)
                        except FileNotFoundError:
                            pass

                        self.assertIsNotNone(content, 'The EnPT_Controller did not dump the '
                                                      'received arguments or did not receive any.')

                        none_params = [k for k, v in params.items() if params[k] in [None, NULL]]
                        for k, v in params.items():
                            if k not in ['anaconda_root', 'json_config'] + none_params:
                                self.assertTrue(k in content['kwargs'],
                                                f"Missing key '{k}' in received parameters.")
                                self.assertEqual(v, content['kwargs'][k])

                finally:
                    del os.environ['IS_ENPT_GUI_TEST']
149

150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
    # def test_dialog(self):
    #     """
    #     Test your Qt GUI components, without any EnMAP-Box
    #     """
    #     g = ExampleAppGUI()
    #     g.show()
    #
    #     self.assertIsInstance(g.numberOfClicks(), int)
    #     self.assertEqual(g.numberOfClicks(), 0)
    #
    #     # click the button programmatically
    #     g.btn.click()
    #     self.assertEqual(g.numberOfClicks(), 1)
    #
    #     if SHOW_GUI:
    #         APP.exec_()
Daniel Scheffler's avatar
Daniel Scheffler committed
166

167
    @skipIf(os.getenv('IS_CI_ENV'), reason='to be tested manually')
Daniel Scheffler's avatar
Daniel Scheffler committed
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
    def test_with_EnMAPBox(self):
        """
        Finally, test if your application can be added into the EnMAP-Box
        """
        from enmapbox import EnMAPBox
        enmapBox = EnMAPBox(None)
        self.assertIsInstance(enmapBox, EnMAPBox)

        myApp = EnPTEnMAPBoxApp(enmapBox)
        self.assertIsInstance(myApp, EnMAPBoxApplication)
        enmapBox.addApplication(myApp)

        provider = enmapBox.processingProvider()
        self.assertIsInstance(provider, QgsProcessingProvider)
        algorithmNames = [a.name() for a in provider.algorithms()]
183
        for name in ['EnPTAlgorithm', ]:
Daniel Scheffler's avatar
Daniel Scheffler committed
184
185
186
187
188
189
190
191
192
            self.assertTrue(name in algorithmNames)

        if SHOW_GUI:
            APP.exec_()


if __name__ == "__main__":
    import unittest
    SHOW_GUI = False
193
194
195
196
197
198
199

    # quiet matplotlib
    import logging
    mpl_logger = logging.getLogger('matplotlib')
    mpl_logger.setLevel(logging.WARNING)

    # run tests
Daniel Scheffler's avatar
Daniel Scheffler committed
200
    unittest.main()