Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit d78e6c4

Browse files
committed
support for shared axes
svn path=/trunk/matplotlib/; revision=888
1 parent f5fff32 commit d78e6c4

7 files changed

Lines changed: 154 additions & 105 deletions

File tree

CHANGELOG

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
New entries should be added at the top
22

3+
2005-01-27 Added support for shared x or y axes. See
4+
examples/shared_axis_demo.py and examples/ganged_plots.py
5+
36
2005-01-27 Added Lee's patch for missing symbols \leq and \LEFTbracket
47
to _mathtext_data - JDH
58

examples/ganged_plots.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@
1919
# axes rect in relative 0,1 coords left, bottom, width, height. Turn
2020
# off xtick labels on all but the lower plot
2121
ax1 = axes([0.1, 0.1, 0.8, 0.25]) # lower
22-
ax2 = axes([0.1, 0.35, 0.8, 0.25]) # middle
22+
ax2 = axes([0.1, 0.35, 0.8, 0.25], sharex=ax1) # middle
2323
ax2.set_xticklabels([])
24-
ax3 = axes([0.1, 0.6, 0.8, 0.25]) # upper
24+
ax3 = axes([0.1, 0.6, 0.8, 0.25], sharex=ax1) # upper
2525
ax3.set_xticklabels([])
2626

2727
ax1.plot(t,s1)

examples/shared_axis_demo.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
"""
2+
You can share the x or y axis limits for one axis with another by
3+
passing an axes instance as a sharex or sharey kwarg.
4+
5+
Changing the axis limits on one axes will be reflected automatically
6+
in the other, and vice-versa, so when you navigate with the toolbar
7+
the axes will follow each other on their shared axes. Ditto for
8+
changes in the axis scaling (eg log vs linear). However, it is
9+
possible to have differences in tick labeling, eg you can selectively
10+
turn off the tick labels on one axes.
11+
"""
12+
from pylab import *
13+
14+
t = arange(0.01, 5.0, 0.01)
15+
s1 = sin(2*pi*t)
16+
s2 = exp(-t)
17+
s3 = sin(4*pi*t)
18+
ax1 = subplot(311)
19+
plot(t,s1)
20+
21+
## share x only
22+
ax2 = subplot(312, sharex=ax1)
23+
plot(t, s2)
24+
25+
# share x and y
26+
ax3 = subplot(313, sharex=ax1, sharey=ax1)
27+
plot(t, s3)
28+
xlim(0.01,5.0)
29+
#set(gca(), xscale='log')
30+
show()

examples/two_scales.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,11 @@
2727

2828

2929
# turn off the 2nd axes rectangle with frameon kwarg
30-
ax2 = twin()
30+
ax2 = twinx()
3131
s2 = sin(2*pi*t)
3232
plot(t, s2, 'r.')
3333
ylabel('sin')
34-
xlim(0.01, 10)
35-
set(gca(), xscale='log')
34+
#xlim(0.01, 10)
35+
#set(gca(), xscale='log')
3636

3737
show()

lib/matplotlib/axes.py

Lines changed: 59 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -307,19 +307,28 @@ class Axes(Artist):
307307
308308
"""
309309

310+
scaled = {IDENTITY : 'linear',
311+
LOG10 : 'log',
312+
}
310313
def __init__(self, fig, rect,
311314
axisbg = None, # defaults to rc axes.facecolor
312-
frameon = True):
315+
frameon = True,
316+
sharex=None, # use Axes instance's xaxis info
317+
sharey=None, # use Axes instance's yaxis info
318+
):
313319
Artist.__init__(self)
314320
self._position = map(makeValue, rect)
321+
# must be set before set_figure
322+
self._sharex = sharex # I use sharex's
323+
self._sharey = sharey
324+
325+
315326
self.set_figure(fig)
316327

317328
if axisbg is None: axisbg = rcParams['axes.facecolor']
318329
self._axisbg = axisbg
319330
self._frameon = frameon
320-
self._xscale = 'linear'
321-
self._yscale = 'linear'
322-
331+
323332

324333
self._hold = rcParams['axes.hold']
325334
self._connected = {} # a dict from events to (id, func)
@@ -360,11 +369,33 @@ def _set_lim_and_transforms(self):
360369
set the dataLim and viewLim BBox attributes and the
361370
transData and transAxes Transformation attributes
362371
"""
372+
373+
374+
if self._sharex is not None:
375+
left=self._sharex.viewLim.ll().x()
376+
right=self._sharex.viewLim.ur().x()
377+
else:
378+
left=zero()
379+
right=one()
380+
if self._sharey is not None:
381+
bottom=self._sharey.viewLim.ll().y()
382+
top=self._sharey.viewLim.ur().y()
383+
else:
384+
bottom=zero()
385+
top=one()
386+
387+
self.viewLim = Bbox(Point(left, bottom), Point(right, top))
363388
self.dataLim = unit_bbox()
364-
self.viewLim = unit_bbox()
389+
390+
365391
self.transData = get_bbox_transform(self.viewLim, self.bbox)
366392
self.transAxes = get_bbox_transform(unit_bbox(), self.bbox)
367393

394+
if self._sharex:
395+
self.transData.set_funcx(self._sharex.transData.get_funcx())
396+
397+
if self._sharey:
398+
self.transData.set_funcy(self._sharey.transData.get_funcy())
368399

369400
def axhline(self, y=0, xmin=0, xmax=1, **kwargs):
370401
"""\
@@ -569,12 +600,19 @@ def _set_artist_props(self, a):
569600
def cla(self):
570601
'Clear the current axes'
571602

572-
# init these w/ some arbitrary numbers - they'll be updated as
573-
# data is added to the axes
574603

604+
# TODO: don't recreate x and y axis instances on cla, simply
605+
# clear them
575606
self.xaxis = XAxis(self)
576607
self.yaxis = YAxis(self)
577608

609+
if self._sharex is not None:
610+
self.xaxis._major = self._sharex.xaxis._major
611+
self.xaxis._minor = self._sharex.xaxis._minor
612+
if self._sharey is not None:
613+
self.yaxis._major = self._sharey.yaxis._major
614+
self.yaxis._minor = self._sharey.yaxis._minor
615+
578616
self._get_lines = _process_plot_var_args()
579617
self._get_patches_for_fill = _process_plot_var_args('fill')
580618

@@ -628,11 +666,11 @@ def get_images(self):
628666

629667
def get_xscale(self):
630668
'return the xaxis scale string: log or linear'
631-
return self._xscale
669+
return self.scaled[self.transData.get_funcx().get_type()]
632670

633671
def get_yscale(self):
634672
'return the yaxis scale string: log or linear'
635-
return self._yscale
673+
return self.scaled[self.transData.get_funcy().get_type()]
636674

637675
def update_datalim(self, xys):
638676
'Update the data lim bbox with seq of xy tups'
@@ -2754,17 +2792,17 @@ def set_xscale(self, value, basex = 10, subsx=None):
27542792

27552793
if subsx is None: subsx = range(2, basex)
27562794
assert(value.lower() in ('log', 'linear', ))
2757-
self._xscale = value
27582795
if value == 'log':
27592796
self.xaxis.set_major_locator(LogLocator(basex))
27602797
self.xaxis.set_major_formatter(LogFormatterMathtext(basex))
27612798
self.xaxis.set_minor_locator(LogLocator(basex,subsx))
2799+
27622800
self.transData.get_funcx().set_type(LOG10)
27632801
elif value == 'linear':
27642802
self.xaxis.set_major_locator(AutoLocator())
27652803
self.xaxis.set_major_formatter(ScalarFormatter())
27662804
self.transData.get_funcx().set_type( IDENTITY )
2767-
2805+
27682806

27692807
def set_xticklabels(self, labels, fontdict=None, **kwargs):
27702808
"""\
@@ -2833,7 +2871,7 @@ def set_yscale(self, value, basey=10, subsy=None):
28332871

28342872
if subsy is None: subsy = range(2, basey)
28352873
assert(value.lower() in ('log', 'linear', ))
2836-
self._yscale = value
2874+
28372875
if value == 'log':
28382876
self.yaxis.set_major_locator(LogLocator(basey))
28392877
self.yaxis.set_major_formatter(LogFormatterMathtext(basey))
@@ -2844,8 +2882,6 @@ def set_yscale(self, value, basey=10, subsy=None):
28442882
self.yaxis.set_major_formatter(ScalarFormatter())
28452883
self.transData.get_funcy().set_type( IDENTITY )
28462884

2847-
2848-
28492885
def set_yticklabels(self, labels, fontdict=None, **kwargs):
28502886
"""\
28512887
SET_YTICKLABELS(labels, fontdict=None, **kwargs)
@@ -3627,6 +3663,15 @@ def set_xlabel(self, xlabel, fontdict=None, **kwargs):
36273663
def set_ylabel(self, ylabel, fontdict=None, **kwargs):
36283664
'ylabel not implemented'
36293665
raise NotImplementedError('ylabel not defined for polar axes (yet)')
3666+
3667+
3668+
def get_xscale(self):
3669+
'return the xaxis scale string'
3670+
return 'polar'
3671+
3672+
def get_yscale(self):
3673+
'return the yaxis scale string'
3674+
return 'polar'
36303675

36313676
class PolarSubplot(SubplotBase, PolarAxes):
36323677
"""
@@ -3646,45 +3691,3 @@ def __init__(self, fig, *args, **kwargs):
36463691
SubplotBase.__init__(self, *args)
36473692
PolarAxes.__init__(self, fig, [self.figLeft, self.figBottom, self.figW, self.figH], **kwargs)
36483693

3649-
class TwinAxes(Axes):
3650-
"""
3651-
Create an Axes instance that shares the X axis with another:
3652-
3653-
TwinAxes(existing_axes)
3654-
"""
3655-
def __init__(self, axes):
3656-
Axes.__init__(self, axes.figure, axes._position, frameon=False)
3657-
3658-
self._xscale=axes._xscale
3659-
self.fmt_xdata=axes.fmt_xdata
3660-
3661-
vl_left=axes.viewLim.ll().x()
3662-
vl_right=axes.viewLim.ur().x()
3663-
vl_bottom=self.viewLim.ll().y()
3664-
vl_top=self.viewLim.ur().y()
3665-
self.viewLim=Bbox(Point(vl_left,vl_bottom),Point(vl_right, vl_top))
3666-
3667-
dl_left=axes.dataLim.ll().x()
3668-
dl_right=axes.dataLim.ur().x()
3669-
dl_bottom=self.dataLim.ll().y()
3670-
dl_top=self.dataLim.ur().y()
3671-
self.dataLim=Bbox(Point(dl_left,dl_bottom),Point(dl_right, dl_top))
3672-
3673-
try:
3674-
self.transData = blend_xy_sep_transform(axes.transData, self.transData)
3675-
except RuntimeError:
3676-
raise RuntimeError, "TwinAxes only works with cartesian axes"
3677-
3678-
self.xaxis=axes.xaxis
3679-
3680-
self.yaxis.tick_right()
3681-
self.yaxis.set_label_position('right')
3682-
axes.yaxis.tick_left()
3683-
3684-
def set_figure(self, fig):
3685-
if self.figure is None:
3686-
Axes.set_figure(self, fig)
3687-
return None
3688-
if fig is not self.figure:
3689-
raise RuntimeError, "TwinAxes can only be added to the same figure"
3690-

0 commit comments

Comments
 (0)