8000 New milestone -- resizing figure window works. shared_axis_demo.py · matplotlib/matplotlib@6494ec5 · GitHub
[go: up one dir, main page]

Skip to content

Commit 6494ec5

Browse files
committed
New milestone -- resizing figure window works. shared_axis_demo.py
works. (Uses callbacks to track changes between axes's). svn path=/branches/transforms/; revision=3848
1 parent abd4723 commit 6494ec5

File tree

8 files changed

+625
-437
lines changed

8 files changed

+625
-437
lines changed

lib/matplotlib/affine.py

Lines changed: 514 additions & 322 deletions
Large diffs are not rendered by default.

lib/matplotlib/artist.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
# http://groups.google.com/groups?hl=en&lr=&threadm=mailman.5090.1098044946.5135.python-list%40python.org&rnum=1&prev=/groups%3Fq%3D__doc__%2Bauthor%253Ajdhunter%2540ace.bsd.uchicago.edu%26hl%3Den%26btnG%3DGoogle%2BSearch
2222

2323

24-
class Artist:
24+
class Artist(object):
2525
"""
2626
Abstract base class for someone who renders into a FigureCanvas
2727
"""

lib/matplotlib/axes.py

Lines changed: 61 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -436,8 +436,7 @@ class Axes(martist.Artist):
436436
}
437437

438438
def __str__(self):
439-
return "Axes(%g,%g;%gx%g)"%(self._position[0].get(),self._position[1].get(),
440-
self._position[2].get(),self._position[3].get())
439+
return "Axes(%g,%g;%gx%g)" % tuple(self._position.bounds)
441440
def __init__(self, fig, rect,
442441
axisbg = None, # defaults to rc axes.facecolor
443442
frameon = True,
@@ -590,13 +589,13 @@ def sharey_foreign(self, axforeign):
590589

591590
def follow_foreign_ylim(ax):
592591
ymin, ymax = axforeign.get_ylim()
593-
# do not emit here or we'll get a ping png effect
592+
# do not emit here or we'll get a ping pong effect
594593
self.set_ylim(ymin, ymax, emit=False)
595594
self.figure.canvas.draw_idle()
596595

597596
def follow_self_ylim(ax):
598597
ymin, ymax = self.get_ylim()
599-
# do not emit here or we'll get a ping png effect
598+
# do not emit here or we'll get a ping pong effect
600599
axforeign.set_ylim(ymin, ymax, emit=False)
601600
axforeign.figure.canvas.draw_idle()
602601

@@ -613,65 +612,66 @@ def set_figure(self, fig):
613612
"""
614613
martist.Artist.set_figure(self, fig)
615614

616-
l, b, w, h = self._position.bounds
617-
xmin = fig.bbox.xmin
618-
xmax = fig.bbox.xmax
619-
ymin = fig.bbox.ymin
620-
ymax = fig.bbox.ymax
621-
figw = xmax-xmin
622-
figh = ymax-ymin
623-
self.left = l*figw
624-
self.bottom = b*figh
625-
self.right = (l+w)*figw
626-
self.top = (b+h)*figh
627-
628-
self.bbox = maffine.Bbox.from_lbrt(
629-
self.left, self.bottom,
630-
self.right, self.top,
631-
)
615+
self.bbox = maffine.TransformedBbox(self._position, fig.transFigure)
632616
#these will be updated later as data is added
633617
self._set_lim_and_transforms()
634618

619+
def _shared_xlim_callback(self, ax):
620+
xmin, xmax = ax.get_xlim()
621+
self.set_xlim(xmin, xmax, emit=False)
622+
self.figure.canvas.draw_idle()
623+
624+
def _shared_ylim_callback(self, ax):
625+
ymin, ymax = ax.get_ylim()
626+
self.set_ylim(ymin, ymax, emit=False)
627+
self.figure.canvas.draw_idle()
628+
635629
def _set_lim_and_transforms(self):
636630
"""
637631
set the dataLim and viewLim BBox attributes and the
638632
transData and transAxes Transformation attributes
639633
"""
640-
Bbox = maffine.Bbox
634+
Bbox = maffine.Bbox
635+
self.viewLim = Bbox.unit()
636+
641637
if self._sharex is not None:
642-
left = self._sharex.viewLim.xmin()
643-
right = self._sharex.viewLim.xmax()
644-
else:
645-
left = 0.0
646-
right = 1.0
638+
# MGDTODO: This may be doing at least one too many updates
639+
# than necessary
640+
self._sharex.callbacks.connect(
641+
'xlim_changed', self._shared_xlim_callback)
642+
self.viewLim.intervalx = self._sharex.viewLim.intervalx
647643
if self._sharey is not None:
648-
bottom = self._sharey.viewLim.ymin()
649-
top = self._sharey.viewLim.ymax()
650-
else:
651-
bottom = 0.0
652-
top = 1.0
644+
self._sharey.callbacks.connect(
645+
'ylim_changed', self._shared_ylim_callback)
646+
self.viewLim.intervaly = self._sharex.viewLim.intervaly
653647

654-
self.viewLim = Bbox.from_lbrt(left, bottom, right, top)
655648
self.dataLim = Bbox.unit()
656649

657-
self.transData = maffine.BboxTransform(
658-
self.viewLim, self.bbox)
659650
self.transAxes = maffine.BboxTransform(
660651
Bbox.unit(), self.bbox)
661652

662-
# MGDTODO
663-
# if self._sharex:
664-
# self.transData.set_funcx(self._sharex.transData.get_funcx())
665-
666-
# if self._sharey:
667-
# self.transData.set_funcy(self._sharey.transData.get_funcy())
668-
653+
localTransData = maffine.BboxTransform(
654+
self.viewLim, self.bbox)
655+
if self._sharex:
656+
transDataX = self._sharex.transData
657+
else:
658+
transDataX = localTransData
659+
if self._sharey:
660+
transDataY = self._sharey.transData
661+
else:
662+
transDataY = localTransData
663+
self.transData = localTransData # maffine.blend_xy_sep_transform(transDataX, transDataY)
664+
665+
669666
def get_position(self, original=False):
670667
'Return the axes rectangle left, bottom, width, height'
668+
# MGDTODO: This changed from returning a list to returning a Bbox
669+
# If you get any errors with the result of this function, please
670+
# update the calling code
671671
if original:
672-
return self._originalPosition.bounds
672+
return copy.copy(self._originalPosition)
673673
else:
674-
return self._position.bounds
674+
return copy.copy(self._position)
675675
# return [val.get() for val in self._position]
676676

677677
def set_position(self, pos, which='both'):
@@ -690,14 +690,9 @@ def set_position(self, pos, which='both'):
690690
ACCEPTS: len(4) sequence of floats
691691
"""
692692
if which in ('both', 'active'):
693-
# MGDTODO
694-
# # Change values within self._position--don't replace it.
695-
# for num,val in zip(pos, self._position):
696-
# val.set(num)
697-
self._position.bounds = pos.bounds
698-
# MGDTODO: side-effects
693+
self._position.set(pos)
699694
if which in ('both', 'original'):
700-
self._originalPosition.bounds = pos.bounds
695+
self._originalPosition.set(pos)
701696

702697

703698
def _set_artist_props(self, a):
@@ -1546,7 +1541,14 @@ def set_xlim(self, xmin=None, xmax=None, emit=True, **kwargs):
15461541
xmin, xmax = maffine.nonsingular(xmin, xmax, increasing=False)
15471542

15481543
self.viewLim.intervalx = (xmin, xmax)
1549-
1544+
if emit:
1545+
self.callbacks.process('xlim_changed', self)
1546+
# MGDTODO: It would be nice to do this is in the above callback list,
1547+
# but it's difficult to tell how to initialize this at the
1548+
# right time
1549+
if self._sharex:
1550+
self._sharex.set_xlim(*self.viewLim.intervalx)
1551+
15501552
return xmin, xmax
15511553

15521554
def get_xscale(self):
@@ -1650,7 +1652,6 @@ def set_ylim(self, ymin=None, ymax=None, emit=True, **kwargs):
16501652
16511653
ACCEPTS: len(2) sequence of floats
16521654
"""
1653-
16541655
if ymax is None and iterable(ymin):
16551656
ymin,ymax = ymin
16561657

@@ -1671,8 +1672,14 @@ def set_ylim(self, ymin=None, ymax=None, emit=True, **kwargs):
16711672

16721673
ymin, ymax = maffine.nonsingular(ymin, ymax, increasing=False)
16731674
self.viewLim.intervaly = (ymin, ymax)
1674-
if emit: self.callbacks.process('ylim_changed', self)
1675-
1675+
if emit:
1676+
self.callbacks.process('ylim_changed', self)
1677+
# MGDTODO: It would be nice to do this is in the above callback list,
1678+
# but it's difficult to tell how to initialize this at the
1679+
# right time
1680+
if self._sharey:
1681+
self._sharey.set_ylim(*self.viewLim.intervaly)
1682+
16761683
return ymin, ymax
16771684

16781685
def get_yscale(self):

lib/matplotlib/axis.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1028,9 +1028,8 @@ def _update_label_position(self, bboxes, bboxes2):
10281028
x,y = self.label.get_position()
10291029
if self.label_position == 'bottom':
10301030
if not len(bboxes):
1031-
bottom = self.axes.bbox.ymin()
1031+
bottom = self.axes.bbox.ymin
10321032
else:
1033-
10341033
bbox = Bbox.union(bboxes)
10351034
bottom = bbox.ymin
10361035

@@ -1041,7 +1040,6 @@ def _update_label_position(self, bboxes, bboxes2):
10411040
if not len(bboxes2):
10421041
top = self.axes.bbox.ymax
10431042
else:
1044-
10451043
bbox = bbox_union(bboxes2)
10461044
top = bbox.ymax
10471045

@@ -1054,7 +1052,7 @@ def _update_offset_text_position(self, bboxes, bboxes2):
10541052
"""
10551053
x,y = self.offsetText.get_position()
10561054
if not len(bboxes):
1057-
bottom = self.axes.bbox.ymin()
1055+
bottom = self.axes.bbox.ymin
10581056
else:
10591057
bbox = Bbox.union(bboxes)
10601058
bottom = bbox.ymin

lib/matplotlib/backend_bases.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -752,7 +752,8 @@ def __init__(self, name, canvas, x, y,guiEvent=None):
752752
else: # Just found one hit
753753
self.inaxes = axes_list[0]
754754

755-
try: xdata, ydata = self.inaxes.transData.inverted()([[x, y]])[0]
755+
try:
756+
xdata, ydata = self.inaxes.transData.inverted().transform_point((x, y))
756757
except ValueError:
757758
self.xdata = None
758759
self.ydata = None
@@ -1584,8 +1585,8 @@ def push_current(self):
15841585
lims.append( (xmin, xmax, ymin, ymax) )
15851586
< 10000 span class=pl-c># Store both the original and modified positions
15861587
pos.append( (
1587-
tuple( a.get_position(True) ),
1588-
tuple( a.get_position() ) ) )
1588+
a.get_position(True),
1589+
a.get_position() ) )
15891590
self._views.push(lims)
15901591
self._positions.push(pos)
15911592
self.set_history_buttons()

lib/matplotlib/figure.py

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
from text import Text, _process_text_args
1919

2020
from legend import Legend
21-
from affine import Bbox, BboxTransform
21+
from affine import Affine2D, Bbox, BboxTransform, TransformedBbox
2222
from ticker import FormatStrFormatter
2323
from cm import ScalarMappable
2424
from contour import ContourSet
@@ -128,16 +128,14 @@ def __init__(self,
128128
if facecolor is None: facecolor = rcParams['figure.facecolor']
129129
if edgecolor is None: edgecolor = rcParams['figure.edgecolor']
130130

131+
self._dpi_scale_trans = Affine2D()
131132
self.dpi = dpi
132-
figwidth = figsize[0] * dpi
133-
figheight = figsize[1] * dpi
134-
self.bbox = Bbox.from_lbwh(0, 0, figwidth, figheight)
133+
self.bbox_inches = Bbox.from_lbwh(0, 0, *figsize)
134+
self.bbox = TransformedBbox(self.bbox_inches, self._dpi_scale_trans)
135135

136136
self.frameon = frameon
137137

138-
self.transFigure = BboxTransform( Bbox.unit(), self.bbox)
139-
140-
138+
self.transFigure = BboxTransform(Bbox.unit(), self.bbox)
141139

142140
self.figurePatch = Rectangle(
143141
xy=(0,0), width=1, height=1,
@@ -160,6 +158,15 @@ def __init__(self,
160158

161159
self._cachedRenderer = None
162160

161+
def _get_dpi(self):
162+
return self._dpi
163+
def _set_dpi(self, dpi):
164+
print "setting dpi"
165+
self._dpi = dpi
166+
self._dpi_scale_trans.clear().scale(dpi, dpi)
167+
print self._dpi_scale_trans
168+
dpi = property(_get_dpi, _set_dpi)
169+
163170
def autofmt_xdate(self, bottom=0.2, rotation=30, ha='right'):
164171
"""
165172
A common use case is a number of subplots with shared xaxes
@@ -325,7 +332,7 @@ def set_size_inches(self, *args, **kwargs):
325332
w,h = args
326333

327334
dpival = self.dpi
328-
self.bbox.max = w * dpival, h * dpival
335+
self.bbox_inches.max = w, h
329336
# self.figwidth.set(w) MGDTODO
330337
# self.figheight.set(h)
331338

@@ -339,7 +346,7 @@ def set_size_inches(self, *args, **kwargs):
339346
manager.resize(int(canvasw), int(canvash))
340347

341348
def get_size_inches(self):
342-
return self.bbox.max
349+
return self.bbox_inches.max
343350
# return self.figwidth.get(), self.figheight.get() MGDTODO
344351

345352
def get_edgecolor(self):
@@ -352,12 +359,12 @@ def get_facecolor(self):
352359

353360
def get_figwidth(self):
354361
'Return the figwidth as a float'
355-
return self.bbox.xmax
362+
return self.bbox_inches.xmax
356363
# return self.figwidth.get() MGDTODO
357364

358365
def get_figheight(self):
359366
'Return the figheight as a float'
360-
return self.bbox.ymax
367+
return self.bbox_inches.ymax
361368

362369
def get_dpi(self):
363370
'Return the dpi as a float'
@@ -400,7 +407,7 @@ def set_figwidth(self, val):
400407
ACCEPTS: float
401408
"""
402409
# self.figwidth.set(val) MGDTODO
403-
self.bbox.xmax = val
410+
self.bbox_inches.xmax = val
404411

405412
def set_figheight(self, val):
406413
"""
@@ -409,7 +416,7 @@ def set_figheight(self, val):
409416
ACCEPTS: float
410417
"""
411418
# MGDTODO (set())
412-
self.bbox.ymax = val
419+
self.bbox_inches.ymax = val
413420

414421
def set_frameon(self, b):
415422
"""

lib/matplotlib/pyplot.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -481,7 +481,7 @@ def subplot(*args, **kwargs):
481481
byebye = []
482482
for other in fig.axes:
483483
if other==a: continue
484-
if bbox.overlaps(other.bbox, ignoreend=True):
484+
if bbox.fully_overlaps(other.bbox):
485485
byebye.append(other)
486486
for ax in byebye: delaxes(ax)
487487

0 commit comments

Comments
 (0)
0