|
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
|
|
|
|