Completed
Push — main ( a2e919...ba9c59 )
by Angeline
15s queued 12s
created

test_helpers.test_checklat_message()   A

Complexity

Conditions 3

Size

Total Lines 7
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 7
dl 0
loc 7
rs 10
c 0
b 0
f 0
cc 3
nop 0
1
# -*- coding: utf-8 -*-
2
3
from __future__ import division, absolute_import, unicode_literals
4
5
import datetime as dt
6
7
import numpy as np
8
import pytest
9
from numpy.testing import assert_allclose
10
11
from apexpy import helpers
12
13
14
# ----------------------------------------------------------------------------
15
# NOTE: whenever function outputs are tested against hard-coded numbers, the
16
# test results (numbers) were obtained by running the code that is tested.
17
# Therefore these tests below only check that nothing changes when refactoring,
18
# etc., and not if the results are actually correct
19
# ----------------------------------------------------------------------------
20
21
22
# ============================================================================
23
#  Test checklat
24
# ============================================================================
25
26
@pytest.mark.parametrize('lat', [(90), (0), (-90), (np.nan)])
27
def test_checklat_scalar(lat):
28
    """Test good latitude check with scalars."""
29
    if np.isnan(lat):
30
        assert np.isnan(helpers.checklat(lat))
31
    else:
32
        assert helpers.checklat(lat) == lat
33
34
35
@pytest.mark.parametrize('lat', [(90 + 1e-5), (-90 - 1e-5)])
36
def test_checklat_scalar_clip(lat):
37
    """Test good latitude check with scalars just beyond the lat limits."""
38
    assert helpers.checklat(lat) == np.sign(lat) * np.floor(abs(lat))
39
40
41
@pytest.mark.parametrize('in_args,msg',
42
                         [([90 + 1e-4], "lat must be in"),
43
                          ([-90 - 1e-4, 'glat'], "glat must be in"),
44
                          ([[-90 - 1e-5, -90, 0, 90, 90 + 1e-4], 'glat'],
45
                           "glat must be in"),
46
                          ([[-90 - 1e-4, -90, np.nan, np.nan, 90 + 1e-5]],
47
                           'lat must be in')])
48
def test_checklat_error(in_args, msg):
49
    """Test bad latitude raises ValueError with appropriate message."""
50
    with pytest.raises(ValueError) as verr:
51
        helpers.checklat(*in_args)
52
53
    assert str(verr.value).startswith(msg)
54
55
56
def test_checklat_array():
57
    """Test good latitude with finite values."""
58
    assert_allclose(helpers.checklat([-90 - 1e-5, -90, 0, 90, 90 + 1e-5]),
59
                    np.array([-90, -90, 0, 90, 90]), rtol=0, atol=1e-8)
60
61
    return
62
63
64
def test_checklat_array_withnan():
65
    """Test good latitude input mixed with NaNs."""
66
67
    in_lat = np.array([-90 - 1e-5, -90, 0, 90, 90 + 1e-5, np.nan, np.nan])
68
    fin_mask = np.isfinite(in_lat)
69
    out_lat = helpers.checklat(in_lat)
70
    assert_allclose(np.array([-90, -90, 0, 90, 90]), out_lat[fin_mask],
71
                    rtol=0, atol=1e-8)
72
73
    assert np.all(np.isnan(out_lat[~fin_mask]))
74
75
76
# ============================================================================
77
#  Test getsinIm
78
# ============================================================================
79
80
def test_getsinIm_scalar():
81
    assert_allclose(helpers.getsinIm(60), 0.96076892283052284)
82
    assert_allclose(helpers.getsinIm(10), 0.33257924500670238)
83
    assert type(helpers.getsinIm(60)) != np.ndarray
84
85
86
def test_getsinIm_1Darray():
87
    assert_allclose(helpers.getsinIm([60, 10]),
88
                    [0.96076892283052284, 0.33257924500670238])
89
90
91
def test_getsinIm_2Darray():
92
    assert_allclose(helpers.getsinIm([[60, 10], [60, 10]]),
93
                    [[0.96076892283052284, 0.33257924500670238],
94
                     [0.96076892283052284, 0.33257924500670238]])
95
96
97
# ============================================================================
98
#  Test getcosIm
99
# ============================================================================
100
101
102
def test_getcosIm_scalar():
103
    assert_allclose(helpers.getcosIm(60), 0.27735009811261463)
104
    assert_allclose(helpers.getcosIm(10), 0.94307531289434765)
105
    assert type(helpers.getcosIm(60)) != np.ndarray
106
107
108
def test_getcosIm_1Darray():
109
    assert_allclose(helpers.getcosIm([60, 10]),
110
                    [0.27735009811261463, 0.94307531289434765])
111
112
113
def test_getcosIm_2Darray():
114
    assert_allclose(helpers.getcosIm([[60, 10], [60, 10]]),
115
                    [[0.27735009811261463, 0.94307531289434765],
116
                     [0.27735009811261463, 0.94307531289434765]])
117
118
119
# ============================================================================
120
#  Test toYearFraction
121
# ============================================================================
122
123
124
def test_toYearFraction():
125
    assert_allclose(helpers.toYearFraction(dt.datetime(2001, 1, 1, 0, 0, 0)),
126
                    2001)
127
    assert_allclose(helpers.toYearFraction(dt.date(2001, 1, 1)), 2001)
128
    assert_allclose(helpers.toYearFraction(dt.datetime(2002, 1, 1, 0, 0, 0)),
129
                    2002)
130
    assert_allclose(helpers.toYearFraction(dt.datetime(2005, 2, 3, 4, 5, 6)),
131
                    2005.090877283105)
132
    assert_allclose(helpers.toYearFraction(dt.datetime(2005, 12, 11, 10, 9, 8)),
133
                    2005.943624682902)
134
135
136
# ============================================================================
137
#  Test gc2gdlat
138
# ============================================================================
139
140
141
def test_gc2gdlat():
142
    assert_allclose(helpers.gc2gdlat(0), 0)
143
    assert_allclose(helpers.gc2gdlat(90), 90)
144
    assert_allclose(helpers.gc2gdlat(30), 30.166923849507356)
145
    assert_allclose(helpers.gc2gdlat(60), 60.166364190170931)
146
147
148
# ============================================================================
149
#  Test subsol
150
# ============================================================================
151
152
def test_subsol():
153
    assert_allclose(helpers.subsol(dt.datetime(2005, 2, 3, 4, 5, 6)),
154
                    (-16.505391672592904, 122.17768157084515))
155
    assert_allclose(helpers.subsol(dt.datetime(2010, 12, 11, 10, 9, 8)),
156
                    (-23.001554595838947, 26.008999999955023))
157
158
    with pytest.raises(ValueError):
159
        helpers.subsol(dt.datetime(1600, 12, 31, 23, 59, 59))
160
    assert_allclose(helpers.subsol(dt.datetime(1601, 1, 1, 0, 0, 0)),
161
                    (-23.06239721771427, -178.90131731228584))
162
    with pytest.raises(ValueError):
163
        helpers.subsol(dt.datetime(2101, 1, 1, 0, 0, 0))
164
    assert_allclose(helpers.subsol(dt.datetime(2100, 12, 31, 23, 59, 59)),
165
                    (-23.021061422069053, -179.23129780639425))
166
167
168
def datetime64_to_datetime(dt64):
169
    """Convert numpy datetime64 object to a datetime datetime object.
170
171
    Notes
172
    -----
173
    Works outside 32 bit int second range of 1970
174
175
    """
176
    year_floor = dt64.astype('datetime64[Y]')
177
    month_floor = dt64.astype('datetime64[M]')
178
    day_floor = dt64.astype('datetime64[D]')
179
    year = year_floor.astype(int) + 1970
180
    month = (month_floor - year_floor).astype('timedelta64[M]').astype(int) + 1
181
    day = (day_floor - month_floor).astype('timedelta64[D]').astype(int) + 1
182
    return dt.datetime(year, month, day)
183
184
185
def test_subsol_array():
186
    """Verify subsolar point calculation using an array of np.datetime64.
187
188
    Notes
189
    -----
190
    Tested by ensuring the array of np.datetime64 is equivalent to converting
191
    using single dt.datetime values
192
193
    """
194
    dates = np.arange(np.datetime64("1601"), np.datetime64("2100"),
195
                      np.timedelta64(100, 'D')).astype('datetime64[s]')
196
    sslat, sslon = helpers.subsol(dates)
197
    for i, date in enumerate(dates):
198
        datetime = datetime64_to_datetime(date)
199
        true_sslat, true_sslon = helpers.subsol(datetime)
200
        assert sslat[i] == true_sslat
201
        assert sslon[i] == true_sslon
202
203
204
if __name__ == '__main__':
205
    pytest.main()
206