Skip to content

Commit

Permalink
Check that pressure decreases monotonically in parcel calculations
Browse files Browse the repository at this point in the history
This commit addresses #1339 using ideas from #1654.  A new exception
is added on the theory that parcel calculations are complicated, so
there may be other problems with input soundings (extreme
supersaturation?) that might want to be flagged in the future.
  • Loading branch information
sgdecker committed Jul 14, 2021
1 parent 77fafe5 commit 40fccff
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/metpy/calc/exceptions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
class InvalidSoundingError(ValueError):
"""Raise when a sounding does not meet thermodynamic calculation expectations."""
16 changes: 16 additions & 0 deletions src/metpy/calc/thermo.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

from .tools import (_greater_or_close, _less_or_close, _remove_nans, find_bounding_indices,
find_intersections, first_derivative, get_layer)
from .exceptions import InvalidSoundingError
from .. import constants as mpconsts
from ..cbook import broadcast_indices
from ..interpolate.one_dimension import interpolate_1d
Expand Down Expand Up @@ -873,13 +874,28 @@ def parcel_profile_with_lcl_as_dataset(pressure, temperature, dewpoint):
)


def _check_pressure(pressure):
"""Check that pressure decreases monotonically.
Returns True if the pressure decreases monotonically; otherwise, returns False."""

return np.all(pressure[:-1] > pressure[1:])


def _parcel_profile_helper(pressure, temperature, dewpoint):
"""Help calculate parcel profiles.
Returns the temperature and pressure, above, below, and including the LCL. The
other calculation functions decide what to do with the pieces.
"""
# Check that pressure is monotonic decreasing.
if not _check_pressure(pressure):
msg = """
Pressure does not decrease monotonically in your sounding.
Using scipy.signal.medfilt may fix this."""
raise InvalidSoundingError(msg)

# Find the LCL
press_lcl, temp_lcl = lcl(pressure[0], temperature, dewpoint)
press_lcl = press_lcl.to(pressure.units)
Expand Down
11 changes: 11 additions & 0 deletions tests/calc/test_thermo.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
vertical_velocity, vertical_velocity_pressure,
virtual_potential_temperature, virtual_temperature,
wet_bulb_temperature)
from metpy.calc.exceptions import InvalidSoundingError
from metpy.calc.thermo import _find_append_zero_crossings
from metpy.testing import assert_almost_equal, assert_array_almost_equal, assert_nan
from metpy.units import masked_array, units
Expand Down Expand Up @@ -190,6 +191,16 @@ def test_parcel_profile_lcl():
assert_array_almost_equal(prof, true_prof, 2)


def test_parcel_profile_lcl_not_monotonic():
"""Test parcel profile with lcl calculation."""
with pytest.raises(InvalidSoundingError):
p = np.array([1004., 1000., 943., 925., 928., 850., 839., 749., 700.]) * units.hPa
t = np.array([24.2, 24., 20.2, 21.6, 21.4, 20.4, 20.2, 14.4, 13.2]) * units.degC
td = np.array([21.9, 22.1, 19.2, 20.5, 20.4, 18.4, 17.4, 8.4, -2.8]) * units.degC

pressure, temp, dewp, prof = parcel_profile_with_lcl(p, t, td)


def test_parcel_profile_with_lcl_as_dataset():
"""Test parcel profile with lcl calculation with xarray."""
p = np.array([1004., 1000., 943., 928., 925., 850., 839., 749., 700., 699.]) * units.hPa
Expand Down

0 comments on commit 40fccff

Please sign in to comment.