Completed
Pull Request — master (#465)
by
unknown
49s
created

test_find_append_zero_crossings()   A

Complexity

Conditions 1

Size

Total Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
c 1
b 0
f 0
dl 0
loc 11
rs 9.4285
1
# Copyright (c) 2008-2015 MetPy Developers.
2
# Distributed under the terms of the BSD 3-Clause License.
3
# SPDX-License-Identifier: BSD-3-Clause
4
"""Test the `thermo` module."""
5
6
import numpy as np
7
import pytest
8
9
from metpy.calc import (cape_cin, density, dewpoint, dewpoint_rh, dry_lapse, el,
10
                        equivalent_potential_temperature, lcl, lfc, mixing_ratio,
11
                        mixing_ratio_from_specific_humidity, moist_lapse,
12
                        parcel_profile, potential_temperature,
13
                        psychrometric_vapor_pressure_wet,
14
                        relative_humidity_from_mixing_ratio,
15
                        relative_humidity_from_specific_humidity,
16
                        relative_humidity_wet_psychrometric,
17
                        saturation_mixing_ratio,
18
                        saturation_vapor_pressure, vapor_pressure,
19
                        virtual_potential_temperature, virtual_temperature)
20
21
from metpy.calc.thermo import _find_append_zero_crossings
22
from metpy.testing import assert_almost_equal, assert_array_almost_equal, assert_nan
23
from metpy.units import units
24
25
26
def test_potential_temperature():
27
    """Test potential_temperature calculation."""
28
    temp = np.array([278., 283., 291., 298.]) * units.kelvin
29
    pres = np.array([900., 500., 300., 100.]) * units.mbar
30
    real_th = np.array([286.493, 344.961, 410.4335, 575.236]) * units.kelvin
31
    assert_array_almost_equal(potential_temperature(pres, temp), real_th, 3)
32
33
34
def test_scalar():
35
    """Test potential_temperature accepts scalar values."""
36
    assert_almost_equal(potential_temperature(1000. * units.mbar, 293. * units.kelvin),
37
                        293. * units.kelvin, 4)
38
    assert_almost_equal(potential_temperature(800. * units.mbar, 293. * units.kelvin),
39
                        312.2828 * units.kelvin, 4)
40
41
42
def test_fahrenheit():
43
    """Test that potential_temperature handles temperature values in Fahrenheit."""
44
    assert_almost_equal(potential_temperature(800. * units.mbar, 68. * units.degF),
45
                        (312.444 * units.kelvin).to(units.degF), 2)
46
47
48
def test_pot_temp_inhg():
49
    """Test that potential_temperature can handle pressure not in mb (issue #165)."""
50
    assert_almost_equal(potential_temperature(29.92 * units.inHg, 29 * units.degC),
51
                        301.019735 * units.kelvin, 4)
52
53
54
def test_dry_lapse():
55
    """Test dry_lapse calculation."""
56
    levels = np.array([1000, 900, 864.89]) * units.mbar
57
    temps = dry_lapse(levels, 303.15 * units.kelvin)
58
    assert_array_almost_equal(temps,
59
                              np.array([303.15, 294.16, 290.83]) * units.kelvin, 2)
60
61
62
def test_dry_lapse_2_levels():
63
    """Test dry_lapse calculation when given only two levels."""
64
    temps = dry_lapse(np.array([1000., 500.]) * units.mbar, 293. * units.kelvin)
65
    assert_array_almost_equal(temps, [293., 240.3723] * units.kelvin, 4)
66
67
68
def test_moist_lapse():
69
    """Test moist_lapse calculation."""
70
    temp = moist_lapse(np.array([1000., 800., 600., 500., 400.]) * units.mbar,
71
                       293. * units.kelvin)
72
    true_temp = np.array([293, 284.64, 272.81, 264.42, 252.91]) * units.kelvin
73
    assert_array_almost_equal(temp, true_temp, 2)
74
75
76
def test_moist_lapse_degc():
77
    """Test moist_lapse with Celsius temperatures."""
78
    temp = moist_lapse(np.array([1000., 800., 600., 500., 400.]) * units.mbar,
79
                       19.85 * units.degC)
80
    true_temp = np.array([293, 284.64, 272.81, 264.42, 252.91]) * units.kelvin
81
    assert_array_almost_equal(temp, true_temp, 2)
82
83
84
def test_parcel_profile():
85
    """Test parcel profile calculation."""
86
    levels = np.array([1000., 900., 800., 700., 600., 500., 400.]) * units.mbar
87
    true_prof = np.array([303.15, 294.16, 288.026, 283.073, 277.058, 269.402,
88
                          258.966]) * units.kelvin
89
90
    prof = parcel_profile(levels, 30. * units.degC, 20. * units.degC)
91
    assert_array_almost_equal(prof, true_prof, 2)
92
93
94
def test_parcel_profile_saturated():
95
    """Test parcel_profile works when LCL in levels (issue #232)."""
96
    levels = np.array([1000., 700., 500.]) * units.mbar
97
    true_prof = np.array([296.95, 284.381, 271.123]) * units.kelvin
98
99
    prof = parcel_profile(levels, 23.8 * units.degC, 23.8 * units.degC)
100
    assert_array_almost_equal(prof, true_prof, 2)
101
102
103
def test_sat_vapor_pressure():
104
    """Test saturation_vapor_pressure calculation."""
105
    temp = np.array([5., 10., 18., 25.]) * units.degC
106
    real_es = np.array([8.72, 12.27, 20.63, 31.67]) * units.mbar
107
    assert_array_almost_equal(saturation_vapor_pressure(temp), real_es, 2)
108
109
110
def test_sat_vapor_pressure_scalar():
111
    """Test saturation_vapor_pressure handles scalar values."""
112
    es = saturation_vapor_pressure(0 * units.degC)
113
    assert_almost_equal(es, 6.112 * units.mbar, 3)
114
115
116
def test_sat_vapor_pressure_fahrenheit():
117
    """Test saturation_vapor_pressure handles temperature in Fahrenheit."""
118
    temp = np.array([50., 68.]) * units.degF
119
    real_es = np.array([12.2717, 23.3695]) * units.mbar
120
    assert_array_almost_equal(saturation_vapor_pressure(temp), real_es, 4)
121
122
123
def test_basic_dewpoint_rh():
124
    """Test dewpoint_rh function."""
125
    temp = np.array([30., 25., 10., 20., 25.]) * units.degC
126
    rh = np.array([30., 45., 55., 80., 85.]) / 100.
127
128
    real_td = np.array([11, 12, 1, 16, 22]) * units.degC
129
    assert_array_almost_equal(real_td, dewpoint_rh(temp, rh), 0)
130
131
132
def test_scalar_dewpoint_rh():
133
    """Test dewpoint_rh with scalar values."""
134
    td = dewpoint_rh(10.6 * units.degC, 0.37)
135
    assert_almost_equal(td, 26. * units.degF, 0)
136
137
138
def test_dewpoint():
139
    """Test dewpoint calculation."""
140
    assert_almost_equal(dewpoint(6.112 * units.mbar), 0. * units.degC, 2)
141
142
143
def test_dewpoint_weird_units():
144
    """Test dewpoint using non-standard units.
145
146
    Revealed from odd dimensionless units and ending up using numpy.ma math
147
    functions instead of numpy ones.
148
    """
149
    assert_almost_equal(dewpoint(15825.6 * units('g * mbar / kg')),
150
                        13.8564 * units.degC, 4)
151
152
153
def test_mixing_ratio():
154
    """Test mixing ratio calculation."""
155
    p = 998. * units.mbar
156
    e = 73.75 * units.mbar
157
    assert_almost_equal(mixing_ratio(e, p), 0.04963, 2)
158
159
160
def test_vapor_pressure():
161
    """Test vapor pressure calculation."""
162
    assert_almost_equal(vapor_pressure(998. * units.mbar, 0.04963),
163
                        73.74925 * units.mbar, 5)
164
165
166
def test_lcl():
167
    """Test LCL calculation."""
168
    lcl_pressure, lcl_temperature = lcl(1000. * units.mbar, 30. * units.degC, 20. * units.degC)
169
    assert_almost_equal(lcl_pressure, 864.761 * units.mbar, 2)
170
    assert_almost_equal(lcl_temperature, 17.676 * units.degC, 2)
171
172
173
def test_lcl_convergence():
174
    """Test LCL calculation convergence failure."""
175
    with pytest.raises(RuntimeError):
176
        lcl(1000. * units.mbar, 30. * units.degC, 20. * units.degC, max_iters=2)
177
178
179 View Code Duplication
def test_lfc_basic():
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
180
    """Test LFC calculation."""
181
    levels = np.array([959., 779.2, 751.3, 724.3, 700., 269.]) * units.mbar
182
    temperatures = np.array([22.2, 14.6, 12., 9.4, 7., -49.]) * units.celsius
183
    dewpoints = np.array([19., -11.2, -10.8, -10.4, -10., -53.2]) * units.celsius
184
    l = lfc(levels, temperatures, dewpoints)
185
    assert_almost_equal(l[0], 727.468 * units.mbar, 2)
186
    assert_almost_equal(l[1], 9.705 * units.celsius, 2)
187
188
189
def test_no_lfc():
190
    """Test LFC calculation when there is no LFC in the data."""
191
    levels = np.array([959., 867.9, 779.2, 647.5, 472.5, 321.9, 251.]) * units.mbar
192
    temperatures = np.array([22.2, 17.4, 14.6, 1.4, -17.6, -39.4, -52.5]) * units.celsius
193
    dewpoints = np.array([9., 4.3, -21.2, -26.7, -31., -53.3, -66.7]) * units.celsius
194
    lfc_pressure, lfc_temperature = lfc(levels, temperatures, dewpoints)
195
    assert assert_nan(lfc_pressure, levels.units)
196
    assert assert_nan(lfc_temperature, temperatures.units)
197
198
199 View Code Duplication
def test_lfc_inversion():
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
200
    """Test LFC when there is an inversion to be sure we don't pick that."""
201
    levels = np.array([963., 789., 782.3, 754.8, 728.1, 727., 700.,
202
                       571., 450., 300., 248.]) * units.mbar
203
    temperatures = np.array([25.4, 18.4, 17.8, 15.4, 12.9, 12.8,
204
                             10., -3.9, -16.3, -41.1, -51.5]) * units.celsius
205
    dewpoints = np.array([20.4, 0.4, -0.5, -4.3, -8., -8.2, -9.,
206
                          -23.9, -33.3, -54.1, -63.5]) * units.celsius
207
    l = lfc(levels, temperatures, dewpoints)
208
    assert_almost_equal(l[0], 706.0103 * units.mbar, 2)
209
    assert_almost_equal(l[1], 10.6232 * units.celsius, 2)
210
211
212
def test_saturation_mixing_ratio():
213
    """Test saturation mixing ratio calculation."""
214
    p = 999. * units.mbar
215
    t = 288. * units.kelvin
216
    assert_almost_equal(saturation_mixing_ratio(p, t), .01068, 3)
217
218
219
def test_equivalent_potential_temperature():
220
    """Test equivalent potential temperature calculation."""
221
    p = 999. * units.mbar
222
    t = 288. * units.kelvin
223
    ept = equivalent_potential_temperature(p, t)
224
    assert_almost_equal(ept, 315.9548 * units.kelvin, 3)
225
226
227
def test_virtual_temperature():
228
    """Test virtual temperature calculation."""
229
    t = 288. * units.kelvin
230
    qv = .0016  # kg/kg
231
    tv = virtual_temperature(t, qv)
232
    assert_almost_equal(tv, 288.2796 * units.kelvin, 3)
233
234
235
def test_virtual_potential_temperature():
236
    """Test virtual potential temperature calculation."""
237
    p = 999. * units.mbar
238
    t = 288. * units.kelvin
239
    qv = .0016  # kg/kg
240
    theta_v = virtual_potential_temperature(p, t, qv)
241
    assert_almost_equal(theta_v, 288.3620 * units.kelvin, 3)
242
243
244
def test_density():
245
    """Test density calculation."""
246
    p = 999. * units.mbar
247
    t = 288. * units.kelvin
248
    qv = .0016  # kg/kg
249
    rho = density(p, t, qv).to(units.kilogram / units.meter ** 3)
250
    assert_almost_equal(rho, 1.2072 * (units.kilogram / units.meter ** 3), 3)
251
252
253
def test_el():
254
    """Test equilibrium layer calculation."""
255
    levels = np.array([959., 779.2, 751.3, 724.3, 700., 269.]) * units.mbar
256
    temperatures = np.array([22.2, 14.6, 12., 9.4, 7., -38.]) * units.celsius
257
    dewpoints = np.array([19., -11.2, -10.8, -10.4, -10., -53.2]) * units.celsius
258
    el_pressure, el_temperature = el(levels, temperatures, dewpoints)
259
    assert_almost_equal(el_pressure, 520.8700 * units.mbar, 3)
260
    assert_almost_equal(el_temperature, -11.7027 * units.degC, 3)
261
262
263
def test_no_el():
264
    """Test equilibrium layer calculation when there is no EL in the data."""
265
    levels = np.array([959., 867.9, 779.2, 647.5, 472.5, 321.9, 251.]) * units.mbar
266
    temperatures = np.array([22.2, 17.4, 14.6, 1.4, -17.6, -39.4, -52.5]) * units.celsius
267
    dewpoints = np.array([19., 14.3, -11.2, -16.7, -21., -43.3, -56.7]) * units.celsius
268
    el_pressure, el_temperature = el(levels, temperatures, dewpoints)
269
    assert assert_nan(el_pressure, levels.units)
270
    assert assert_nan(el_temperature, temperatures.units)
271
272
273
def test_wet_psychrometric_vapor_pressure():
274
    """Test calculation of vapor pressure from wet and dry bulb temperatures."""
275
    p = 1013.25 * units.mbar
276
    dry_bulb_temperature = 20. * units.degC
277
    wet_bulb_temperature = 18. * units.degC
278
    psychrometric_vapor_pressure = psychrometric_vapor_pressure_wet(dry_bulb_temperature,
279
                                                                    wet_bulb_temperature, p)
280
    assert_almost_equal(psychrometric_vapor_pressure, 19.3673 * units.mbar, 3)
281
282
283
def test_wet_psychrometric_rh():
284
    """Test calculation of relative humidity from wet and dry bulb temperatures."""
285
    p = 1013.25 * units.mbar
286
    dry_bulb_temperature = 20. * units.degC
287
    wet_bulb_temperature = 18. * units.degC
288
    psychrometric_rh = relative_humidity_wet_psychrometric(dry_bulb_temperature,
289
                                                           wet_bulb_temperature, p)
290
    assert_almost_equal(psychrometric_rh, 82.8747 * units.percent, 3)
291
292
293
def test_wet_psychrometric_rh_kwargs():
294
    """Test calculation of relative humidity from wet and dry bulb temperatures."""
295
    p = 1013.25 * units.mbar
296
    dry_bulb_temperature = 20. * units.degC
297
    wet_bulb_temperature = 18. * units.degC
298
    coeff = 6.1e-4 / units.kelvin
299
    psychrometric_rh = relative_humidity_wet_psychrometric(dry_bulb_temperature,
300
                                                           wet_bulb_temperature, p,
301
                                                           psychrometer_coefficient=coeff)
302
    assert_almost_equal(psychrometric_rh, 82.9701 * units.percent, 3)
303
304
305
def test_rh_mixing_ratio():
306
    """Tests relative humidity from mixing ratio."""
307
    p = 1013.25 * units.mbar
308
    temperature = 20. * units.degC
309
    w = 0.012
310
    rh = relative_humidity_from_mixing_ratio(w, temperature, p)
311
    assert_almost_equal(rh, 81.7219 * units.percent, 3)
312
313
314
def test_mixing_ratio_from_specific_humidity():
315
    """Tests mixing ratio from specific humidity."""
316
    q = 0.012
317
    w = mixing_ratio_from_specific_humidity(q)
318
    assert_almost_equal(w, 0.01215, 3)
319
320
321
def test_rh_specific_humidity():
322
    """Tests relative humidity from specific humidity."""
323
    p = 1013.25 * units.mbar
324
    temperature = 20. * units.degC
325
    q = 0.012
326
    rh = relative_humidity_from_specific_humidity(q, temperature, p)
327
    assert_almost_equal(rh, 82.7145 * units.percent, 3)
328
329
330 View Code Duplication
def test_cape_cin():
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
331
    """Tests the basic CAPE and CIN calculation."""
332
    p = np.array([959., 779.2, 751.3, 724.3, 700., 269.]) * units.mbar
333
    T = np.array([22.2, 14.6, 12., 9.4, 7., -38.]) * units.celsius
334
    Td = np.array([19., -11.2, -10.8, -10.4, -10., -53.2]) * units.celsius
335
    parcel_prof = parcel_profile(p, T[0], Td[0]).to('degC')
336
    cape, cin = cape_cin(p, T, Td, parcel_prof)
337
    assert_almost_equal(cape, 58.0368212 * units('joule / kilogram'), 6)
338
    assert_almost_equal(cin, -89.8073512 * units('joule / kilogram'), 6)
339
340
341
def test_find_append_zero_crossings():
342
    """Tests finding and appending zero crossings of an x, y series."""
343
    x = np.arange(11) * units.hPa
344
    y = np.array([3, 2, 1, -1, 2, 2, 0, 1, 0, -1, 2]) * units.degC
345
    x2, y2 = _find_append_zero_crossings(x, y)
346
347
    x_truth = np.array([0., 1., 2., 2.5, 3., 3.33333333, 4., 5.,
348
                        6., 7., 8., 9., 9.33333333, 10.]) * units.hPa
349
    y_truth = np.array([3, 2, 1, 0, -1, 0, 2, 2, 0, 1, 0, -1, 0, 2]) * units.degC
350
    assert_array_almost_equal(x2, x_truth, 6)
351
    assert_almost_equal(y2, y_truth, 6)
352