Skip to content

Commit 1e3c54a

Browse files
Revert extra arguments added to handle zero humidity in thermo computations (#26)
* Revert extra arguments added to handle zero humidity in thermo computations
1 parent ef58809 commit 1e3c54a

File tree

4 files changed

+40
-143
lines changed

4 files changed

+40
-143
lines changed

docs/release_notes/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@ Release notes
44
.. toctree::
55
:maxdepth: 1
66

7+
version_0.3_updates
78
version_0.2_updates
89
version_0.1_updates
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
Version 0.3 Updates
2+
/////////////////////////
3+
4+
5+
Version 0.3.0
6+
===============
7+
8+
- Removed the ``eps`` and ``out`` keywords arguments to control zero humidity in
9+
10+
- :py:meth:`dewpoint_from_specific_humidity <meteo.thermo.array.dewpoint_from_specific_humidity>`
11+
- :py:meth:`dewpoint_from_relative_humidity <meteo.thermo.array.dewpoint_from_relative_humidity>`
12+
- :py:meth:`temperature_from_saturation_vapour_pressure <meteo.thermo.array.temperature_from_saturation_vapour_pressure>`
13+
14+
This was done to revert the changes added in version 0.2.0.

src/earthkit/meteo/thermo/array/thermo.py

Lines changed: 12 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -263,21 +263,9 @@ def compute_slope(self, t, phase):
263263
elif phase == "ice":
264264
return self._es_ice_slope(t)
265265

266-
def t_from_es(self, es, eps=1e-8, out=None):
267-
def _comp(x):
268-
x = x / self.c1
269-
x = np.log(x)
270-
return (x * self.c4w - self.c3w * self.t0) / (x - self.c3w)
271-
272-
if out is not None:
273-
v = np.asarray(es)
274-
z_mask = v < eps
275-
v_mask = ~z_mask
276-
v[v_mask] = _comp(v[v_mask])
277-
v[z_mask] = out
278-
return v
279-
else:
280-
return _comp(es)
266+
def t_from_es(self, es):
267+
v = np.log(es / self.c1)
268+
return (v * self.c4w - self.c3w * self.t0) / (v - self.c3w)
281269

282270
def _es_water(self, t):
283271
return self.c1 * np.exp(self.c3w * (t - self.t0) / (t - self.c4w))
@@ -572,35 +560,26 @@ def saturation_specific_humidity_slope(t, p, es=None, es_slope=None, phase="mixe
572560
return constants.epsilon * es_slope * p / v
573561

574562

575-
def temperature_from_saturation_vapour_pressure(es, eps=1e-8, out=None):
563+
def temperature_from_saturation_vapour_pressure(es):
576564
r"""Compute the temperature from saturation vapour pressure.
577565
578566
Parameters
579567
----------
580568
es: ndarray
581569
:func:`saturation_vapour_pressure` (Pa)
582-
eps: number
583-
If ``out`` is not None, return ``out`` when ``es`` < ``eps``. If out
584-
is None, ``eps`` is ignored and return np.nan for ``es`` values very
585-
close to zero. *New in version 0.2.0*
586-
out: number or None
587-
If not None, return ``out`` when ``es`` < ``eps``. If None, ``eps`` is
588-
ignored and return np.nan for ``es`` values very close to zero.
589-
*New in version 0.2.0*
590-
591570
592571
Returns
593572
-------
594573
ndarray
595-
Temperature (K)
574+
Temperature (K). For zero ``es`` values returns np.nan.
596575
597576
598577
The computation is always based on the "water" phase of
599578
the :func:`saturation_vapour_pressure` formulation irrespective of the
600579
phase ``es`` was computed to.
601580
602581
"""
603-
return _EsComp().t_from_es(es, eps=eps, out=out)
582+
return _EsComp().t_from_es(es)
604583

605584

606585
def relative_humidity_from_dewpoint(t, td):
@@ -775,7 +754,7 @@ def specific_humidity_from_relative_humidity(t, r, p):
775754
return specific_humidity_from_vapour_pressure(e, p)
776755

777756

778-
def dewpoint_from_relative_humidity(t, r, eps=1e-8, out=None):
757+
def dewpoint_from_relative_humidity(t, r):
779758
r"""Compute the dewpoint temperature from relative humidity.
780759
781760
Parameters
@@ -784,19 +763,11 @@ def dewpoint_from_relative_humidity(t, r, eps=1e-8, out=None):
784763
Temperature (K)
785764
r: ndarray
786765
Relative humidity (%)
787-
eps: number
788-
If ``out`` is not None, return ``out`` when ``r`` < ``eps``.
789-
If out is None, ``eps`` is ignored and return np.nan for ``r``
790-
values very close to zero. *New in version 0.2.0*
791-
out: number or None
792-
If not None, return ``out`` when ``r`` < ``eps``. If None, ``eps`` is
793-
ignored and return np.nan for ``r`` values very close to zero.
794-
*New in version 0.2.0*
795766
796767
Returns
797768
-------
798769
ndarray
799-
Dewpoint temperature (K)
770+
Dewpoint temperature (K). For zero ``r`` values returns np.nan.
800771
801772
802773
The computation starts with determining the the saturation vapour pressure over
@@ -815,24 +786,11 @@ def dewpoint_from_relative_humidity(t, r, eps=1e-8, out=None):
815786
equations used in :func:`saturation_vapour_pressure`.
816787
817788
"""
818-
# by masking upfront we avoid RuntimeWarning when calling log() in
819-
# the computation of td when r is very small
820-
if out is not None:
821-
r = np.asarray(r)
822-
mask = r < eps
823-
r[mask] = np.nan
824-
825789
es = saturation_vapour_pressure(t, phase="water") * r / 100.0
826-
td = temperature_from_saturation_vapour_pressure(es)
790+
return temperature_from_saturation_vapour_pressure(es)
827791

828-
if out is not None and not np.isnan(out):
829-
td = np.asarray(td)
830-
td[mask] = out
831792

832-
return td
833-
834-
835-
def dewpoint_from_specific_humidity(q, p, eps=1e-8, out=None):
793+
def dewpoint_from_specific_humidity(q, p):
836794
r"""Compute the dewpoint temperature from specific humidity.
837795
838796
Parameters
@@ -841,19 +799,11 @@ def dewpoint_from_specific_humidity(q, p, eps=1e-8, out=None):
841799
Specific humidity (kg/kg)
842800
p: ndarray
843801
Pressure (Pa)
844-
eps: number
845-
If ``out`` is not None, return ``out`` when ``q`` < ``eps``.
846-
If out is None, ``eps`` is ignored and return np.nan for ``q``
847-
values very close to zero. *New in version 0.2.0*
848-
out: number or None
849-
If not None, return ``out`` when ``q`` < ``eps``. If None, ``eps`` is
850-
ignored and return np.nan for ``q`` values very close to zero.
851-
*New in version 0.2.0*
852802
853803
Returns
854804
-------
855805
ndarray
856-
Dewpoint temperature (K)
806+
Dewpoint temperature (K). For zero ``q`` values returns np.nan.
857807
858808
859809
The computation starts with determining the the saturation vapour pressure over
@@ -873,21 +823,7 @@ def dewpoint_from_specific_humidity(q, p, eps=1e-8, out=None):
873823
used in :func:`saturation_vapour_pressure`.
874824
875825
"""
876-
# by masking upfront we avoid RuntimeWarning when calling log() in
877-
# the computation of td when q is very small
878-
if out is not None:
879-
q = np.asarray(q)
880-
mask = q < eps
881-
q[mask] = np.nan
882-
883-
es = vapour_pressure_from_specific_humidity(q, p)
884-
td = temperature_from_saturation_vapour_pressure(es)
885-
886-
if out is not None and not np.isnan(out):
887-
td = np.asarray(td)
888-
td[mask] = out
889-
890-
return td
826+
return temperature_from_saturation_vapour_pressure(vapour_pressure_from_specific_humidity(q, p))
891827

892828

893829
def virtual_temperature(t, q):

tests/thermo/test_thermo_array.py

Lines changed: 13 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -334,24 +334,20 @@ def test_temperature_from_saturation_vapour_pressure_1():
334334

335335

336336
@pytest.mark.parametrize(
337-
"es,kwargs,expected_values",
337+
"es,expected_values",
338338
[
339-
(4.2, {}, 219.7796336743947),
340-
([4.2, 0, 0.001, np.nan], {"eps": 1e-2, "out": 100}, [219.7796336743947, 100, 100, np.nan]),
341-
([4.2, 0, 0.001, np.nan], {"eps": 1e-2, "out": np.nan}, [219.7796336743947, np.nan, np.nan, np.nan]),
342-
(0, {}, np.nan),
343-
(0.001, {"eps": 1e-2, "out": 100}, 100.0),
344-
(0.001, {"eps": 1e-2, "out": np.nan}, np.nan),
339+
(4.2, 219.7796336743947),
340+
(0, np.nan),
345341
],
346342
)
347-
def test_temperature_from_saturation_vapour_pressure_2(es, kwargs, expected_values):
343+
def test_temperature_from_saturation_vapour_pressure_2(es, expected_values):
348344

349345
multi = isinstance(es, list)
350346
if multi:
351347
es = np.array(es)
352348
expected_values = np.array(expected_values)
353349

354-
t = thermo.array.temperature_from_saturation_vapour_pressure(es, **kwargs)
350+
t = thermo.array.temperature_from_saturation_vapour_pressure(es)
355351
if multi:
356352
np.testing.assert_allclose(t, expected_values, equal_nan=True)
357353
else:
@@ -448,7 +444,7 @@ def test_specific_humidity_from_relative_humidity():
448444

449445

450446
@pytest.mark.parametrize(
451-
"t,r,kwargs,expected_values",
447+
"t,r,expected_values",
452448
[
453449
(
454450
[20.0, 20, 0, 35, 5, -15, 25, 25],
@@ -462,37 +458,12 @@ def test_specific_humidity_from_relative_humidity():
462458
15.4779832381,
463459
0,
464460
],
465-
{},
466461
[20.0, 10, -10, 32, -15, -24, -3, np.nan],
467462
),
468-
(
469-
[20.0, 20.0, 20.0],
470-
[
471-
52.5224541378,
472-
0.0,
473-
0.000001,
474-
],
475-
{"eps": 1e-3, "out": thermo.array.celsius_to_kelvin(100)},
476-
[10, 100, 100],
477-
),
478-
(
479-
[20.0, 20.0, 20.0],
480-
[
481-
52.5224541378,
482-
0.0,
483-
0.000001,
484-
],
485-
{"eps": 1e-3, "out": np.nan},
486-
[10, np.nan, np.nan],
487-
),
488-
(20.0, 52.5224541378, {}, 10.0),
489-
(20.0, 0.0, {"eps": 1e-3, "out": thermo.array.celsius_to_kelvin(100)}, 100),
490-
(20.0, 0.000001, {"eps": 1e-3, "out": thermo.array.celsius_to_kelvin(100)}, 100),
491-
(20.0, 0.0, {"eps": 1e-3, "out": np.nan}, np.nan),
492-
(20, 0.000001, {"eps": 1e-3, "out": np.nan}, np.nan),
463+
(20.0, 52.5224541378, 10.0),
493464
],
494465
)
495-
def test_dewpoint_from_relative_humidity(t, r, kwargs, expected_values):
466+
def test_dewpoint_from_relative_humidity(t, r, expected_values):
496467
# reference was tested with an online relhum calculator at:
497468
# https://bmcnoldy.rsmas.miami.edu/Humidity.html
498469

@@ -505,50 +476,25 @@ def test_dewpoint_from_relative_humidity(t, r, kwargs, expected_values):
505476
t = thermo.array.celsius_to_kelvin(t)
506477
v_ref = thermo.array.celsius_to_kelvin(expected_values)
507478

508-
td = thermo.array.dewpoint_from_relative_humidity(t, r, **kwargs)
479+
td = thermo.array.dewpoint_from_relative_humidity(t, r)
509480
if multi:
510481
assert np.allclose(td, v_ref, equal_nan=True)
511482
else:
512483
assert np.isclose(td, v_ref, equal_nan=True)
513484

514485

515486
@pytest.mark.parametrize(
516-
"q,p,kwargs,expected_values",
487+
"q,p,expected_values",
517488
[
518489
(
519490
[0.0169461501, 0.0155840075, 0.0134912382, 0.0083409720, 0.0057268584, 0.0025150791, 0],
520491
[967.5085, 936.3775, 872.248, 756.1647, 649.157, 422.4207, 422.4207],
521-
{},
522492
[21.78907, 19.90885, 16.50236, 7.104064, -0.3548709, -16.37916, np.nan],
523493
),
524-
(
525-
[
526-
0.0169461501,
527-
0.0,
528-
0.000001,
529-
],
530-
[967.5085, 967.5085, 967.5085],
531-
{"eps": 1e-3, "out": thermo.array.celsius_to_kelvin(100)},
532-
[21.78907, 100, 100],
533-
),
534-
(
535-
[
536-
0.0169461501,
537-
0.0,
538-
0.000001,
539-
],
540-
[967.5085, 967.5085, 967.5085],
541-
{"eps": 1e-3, "out": np.nan},
542-
[21.78907, np.nan, np.nan],
543-
),
544-
(0.0169461501, 967.508, {}, 21.78907),
545-
(0.0, 967.5085, {"eps": 1e-3, "out": thermo.array.celsius_to_kelvin(100)}, 100),
546-
(0.000001, 967.5085, {"eps": 1e-3, "out": thermo.array.celsius_to_kelvin(100)}, 100),
547-
(0.0, 967.5085, {"eps": 1e-3, "out": np.nan}, np.nan),
548-
(0.000001, 967.5085, {"eps": 1e-3, "out": np.nan}, np.nan),
494+
(0.0169461501, 967.508, 21.78907),
549495
],
550496
)
551-
def test_dewpoint_from_specific_humidity(q, p, kwargs, expected_values):
497+
def test_dewpoint_from_specific_humidity(q, p, expected_values):
552498
multi = isinstance(q, list)
553499
if multi:
554500
q = np.array(q)
@@ -558,7 +504,7 @@ def test_dewpoint_from_specific_humidity(q, p, kwargs, expected_values):
558504
p = p * 100.0
559505
v_ref = thermo.array.celsius_to_kelvin(expected_values)
560506

561-
td = thermo.array.dewpoint_from_specific_humidity(q, p, **kwargs)
507+
td = thermo.array.dewpoint_from_specific_humidity(q, p)
562508
if multi:
563509
assert np.allclose(td, v_ref, equal_nan=True)
564510
else:

0 commit comments

Comments
 (0)