Passed
Pull Request — develop (#43)
by Angeline
03:32
created

TestMLTConvert.test_mlt_convert_mismatch_failure()   A

Complexity

Conditions 2

Size

Total Lines 5
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

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