Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Limit shading of CIN #1139

Merged
merged 4 commits into from Jan 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion examples/Advanced_Sounding.py
Expand Up @@ -73,7 +73,7 @@
skew.plot(p, prof, 'k', linewidth=2)

# Shade areas of CAPE and CIN
skew.shade_cin(p, T, prof)
skew.shade_cin(p, T, prof, Td)
skew.shade_cape(p, T, prof)

# An example of a slanted line at constant T -- in this case the 0
Expand Down
25 changes: 19 additions & 6 deletions src/metpy/plots/skewt.py
Expand Up @@ -23,7 +23,7 @@
import numpy as np

from ._util import colored_line
from ..calc import dewpoint, dry_lapse, moist_lapse, vapor_pressure
from ..calc import dewpoint, dry_lapse, el, lcl, moist_lapse, vapor_pressure
from ..calc.tools import _delete_masked_points
from ..deprecation import metpyDeprecation
from ..interpolate import interpolate_1d
Expand Down Expand Up @@ -666,7 +666,7 @@ def shade_area(self, y, x1, x2=0, which='both', **kwargs):
return self.ax.fill_betweenx(*arrs, **fill_args)

def shade_cape(self, p, t, t_parcel, **kwargs):
r"""Shade areas of CAPE.
r"""Shade areas of Convective Available Potential Energy (CAPE).

Shades areas where the parcel is warmer than the environment (areas of positive
buoyancy.
Expand All @@ -677,8 +677,12 @@ def shade_cape(self, p, t, t_parcel, **kwargs):
Pressure values
t : array_like
Temperature values
dewpoint : array_like
Dewpoint values
t_parcel : array_like
Parcel path temperature values
limit_shading : bool
Eliminate shading below the LCL or above the EL, default is True
kwargs
Other keyword arguments to pass to :class:`matplotlib.collections.PolyCollection`

Expand All @@ -694,11 +698,12 @@ def shade_cape(self, p, t, t_parcel, **kwargs):
"""
return self.shade_area(p, t_parcel, t, which='positive', **kwargs)

def shade_cin(self, p, t, t_parcel, **kwargs):
r"""Shade areas of CIN.
def shade_cin(self, p, t, t_parcel, dewpoint=None, **kwargs):
r"""Shade areas of Convective INhibition (CIN).

Shades areas where the parcel is cooler than the environment (areas of negative
buoyancy.
buoyancy. If `dewpoint` is passed in, negative area below the lifting condensation
level or above the equilibrium level is not shaded.

Parameters
----------
Expand All @@ -708,6 +713,8 @@ def shade_cin(self, p, t, t_parcel, **kwargs):
Temperature values
t_parcel : array_like
Parcel path temperature values
dewpoint : array_like
Dew point values, optional
kwargs
Other keyword arguments to pass to :class:`matplotlib.collections.PolyCollection`

Expand All @@ -721,7 +728,13 @@ def shade_cin(self, p, t, t_parcel, **kwargs):
:func:`matplotlib.axes.Axes.fill_betweenx`

"""
return self.shade_area(p, t_parcel, t, which='negative', **kwargs)
if dewpoint is not None:
lcl_p, _ = lcl(p[0], t[0], dewpoint[0])
el_p, _ = el(p, t, dewpoint, t_parcel)
idx = np.logical_and(p > el_p, p < lcl_p)
else:
idx = np.arange(0, len(p))
return self.shade_area(p[idx], t_parcel[idx], t[idx], which='negative', **kwargs)


@exporter.export
Expand Down
Binary file modified tests/plots/baseline/test_skewt_shade_area.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/plots/baseline/test_skewt_shade_area_kwargs.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/plots/baseline/test_skewt_shade_cape_cin.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/plots/baseline/test_skewt_wide_aspect_ratio.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
66 changes: 54 additions & 12 deletions tests/plots/test_skewt.py
Expand Up @@ -147,31 +147,73 @@ def test_skewt_units():
@pytest.fixture()
def test_profile():
"""Return data for a test profile."""
return np.linspace(1000, 100, 10), np.linspace(20, -20, 10), np.linspace(25, -30, 10)


@pytest.mark.mpl_image_compare(tolerance=.02, remove_text=True, style='default')
pressure = np.array([966., 937.2, 925., 904.6, 872.6, 853., 850., 836., 821., 811.6, 782.3,
754.2, 726.9, 700., 648.9, 624.6, 601.1, 595., 587., 576., 555.7,
534.2, 524., 500., 473.3, 400., 384.5, 358., 343., 308.3, 300., 276.,
273., 268.5, 250., 244.2, 233., 200.]) * units.mbar
temperature = np.array([18.2, 16.8, 16.2, 15.1, 13.3, 12.2, 12.4, 14., 14.4,
13.7, 11.4, 9.1, 6.8, 4.4, -1.4, -4.4, -7.3, -8.1,
-7.9, -7.7, -8.7, -9.8, -10.3, -13.5, -17.1, -28.1, -30.7,
-35.3, -37.1, -43.5, -45.1, -49.9, -50.4, -51.1, -54.1, -55.,
-56.7, -57.5]) * units.degC
dewpoint = np.array([16.9, 15.9, 15.5, 14.2, 12.1, 10.8, 8.6, 0., -3.6, -4.4,
-6.9, -9.5, -12., -14.6, -15.8, -16.4, -16.9, -17.1, -27.9, -42.7,
-44.1, -45.6, -46.3, -45.5, -47.1, -52.1, -50.4, -47.3, -57.1,
-57.9, -58.1, -60.9, -61.4, -62.1, -65.1, -65.6,
-66.7, -70.5]) * units.degC
profile = np. array([18.2, 16.18287437, 15.68644745, 14.8369451,
13.45220646, 12.57020365, 12.43280242, 11.78283506,
11.0698586, 10.61393901, 9.14490966, 7.66233636,
6.1454231, 4.56888673, 1.31644072, -0.36678427,
-2.09120703, -2.55566745, -3.17594616, -4.05032505,
-5.73356001, -7.62361933, -8.56236581, -10.88846868,
-13.69095789, -22.82604468, -25.08463516, -29.26014016,
-31.81335912, -38.29612829, -39.97374452, -45.11966793,
-45.79482793, -46.82129892, -51.21936594, -52.65924319,
-55.52598916, -64.68843697]) * units.degC
return pressure, temperature, dewpoint, profile


@pytest.mark.mpl_image_compare(tolerance=.033, remove_text=True, style='default')
def test_skewt_shade_cape_cin(test_profile):
"""Test shading CAPE and CIN on a SkewT plot."""
p, t, tp = test_profile
p, t, td, tp = test_profile

with matplotlib.rc_context({'axes.autolimit_mode': 'data'}):
fig = plt.figure(figsize=(9, 9))
skew = SkewT(fig, aspect='auto')
skew.plot(p, t, 'r')
skew.plot(p, tp, 'k')
skew.shade_cape(p, t, tp)
skew.shade_cin(p, t, tp, td)
skew.ax.set_xlim(-50, 50)
skew.ax.set_ylim(1000, 100)

return fig


@pytest.mark.mpl_image_compare(tolerance=0.033, remove_text=True, style='default')
def test_skewt_shade_cape_cin_no_limit(test_profile):
"""Test shading CIN without limits."""
p, t, _, tp = test_profile

with matplotlib.rc_context({'axes.autolimit_mode': 'data'}):
fig = plt.figure(figsize=(9, 9))
skew = SkewT(fig)
skew.plot(p, t, 'r')
skew.plot(p, tp, 'k')
skew.shade_cape(p, t, tp)
skew.shade_cin(p, t, tp)
skew.ax.set_xlim(-50, 50)
skew.ax.set_ylim(1000, 100)

return fig


@pytest.mark.mpl_image_compare(tolerance=0.02, remove_text=True, style='default')
@pytest.mark.mpl_image_compare(tolerance=0.033, remove_text=True, style='default')
def test_skewt_shade_area(test_profile):
"""Test shading areas on a SkewT plot."""
p, t, tp = test_profile
p, t, _, tp = test_profile

with matplotlib.rc_context({'axes.autolimit_mode': 'data'}):
fig = plt.figure(figsize=(9, 9))
Expand All @@ -187,7 +229,7 @@ def test_skewt_shade_area(test_profile):

def test_skewt_shade_area_invalid(test_profile):
"""Test shading areas on a SkewT plot."""
p, t, tp = test_profile
p, t, _, tp = test_profile
fig = plt.figure(figsize=(9, 9))
skew = SkewT(fig, aspect='auto')
skew.plot(p, t, 'r')
Expand All @@ -196,10 +238,10 @@ def test_skewt_shade_area_invalid(test_profile):
skew.shade_area(p, t, tp, which='positve')


@pytest.mark.mpl_image_compare(tolerance=0.02, remove_text=True, style='default')
@pytest.mark.mpl_image_compare(tolerance=0.033, remove_text=True, style='default')
def test_skewt_shade_area_kwargs(test_profile):
"""Test shading areas on a SkewT plot with kwargs."""
p, t, tp = test_profile
p, t, _, tp = test_profile

with matplotlib.rc_context({'axes.autolimit_mode': 'data'}):
fig = plt.figure(figsize=(9, 9))
Expand All @@ -213,10 +255,10 @@ def test_skewt_shade_area_kwargs(test_profile):
return fig


@pytest.mark.mpl_image_compare(tolerance=0, remove_text=True, style='default')
@pytest.mark.mpl_image_compare(tolerance=0.039, remove_text=True, style='default')
def test_skewt_wide_aspect_ratio(test_profile):
"""Test plotting a skewT with a wide aspect ratio."""
p, t, tp = test_profile
p, t, _, tp = test_profile

fig = plt.figure(figsize=(12.5, 3))
skew = SkewT(fig, aspect='auto')
Expand Down
4 changes: 2 additions & 2 deletions tutorials/upperair_soundings.py
Expand Up @@ -139,7 +139,7 @@
skew.plot(p, parcel_prof, 'k', linewidth=2)

# Shade areas of CAPE and CIN
skew.shade_cin(p, T, parcel_prof)
skew.shade_cin(p, T, parcel_prof, Td)
skew.shade_cape(p, T, parcel_prof)

# Plot a zero degree isotherm
Expand Down Expand Up @@ -182,7 +182,7 @@
skew.plot(p, parcel_prof, 'k', linewidth=2)

# Shade areas of CAPE and CIN
skew.shade_cin(p, T, parcel_prof)
skew.shade_cin(p, T, parcel_prof, Td)
skew.shade_cape(p, T, parcel_prof)

# Plot a zero degree isotherm
Expand Down