Skip to content

Commit 59a4077

Browse files
authored
Merge pull request #7479 from dopplershift/fix-skew
Fix and clean up Skew-T example
2 parents e46e1c0 + 73ee9f2 commit 59a4077

File tree

3 files changed

+164
-104
lines changed

3 files changed

+164
-104
lines changed

examples/api/skewt.py

+80-47
Original file line numberDiff line numberDiff line change
@@ -18,76 +18,97 @@
1818
import matplotlib.transforms as transforms
1919
import matplotlib.axis as maxis
2020
import matplotlib.spines as mspines
21-
import matplotlib.path as mpath
2221
from matplotlib.projections import register_projection
2322

23+
2424
# The sole purpose of this class is to look at the upper, lower, or total
2525
# interval as appropriate and see what parts of the tick to draw, if any.
26+
class SkewXTick(maxis.XTick):
27+
def update_position(self, loc):
28+
# This ensures that the new value of the location is set before
29+
# any other updates take place
30+
self._loc = loc
31+
super(SkewXTick, self).update_position(loc)
2632

33+
def _has_default_loc(self):
34+
return self.get_loc() is None
2735

28-
class SkewXTick(maxis.XTick):
29-
def draw(self, renderer):
30-
if not self.get_visible():
31-
return
32-
renderer.open_group(self.__name__)
36+
def _need_lower(self):
37+
return (self._has_default_loc() or
38+
transforms.interval_contains(self.axes.lower_xlim,
39+
self.get_loc()))
40+
41+
def _need_upper(self):
42+
return (self._has_default_loc() or
43+
transforms.interval_contains(self.axes.upper_xlim,
44+
self.get_loc()))
3345

34-
lower_interval = self.axes.xaxis.lower_interval
35-
upper_interval = self.axes.xaxis.upper_interval
46+
@property
47+
def gridOn(self):
48+
return (self._gridOn and (self._has_default_loc() or
49+
transforms.interval_contains(self.get_view_interval(),
50+
self.get_loc())))
51+
52+
@gridOn.setter
53+
def gridOn(self, value):
54+
self._gridOn = value
3655

37-
if self.gridOn and transforms.interval_contains(
38-
self.axes.xaxis.get_view_interval(), self.get_loc()):
39-
self.gridline.draw(renderer)
56+
@property
57+
def tick1On(self):
58+
return self._tick1On and self._need_lower()
4059

41-
if transforms.interval_contains(lower_interval, self.get_loc()):
42-
if self.tick1On:
43-
self.tick1line.draw(renderer)
44-
if self.label1On:
45-
self.label1.draw(renderer)
60+
@tick1On.setter
61+
def tick1On(self, value):
62+
self._tick1On = value
4663

47-
if transforms.interval_contains(upper_interval, self.get_loc()):
48-
if self.tick2On:
49-
self.tick2line.draw(renderer)
50-
if self.label2On:
51-
self.label2.draw(renderer)
64+
@property
65+
def label1On(self):
66+
return self._label1On and self._need_lower()
5267

53-
renderer.close_group(self.__name__)
68+
@label1On.setter
69+
def label1On(self, value):
70+
self._label1On = value
71+
72+
@property
73+
def tick2On(self):
74+
return self._tick2On and self._need_upper()
75+
76+
@tick2On.setter
77+
def tick2On(self, value):
78+
self._tick2On = value
79+
80+
@property
81+
def label2On(self):
82+
return self._label2On and self._need_upper()
83+
84+
@label2On.setter
85+
def label2On(self, value):
86+
self._label2On = value
87+
88+
def get_view_interval(self):
89+
return self.axes.xaxis.get_view_interval()
5490

5591

5692
# This class exists to provide two separate sets of intervals to the tick,
5793
# as well as create instances of the custom tick
5894
class SkewXAxis(maxis.XAxis):
59-
def __init__(self, *args, **kwargs):
60-
maxis.XAxis.__init__(self, *args, **kwargs)
61-
self.upper_interval = 0.0, 1.0
62-
6395
def _get_tick(self, major):
64-
return SkewXTick(self.axes, 0, '', major=major)
65-
66-
@property
67-
def lower_interval(self):
68-
return self.axes.viewLim.intervalx
96+
return SkewXTick(self.axes, None, '', major=major)
6997

7098
def get_view_interval(self):
71-
return self.upper_interval[0], self.axes.viewLim.intervalx[1]
99+
return self.axes.upper_xlim[0], self.axes.lower_xlim[1]
72100

73101

74102
# This class exists to calculate the separate data range of the
75103
# upper X-axis and draw the spine there. It also provides this range
76104
# to the X-axis artist for ticking and gridlines
77105
class SkewSpine(mspines.Spine):
78106
def _adjust_location(self):
79-
trans = self.axes.transDataToAxes.inverted()
107+
pts = self._path.vertices
80108
if self.spine_type == 'top':
81-
yloc = 1.0
109+
pts[:, 0] = self.axes.upper_xlim
82110
else:
83-
yloc = 0.0
84-
left = trans.transform_point((0.0, yloc))[0]
85-
right = trans.transform_point((1.0, yloc))[0]
86-
87-
pts = self._path.vertices
88-
pts[0, 0] = left
89-
pts[1, 0] = right
90-
self.axis.upper_interval = (left, right)
111+
pts[:, 0] = self.axes.lower_xlim
91112

92113

93114
# This class handles registration of the skew-xaxes as a projection as well
@@ -143,13 +164,24 @@ def _set_lim_and_transforms(self):
143164
transforms.IdentityTransform()) +
144165
transforms.Affine2D().skew_deg(rot, 0)) + self.transAxes
145166

167+
@property
168+
def lower_xlim(self):
169+
return self.axes.viewLim.intervalx
170+
171+
@property
172+
def upper_xlim(self):
173+
pts = [[0., 1.], [1., 1.]]
174+
return self.transDataToAxes.inverted().transform(pts)[:, 0]
175+
176+
146177
# Now register the projection with matplotlib so the user can select
147178
# it.
148179
register_projection(SkewXAxes)
149180

150181
if __name__ == '__main__':
151182
# Now make a simple example using the custom projection.
152-
from matplotlib.ticker import ScalarFormatter, MultipleLocator
183+
from matplotlib.ticker import (MultipleLocator, NullFormatter,
184+
ScalarFormatter)
153185
import matplotlib.pyplot as plt
154186
from six import StringIO
155187
import numpy as np
@@ -242,15 +274,16 @@ def _set_lim_and_transforms(self):
242274
plt.grid(True)
243275

244276
# Plot the data using normal plotting functions, in this case using
245-
# log scaling in Y, as dicatated by the typical meteorological plot
246-
ax.semilogy(T, p)
247-
ax.semilogy(Td, p)
277+
# log scaling in Y, as dictated by the typical meteorological plot
278+
ax.semilogy(T, p, color='C3')
279+
ax.semilogy(Td, p, color='C2')
248280

249281
# An example of a slanted line at constant X
250-
l = ax.axvline(0)
282+
l = ax.axvline(0, color='C0')
251283

252284
# Disables the log-formatting that comes with semilogy
253285
ax.yaxis.set_major_formatter(ScalarFormatter())
286+
ax.yaxis.set_minor_formatter(NullFormatter())
254287
ax.set_yticks(np.linspace(100, 1000, 10))
255288
ax.set_ylim(1050, 100)
256289

lib/matplotlib/axis.py

+6
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,12 @@ def update_position(self, loc):
344344
'Set the location of tick in data coords with scalar *loc*'
345345
raise NotImplementedError('Derived must override')
346346

347+
def _get_text1_transform(self):
348+
raise NotImplementedError('Derived must override')
349+
350+
def _get_text2_transform(self):
351+
raise NotImplementedError('Derived must override')
352+
347353

348354
class XTick(Tick):
349355
"""

0 commit comments

Comments
 (0)