Completed
Pull Request — develop (#43)
by Angeline
03:39
created

TestConvertLatLon.test_convert_latlon_location_failure()   A

Complexity

Conditions 1

Size

Total Lines 6
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 5
dl 0
loc 6
rs 10
c 0
b 0
f 0
cc 1
nop 1
1
# -*- coding: utf-8 -*-
2
from __future__ import division, absolute_import, unicode_literals
3
4
import datetime as dt
5
from io import StringIO
6
import logging
7
import numpy as np
8
import os
9
from sys import version_info
10
import pytest
11
import warnings
12
13
import aacgmv2
14
15
class TestConvertLatLon:
16
    def setup(self):
17
        """Runs before every method to create a clean testing setup"""
18
        self.dtime = dt.datetime(2015, 1, 1, 0, 0, 0)
19
        self.ddate = dt.date(2015, 1, 1)
20
        self.in_args = [60, 0, 300, self.dtime, 'TRACE']
21
        self.out = None
22
        self.ref = [58.2258, 81.1685, 1.0457]
23
        self.rtol = 1.0e-4
24
25
    def teardown(self):
26
        """Runs after every method to clean up previous testing"""
27
        del self.out, self.in_args, self.ref, self.rtol, self.dtime, self.ddate
28
29
    def test_convert_latlon(self):
30
        """Test single value latlon conversion"""
31
        self.out = aacgmv2.convert_latlon(*self.in_args)
32
        np.testing.assert_allclose(self.out, self.ref, rtol=self.rtol)
33
34
    def test_convert_latlon_badidea(self):
35
        """Test single value latlon conversion with a bad flag"""
36
        self.in_args[2] = 3000.0
37
        self.in_args[-1] = "G2A|BADIDEA"
38
        self.ref = [64.3568, 83.3027, 1.4694]
39
        self.out = aacgmv2.convert_latlon(*self.in_args)
40
        np.testing.assert_allclose(self.out, self.ref, rtol=self.rtol)
41
42
    def test_convert_latlon_trace_badidea(self):
43
        """Test single value latlon conversion with a bad flag for trace"""
44
        self.in_args[2] = 7000.0
45
        self.in_args[-1] = "G2A|TRACE|BADIDEA"
46
        self.ref = [69.3174, 85.0995, 2.0973]
47
        self.out = aacgmv2.convert_latlon(*self.in_args)
48
        np.testing.assert_allclose(self.out, self.ref, rtol=self.rtol)
49
50
    @pytest.mark.skipif(version_info.major == 2,
51
                        reason='Not raised in Python 2')
52
    def test_convert_latlon_location_failure(self):
53
        """Test single value latlon conversion with a bad location"""
54
        self.out = aacgmv2.convert_latlon(0, 0, 0, self.dtime, self.in_args[-1])
55
        assert np.all(np.isnan(np.array(self.out)))
56
57
    def test_convert_latlon_time_failure(self):
58
        """Test single value latlon conversion with a bad datetime"""
59
        self.in_args[3] = None
60
        with pytest.raises(ValueError):
61
            self.out = aacgmv2.convert_latlon(*self.in_args)
62
63
    def test_convert_latlon_datetime_date(self):
64
        """Test single latlon conversion with date and datetime input"""
65
        self.in_args[3] = self.ddate
66
        self.out = aacgmv2.convert_latlon(*self.in_args)
67
        np.testing.assert_allclose(self.out, self.ref, rtol=self.rtol)
68
69
    def test_convert_latlon_maxalt_failure(self):
70
        """test convert_latlon failure for an altitude too high for coeffs"""
71
        self.in_args[2] = 2001
72
        self.in_args[-1] = ""
73
        self.out = aacgmv2.convert_latlon(*self.in_args)
74
        assert np.all(np.isnan(np.array(self.out)))
75
76
    def test_convert_latlon_lat_high_failure(self):
77
        """Test error return for co-latitudes above 90 for a single value"""
78
        with pytest.raises(ValueError):
79
            aacgmv2.convert_latlon(91, 0, 300, self.dtime)
80
81
    def test_convert_latlon_lat_low_failure(self):
82
        """Test error return for co-latitudes below -90 for a single value"""
83
        with pytest.raises(ValueError):
84
            aacgmv2.convert_latlon(-91, 0, 300, self.dtime)
85
86
class TestConvertLatLonArr:
87 View Code Duplication
    def setup(self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
88
        """Runs before every method to create a clean testing setup"""
89
        self.dtime = dt.datetime(2015, 1, 1, 0, 0, 0)
90
        self.ddate = dt.date(2015, 1, 1)
91
        self.lat_in = [60.0, 61.0]
92
        self.lon_in = [0.0, 0.0]
93
        self.alt_in = [300.0, 300.0]
94
        self.method = 'TRACE'
95
        self.out = None
96
        self.ref = [[58.22474610, 59.31648007], [81.17611033, 81.62281360],
97
                    [1.04566346, 1.04561304]]
98
        self.rtol = 1.0e-4
99
100
    def teardown(self):
101
        """Runs after every method to clean up previous testing"""
102
        del self.lat_in, self.lon_in, self.alt_in, self.dtime, self.ddate
103
        del self.method, self.out, self.ref, self.rtol
104
105
    def test_convert_latlon_arr_single_val(self):
106
        """Test array latlon conversion for a single value"""
107
        self.out = aacgmv2.convert_latlon_arr(self.lat_in[0], self.lon_in[0],
108
                                              self.alt_in[0], self.dtime,
109
                                              self.method)
110
111
        assert len(self.out) == len(self.ref)
112
        assert [isinstance(oo, np.ndarray) and len(oo) == 1 for oo in self.out]
113
114
        for i, oo in enumerate(self.out):
115
            np.testing.assert_allclose(oo, [self.ref[i][0]], rtol=self.rtol)
116
117 View Code Duplication
    def test_convert_latlon_arr_list_single(self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
118
        """Test array latlon conversion for list input of single values"""
119
        self.out = aacgmv2.convert_latlon_arr([self.lat_in[0]],
120
                                              [self.lon_in[0]],
121
                                              [self.alt_in[0]], self.dtime,
122
                                              self.method)
123
124
        assert len(self.out) == len(self.ref)
125
        assert [isinstance(oo, np.ndarray) and len(oo) == 1 for oo in self.out]
126
127
        for i, oo in enumerate(self.out):
128
            np.testing.assert_allclose(oo, [self.ref[i][0]], rtol=self.rtol)
129
130
    def test_convert_latlon_arr_list(self):
131
        """Test array latlon conversion for list input"""
132
        self.out = aacgmv2.convert_latlon_arr(self.lat_in, self.lon_in,
133
                                              self.alt_in, self.dtime,
134
                                              self.method)
135
136
        assert len(self.out) == len(self.ref)
137
        assert [isinstance(oo, np.ndarray) and len(oo) == len(self.ref[i])
138
                for i, oo in enumerate(self.out)]
139
140
        for i, oo in enumerate(self.out):
141
            np.testing.assert_allclose(oo, self.ref[i], rtol=self.rtol)
142
143 View Code Duplication
    def test_convert_latlon_arr_arr_single(self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
144
        """Test array latlon conversion for array input of shape (1,)"""
145
        self.out = aacgmv2.convert_latlon_arr(np.array([self.lat_in[0]]),
146
                                              np.array([self.lon_in[0]]),
147
                                              np.array([self.alt_in[0]]),
148
                                              self.dtime, self.method)
149
150
        assert len(self.out) == len(self.ref)
151
        assert [isinstance(oo, np.ndarray) and len(oo) == 1 for oo in self.out]
152
153
        for i, oo in enumerate(self.out):
154
            np.testing.assert_allclose(oo, [self.ref[i][0]], rtol=self.rtol)
155
156 View Code Duplication
    def test_convert_latlon_arr_arr(self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
157
        """Test array latlon conversion for array input"""
158
        self.out = aacgmv2.convert_latlon_arr(np.array(self.lat_in),
159
                                              np.array(self.lon_in),
160
                                              np.array(self.alt_in),
161
                                              self.dtime, self.method)
162
163
        assert len(self.out) == len(self.ref)
164
        assert [isinstance(oo, np.ndarray) and len(oo) == len(self.ref[i])
165
                for i, oo in enumerate(self.out)]
166
167
        for i, oo in enumerate(self.out):
168
            np.testing.assert_allclose(oo, self.ref[i], rtol=self.rtol)
169
170
    def test_convert_latlon_arr_list_mix(self):
171
        """Test array latlon conversion for mixed types with list"""
172
        self.out = aacgmv2.convert_latlon_arr(self.lat_in, self.lon_in[0],
173
                                              self.alt_in[0], self.dtime,
174
                                              self.method)
175
176
        assert len(self.out) == len(self.ref)
177
        assert [isinstance(oo, np.ndarray) and len(oo) == len(self.ref[i])
178
                for i, oo in enumerate(self.out)]
179
180
        for i, oo in enumerate(self.out):
181
            np.testing.assert_allclose(oo, self.ref[i], rtol=self.rtol)
182
183
    def test_convert_latlon_arr_arr_mix(self):
184
        """Test array latlon conversion for mixed type with an array"""
185
        self.out = aacgmv2.convert_latlon_arr(np.array(self.lat_in),
186
                                              self.lon_in[0], self.alt_in[0],
187
                                              self.dtime, self.method)
188
189
        assert len(self.out) == len(self.ref)
190
        assert [isinstance(oo, np.ndarray) and len(oo) == len(self.ref[i])
191
                for i, oo in enumerate(self.out)]
192
193
        for i, oo in enumerate(self.out):
194
            np.testing.assert_allclose(oo, self.ref[i], rtol=self.rtol)
195
196
    def test_convert_latlon_arr_mult_failure(self):
197
        """Test array latlon conversion for mix type with multi-dim array"""
198
        with pytest.raises(ValueError):
199
            aacgmv2.convert_latlon_arr(np.full(shape=(3,2), fill_value=50.0),
200
                                       0, 300, self.dtime)
201
202
203 View Code Duplication
    def test_convert_latlon_arr_badidea(self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
204
        """Test array latlon conversion for BADIDEA"""
205
        self.method = "G2A | BADIDEA"
206
        self.ref = [64.35677791, 83.30272053, 1.46944431]
207
        self.out = aacgmv2.convert_latlon_arr(self.lat_in[0], self.lon_in[0],
208
                                              [3000], self.dtime, self.method)
209
210
        assert len(self.out) == len(self.ref)
211
        assert [isinstance(oo, np.ndarray) and len(oo) == 1 for oo in self.out]
212
213
        for i, oo in enumerate(self.out):
214
            np.testing.assert_allclose(oo, [self.ref[i]], rtol=self.rtol)
215
216 View Code Duplication
    def test_convert_latlon_arr_badidea_trace(self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
217
        """Test array latlon conversion for BADIDEA with trace"""
218
        self.method = "G2A | BADIDEA | TRACE"
219
        self.ref = [69.317391, 85.099499, 2.09726]
220
        self.out = aacgmv2.convert_latlon_arr(self.lat_in[0], self.lon_in[0],
221
                                              [7000], self.dtime, self.method)
222
223
        assert len(self.out) == len(self.ref)
224
        assert [isinstance(oo, np.ndarray) and len(oo) == 1 for oo in self.out]
225
226
        for i, oo in enumerate(self.out):
227
            np.testing.assert_allclose(oo, [self.ref[i]], rtol=self.rtol)
228
229
    @pytest.mark.skipif(version_info.major == 2,
230
                        reason='Not raised in Python 2')
231
    def test_convert_latlon_arr_location_failure(self):
232
        """Test array latlon conversion with a bad location"""
233
234
        with warnings.catch_warnings():
235
            # Causes all warnings to be surpressed
236
            warnings.simplefilter("ignore")
237
238
            # Trigger a warning
239
            self.out = aacgmv2.convert_latlon_arr([0], [0], [0], self.dtime, "")
240
241
            # Test the output
242
            assert len(self.out) == len(self.ref)
243
            assert np.any(~np.isfinite(np.array(self.out)))
244
245
    def test_convert_latlon_arr_mult_arr_unequal_failure(self):
246
        """Test array latlon conversion for unequal sized arrays"""
247
        with pytest.raises(ValueError):
248
            aacgmv2.convert_latlon_arr(np.array([[60, 61, 62], [63, 64, 65]]),
249
                                       np.array([0, 1]), 300, self.dtime)
250
251
    def test_convert_latlon_arr_time_failure(self):
252
        """Test array latlon conversion with a bad time"""
253
        with pytest.raises(ValueError):
254
            aacgmv2.convert_latlon_arr(self.lat_in, self.lon_in, self.alt_in,
255
                                       None, self.method)
256
257
    def test_convert_latlon_arr_datetime_date(self):
258
        """Test array latlon conversion with date and datetime input"""
259
        self.out = aacgmv2.convert_latlon_arr(self.lat_in, self.lon_in,
260
                                              self.alt_in, self.ddate,
261
                                              self.method)
262
263
        assert len(self.out) == len(self.ref)
264
        assert [isinstance(oo, np.ndarray) and len(oo) == len(self.ref[i])
265
                for i, oo in enumerate(self.out)]
266
267
        for i, oo in enumerate(self.out):
268
            np.testing.assert_allclose(oo, self.ref[i], rtol=self.rtol)
269
270
    def test_convert_latlon_arr_maxalt_failure(self):
271
        """test convert_latlon_arr failure for altitudes too high for coeffs"""
272
        self.method = ""
273
        self.out = aacgmv2.convert_latlon_arr(self.lat_in[0], self.lon_in[0],
274
                                              [2001], self.dtime, self.method)
275
        assert np.all(np.isnan(np.array(self.out)))
276
277
    def test_convert_latlon_arr_lat_failure(self):
278
        """Test error return for co-latitudes above 90 for an array"""
279
        with pytest.raises(ValueError):
280
            aacgmv2.convert_latlon_arr([91, 60, -91], 0, 300, self.dtime)
281
282
class TestGetAACGMCoord:
283
    def setup(self):
284
        """Runs before every method to create a clean testing setup"""
285
        self.dtime = dt.datetime(2015, 1, 1, 0, 0, 0)
286
        self.ddate = dt.date(2015, 1, 1)
287
        self.in_args = [60, 0, 300, self.dtime, 'TRACE']
288
        self.out = None
289
        self.ref = [58.22474610, 81.17611033, 0.18892]
290
        self.rtol = 1.0e-4
291
292
    def teardown(self):
293
        """Runs after every method to clean up previous testing"""
294
        del self.out, self.in_args, self.ref, self.rtol, self.dtime, self.ddate
295
296
    def test_get_aacgm_coord(self):
297
        """Test single value AACGMV2 calculation, defaults to TRACE"""
298
        self.out = aacgmv2.get_aacgm_coord(*self.in_args)
299
        np.testing.assert_allclose(self.out, self.ref, rtol=self.rtol)
300
301
    def test_get_aacgm_coord_badidea(self):
302
        """Test single value AACGMV2 calculation with a bad flag"""
303
        self.in_args[-1] = "BADIDEA"
304
        self.in_args[2] = 3000
305
        self.ref = [64.3568, 83.3027, 0.3307]
306
        self.out = aacgmv2.get_aacgm_coord(*self.in_args)
307
        np.testing.assert_allclose(self.out, self.ref, rtol=self.rtol)
308
309
    @pytest.mark.skipif(version_info.major == 2,
310
                        reason='Not raised in Python 2')
311
    def test_get_aacgm_coord_location_failure(self):
312
        """Test single value AACGMV2 calculation with a bad location"""
313
314
        self.in_args[0] = 0.0
315
        self.in_args[2] = 0.0
316
        self.out = aacgmv2.get_aacgm_coord(*self.in_args)
317
        np.all(np.isnan(np.array(self.out)))
318
319
    def test_get_aacgm_coord_time_failure(self):
320
        """Test single value AACGMV2 calculation with a bad datetime"""
321
        self.in_args[3] = None
322
        with pytest.raises(ValueError):
323
            self.out = aacgmv2.get_aacgm_coord(*self.in_args)
324
325
    def test_get_aacgm_coord_mlat_high_failure(self):
326
        """Test error return for co-latitudes above 90 for a single value"""
327
        self.in_args[0] = 91.0
328
        with pytest.raises(ValueError):
329
            aacgmv2.get_aacgm_coord(*self.in_args)
330
331
    def test_get_aacgm_coord_mlat_low_failure(self):
332
        """Test error return for co-latitudes below -90 for a single value"""
333
        self.in_args[0] = -91.0
334
        with pytest.raises(ValueError):
335
            aacgmv2.get_aacgm_coord(*self.in_args)
336
337
    def test_get_aacgm_coord_datetime_date(self):
338
        """Test single AACGMV2 calculation with date and datetime input"""
339
        self.in_args[3] = self.ddate
340
        self.out = aacgmv2.get_aacgm_coord(*self.in_args)
341
        np.testing.assert_allclose(self.out, self.ref, rtol=self.rtol)
342
343
    def test_get_aacgm_coord_maxalt_failure(self):
344
        """test get_aacgm_coord failure for an altitude too high for coeffs"""
345
        self.in_args[2] = 2001
346
        self.in_args[-1] = ""
347
        self.out = aacgmv2.get_aacgm_coord(*self.in_args)
348
        assert np.all(np.isnan(np.array(self.out)))
349
350
class TestGetAACGMCoordArr:
351 View Code Duplication
    def setup(self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
352
        """Runs before every method to create a clean testing setup"""
353
        self.dtime = dt.datetime(2015, 1, 1, 0, 0, 0)
354
        self.ddate = dt.date(2015, 1, 1)
355
        self.lat_in = [60.0, 61.0]
356
        self.lon_in = [0.0, 0.0]
357
        self.alt_in = [300.0, 300.0]
358
        self.method = 'TRACE'
359
        self.out = None
360
        self.ref = [[58.22474610, 59.31648007], [81.17611033, 81.62281360],
361
                    [0.18891995, 0.21870017]]
362
        self.rtol = 1.0e-4
363
364
    def teardown(self):
365
        """Runs after every method to clean up previous testing"""
366
        del self.out, self.ref, self.lat_in, self.dtime, self.ddate
367
        del self.lon_in, self.alt_in, self.method, self.rtol
368
369
    def test_get_aacgm_coord_arr_single_val(self):
370
        """Test array AACGMV2 calculation for a single value"""
371
        self.out = aacgmv2.get_aacgm_coord_arr(self.lat_in[0], self.lon_in[0],
372
                                               self.alt_in[0], self.dtime,
373
                                               self.method)
374
375
        assert len(self.out) == len(self.ref)
376
        assert [isinstance(oo, np.ndarray) and len(oo) == 1 for oo in self.out]
377
378
        for i, oo in enumerate(self.out):
379
            np.testing.assert_allclose(oo, [self.ref[i][0]], rtol=self.rtol)
380
381 View Code Duplication
    def test_get_aacgm_coord_arr_list_single(self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
382
        """Test array AACGMV2 calculation for list input of single values"""
383
        self.out = aacgmv2.get_aacgm_coord_arr([self.lat_in[0]],
384
                                               [self.lon_in[0]],
385
                                               [self.alt_in[0]], self.dtime,
386
                                               self.method)
387
388
        assert len(self.out) == len(self.ref)
389
        assert [isinstance(oo, np.ndarray) and len(oo) == 1 for oo in self.out]
390
391
        for i, oo in enumerate(self.out):
392
            np.testing.assert_allclose(oo, [self.ref[i][0]], rtol=self.rtol)
393
394
    def test_get_aacgm_coord_arr_list(self):
395
        """Test array AACGMV2 calculation for list input"""
396
        self.out = aacgmv2.get_aacgm_coord_arr(self.lat_in,self.lon_in,
397
                                               self.alt_in, self.dtime,
398
                                               self.method)
399
400
        assert len(self.out) == len(self.ref)
401
        assert [isinstance(oo, np.ndarray) and len(oo) == len(self.lat_in)
402
                for oo in self.out]
403
404
        for i, oo in enumerate(self.out):
405
            np.testing.assert_allclose(oo, self.ref[i], rtol=self.rtol)
406
407 View Code Duplication
    def test_get_aacgm_coord_arr_arr_single(self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
408
        """Test array AACGMV2 calculation for array with a single value"""
409
        self.out = aacgmv2.get_aacgm_coord_arr(np.array([self.lat_in[0]]),
410
                                               np.array([self.lon_in[0]]),
411
                                               np.array([self.alt_in[0]]),
412
                                               self.dtime, self.method)
413
414
415
        assert len(self.out) == len(self.ref)
416
        assert [isinstance(oo, np.ndarray) and len(oo) == 1 for oo in self.out]
417
418
        for i, oo in enumerate(self.out):
419
            np.testing.assert_allclose(oo, [self.ref[i][0]], rtol=self.rtol)
420
421 View Code Duplication
    def test_get_aacgm_coord_arr_arr(self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
422
        """Test array AACGMV2 calculation for an array"""
423
        self.out = aacgmv2.get_aacgm_coord_arr(np.array(self.lat_in),
424
                                               np.array(self.lon_in),
425
                                               np.array(self.alt_in),
426
                                               self.dtime, self.method)
427
428
        assert len(self.out) == len(self.ref)
429
        assert [isinstance(oo, np.ndarray) and len(oo) == len(self.lat_in)
430
                for oo in self.out]
431
432
        for i, oo in enumerate(self.out):
433
            np.testing.assert_allclose(oo, self.ref[i], rtol=self.rtol)
434
435
    def test_get_aacgm_coord_arr_list_mix(self):
436
        """Test array AACGMV2 calculation for a list and floats"""
437
        self.out = aacgmv2.get_aacgm_coord_arr(self.lat_in, self.lon_in[0],
438
                                               self.alt_in[0], self.dtime,
439
                                               self.method)
440
441
        assert len(self.out) == len(self.ref)
442
        assert [isinstance(oo, np.ndarray) and len(oo) == len(self.lat_in)
443
                for oo in self.out]
444
445
        for i, oo in enumerate(self.out):
446
            np.testing.assert_allclose(oo, self.ref[i], rtol=self.rtol)  
447
448
    def test_get_aacgm_coord_arr_arr_mix(self):
449
        """Test array AACGMV2 calculation for an array and floats"""
450
        self.out = aacgmv2.get_aacgm_coord_arr(np.array(self.lat_in),
451
                                               self.lon_in[0], self.alt_in[0],
452
                                               self.dtime, self.method)
453
454
        assert len(self.out) == len(self.ref)
455
        assert [isinstance(oo, np.ndarray) and len(oo) == len(self.lat_in)
456
                for oo in self.out]
457
458
        for i, oo in enumerate(self.out):
459
            np.testing.assert_allclose(oo, self.ref[i], rtol=self.rtol)
460
461
    def test_get_aacgm_coord_arr_mult_failure(self):
462
        """Test aacgm_coord_arr failure with multi-dim array input"""
463
464
        with pytest.raises(ValueError):
465
            (self.mlat_out, self.mlon_out,
466
             self.mlt_out) = aacgmv2.get_aacgm_coord_arr(
467
                 np.array([[60, 61, 62], [63, 64, 65]]), 0, 300, self.dtime)
468
469 View Code Duplication
    def test_get_aacgm_coord_arr_badidea(self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
470
        """Test array AACGMV2 calculation for BADIDEA"""
471
        self.method = "|".join([self.method, "BADIDEA"])
472
        self.out = aacgmv2.get_aacgm_coord_arr(self.lat_in[0], self.lon_in[0],
473
                                               [3000.0], self.dtime,
474
                                               self.method)
475
476
        assert len(self.out) == len(self.ref)
477
        assert [isinstance(oo, np.ndarray) and len(oo) == 1 for oo in self.out]
478
479
        self.ref = [64.34650424987989, 83.30339395305012, 0.3307388620896745]
480
        for i, oo in enumerate(self.out):
481
            np.testing.assert_allclose(oo, self.ref[i], rtol=self.rtol)
482
483
    @pytest.mark.skipif(version_info.major == 2,
484
                        reason='Not raised in Python 2')
485
    def test_get_aacgm_coord_arr_location_failure(self):
486
        """Test array AACGMV2 calculation with a bad location"""
487
        self.out = aacgmv2.get_aacgm_coord_arr([0], [0], [0], self.dtime,
488
                                               self.method)
489
490
        
491
        assert len(self.out) == len(self.ref)
492
        assert [isinstance(oo, np.ndarray) and len(oo) == 1 for oo in self.out]
493
        assert np.any([np.isnan(oo) for oo in self.out])
494
495
    def test_get_aacgm_coord_arr_time_failure(self):
496
        """Test array AACGMV2 calculation with a bad time"""
497
        with pytest.raises(ValueError):
498
            aacgmv2.get_aacgm_coord_arr(self.lat_in, self.lon_in, self.alt_in,
499
                                        None, self.method)
500
501
    def test_get_aacgm_coord_arr_mlat_failure(self):
502
        """Test error return for co-latitudes above 90 for an array"""
503
504
        self.lat_in = [91, 60, -91]
505
        with pytest.raises(ValueError):
506
            self.out = aacgmv2.get_aacgm_coord_arr(self.lat_in, self.lon_in[0],
507
                                                   self.alt_in[0], self.dtime,
508
                                                   self.method)
509
510 View Code Duplication
    def test_get_aacgm_coord_arr_datetime_date(self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
511
        """Test array AACGMV2 calculation with date and datetime input"""
512
        self.out = aacgmv2.get_aacgm_coord_arr(self.lat_in, self.lon_in,
513
                                               self.alt_in, self.ddate,
514
                                               self.method)
515
        self.ref = aacgmv2.get_aacgm_coord_arr(self.lat_in, self.lon_in,
516
                                               self.alt_in, self.dtime,
517
                                               self.method)
518
519
        assert len(self.out) == len(self.ref)
520
        assert [isinstance(oo, np.ndarray) and len(oo) == len(self.lat_in)
521
                for oo in self.out]
522
523
        for i, oo in enumerate(self.out):
524
            np.testing.assert_allclose(oo, self.ref[i], rtol=self.rtol)
525
526
    def test_get_aacgm_coord_arr_maxalt_failure(self):
527
        """test aacgm_coord_arr failure for an altitude too high for coeff"""
528
        self.method = ""
529
        self.alt_in = [2001 for ll in self.lat_in]
530
        self.out = aacgmv2.get_aacgm_coord_arr(self.lat_in, self.lon_in,
531
                                               self.alt_in, self.dtime,
532
                                               self.method)
533
534
        assert len(self.out) == len(self.ref)
535
        assert [isinstance(oo, np.ndarray) and len(oo) == len(self.lat_in)
536
                for oo in self.out]
537
        assert np.all(np.isnan(np.array(self.out)))
538
539
540
class TestConvertCode:
541
    @classmethod
542
    def test_convert_str_to_bit_g2a(self):
543
        """Test conversion from string code to bit G2A"""
544
        if aacgmv2.convert_str_to_bit("G2A") != aacgmv2._aacgmv2.G2A:
545
            raise AssertionError()
546
547
    @classmethod
548
    def test_convert_str_to_bit_a2g(self):
549
        """Test conversion from string code to bit A2G"""
550
        if aacgmv2.convert_str_to_bit("A2G") != aacgmv2._aacgmv2.A2G:
551
            raise AssertionError()
552
553
    @classmethod
554
    def test_convert_str_to_bit_trace(self):
555
        """Test conversion from string code to bit TRACE"""
556
        if aacgmv2.convert_str_to_bit("TRACE") != aacgmv2._aacgmv2.TRACE:
557
            raise AssertionError()
558
559
    @classmethod
560
    def test_convert_str_to_bit_allowtrace(self):
561
        """Test conversion from string code to bit ALLOWTRACE"""
562
        if(aacgmv2.convert_str_to_bit("ALLOWTRACE") !=
563
           aacgmv2._aacgmv2.ALLOWTRACE):
564
            raise AssertionError()
565
566
    @classmethod
567
    def test_convert_str_to_bit_badidea(self):
568
        """Test conversion from string code to bit BADIDEA"""
569
        if(aacgmv2.convert_str_to_bit("BADIDEA") !=
570
           aacgmv2._aacgmv2.BADIDEA):
571
            raise AssertionError()
572
573
    @classmethod
574
    def test_convert_str_to_bit_geocentric(self):
575
        """Test conversion from string code to bit GEOCENTRIC"""
576
        if(aacgmv2.convert_str_to_bit("GEOCENTRIC") !=
577
           aacgmv2._aacgmv2.GEOCENTRIC):
578
            raise AssertionError()
579
580
    @classmethod
581
    def test_convert_str_to_bit_lowercase(self):
582
        """Test conversion from string code to bit for a lowercase code"""
583
        if aacgmv2.convert_str_to_bit("g2a") != aacgmv2._aacgmv2.G2A:
584
            raise AssertionError()
585
586
    @classmethod
587
    def test_convert_str_to_bit_spaces(self):
588
        """Test conversion from string code to bit for a code with spaces"""
589
        if(aacgmv2.convert_str_to_bit("G2A | trace") !=
590
           aacgmv2._aacgmv2.G2A + aacgmv2._aacgmv2.TRACE):
591
            raise AssertionError()
592
593
    @classmethod
594
    def test_convert_str_to_bit_invalid(self):
595
        """Test conversion from string code to bit for an invalid code"""
596
        if aacgmv2.convert_str_to_bit("ggoogg|") != aacgmv2._aacgmv2.G2A:
597
            raise AssertionError()
598
599
    @classmethod
600
    def test_convert_bool_to_bit_g2a(self):
601
        """Test conversion from string code to bit G2A"""
602
        if aacgmv2.convert_bool_to_bit() != aacgmv2._aacgmv2.G2A:
603
            raise AssertionError()
604
605
    @classmethod
606
    def test_convert_bool_to_bit_a2g(self):
607
        """Test conversion from string code to bit A2G"""
608
        if aacgmv2.convert_bool_to_bit(a2g=True) != aacgmv2._aacgmv2.A2G:
609
            raise AssertionError()
610
611
    @classmethod
612
    def test_convert_bool_to_bit_trace(self):
613
        """Test conversion from string code to bit TRACE"""
614
        if aacgmv2.convert_bool_to_bit(trace=True) != aacgmv2._aacgmv2.TRACE:
615
            raise AssertionError()
616
617
    @classmethod
618
    def test_convert_bool_to_bit_allowtrace(self):
619
        """Test conversion from string code to bit ALLOWTRACE"""
620
        if(aacgmv2.convert_bool_to_bit(allowtrace=True) !=
621
           aacgmv2._aacgmv2.ALLOWTRACE):
622
            raise AssertionError()
623
624
    @classmethod
625
    def test_convert_bool_to_bit_badidea(self):
626
        """Test conversion from string code to bit BADIDEA"""
627
        if(aacgmv2.convert_bool_to_bit(badidea=True) !=
628
           aacgmv2._aacgmv2.BADIDEA):
629
            raise AssertionError()
630
631
    @classmethod
632
    def test_convert_bool_to_bit_geocentric(self):
633
        """Test conversion from string code to bit GEOCENTRIC"""
634
        if(aacgmv2.convert_bool_to_bit(geocentric=True) !=
635
           aacgmv2._aacgmv2.GEOCENTRIC):
636
            raise AssertionError()
637
638
class TestMLTConvert:
639
    def setup(self):
640
        """Runs before every method to create a clean testing setup"""
641
        self.dtime = dt.datetime(2015, 1, 1, 0, 0, 0)
642
        self.dtime2 = dt.datetime(2015, 1, 1, 10, 0, 0)
643
        self.ddate = dt.date(2015, 1, 1)
644
        self.mlon_out = None
645
        self.mlt_out = None
646
        self.mlt_diff = None
647
        self.mlon_list = [270.0, 80.0, -95.0]
648
        self.mlt_list = [12.0, 25.0, -1.0]
649
        self.mlon_comp = [-101.657689, 93.34231102, 63.34231102]
650
        self.mlt_comp = [12.77717927, 0.1105126, 12.44384593]
651
        self.diff_comp = np.ones(shape=(3,)) * -10.52411552
652
653
    def teardown(self):
654
        """Runs after every method to clean up previous testing"""
655
        del self.mlon_out, self.mlt_out, self.mlt_list, self.mlon_list
656
        del self.mlon_comp, self.mlt_comp, self.mlt_diff, self.diff_comp
657
658
    def test_date_input(self):
659
        """Test to see that the date input works"""
660
        self.mlt_out = aacgmv2.convert_mlt(self.mlon_list, self.ddate,
661
                                           m2a=False)
662
        np.testing.assert_allclose(self.mlt_out, self.mlt_comp, rtol=1.0e-4)
663
664
    def test_datetime_exception(self):
665
        """Test to see that a value error is raised with bad time input"""
666
        with pytest.raises(ValueError):
667
            self.mlt_out = aacgmv2.wrapper.convert_mlt(self.mlon_list, 1997)
668
669
    def test_inv_convert_mlt_single(self):
670
        """Test MLT inversion for a single value"""
671
        for i,mlt in enumerate(self.mlt_list):
672
            self.mlon_out = aacgmv2.convert_mlt(mlt, self.dtime, m2a=True)
673
            np.testing.assert_almost_equal(self.mlon_out, self.mlon_comp[i],
674
                                           decimal=4)
675
676
    def test_inv_convert_mlt_list(self):
677
        """Test MLT inversion for a list"""
678
        self.mlon_out = aacgmv2.convert_mlt(self.mlt_list, self.dtime, m2a=True)
679
        np.testing.assert_allclose(self.mlon_out, self.mlon_comp, rtol=1.0e-4)
680
681
    def test_inv_convert_mlt_arr(self):
682
        """Test MLT inversion for an array"""
683
        self.mlon_out = aacgmv2.convert_mlt(np.array(self.mlt_list), self.dtime,
684
                                            m2a=True)
685
686
        np.testing.assert_allclose(self.mlon_out, self.mlon_comp, rtol=1.0e-4)
687
688
    def test_inv_convert_mlt_wrapping(self):
689
        """Test MLT wrapping"""
690
        self.mlon_out = aacgmv2.convert_mlt(np.array([1, 25, -1, 23]),
691
                                            self.dtime, m2a=True)
692
693
        np.testing.assert_almost_equal(self.mlon_out[0], self.mlon_out[1],
694
                                       decimal=6)
695
        np.testing.assert_almost_equal(self.mlon_out[2], self.mlon_out[3],
696
                                       decimal=6)
697
698
    def test_mlt_convert_mlon_wrapping(self):
699
        """Test mlon wrapping"""
700
        self.mlt_out = aacgmv2.convert_mlt(np.array([270, -90, 1, 361]),
701
                                           self.dtime, m2a=False)
702
703
        np.testing.assert_almost_equal(self.mlt_out[0], self.mlt_out[1],
704
                                       decimal=6)
705
        np.testing.assert_almost_equal(self.mlt_out[2], self.mlt_out[3],
706
                                       decimal=6)
707
708
    def test_mlt_convert_single(self):
709
        """Test MLT calculation for a single value"""
710
        for i,mlon in enumerate(self.mlon_list):
711
            self.mlt_out = aacgmv2.convert_mlt(mlon, self.dtime, m2a=False)
712
            np.testing.assert_almost_equal(self.mlt_out, self.mlt_comp[i],
713
                                           decimal=4)
714
715
    def test_mlt_convert_list(self):
716
        """Test MLT calculation for a list"""
717
        self.mlt_out = aacgmv2.convert_mlt(self.mlon_list, self.dtime,
718
                                           m2a=False)
719
        np.testing.assert_allclose(self.mlt_out, self.mlt_comp, rtol=1.0e-4)
720
721
    def test_mlt_convert_arr(self):
722
        """Test MLT calculation for an array"""
723
        self.mlt_out = aacgmv2.convert_mlt(np.array(self.mlon_list),
724
                                           self.dtime, m2a=False)
725
        np.testing.assert_allclose(self.mlt_out, self.mlt_comp, rtol=1.0e-4)
726
727
    def test_mlt_convert_list_w_times(self):
728
        """Test MLT calculation for data and time arrays"""
729
        self.dtime = [self.dtime for dd in self.mlon_list]
730
        self.mlt_out = aacgmv2.convert_mlt(self.mlon_list, self.dtime,
731
                                           m2a=False)
732
        np.testing.assert_allclose(self.mlt_out, self.mlt_comp, rtol=1.0e-4)
733
734
    def test_mlt_convert_change(self):
735
        """Test that MLT changes with UT"""
736
        self.mlt_out = aacgmv2.convert_mlt(self.mlon_list, self.dtime)
737
        self.mlt_diff = np.array(self.mlt_out) \
738
            - np.array(aacgmv2.convert_mlt(self.mlon_list, self.dtime2))
739
740
        np.testing.assert_allclose(self.mlt_diff, self.diff_comp, rtol=1.0e-4)
741
742
    def test_mlt_convert_multidim_failure(self):
743
        """Test MLT calculation failure for multi-dimensional arrays"""
744
        self.mlon_list = np.full(shape=(3,2), fill_value=50.0)
745
        with pytest.raises(ValueError):
746
            aacgmv2.convert_mlt(self.mlon_list, self.dtime, m2a=False)
747
748
    def test_mlt_convert_mismatch_failure(self):
749
        """Test MLT calculation failure for mismatched array input"""
750
        with pytest.raises(ValueError):
751
            aacgmv2.convert_mlt(self.mlon_list, [self.dtime, self.dtime2],
752
                                m2a=False)
753
754
class TestCoeffPath:
755
756
    def setup(self):
757
        """Runs before every method to create a clean testing setup"""
758
        os.environ['IGRF_COEFFS'] = "default_igrf"
759
        os.environ['AACGM_v2_DAT_PREFIX'] = "default_coeff"
760
        self.default_igrf = os.environ['IGRF_COEFFS']
761
        self.default_coeff = os.environ['AACGM_v2_DAT_PREFIX']
762
763
    def teardown(self):
764
        """Runs after every method to clean up previous testing"""
765
        del self.default_igrf, self.default_coeff
766
767
    def test_set_coeff_path_default(self):
768
        """Test the coefficient path setting using default values"""
769
        aacgmv2.wrapper.set_coeff_path()
770
771
        if os.environ['IGRF_COEFFS'] != self.default_igrf:
772
            raise AssertionError()
773
        if os.environ['AACGM_v2_DAT_PREFIX'] != self.default_coeff:
774
            raise AssertionError()
775
776
    @classmethod
777
    def test_set_coeff_path_string(self):
778
        """Test the coefficient path setting using two user specified values"""
779
        aacgmv2.wrapper.set_coeff_path("hi", "bye")
780
781
        if os.environ['IGRF_COEFFS'] != "hi":
782
            raise AssertionError()
783
        if os.environ['AACGM_v2_DAT_PREFIX'] != "bye":
784
            raise AssertionError()
785
786
    @classmethod
787
    def test_set_coeff_path_true(self):
788
        """Test the coefficient path setting using the module values"""
789
        aacgmv2.wrapper.set_coeff_path(True, True)
790
791
        if os.environ['IGRF_COEFFS'] != aacgmv2.IGRF_COEFFS:
792
            raise AssertionError()
793
        if os.environ['AACGM_v2_DAT_PREFIX'] != aacgmv2.AACGM_v2_DAT_PREFIX:
794
            raise AssertionError()
795
796
    def test_set_only_aacgm_coeff_path(self):
797
        """Test the coefficient path setting using a mix of input"""
798
        aacgmv2.wrapper.set_coeff_path(coeff_prefix="hi")
799
800
        if os.environ['IGRF_COEFFS'] != self.default_igrf:
801
            raise AssertionError()
802
        if os.environ['AACGM_v2_DAT_PREFIX'] != "hi":
803
            raise AssertionError()
804
805
    def test_set_only_igrf_coeff_path(self):
806
        """Test the coefficient path setting using a mix of input"""
807
        aacgmv2.wrapper.set_coeff_path(igrf_file="hi")
808
809
        if os.environ['IGRF_COEFFS'] != "hi":
810
            raise AssertionError()
811
        if os.environ['AACGM_v2_DAT_PREFIX'] != self.default_coeff:
812
            raise AssertionError()
813
814
    @classmethod
815
    def test_set_both_mixed(self):
816
        """Test the coefficient path setting using a mix of input"""
817
        aacgmv2.wrapper.set_coeff_path(igrf_file=True, coeff_prefix="hi")
818
819
        if os.environ['IGRF_COEFFS'] != aacgmv2.IGRF_COEFFS:
820
            raise AssertionError()
821
        if os.environ['AACGM_v2_DAT_PREFIX'] != "hi":
822
            raise AssertionError()
823
824
class TestHeightReturns:
825
    def setup(self):
826
        """Runs before every method to create a clean testing setup"""
827
        self.code = aacgmv2._aacgmv2.A2G
828
        self.bad_code = aacgmv2._aacgmv2.BADIDEA
829
        self.trace_code = aacgmv2._aacgmv2.TRACE
830
        
831
    def teardown(self):
832
        """Runs after every method to clean up previous testing"""
833
        del self.code, self.bad_code
834
835
    def test_low_height_good(self):
836
        """ Test to see that a very low height is still accepted"""
837
838
        assert aacgmv2.wrapper.test_height(-1, self.code)
839
840
    def test_high_coeff_bad(self):
841
        """ Test to see that a high altitude for coefficent use fails"""
842
843
        assert not aacgmv2.wrapper.test_height(aacgmv2.high_alt_coeff+10.0,
844
                                               self.code)
845
846
    def test_high_coeff_good(self):
847
        """ Test a high altitude for coefficent use with badidea """
848
849
        assert aacgmv2.wrapper.test_height(aacgmv2.high_alt_coeff+10.0,
850
                                           self.bad_code)
851
852
    def test_low_coeff_good(self):
853
        """ Test that a normal height succeeds"""
854
        assert aacgmv2.wrapper.test_height(aacgmv2.high_alt_coeff*0.5,
855
                                           self.code)
856
857
    def test_high_trace_bad(self):
858
        """ Test that a high trace height fails"""
859
        assert not aacgmv2.wrapper.test_height(aacgmv2.high_alt_trace+10.0,
860
                                               self.code)
861
862
    def test_low_trace_good(self):
863
        """ Test that a high coefficient height succeeds with trace"""
864
        assert aacgmv2.wrapper.test_height(aacgmv2.high_alt_coeff+10.0,
865
                                           self.trace_code)
866
867
    def test_high_trace_good(self):
868
        """ Test that a high trace height succeeds with badidea"""
869
        assert aacgmv2.wrapper.test_height(aacgmv2.high_alt_trace+10.0,
870
                                           self.bad_code)
871
872
873
class TestPyLogging:
874
    def setup(self):
875
        """Runs before every method to create a clean testing setup"""
876
877
        self.lwarn = u""
878
        self.lout = u""
879
        self.log_capture = StringIO()
880
        aacgmv2.logger.addHandler(logging.StreamHandler(self.log_capture))
881
        aacgmv2.logger.setLevel(logging.INFO)
882
883
    def teardown(self):
884
        """Runs after every method to clean up previous testing"""
885
        self.log_capture.close()
886
        del self.lwarn, self.lout, self.log_capture
887
888
889
    def test_warning_below_ground(self):
890
        """ Test that a warning is issued if height < 0 for height test """
891
        self.lwarn = u"conversion not intended for altitudes < 0 km"
892
893
        aacgmv2.wrapper.test_height(-1, 0)
894
        self.lout = self.log_capture.getvalue()
895
        if self.lout.find(self.lwarn) < 0:
896
            raise AssertionError()
897
898
    def test_warning_magnetosphere(self):
899
        """ Test that a warning is issued if altitude is very high"""
900
        self.lwarn = u"coordinates are not intended for the magnetosphere"
901
902
        aacgmv2.wrapper.test_height(70000, aacgmv2._aacgmv2.TRACE)
903
        self.lout = self.log_capture.getvalue()
904
        if self.lout.find(self.lwarn) < 0:
905
            raise AssertionError()
906
907
    def test_warning_high_coeff(self):
908
        """ Test that a warning is issued if altitude is very high"""
909
        self.lwarn = u"must either use field-line tracing (trace=True"
910
911
        aacgmv2.wrapper.test_height(3000, 0)
912
        self.lout = self.log_capture.getvalue()
913
        if self.lout.find(self.lwarn) < 0:
914
            raise AssertionError()
915
916
    def test_warning_single_loc_in_arr(self):
917
        """ Test that user is warned they should be using simpler routine"""
918
        self.lwarn = u"for a single location, consider using"
919
920
        aacgmv2.convert_latlon_arr(60, 0, 300, dt.datetime(2015,1,1,0,0,0))
921
        self.lout = self.log_capture.getvalue()
922
        if self.lout.find(self.lwarn) < 0:
923
            raise AssertionError()
924
925
class TestTimeReturns:
926
    def setup(self):
927
        """Runs before every method to create a clean testing setup"""
928
        self.dtime = dt.datetime(2015, 1, 1, 0, 0, 0)
929
        self.dtime2 = dt.datetime(2015, 1, 1, 10, 10, 10)
930
        self.ddate = dt.date(2015, 1, 1)
931
        
932
    def teardown(self):
933
        """Runs after every method to clean up previous testing"""
934
        del self.dtime, self.ddate, self.dtime2
935
936
    def test_good_time(self):
937
        """ Test to see that a good datetime is accepted"""
938
939
        assert self.dtime == aacgmv2.wrapper.test_time(self.dtime)
940
941
    def test_good_time_with_nonzero_time(self):
942
        """ Test to see that a good datetime with h/m/s is accepted"""
943
944
        assert self.dtime2 == aacgmv2.wrapper.test_time(self.dtime2)
945
946
    def test_good_date(self):
947
        """ Test to see that a good date has a good datetime output"""
948
949
        assert self.dtime == aacgmv2.wrapper.test_time(self.dtime)
950
951
    def test_bad_time(self):
952
        """ Test to see that a warning is raised with a bad time input"""
953
        with pytest.raises(ValueError):
954
            aacgmv2.wrapper.test_time(2015)
955