1
|
|
|
# -*- coding: utf-8 -*- |
2
|
|
|
# vim:fileencoding=utf-8 |
3
|
|
|
import os |
4
|
|
|
|
5
|
|
|
import datetime as dt |
6
|
|
|
import numpy as np |
7
|
|
|
import pytest |
8
|
|
|
|
9
|
|
|
import nrlmsise00 as msise |
10
|
|
|
|
11
|
|
|
# standard inputs for direct interface |
12
|
|
|
STD_INPUT_C = [ |
13
|
|
|
0, # year /* without effect */ |
14
|
|
|
172, # doy |
15
|
|
|
29000, # sec |
16
|
|
|
400, # alt |
17
|
|
|
60, # g_lat |
18
|
|
|
-70, # g_long |
19
|
|
|
16, # lst |
20
|
|
|
150, # f107A |
21
|
|
|
150, # f107 |
22
|
|
|
4, # ap |
23
|
|
|
] |
24
|
|
|
|
25
|
|
|
# standard inputs for python functions |
26
|
|
|
STD_INPUT_PY = [ |
27
|
|
|
dt.datetime(2009, 6, 21, 8, 3, 20), |
28
|
|
|
400, # alt |
29
|
|
|
60, # g_lat |
30
|
|
|
-70, # g_long |
31
|
|
|
150, # f107A |
32
|
|
|
150, # f107 |
33
|
|
|
4, # ap |
34
|
|
|
] |
35
|
|
|
STD_KW_PY = {"lst": 16} |
36
|
|
|
|
37
|
|
|
|
38
|
|
|
def test_structure(): |
39
|
|
|
assert msise |
40
|
|
|
assert msise._nrlmsise00 |
41
|
|
|
assert msise._nrlmsise00.gtd7 |
42
|
|
|
assert msise._nrlmsise00.gtd7d |
43
|
|
|
assert msise.msise_model |
44
|
|
|
assert msise.msise_flat |
45
|
|
|
|
46
|
|
|
|
47
|
|
|
def test_c_gtd7(): |
48
|
|
|
# high ap values |
49
|
|
|
aph = [100.] * 7 |
50
|
|
|
# standard flags |
51
|
|
|
flags = [0] + [1] * 23 |
52
|
|
|
# copy the list contents, otherwise they would all point to the |
53
|
|
|
# same list which would get overwritten every time a value changes |
54
|
|
|
inputs = [STD_INPUT_C[:] for _ in range(17)] |
55
|
|
|
# update input lists with values to test |
56
|
|
|
inputs[1][1] = 81 # doy |
57
|
|
|
inputs[2][2] = 75000 # sec |
58
|
|
|
inputs[2][3] = 1000 # alt |
59
|
|
|
inputs[3][3] = 100 # alt |
60
|
|
|
inputs[10][3] = 0 # alt |
61
|
|
|
inputs[11][3] = 10 # alt |
62
|
|
|
inputs[12][3] = 30 # alt |
63
|
|
|
inputs[13][3] = 50 # alt |
64
|
|
|
inputs[14][3] = 70 # alt |
65
|
|
|
inputs[16][3] = 100 # alt |
66
|
|
|
inputs[4][4] = 0 # g_lat |
67
|
|
|
inputs[5][5] = 0 # g_long |
68
|
|
|
inputs[6][6] = 4 # lst |
69
|
|
|
inputs[7][7] = 70 # f107A |
70
|
|
|
inputs[8][8] = 180 # f107 |
71
|
|
|
inputs[9][9] = 40 # ap |
72
|
|
|
# MSIS test outputs from the documentation |
73
|
|
|
test_file = os.path.join( |
74
|
|
|
os.path.realpath(os.path.dirname(__file__)), |
75
|
|
|
"msis_testoutput.txt") |
76
|
|
|
test_output = np.genfromtxt(test_file) |
77
|
|
|
|
78
|
|
|
outputs = [] |
79
|
|
|
for inp in inputs[:15]: |
80
|
|
|
ds, ts = msise._nrlmsise00.gtd7(*inp, flags=flags) |
81
|
|
|
outputs.append(ds + ts) |
82
|
|
|
flags[9] = -1 |
83
|
|
|
for inp in inputs[15:17]: |
84
|
|
|
ds, ts = msise._nrlmsise00.gtd7(*inp, ap_a=aph, flags=flags) |
85
|
|
|
outputs.append(ds + ts) |
86
|
|
|
# Compare results |
87
|
|
|
np.testing.assert_allclose(np.asarray(outputs), test_output, rtol=1e-6) |
88
|
|
|
|
89
|
|
|
|
90
|
|
|
def test_py_msise(): |
91
|
|
|
# high ap values |
92
|
|
|
aph = [100.] * 7 |
93
|
|
|
# standard flags |
94
|
|
|
flags = [0] + [1] * 23 |
95
|
|
|
kws = [STD_KW_PY.copy() for _ in range(17)] |
96
|
|
|
# copy the list contents, otherwise they would all point to the |
97
|
|
|
# same list which would get overwritten every time a value changes |
98
|
|
|
inputs = [STD_INPUT_PY[:] for _ in range(17)] |
99
|
|
|
# update input lists with values to test |
100
|
|
|
inputs[1][0] = dt.datetime(2009, 3, 22, 8, 3, 20) |
101
|
|
|
inputs[2][0] = dt.datetime(2009, 6, 21, 20, 50, 0) |
102
|
|
|
inputs[2][1] = 1000 # alt |
103
|
|
|
inputs[3][1] = 100 # alt |
104
|
|
|
inputs[10][1] = 0 # alt |
105
|
|
|
inputs[11][1] = 10 # alt |
106
|
|
|
inputs[12][1] = 30 # alt |
107
|
|
|
inputs[13][1] = 50 # alt |
108
|
|
|
inputs[14][1] = 70 # alt |
109
|
|
|
inputs[16][1] = 100 # alt |
110
|
|
|
inputs[4][2] = 0 # g_lat |
111
|
|
|
inputs[5][3] = 0 # g_long |
112
|
|
|
inputs[7][4] = 70 # f107A |
113
|
|
|
inputs[8][5] = 180 # f107 |
114
|
|
|
inputs[9][6] = 40 # ap |
115
|
|
|
kws[6].update({"lst": 4}) # lst |
116
|
|
|
# MSIS test outputs from the documentation |
117
|
|
|
test_file = os.path.join( |
118
|
|
|
os.path.realpath(os.path.dirname(__file__)), |
119
|
|
|
"msis_testoutput.txt") |
120
|
|
|
test_output = np.genfromtxt(test_file) |
121
|
|
|
|
122
|
|
|
outputs = [] |
123
|
|
|
for inp, kw in zip(inputs[:15], kws[:15]): |
124
|
|
|
ds, ts = msise.msise_model(*inp, flags=flags, **kw) |
125
|
|
|
outputs.append(ds + ts) |
126
|
|
|
flags[9] = -1 |
127
|
|
|
for inp, kw in zip(inputs[15:17], kws[15:17]): |
128
|
|
|
ds, ts = msise.msise_model(*inp, ap_a=aph, flags=flags, **kw) |
129
|
|
|
outputs.append(ds + ts) |
130
|
|
|
# Compare results |
131
|
|
|
np.testing.assert_allclose(np.asarray(outputs), test_output, rtol=1e-6) |
132
|
|
|
|
133
|
|
|
|
134
|
|
|
def test_py_msise_flat(): |
135
|
|
|
# high ap values |
136
|
|
|
aph = [100.] * 7 |
137
|
|
|
# set up empty arrays for the aps and flags |
138
|
|
|
aphs = np.empty((17,), dtype=object) |
139
|
|
|
flags = np.empty((17,), dtype=object) |
140
|
|
|
# standard flags |
141
|
|
|
for i in range(17): |
142
|
|
|
flags[i] = [0] + [1] * 23 |
143
|
|
|
# set the standard values 17 times |
144
|
|
|
times = [dt.datetime(2009, 6, 21, 8, 3, 20)] * 17 |
145
|
|
|
alts = [400] * 17 # alt |
146
|
|
|
lats = [60] * 17 # g_lat |
147
|
|
|
lons = [-70] * 17 # g_long |
148
|
|
|
f107a = [150] * 17 # f107A |
149
|
|
|
f107 = [150] * 17 # f107 |
150
|
|
|
ap = [4] * 17 # ap |
151
|
|
|
lsts = [16] * 17 |
152
|
|
|
# update for individual tests |
153
|
|
|
times[1] = dt.datetime(2009, 3, 22, 8, 3, 20) |
154
|
|
|
times[2] = dt.datetime(2009, 6, 21, 20, 50, 0) |
155
|
|
|
alts[2] = 1000 # alt |
156
|
|
|
alts[3] = 100 # alt |
157
|
|
|
alts[10] = 0 # alt |
158
|
|
|
alts[11] = 10 # alt |
159
|
|
|
alts[12] = 30 # alt |
160
|
|
|
alts[13] = 50 # alt |
161
|
|
|
alts[14] = 70 # alt |
162
|
|
|
alts[16] = 100 # alt |
163
|
|
|
lats[4] = 0 # g_lat |
164
|
|
|
lons[5] = 0 # g_long |
165
|
|
|
f107a[7] = 70 # f107A |
166
|
|
|
f107[8] = 180 # f107 |
167
|
|
|
ap[9] = 40 # ap |
168
|
|
|
lsts[6] = 4 |
169
|
|
|
# include ap array for the last two tests |
170
|
|
|
flags[15][9] = -1 |
171
|
|
|
flags[16][9] = -1 |
172
|
|
|
aphs[15] = aph |
173
|
|
|
aphs[16] = aph |
174
|
|
|
# MSIS test outputs from the documentation |
175
|
|
|
test_file = os.path.join( |
176
|
|
|
os.path.realpath(os.path.dirname(__file__)), |
177
|
|
|
"msis_testoutput.txt") |
178
|
|
|
test_output = np.genfromtxt(test_file) |
179
|
|
|
output = msise.msise_flat(times, alts, lats, lons, |
180
|
|
|
f107a, f107, ap, lst=lsts, ap_a=aphs, flags=flags) |
181
|
|
|
# Compare results |
182
|
|
|
np.testing.assert_allclose(output, test_output, rtol=1e-6) |
183
|
|
|
# single call only, default ap and flags |
184
|
|
|
output0 = msise.msise_flat(times[0], alts[0], lats[0], lons[0], |
185
|
|
|
f107a[0], f107[0], ap[0], lst=lsts[0]) |
186
|
|
|
np.testing.assert_allclose(output0, test_output[0], rtol=1e-6) |
187
|
|
|
# special flags and ap setting in a single call |
188
|
|
|
aps0 = np.empty((1,), dtype=object) |
189
|
|
|
flags0 = np.empty((1,), dtype=object) |
190
|
|
|
aps0[0] = aphs[16] |
191
|
|
|
flags0[0] = flags[16] |
192
|
|
|
output0 = msise.msise_flat(times[16], alts[16], lats[16], lons[16], |
193
|
|
|
f107a[16], f107[16], ap[16], lst=lsts[16], ap_a=aps0, flags=flags0) |
194
|
|
|
np.testing.assert_allclose(output0[0], test_output[16], rtol=1e-6) |
195
|
|
|
|
196
|
|
|
|
197
|
|
|
def test_c_invalid_length(): |
198
|
|
|
# C interface |
199
|
|
|
with pytest.raises(ValueError): |
200
|
|
|
ds, ts = msise._nrlmsise00.gtd7(*STD_INPUT_C, ap_a=[0., 1., 2., 3.]) |
201
|
|
|
with pytest.raises(ValueError): |
202
|
|
|
ds, ts = msise._nrlmsise00.gtd7(*STD_INPUT_C, flags=[0, 1, 2, 3]) |
203
|
|
|
|
204
|
|
|
|
205
|
|
|
def test_c_invalid_types(): |
206
|
|
|
# C interface |
207
|
|
|
with pytest.raises(ValueError): |
208
|
|
|
ds, ts = msise._nrlmsise00.gtd7(*STD_INPUT_C, ap_a=list(range(6)) + ["6"]) |
209
|
|
|
# C interface |
210
|
|
|
with pytest.raises(ValueError): |
211
|
|
|
ds, ts = msise._nrlmsise00.gtd7(*STD_INPUT_C, flags=list(range(23)) + [24.]) |
212
|
|
|
|
213
|
|
|
|
214
|
|
|
def test_py_invalid_length(): |
215
|
|
|
# python functions |
216
|
|
|
with pytest.raises(ValueError): |
217
|
|
|
ds, ts = msise.msise_model(*STD_INPUT_PY, ap_a=[0., 1., 2., 3.]) |
218
|
|
|
with pytest.raises(ValueError): |
219
|
|
|
ds, ts = msise.msise_model(*STD_INPUT_PY, flags=[0, 1, 2, 3]) |
220
|
|
|
|
221
|
|
|
|
222
|
|
|
def test_py_invalid_types(): |
223
|
|
|
# python functions |
224
|
|
|
with pytest.raises(ValueError): |
225
|
|
|
ds, ts = msise.msise_model(*STD_INPUT_PY, ap_a=list(range(6)) + ["6"]) |
226
|
|
|
with pytest.raises(ValueError): |
227
|
|
|
ds, ts = msise.msise_model(*STD_INPUT_PY, flags=list(range(23)) + [24.]) |
228
|
|
|
|