Completed
Push — master ( 6267cd...a45047 )
by Ryan
17s
created

test_cape_cin_no_lfc()   A

Complexity

Conditions 1

Size

Total Lines 9

Duplication

Lines 9
Ratio 100 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
c 1
b 0
f 0
dl 9
loc 9
rs 9.6666
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
def test_lfc_basic():
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
def test_lfc_inversion():
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_lfc_equals_lcl():
213
    """Test LFC when there is no cap and the lfc is equal to the lcl."""
214
    levels = np.array([912., 905.3, 874.4, 850., 815.1, 786.6, 759.1,
215
                       748., 732.2, 700., 654.8]) * units.mbar
216
    temperatures = np.array([29.4, 28.7, 25.2, 22.4, 19.4, 16.8,
217
                             14.3, 13.2, 12.6, 11.4, 7.1]) * units.celsius
218
    dewpoints = np.array([18.4, 18.1, 16.6, 15.4, 13.2, 11.4, 9.6,
219
                          8.8, 0., -18.6, -22.9]) * units.celsius
220
    l = lfc(levels, temperatures, dewpoints)
221
    assert_almost_equal(l[0], 777.0333 * units.mbar, 2)
222
    assert_almost_equal(l[1], 15.8714 * units.celsius, 2)
223
224
225
def test_saturation_mixing_ratio():
226
    """Test saturation mixing ratio calculation."""
227
    p = 999. * units.mbar
228
    t = 288. * units.kelvin
229
    assert_almost_equal(saturation_mixing_ratio(p, t), .01068, 3)
230
231
232
def test_equivalent_potential_temperature():
233
    """Test equivalent potential temperature calculation."""
234
    p = 999. * units.mbar
235
    t = 288. * units.kelvin
236
    ept = equivalent_potential_temperature(p, t)
237
    assert_almost_equal(ept, 315.9548 * units.kelvin, 3)
238
239
240
def test_virtual_temperature():
241
    """Test virtual temperature calculation."""
242
    t = 288. * units.kelvin
243
    qv = .0016  # kg/kg
244
    tv = virtual_temperature(t, qv)
245
    assert_almost_equal(tv, 288.2796 * units.kelvin, 3)
246
247
248
def test_virtual_potential_temperature():
249
    """Test virtual potential temperature calculation."""
250
    p = 999. * units.mbar
251
    t = 288. * units.kelvin
252
    qv = .0016  # kg/kg
253
    theta_v = virtual_potential_temperature(p, t, qv)
254
    assert_almost_equal(theta_v, 288.3620 * units.kelvin, 3)
255
256
257
def test_density():
258
    """Test density calculation."""
259
    p = 999. * units.mbar
260
    t = 288. * units.kelvin
261
    qv = .0016  # kg/kg
262
    rho = density(p, t, qv).to(units.kilogram / units.meter ** 3)
263
    assert_almost_equal(rho, 1.2072 * (units.kilogram / units.meter ** 3), 3)
264
265
266
def test_el():
267
    """Test equilibrium layer calculation."""
268
    levels = np.array([959., 779.2, 751.3, 724.3, 700., 269.]) * units.mbar
269
    temperatures = np.array([22.2, 14.6, 12., 9.4, 7., -38.]) * units.celsius
270
    dewpoints = np.array([19., -11.2, -10.8, -10.4, -10., -53.2]) * units.celsius
271
    el_pressure, el_temperature = el(levels, temperatures, dewpoints)
272
    assert_almost_equal(el_pressure, 520.8700 * units.mbar, 3)
273
    assert_almost_equal(el_temperature, -11.7027 * units.degC, 3)
274
275
276
def test_no_el():
277
    """Test equilibrium layer calculation when there is no EL in the data."""
278
    levels = np.array([959., 867.9, 779.2, 647.5, 472.5, 321.9, 251.]) * units.mbar
279
    temperatures = np.array([22.2, 17.4, 14.6, 1.4, -17.6, -39.4, -52.5]) * units.celsius
280
    dewpoints = np.array([19., 14.3, -11.2, -16.7, -21., -43.3, -56.7]) * units.celsius
281
    el_pressure, el_temperature = el(levels, temperatures, dewpoints)
282
    assert assert_nan(el_pressure, levels.units)
283
    assert assert_nan(el_temperature, temperatures.units)
284
285
286
def test_el_lfc_equals_lcl():
287
    """Test equilibrium layer calculation when the lfc equals the lcl."""
288
    levels = np.array([912., 905.3, 874.4, 850., 815.1, 786.6, 759.1, 748.,
289
                       732.3, 700., 654.8, 606.8, 562.4, 501.8, 500., 482.,
290
                       400., 393.3, 317.1, 307., 300., 252.7, 250., 200.,
291
                       199.3, 197., 190., 172., 156.6, 150., 122.9, 112.,
292
                       106.2, 100.]) * units.mbar
293
    temperatures = np.array([29.4, 28.7, 25.2, 22.4, 19.4, 16.8, 14.3,
294
                             13.2, 12.6, 11.4, 7.1, 2.2, -2.7, -10.1,
295
                             -10.3, -12.4, -23.3, -24.4, -38., -40.1, -41.1,
296
                             -49.8, -50.3, -59.1, -59.1, -59.3, -59.7, -56.3,
297
                             -56.9, -57.1, -59.1, -60.1, -58.6, -56.9]) * units.celsius
298
    dewpoints = np.array([18.4, 18.1, 16.6, 15.4, 13.2, 11.4, 9.6, 8.8, 0.,
299
                          -18.6, -22.9, -27.8, -32.7, -40.1, -40.3, -42.4, -53.3,
300
                          -54.4, -68., -70.1, -70., -70., -70., -70., -70., -70.,
301
                          -70., -70., -70., -70., -70., -70., -70., -70.]) * units.celsius
302
    el_pressure, el_temperature = el(levels, temperatures, dewpoints)
303
    assert_almost_equal(el_pressure, 175.8684 * units.mbar, 3)
304
    assert_almost_equal(el_temperature, -57.0307 * units.degC, 3)
305
306
307
def test_wet_psychrometric_vapor_pressure():
308
    """Test calculation of vapor pressure from wet and dry bulb temperatures."""
309
    p = 1013.25 * units.mbar
310
    dry_bulb_temperature = 20. * units.degC
311
    wet_bulb_temperature = 18. * units.degC
312
    psychrometric_vapor_pressure = psychrometric_vapor_pressure_wet(dry_bulb_temperature,
313
                                                                    wet_bulb_temperature, p)
314
    assert_almost_equal(psychrometric_vapor_pressure, 19.3673 * units.mbar, 3)
315
316
317
def test_wet_psychrometric_rh():
318
    """Test calculation of relative humidity from wet and dry bulb temperatures."""
319
    p = 1013.25 * units.mbar
320
    dry_bulb_temperature = 20. * units.degC
321
    wet_bulb_temperature = 18. * units.degC
322
    psychrometric_rh = relative_humidity_wet_psychrometric(dry_bulb_temperature,
323
                                                           wet_bulb_temperature, p)
324
    assert_almost_equal(psychrometric_rh, 82.8747 * units.percent, 3)
325
326
327
def test_wet_psychrometric_rh_kwargs():
328
    """Test calculation of relative humidity from wet and dry bulb temperatures."""
329
    p = 1013.25 * units.mbar
330
    dry_bulb_temperature = 20. * units.degC
331
    wet_bulb_temperature = 18. * units.degC
332
    coeff = 6.1e-4 / units.kelvin
333
    psychrometric_rh = relative_humidity_wet_psychrometric(dry_bulb_temperature,
334
                                                           wet_bulb_temperature, p,
335
                                                           psychrometer_coefficient=coeff)
336
    assert_almost_equal(psychrometric_rh, 82.9701 * units.percent, 3)
337
338
339
def test_rh_mixing_ratio():
340
    """Tests relative humidity from mixing ratio."""
341
    p = 1013.25 * units.mbar
342
    temperature = 20. * units.degC
343
    w = 0.012
344
    rh = relative_humidity_from_mixing_ratio(w, temperature, p)
345
    assert_almost_equal(rh, 81.7219 * units.percent, 3)
346
347
348
def test_mixing_ratio_from_specific_humidity():
349
    """Tests mixing ratio from specific humidity."""
350
    q = 0.012
351
    w = mixing_ratio_from_specific_humidity(q)
352
    assert_almost_equal(w, 0.01215, 3)
353
354
355
def test_rh_specific_humidity():
356
    """Tests relative humidity from specific humidity."""
357
    p = 1013.25 * units.mbar
358
    temperature = 20. * units.degC
359
    q = 0.012
360
    rh = relative_humidity_from_specific_humidity(q, temperature, p)
361
    assert_almost_equal(rh, 82.7145 * units.percent, 3)
362
363
364 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...
365
    """Tests the basic CAPE and CIN calculation."""
366
    p = np.array([959., 779.2, 751.3, 724.3, 700., 269.]) * units.mbar
367
    temperature = np.array([22.2, 14.6, 12., 9.4, 7., -38.]) * units.celsius
368
    dewpoint = np.array([19., -11.2, -10.8, -10.4, -10., -53.2]) * units.celsius
369
    parcel_prof = parcel_profile(p, temperature[0], dewpoint[0]).to('degC')
370
    cape, cin = cape_cin(p, temperature, dewpoint, parcel_prof)
371
    assert_almost_equal(cape, 58.0368212 * units('joule / kilogram'), 6)
372
    assert_almost_equal(cin, -89.8073512 * units('joule / kilogram'), 6)
373
374
375 View Code Duplication
def test_cape_cin_no_el():
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
376
    """Tests that CAPE works with no EL."""
377
    p = np.array([959., 779.2, 751.3, 724.3]) * units.mbar
378
    temperature = np.array([22.2, 14.6, 12., 9.4]) * units.celsius
379
    dewpoint = np.array([19., -11.2, -10.8, -10.4]) * units.celsius
380
    parcel_prof = parcel_profile(p, temperature[0], dewpoint[0]).to('degC')
381
    cape, cin = cape_cin(p, temperature, dewpoint, parcel_prof)
382
    assert_almost_equal(cape, 0.08750805 * units('joule / kilogram'), 6)
383
    assert_almost_equal(cin, -89.8073512 * units('joule / kilogram'), 6)
384
385
386 View Code Duplication
def test_cape_cin_no_lfc():
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
387
    """Tests that CAPE is zero with no LFC."""
388
    p = np.array([959., 779.2, 751.3, 724.3, 700., 269.]) * units.mbar
389
    temperature = np.array([22.2, 24.6, 22., 20.4, 18., -10.]) * units.celsius
390
    dewpoint = np.array([19., -11.2, -10.8, -10.4, -10., -53.2]) * units.celsius
391
    parcel_prof = parcel_profile(p, temperature[0], dewpoint[0]).to('degC')
392
    cape, cin = cape_cin(p, temperature, dewpoint, parcel_prof)
393
    assert_almost_equal(cape, 0.0 * units('joule / kilogram'), 6)
394
    assert_almost_equal(cin, 0.0 * units('joule / kilogram'), 6)
395
396
397
def test_find_append_zero_crossings():
398
    """Tests finding and appending zero crossings of an x, y series."""
399
    x = np.arange(11) * units.hPa
400
    y = np.array([3, 2, 1, -1, 2, 2, 0, 1, 0, -1, 2]) * units.degC
401
    x2, y2 = _find_append_zero_crossings(x, y)
402
403
    x_truth = np.array([0., 1., 2., 2.5, 3., 3.33333333, 4., 5.,
404
                        6., 7., 8., 9., 9.33333333, 10.]) * units.hPa
405
    y_truth = np.array([3, 2, 1, 0, -1, 0, 2, 2, 0, 1, 0, -1, 0, 2]) * units.degC
406
    assert_array_almost_equal(x2, x_truth, 6)
407
    assert_almost_equal(y2, y_truth, 6)
408