Completed
Push — develop ( 425f6a...0a4fb9 )
by Adam
13s
created

TestRayleigh.test_rayleigh_init()   B

Complexity

Conditions 4

Size

Total Lines 25

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
c 0
b 0
f 0
dl 0
loc 25
rs 8.5806
1
#!/usr/bin/env python
2
# -*- coding: utf-8 -*-
3
4
# Copyright (c) 2016, 2017, 2018 Adam.Dybbroe
5
6
# Author(s):
7
8
#   Adam.Dybbroe <[email protected]>
9
10
# This program is free software: you can redistribute it and/or modify
11
# it under the terms of the GNU General Public License as published by
12
# the Free Software Foundation, either version 3 of the License, or
13
# (at your option) any later version.
14
15
# This program is distributed in the hope that it will be useful,
16
# but WITHOUT ANY WARRANTY; without even the implied warranty of
17
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
# GNU General Public License for more details.
19
20
# You should have received a copy of the GNU General Public License
21
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
22
23
"""Unittest for the rayleigh correction utilities
24
"""
25
26
import sys
27
if sys.version_info < (2, 7):
28
    import unittest2 as unittest
29
else:
30
    import unittest
31
32
import numpy as np
33
from pyspectral import rayleigh
34
from pyspectral.rayleigh import BandFrequencyOutOfRange
35
from pyspectral.tests.data import (
36
    TEST_RAYLEIGH_LUT,
37
    TEST_RAYLEIGH_AZID_COORD,
38
    TEST_RAYLEIGH_SUNZ_COORD,
39
    TEST_RAYLEIGH_SATZ_COORD,
40
    TEST_RAYLEIGH_WVL_COORD)
41
42
43 View Code Duplication
TEST_RAYLEIGH_RESULT1 = np.array([10.40727436,   8.69775471], dtype='float32')
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
44
TEST_RAYLEIGH_RESULT2 = np.array([9.71695252,  8.51415601], dtype='float32')
45
TEST_RAYLEIGH_RESULT3 = np.array([5.61532271,  8.69267476], dtype='float32')
46
47
48
import os
49
from mock import patch
50
51
# Mock some modules, so we don't need them for tests.
52
53
# sys.modules['pyresample'] = MagicMock()
54
55
56
class RelativeSpectralResponseTestData(object):
57
58
    """RSR test data"""
59
60
    def __init__(self):
61
        """Making a testdata set of relative spectral responses"""
62
63
        self.rsr = {}
64
        channel_names = ['ch12', 'ch13', 'ch10', 'ch11', 'ch16', 'ch14',
65
                         'ch15', 'ch1', 'ch2', 'ch3', 'ch4', 'ch5', 'ch6',
66
                         'ch7', 'ch8', 'ch9']
67
        wvl = [9.6372744012936646, 10.407492196078628, 7.3468642293967275,
68
               8.5926867614178715, 13.280724258676756, 11.239642285822033,
69
               12.380741429961382, 0.47063607733748003, 0.5099976405799187,
70
               0.63914891611559055, 0.85668832355426627, 1.6100814361999056,
71
               2.2568056299864101, 3.8853663735353847, 6.2428987228916233,
72
               6.9411756334211789]
73
        ch3_wvl = np.array([0.55518544, 0.56779468, 0.58099002, 0.59481323, 0.60931027,
74
                            0.62453163, 0.64053291, 0.65737575, 0.67512828, 0.69386619,
75
                            0.71367401])
76
        ch3_resp = np.array([2.61000005e-05, 1.07899999e-04, 3.26119992e-03,
77
                             2.90650606e-01, 9.02460396e-01, 9.60878074e-01,
78
                             9.97266889e-01, 9.94823873e-01, 7.18220174e-01,
79
                             8.31819978e-03, 9.34999989e-05])
80
81
        idx = 0
82
        for chname in channel_names:
83
            self.rsr[chname] = {'det-1': {}}
84
            self.rsr[chname]['det-1']['central_wavelength'] = wvl[idx]
85
            idx = idx + 1
86
87
        chname = 'ch3'
88
        self.rsr[chname]['det-1']['wavelength'] = ch3_wvl
89
        self.rsr[chname]['det-1']['response'] = ch3_resp
90
91
92
class TestRayleigh(unittest.TestCase):
93
94
    """Class for testing pyspectral.rayleigh"""
95
96
    def setUp(self):
97
        """Setup the test"""
98
99
        self.rsr = RelativeSpectralResponseTestData()
100
101
        # mymock:
102
        with patch('pyspectral.rayleigh.RelativeSpectralResponse') as mymock:
103
            instance = mymock.return_value
104
            instance.rsr = RelativeSpectralResponseTestData().rsr
105
            instance.unit = '1e-6 m'
106
            instance.si_scale = 1e-6
107
108
            self.viirs_rayleigh = rayleigh.Rayleigh('NOAA-20', 'viirs', atmosphere='midlatitude summer')
109
110
    def test_get_effective_wavelength(self):
111
        """Test getting the effective wavelength"""
112
113
        # mymock:
114
        with patch('pyspectral.rayleigh.RelativeSpectralResponse') as mymock:
115
            instance = mymock.return_value
116
            instance.rsr = RelativeSpectralResponseTestData().rsr
117
118
            this = rayleigh.Rayleigh('Himawari-8', 'ahi')
119
            with self.assertRaises(BandFrequencyOutOfRange):
120
                this.get_effective_wavelength(0.9)
121
122
            # Only ch3 (~0.63) testdata implemented yet...
123
            ewl = this.get_effective_wavelength(0.65)
124
            self.assertAlmostEqual(ewl, 0.6356167)
125
126
        # mymock:
127
        with patch('pyspectral.rayleigh.RelativeSpectralResponse') as mymock:
128
            instance = mymock.side_effect = IOError(
129
                'Fake that there is no spectral response file...')
130
131
            this = rayleigh.Rayleigh('Himawari-8', 'ahi')
132
            ewl = this.get_effective_wavelength(0.7)
133
            self.assertEqual(ewl, 0.7)
134
            ewl = this.get_effective_wavelength(0.9)
135
            self.assertEqual(ewl, 0.9)
136
            ewl = this.get_effective_wavelength(0.455)
137
            self.assertEqual(ewl, 0.455)
138
139
    @patch('os.path.exists')
140
    @patch('pyspectral.utils.download_luts')
141
    def test_rayleigh_init(self, download_luts, exists):
142
        """Test getting the effective wavelength"""
143
144
        download_luts.return_code = None
145
        exists.return_code = True
146
147
        # mymock:
148
        with patch('pyspectral.rayleigh.RelativeSpectralResponse') as mymock:
149
            instance = mymock.return_value
150
            instance.rsr = RelativeSpectralResponseTestData().rsr
151
152
            with self.assertRaises(AttributeError):
153
                this = rayleigh.Rayleigh('Himawari-8', 'ahi', atmosphere='unknown')
154
155
            with self.assertRaises(AttributeError):
156
                this = rayleigh.Rayleigh('Himawari-8', 'ahi', aerosol_type='unknown')
157
158
            this = rayleigh.Rayleigh('Himawari-8', 'ahi', atmosphere='subarctic winter')
159
            self.assertTrue(os.path.basename(this.reflectance_lut_filename).endswith('subarctic_winter.h5'))
160
            self.assertTrue(this.sensor == 'ahi')
161
162
            this = rayleigh.Rayleigh('NOAA-19', 'avhrr/3', atmosphere='tropical')
163
            self.assertTrue(this.sensor == 'avhrr3')
164
165
    @patch('os.path.exists')
166
    @patch('pyspectral.utils.download_luts')
167
    @patch('pyspectral.rayleigh.get_reflectance_lut')
168
    def test_get_reflectance(self, get_reflectance_lut, download_luts, exists):
169
        """Test getting the reflectance correction"""
170
171
        rayl = TEST_RAYLEIGH_LUT
172
        wvl_coord = TEST_RAYLEIGH_WVL_COORD
173
        azid_coord = TEST_RAYLEIGH_AZID_COORD
174
        sunz_sec_coord = TEST_RAYLEIGH_SUNZ_COORD
175
        satz_sec_coord = TEST_RAYLEIGH_SATZ_COORD
176
177
        get_reflectance_lut.return_value = (rayl, wvl_coord, azid_coord,
178
                                            satz_sec_coord, sunz_sec_coord)
179
        download_luts.return_code = None
180
        exists.return_code = True
181
182
        sun_zenith = np.array([67., 32.])
183
        sat_zenith = np.array([45., 18.])
184
        azidiff = np.array([150., 110.])
185
        blueband = np.array([14., 5.])
186
        retv = self.viirs_rayleigh.get_reflectance(sun_zenith, sat_zenith, azidiff, 'M2', blueband)
187
        self.assertTrue(np.allclose(retv, TEST_RAYLEIGH_RESULT1))
188
189
        sun_zenith = np.array([60., 20.])
190
        sat_zenith = np.array([49., 26.])
191
        azidiff = np.array([140., 130.])
192
        blueband = np.array([12., 8.])
193
        retv = self.viirs_rayleigh.get_reflectance(sun_zenith, sat_zenith, azidiff, 'M2', blueband)
194
        self.assertTrue(np.allclose(retv, TEST_RAYLEIGH_RESULT2))
195
196
    @patch('os.path.exists')
197
    @patch('pyspectral.utils.download_luts')
198
    @patch('pyspectral.rayleigh.get_reflectance_lut')
199
    def test_get_reflectance_no_rsr(self, get_reflectance_lut, download_luts, exists):
200
        """Test getting the reflectance correction, simulating that we have no RSR data"""
201
202
        rayl = TEST_RAYLEIGH_LUT
203
        wvl_coord = TEST_RAYLEIGH_WVL_COORD
204
        azid_coord = TEST_RAYLEIGH_AZID_COORD
205
        sunz_sec_coord = TEST_RAYLEIGH_SUNZ_COORD
206
        satz_sec_coord = TEST_RAYLEIGH_SATZ_COORD
207
208
        get_reflectance_lut.return_value = (rayl, wvl_coord, azid_coord,
209
                                            satz_sec_coord, sunz_sec_coord)
210
        download_luts.return_code = None
211
        exists.return_code = True
212
213
        with patch('pyspectral.rayleigh.RelativeSpectralResponse') as mymock:
214
            instance = mymock.return_value
215
            mymock.side_effect = IOError("No rsr data in pyspectral for this platform and sensor")
216
            instance.rsr = None
217
            instance.unit = '1e-6 m'
218
            instance.si_scale = 1e-6
219
            sun_zenith = np.array([50., 10.])
220
            sat_zenith = np.array([39., 16.])
221
            azidiff = np.array([170., 110.])
222
            blueband = np.array([29., 12.])
223
            ufo = rayleigh.Rayleigh('UFO', 'unknown')
224
225
            retv = ufo.get_reflectance(sun_zenith, sat_zenith, azidiff, 0.441, blueband)
226
            self.assertTrue(np.allclose(retv, TEST_RAYLEIGH_RESULT3))
227
228
    def tearDown(self):
229
        """Clean up"""
230
        pass
231
232
233
def suite():
234
    """The test suite for test_rayleigh.
235
    """
236
    loader = unittest.TestLoader()
237
    mysuite = unittest.TestSuite()
238
    mysuite.addTest(loader.loadTestsFromTestCase(TestRayleigh))
239
240
    return mysuite
241