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

Skip to content

Commit 18dca66

Browse files
committed
refactored axes management
svn path=/trunk/matplotlib/; revision=803
1 parent 625e060 commit 18dca66

12 files changed

Lines changed: 262 additions & 220 deletions

File tree

CHANGELOG

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

3+
2004-12-21 Refactored axes and subplot management - removed
4+
add_subplot and add_axes from the FigureManager. classic
5+
toolbar updates are done via an observer pattern on the
6+
figure using add_axobserver. Figure now maintains the axes
7+
stack (for gca) and supports axes deletion. Ported changes
8+
to GTK, Tk, Wx, and FLTK. Please test! JDH
9+
310
2004-12-21 Lots of image optimizations - 4x performance boost over
411
0.65 JDH
512

TODO

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -558,7 +558,7 @@ ZeroDivisionError: SeparableTransformation::eval_scalars yin interval is zero; c
558558

559559
-- relative distance mode
560560

561-
--backend dependent cursoring
561+
-- backend dependent cursoring
562562

563563
-- relative distance measures
564564

@@ -577,27 +577,27 @@ ZeroDivisionError: SeparableTransformation::eval_scalars yin interval is zero; c
577577

578578
-- colorbar for dynamic images.
579579

580-
-- Finish the coords notification for all backends - allow custom
580+
-- DONE Finish the coords notification for all backends - allow custom
581581
formatters for toolbar
582582

583583
-- DONE an rrulewrapper demo
584584

585585
-- implement a new data clipping method with more exensive cache
586586
interval
587587

588-
-- Humufr errobar
588+
-- Humufr errobar
589589

590590
-- why is tkagg loading init 2x
591591

592-
-- add ishold and spy
592+
-- DONE add ishold and spy
593593

594594
-- Humufr's shared ticker bug
595595

596596
-- figure should increment the figure if one already exists
597597

598598
-- majbase and minbase to plot
599599

600-
-- oplot
600+
-- DONE oplot
601601

602602
-- override setattr in matlab interface for artists.
603603

examples/backend_driver.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,8 @@ def drive(backend, python='python2.3'):
102102

103103
times = {}
104104
#backends = ['Agg', 'Cairo', 'GDK', 'PS', 'SVG', 'Template']
105-
backends = ['Agg', 'PS', 'Template']
106-
#backends.extend([ 'GTK', 'WX', 'TkAgg'])
105+
#backends = ['Agg', 'PS', 'Template']
106+
backends = [ 'GTK', 'WX', 'TkAgg']
107107

108108
python = 'python2.3'
109109
for backend in backends:

lib/matplotlib/axes.py

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -302,18 +302,32 @@ def __init__(self, fig, rect,
302302
axisbg = None, # defaults to rc axes.facecolor
303303
frameon = True):
304304
Artist.__init__(self)
305-
305+
self._position = [Value(val) for val in rect]
306+
self.set_figure(fig)
306307

307308
if axisbg is None: axisbg = rcParams['axes.facecolor']
308-
self.set_figure(fig)
309-
self._position = [Value(val) for val in rect]
310309
self._axisbg = axisbg
311310
self._frameon = frameon
312311
self._xscale = 'linear'
313312
self._yscale = 'linear'
314313

315-
l, b, w, h = self._position
316314

315+
self._hold = rcParams['axes.hold']
316+
self._connected = {} # a dict from events to (id, func)
317+
self.cla()
318+
319+
# funcs used to format x and y - fall back on major formatters
320+
self.fmt_xdata = None
321+
self.fmt_ydata = None
322+
323+
def set_figure(self, fig):
324+
"""
325+
Set the Axes figure
326+
327+
ACCEPTS: a Figure instance"""
328+
Artist.set_figure(self, fig)
329+
330+
l, b, w, h = self._position
317331
xmin = fig.bbox.ll().x()
318332
xmax = fig.bbox.ur().x()
319333
ymin = fig.bbox.ll().y()
@@ -331,15 +345,7 @@ def __init__(self, fig, rect,
331345
)
332346
#these will be updated later as data is added
333347
self._set_lim_and_transforms()
334-
335-
self._hold = rcParams['axes.hold']
336-
self._connected = {} # a dict from events to (id, func)
337-
self.cla()
338-
339-
# funcs used to format x and y - fall back on major formatters
340-
self.fmt_xdata = None
341-
self.fmt_ydata = None
342-
348+
343349
def _set_lim_and_transforms(self):
344350
"""
345351
set the dataLim and viewLim BBox attributes and the

lib/matplotlib/backend_bases.py

Lines changed: 3 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import sys
88

99
from matplotlib import verbose
10-
from cbook import is_string_like, enumerate, strip_math
10+
from cbook import is_string_like, enumerate, strip_math, Stack
1111
from colors import colorConverter
1212
from numerix import array, sqrt, pi, log, asarray, ones, Float
1313
from patches import Rectangle
@@ -630,123 +630,22 @@ class FigureManagerBase:
630630
def __init__(self, canvas, num):
631631
self.canvas = canvas
632632
self.num = num
633-
self.clf()
634-
633+
635634
def clf(self):
636635
'clear the figure'
637-
self.axes = {}
638-
self.currentAxis = None
636+
verbose.report_error('Deprectated; use fig.clf() instead')
639637
self.canvas.figure.clf()
640638

641-
def add_subplot(self, *args, **kwargs):
642-
"""
643-
Add a subplot to the current figure
644-
"""
645-
key = (args, tuple(kwargs.items()))
646-
if self.axes.has_key(key):
647-
self.currentAxis = self.axes[key]
648-
else:
649-
a = self.canvas.figure.add_subplot(*args, **kwargs)
650-
self.axes[key] = a
651-
self.currentAxis = a
652-
return a
653-
654-
def add_axes(self, rect, **kwargs):
655-
"""
656-
Add an axes to the current figure
657-
"""
658-
rect = tuple(rect)
659-
key = (rect, tuple(kwargs.items()))
660-
if self.axes.has_key(key):
661-
self.currentAxis = self.axes[key]
662-
return self.currentAxis
663-
else:
664-
a = self.canvas.figure.add_axes(rect, **kwargs)
665-
self.axes[key] = a
666-
self.currentAxis = a
667-
return a
668-
669-
def get_current_axis(self, **kwargs):
670-
"""
671-
Return the current axes
672-
"""
673-
if self.currentAxis is not None:
674-
return self.currentAxis
675-
else:
676-
self.add_subplot(111, **kwargs)
677-
return self.currentAxis
678-
679-
680-
def set_current_axes(self, a):
681-
"""
682-
Set the current axes to be a
683-
"""
684-
if a is None:
685-
self.currentAxis = None
686-
return
687-
if a not in self.axes.values():
688-
error_msg('Axes is not in current figure')
689-
self.currentAxis = a
690639

691640
def destroy(self):
692641
pass
693642

694-
695643
# cursors
696644
class Cursors: #namespace
697645
HAND, POINTER, SELECT_REGION, MOVE = range(4)
698646
cursors = Cursors()
699647

700648

701-
class Stack:
702-
"""
703-
Implement a stack where elements can be pushed on and you can move
704-
back and forth. But no pop. Should mimib home / back / forward
705-
in a browser
706-
"""
707-
708-
def __init__(self):
709-
self.clear()
710-
711-
def __call__(self):
712-
'return the current element, or None'
713-
if not len(self._elements): return None
714-
else: return self._elements[self._pos]
715-
716-
def forward(self):
717-
'move the position forward and return the current element'
718-
N = len(self._elements)
719-
if self._pos<N-1: self._pos += 1
720-
return self()
721-
722-
def back(self):
723-
'move the position back and return the current element'
724-
if self._pos>0: self._pos -= 1
725-
return self()
726-
727-
def push(self, o):
728-
"""
729-
push object onto stack at current position - all elements
730-
occurring later than the current position are discarded
731-
"""
732-
self._elements = self._elements[:self._pos+1]
733-
self._elements.append(o)
734-
self._pos = len(self._elements)-1
735-
return self()
736-
737-
def home(self):
738-
'push the first element onto the top of the stack'
739-
if not len(self._elements): return
740-
self.push(self._elements[0])
741-
return self()
742-
743-
def empty(self):
744-
return len(self._elements)==0
745-
746-
def clear(self):
747-
'empty the stack'
748-
self._pos = -1
749-
self._elements = []
750649

751650
class NavigationToolbar2:
752651
"""

lib/matplotlib/backends/backend_fltkagg.py

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,11 @@ def __init__(self, canvas, num, window):
311311
self.toolbar.update()
312312
self.window.show()
313313

314+
def notify_axes_change(fig):
315+
'this will be called whenever the current axes is changed'
316+
if self.toolbar != None: self.toolbar.update()
317+
self.canvas.figure.add_axobserver(notify_axes_change)
318+
314319
def resize(self, event):
315320
width, height = event.width, event.height
316321
self.toolbar.configure(width=width) # , height=height)
@@ -320,20 +325,6 @@ def show(self):
320325
self.canvas.draw()
321326
self.window.redraw()
322327

323-
def add_subplot(self, *args, **kwargs):
324-
a = FigureManagerBase.add_subplot(self, *args, **kwargs)
325-
self.toolbar.update()
326-
return a
327-
328-
def add_axes(self, rect, **kwargs):
329-
a = FigureManagerBase.add_axes(self, rect, **kwargs)
330-
self.toolbar.update()
331-
return a
332-
333-
def set_current_axes(self, a):
334-
if a not in self.axes.values():
335-
error_msg_Fltk('Axes is not in current figure')
336-
FigureManagerBase.set_current_axes(self, a)
337328

338329
class AxisMenu:
339330
def __init__(self, toolbar):

lib/matplotlib/backends/backend_gtk.py

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -407,18 +407,11 @@ def destroy(*args): Gcf.destroy(num)
407407
if matplotlib.is_interactive():
408408
self.window.show()
409409

410+
def notify_axes_change(fig):
411+
'this will be called whenever the current axes is changed'
412+
if self.toolbar != None: self.toolbar.update()
413+
self.canvas.figure.add_axobserver(notify_axes_change)
410414

411-
def add_subplot(self, *args, **kwargs):
412-
if DEBUG: print 'FigureManagerGTK.%s' % fn_name()
413-
a = FigureManagerBase.add_subplot(self, *args, **kwargs)
414-
if self.toolbar != None: self.toolbar.update()
415-
return a
416-
417-
def add_axes(self, rect, **kwargs):
418-
if DEBUG: print 'FigureManagerGTK.%s' % fn_name()
419-
a = FigureManagerBase.add_axes(self, rect, **kwargs)
420-
if self.toolbar != None: self.toolbar.update()
421-
return a
422415

423416
def destroy(self, *args):
424417
if DEBUG: print 'FigureManagerGTK.%s' % fn_name()

lib/matplotlib/backends/backend_tkagg.py

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,12 @@ def __init__(self, canvas, num, window):
270270
self.toolbar.update()
271271
self.canvas._tkcanvas.pack(side=Tk.TOP, fill=Tk.BOTH, expand=1)
272272
self._shown = False
273+
274+
def notify_axes_change(fig):
275+
'this will be called whenever the current axes is changed'
276+
if self.toolbar != None: self.toolbar.update()
277+
self.canvas.figure.add_axobserver(notify_axes_change)
278+
273279

274280
def resize(self, event):
275281
width, height = event.width, event.height
@@ -285,23 +291,7 @@ def destroy(*args):
285291
if not self._shown: self.window.deiconify()
286292
else: self.canvas.draw()
287293
self._shown = True
288-
289-
def add_subplot(self, *args, **kwargs):
290-
a = FigureManagerBase.add_subplot(self, *args, **kwargs)
291-
if self.toolbar is not None:
292-
self.toolbar.update()
293-
return a
294-
295-
def add_axes(self, rect, **kwargs):
296-
a = FigureManagerBase.add_axes(self, rect, **kwargs)
297-
if self.toolbar is not None:
298-
self.toolbar.update()
299-
return a
300-
301-
def set_current_axes(self, a):
302-
if a not in self.axes.values():
303-
error_msg_tkpaint('Axes is not in current figure')
304-
FigureManagerBase.set_current_axes(self, a)
294+
305295

306296
def destroy(self, *args):
307297
if Gcf.get_num_fig_managers()==0 and not matplotlib.is_interactive():

lib/matplotlib/backends/backend_wx.py

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1294,23 +1294,12 @@ def __init__(self, canvas, num, frame):
12941294
self.window = frame
12951295
self.tb = frame.GetToolBar()
12961296

1297-
def add_subplot(self, *args, **kwargs):
1298-
DEBUG_MSG("add_subplot()", 1, self)
1299-
a = FigureManagerBase.add_subplot(self, *args, **kwargs)
1300-
if self.tb is not None: self.tb.update()
1301-
return a
1302-
1303-
def add_axes(self, rect, **kwargs):
1304-
DEBUG_MSG("add_axes()", 1, self)
1305-
a = FigureManagerBase.add_axes(self, rect, **kwargs)
1306-
if self.tb is not None: self.tb.update()
1307-
return a
1308-
1309-
def set_current_axes(self, a):
1310-
DEBUG_MSG("set_current_axes()", 1, self)
1311-
if a not in self.axes.values():
1312-
error_msg_wx('Axes is not in current figure')
1313-
FigureManagerBase.set_current_axes(self, a)
1297+
def notify_axes_change(fig):
1298+
'this will be called whenever the current axes is changed'
1299+
if self.tb != None: self.tb.update()
1300+
self.canvas.figure.add_axobserver(notify_axes_change)
1301+
1302+
13141303

13151304
def destroy(self, *args):
13161305
DEBUG_MSG("destroy()", 1, self)

0 commit comments

Comments
 (0)