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

Matplotlib 3.1 fixes #1085

Merged
merged 2 commits into from Jul 5, 2019
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
97 changes: 32 additions & 65 deletions metpy/plots/skewt.py
Expand Up @@ -7,6 +7,11 @@
`SkewT`, as well as a class for making a `Hodograph`.
"""

try:
from contextlib import ExitStack
except ImportError:
from contextlib2 import ExitStack

import matplotlib
from matplotlib.axes import Axes
import matplotlib.axis as maxis
Expand Down Expand Up @@ -37,69 +42,31 @@ class SkewXTick(maxis.XTick):
and draw as appropriate. It also performs similar checking for gridlines.
"""

def update_position(self, loc):
"""Set the location of tick in data coords with scalar *loc*."""
# This ensures that the new value of the location is set before
# any other updates take place.
self._loc = loc
super(SkewXTick, self).update_position(loc)

def _has_default_loc(self):
return self.get_loc() is None

def _need_lower(self):
return (self._has_default_loc()
or transforms.interval_contains(self.axes.lower_xlim, self.get_loc()))

def _need_upper(self):
return (self._has_default_loc()
or transforms.interval_contains(self.axes.upper_xlim, self.get_loc()))

@property
def gridOn(self): # noqa: N802
"""Control whether the gridline is drawn for this tick."""
return (self._gridOn and (self._has_default_loc()
or transforms.interval_contains(self.get_view_interval(), self.get_loc())))

@gridOn.setter
def gridOn(self, value): # noqa: N802
self._gridOn = value

@property
def tick1On(self): # noqa: N802
"""Control whether the lower tick mark is drawn for this tick."""
return self._tick1On and self._need_lower()

@tick1On.setter
def tick1On(self, value): # noqa: N802
self._tick1On = value

@property
def label1On(self): # noqa: N802
"""Control whether the lower tick label is drawn for this tick."""
return self._label1On and self._need_lower()

@label1On.setter
def label1On(self, value): # noqa: N802
self._label1On = value

@property
def tick2On(self): # noqa: N802
"""Control whether the upper tick mark is drawn for this tick."""
return self._tick2On and self._need_upper()

@tick2On.setter
def tick2On(self, value): # noqa: N802
self._tick2On = value

@property
def label2On(self): # noqa: N802
"""Control whether the upper tick label is drawn for this tick."""
return self._label2On and self._need_upper()

@label2On.setter
def label2On(self, value): # noqa: N802
self._label2On = value
# Taken from matplotlib's SkewT example to update for matplotlib 3.1's changes to
# state management for ticks. See matplotlib/matplotlib#10088
def draw(self, renderer):
"""Draw the tick."""
# When adding the callbacks with `stack.callback`, we fetch the current
# visibility state of the artist with `get_visible`; the ExitStack will
# restore these states (`set_visible`) at the end of the block (after
# the draw).
with ExitStack() as stack:
for artist in [self.gridline, self.tick1line, self.tick2line,
self.label1, self.label2]:
stack.callback(artist.set_visible, artist.get_visible())
needs_lower = transforms.interval_contains(
self.axes.lower_xlim, self.get_loc())
needs_upper = transforms.interval_contains(
self.axes.upper_xlim, self.get_loc())
self.tick1line.set_visible(
self.tick1line.get_visible() and needs_lower)
self.label1.set_visible(
self.label1.get_visible() and needs_lower)
self.tick2line.set_visible(
self.tick2line.get_visible() and needs_upper)
self.label2.set_visible(
self.label2.get_visible() and needs_upper)
super(SkewXTick, self).draw(renderer)

def get_view_interval(self):
"""Get the view interval."""
Expand Down Expand Up @@ -168,7 +135,7 @@ def __init__(self, *args, **kwargs):
"""
# This needs to be popped and set before moving on
self.rot = kwargs.pop('rotation', 30)
Axes.__init__(self, *args, **kwargs)
super(Axes, self).__init__(*args, **kwargs)

def _init_axis(self):
# Taken from Axes and modified to use our modified X-axis
Expand All @@ -195,7 +162,7 @@ def _set_lim_and_transforms(self):

"""
# Get the standard transform setup from the Axes base class
Axes._set_lim_and_transforms(self)
super(Axes, self)._set_lim_and_transforms()

# Need to put the skew in the middle, after the scale and limits,
# but before the transAxes. This way, the skew is done in Axes
Expand Down
13 changes: 8 additions & 5 deletions metpy/plots/tests/test_skewt.py
Expand Up @@ -17,7 +17,7 @@
MPL_VERSION = matplotlib.__version__[:3]


@pytest.mark.mpl_image_compare(tolerance=0.021, remove_text=True)
@pytest.mark.mpl_image_compare(tolerance=0.224, remove_text=True)
def test_skewt_api():
"""Test the SkewT API."""
with matplotlib.rc_context({'axes.autolimit_mode': 'data'}):
Expand Down Expand Up @@ -87,7 +87,8 @@ def test_profile():
return np.linspace(1000, 100, 10), np.linspace(20, -20, 10), np.linspace(25, -30, 10)


@pytest.mark.mpl_image_compare(tolerance={'2.0': 1.12}.get(MPL_VERSION, 0.), remove_text=True)
@pytest.mark.mpl_image_compare(tolerance={'2.0': 1.12}.get(MPL_VERSION, 0.2432),
remove_text=True)
def test_skewt_shade_cape_cin(test_profile):
"""Test shading CAPE and CIN on a SkewT plot."""
p, t, tp = test_profile
Expand All @@ -104,7 +105,8 @@ def test_skewt_shade_cape_cin(test_profile):
return fig


@pytest.mark.mpl_image_compare(tolerance={'1.4': 1.70}.get(MPL_VERSION, 0.), remove_text=True)
@pytest.mark.mpl_image_compare(tolerance={'1.4': 1.70}.get(MPL_VERSION, 0.2432),
remove_text=True)
def test_skewt_shade_area(test_profile):
"""Test shading areas on a SkewT plot."""
p, t, tp = test_profile
Expand All @@ -131,7 +133,8 @@ def test_skewt_shade_area_invalid(test_profile):
skew.shade_area(p, t, tp, which='positve')


@pytest.mark.mpl_image_compare(tolerance={'1.4': 1.75}.get(MPL_VERSION, 0.), remove_text=True)
@pytest.mark.mpl_image_compare(tolerance={'1.4': 1.75}.get(MPL_VERSION, 0.2432),
remove_text=True)
def test_skewt_shade_area_kwargs(test_profile):
"""Test shading areas on a SkewT plot with kwargs."""
p, t, tp = test_profile
Expand Down Expand Up @@ -208,7 +211,7 @@ def test_skewt_barb_color():
return fig


@pytest.mark.mpl_image_compare(tolerance={'2.0': 0.2}.get(MPL_VERSION, 0), remove_text=True)
@pytest.mark.mpl_image_compare(tolerance=0.2, remove_text=True)
def test_skewt_barb_unit_conversion():
"""Test that barbs units can be converted at plot time (#737)."""
u_wind = np.array([3.63767155210412]) * units('m/s')
Expand Down
1 change: 1 addition & 0 deletions setup.py
Expand Up @@ -52,6 +52,7 @@
python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*',
install_requires=['matplotlib>=2.0.0', 'numpy>=1.12.0', 'scipy>=0.17.0',
'pint!=0.9', 'xarray>=0.10.7', 'enum34;python_version<"3.4"',
'contextlib2;python_version<"3.6"',
'pooch>=0.1, <0.3', 'traitlets>=4.3.0'],
extras_require={
'dev': ['ipython[all]>=3.1'],
Expand Down