8000 Reduce object-oriented boilerplate for users by dmcdougall · Pull Request #1125 · matplotlib/matplotlib · GitHub
[go: up one dir, main page]

Skip to content

Reduce object-oriented boilerplate for users #1125

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

Merged
merged 5 commits into from
Sep 4, 2012
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions doc/users/whats_new.rst
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,17 @@ Features that depend on the Python Imaging Library, such as JPEG
handling, do not work, since the version of PIL for Python 3.x is not
sufficiently mature.

Object-oriented interface
-------------------------

Damon McDougall has reduced some of the boilerplate code needed to interact
with the object-oriented interface. Now a figure canvas is set up by default::

>>> from matplotlib.figure import Figure
>>> fig = Figure()
>>> ax = fig.add_subplot(1, 1, 1)
>>> fig.savefig('figure.pdf')

PGF/TikZ backend
----------------
Peter Würtz wrote a backend that allows matplotlib to export figures as
Expand Down
2 changes: 2 additions & 0 deletions lib/matplotlib/backends/backend_agg.py
Original file line number Diff line number Diff line change
Expand Up @@ -515,3 +515,5 @@ def print_to_buffer(self):
(int(renderer.width), int(renderer.height)))
renderer.dpi = original_dpi
return result

FigureCanvas = FigureCanvasAgg
2 changes: 2 additions & 0 deletions lib/matplotlib/backends/backend_cairo.py
Original file line number Diff line number Diff line change
Expand Up @@ -512,3 +512,5 @@ def _save (self, fo, format, **kwargs):

ctx.show_page()
surface.finish()

FigureCanvas = FigureCanvasCairo
2 changes: 1 addition & 1 deletion lib/matplotlib/backends/backend_cocoaagg.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ def stop_event_loop(self):
FigureCanvasBase.stop_event_loop_default(self)
stop_event_loop.__doc__=FigureCanvasBase.stop_event_loop_default.__doc__


FigureCanvas = FigureCanvasCocoaAgg

NibClassBuilder.extractClasses('Matplotlib.nib', mplBundle)

Expand Down
2 changes: 2 additions & 0 deletions lib/matplotlib/backends/backend_emf.py
Original file line number Diff line number Diff line change
Expand Up @@ -727,6 +727,8 @@ def print_emf(self, filename, dpi=300, **kwargs):
def get_default_filetype(self):
return 'emf'

FigureCanvas = FigureCanvasEMF

class FigureManagerEMF(FigureManagerBase):
"""
Wrap everything up into a window for the pylab interface
Expand Down
2 changes: 2 additions & 0 deletions lib/matplotlib/backends/backend_fltkagg.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,8 @@ def stop_event_loop(self):
FigureCanvasBase.stop_event_loop_default(self)
stop_event_loop.__doc__=FigureCanvasBase.stop_event_loop_default.__doc__

FigureCanvas = FigureCanvasFltkAgg

def destroy_figure(ptr, figman):
figman.window.hide()
Fltk.Fl.wait(0) # This is needed to make the last figure vanish.
Expand Down
4 changes: 3 additions & 1 deletion lib/matplotlib/backends/backend_gdk.py
Original file line number Diff line number Diff line change
Expand Up @@ -434,7 +434,7 @@ def new_figure_manager_given_figure(num, figure):
return manager


class FigureCanvasGDK (FigureCanvasBase):
class FigureCanvasGDK(FigureCanvasBase):
def __init__(self, figure):
FigureCanvasBase.__init__(self, figure)

Expand Down Expand Up @@ -472,3 +472,5 @@ def _print_image(self, filename, format, *args, **kwargs):
0, 0, 0, 0, width, height)

pixbuf.save(filename, format)

FigureCanvas = FigureCanvasGDK
4 changes: 3 additions & 1 deletion lib/matplotlib/backends/backend_gtk.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ def _on_timer(self):
return False


class FigureCanvasGTK (gtk.DrawingArea, FigureCanvasBase):
class FigureCanvasGTK(gtk.DrawingArea, FigureCanvasBase):
keyvald = {65507 : 'control',
65505 : 'shift',
65513 : 'alt',
Expand Down Expand Up @@ -519,6 +519,8 @@ def stop_event_loop(self):
FigureCanvasBase.stop_event_loop_default(self)
stop_event_loop.__doc__=FigureCanvasBase.stop_event_loop_default.__doc__

FigureCanvas = FigureCanvasGTK

class FigureManagerGTK(FigureManagerBase):
"""
Public attributes
Expand Down
2 changes: 1 addition & 1 deletion lib/matplotlib/backends/backend_gtk3.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ def _on_timer(self):
self._timer = None
return False

class FigureCanvasGTK3 (Gtk.DrawingArea, FigureCanvasBase):
class FigureCanvasGTK3(Gtk.DrawingArea, FigureCanvasBase):
keyvald = {65507 : 'control',
65505 : 'shift',
65513 : 'alt',
Expand Down
1 change: 1 addition & 0 deletions lib/matplotlib/backends/backend_gtk3agg.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ def print_png(self, filename, *args, **kwargs):
agg = self.switch_backends(backend_agg.FigureCanvasAgg)
return agg.print_png(filename, *args, **kwargs)

FigureCanvas = FigureCanvasGTK3Agg

class FigureManagerGTK3Agg(backend_gtk3.FigureManagerGTK3):
pass
Expand Down
1 change: 1 addition & 0 deletions lib/matplotlib/backends/backend_gtk3cairo.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ def on_draw_event(self, widget, ctx):

return False # finish event propagation?

FigureCanvas = FigureCanvasGTK3Cairo

class FigureManagerGTK3Cairo(backend_gtk3.FigureManagerGTK3):
pass
Expand Down
1 change: 1 addition & 0 deletions lib/matplotlib/backends/backend_gtkagg.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ def _get_toolbar(self, canvas):
toolbar = None
return toolbar

FigureCanvas = FigureManagerGTKAgg
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be FigureCanvasGTKAgg (and moved after the definition of FigureCanvasGTKAgg). At least this doesn't work.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops. Yes. Good spot. I will open another PR to address this.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, GtkAgg backend currently does not work, which I believe is due to this.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry! Fixed in #1201.


def new_figure_manager(num, *args, **kwargs):
"""
Expand Down
1 change: 1 addition & 0 deletions lib/matplotlib/backends/backend_gtkcairo.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ def _renderer_init(self):
if _debug: print('%s.%s()' % (self.__class__.__name__, _fn_name()))
self._renderer = RendererGTKCairo (self.figure.dpi)

FigureCanvas = FigureCanvasGTKCairo

class FigureManagerGTKCairo(FigureManagerGTK):
def _get_toolbar(self, canvas):
Expand Down
1 change: 1 addition & 0 deletions lib/matplotlib/backends/backend_macosx.py
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,7 @@ def new_timer(self, *args, **kwargs):
"""
return TimerMac(*args, **kwargs)

FigureCanvas = FigureCanvasMac

class FigureManagerMac(_macosx.FigureManager, FigureManagerBase):
"""
Expand Down
2 changes: 2 additions & 0 deletions lib/matplotlib/backends/backend_pdf.py
Original file line number Diff line number Diff line change
Expand Up @@ -2299,6 +2299,8 @@ def print_pdf(self, filename, **kwargs):
else: # we opened the file above; now finish it off
file.close()

FigureCanvas = FigureCanvasPdf

class FigureManagerPdf(FigureManagerBase):
pass

Expand Down
2 changes: 2 additions & 0 deletions lib/matplotlib/backends/backend_pgf.py
Original file line number Diff line number Diff line change
Expand Up @@ -838,6 +838,8 @@ def _render_texts_pgf(self, fh):
def get_renderer(self):
return RendererPgf(self.figure, None)

FigureCanvas = FigureCanvasPgf

class FigureManagerPgf(FigureManagerBase):
def __init__(self, *args):
FigureManagerBase.__init__(self, *args)
Expand Down
2 changes: 2 additions & 0 deletions lib/matplotlib/backends/backend_ps.py
Original file line number Diff line number Diff line change
Expand Up @@ -1357,6 +1357,8 @@ def write(self, *kl, **kwargs):
shutil.move(tmpfile, outfile)
os.chmod(outfile, mode)

FigureCanvas = FigureCanvasPS

def convert_psfrags(tmpfile, psfrags, font_preamble, custom_preamble,
paperWidth, paperHeight, orientation):
"""
Expand Down
2 changes: 2 additions & 0 deletions lib/matplotlib/backends/backend_qt.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,8 @@ def stop_event_loop(self):
FigureCanvasBase.stop_event_loop_default(self)
stop_event_loop.__doc__=FigureCanvasBase.stop_event_loop_default.__doc__

FigureCanvas = FigureCanvasQT

class FigureManagerQT( FigureManagerBase ):
"""
Public attributes
Expand Down
2 changes: 2 additions & 0 deletions lib/matplotlib/backends/backend_qt4.py
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,8 @@ def idle_draw(*args):
self._idle = True
if d: QtCore.QTimer.singleShot(0, idle_draw)

FigureCanvas = FigureCanvasQT

class FigureManagerQT( FigureManagerBase ):
"""
Public attributes
Expand Down
2 changes: 2 additions & 0 deletions lib/matplotlib/backends/backend_qt4agg.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,3 +145,5 @@ def blit(self, bbox=None):
def print_figure(self, *args, **kwargs):
FigureCanvasAgg.print_figure(self, *args, **kwargs)
self.draw()

FigureCanvas = FigureCanvasQTAgg
2 changes: 2 additions & 0 deletions lib/matplotlib/backends/backend_qtagg.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,3 +156,5 @@ def blit(self, bbox=None):
def print_figure(self, *args, **kwargs):
FigureCanvasAgg.print_figure(self, *args, **kwargs)
self.draw()

FigureCanvas = FigureCanvasQTAgg
2 changes: 2 additions & 0 deletions lib/matplotlib/backends/backend_svg.py
Original file line number Diff line number Diff line change
Expand Up @@ -1143,6 +1143,8 @@ def _print_svg(self, filename, svgwriter, fh_to_close=None, **kwargs):
def get_default_filetype(self):
return 'svg'

FigureCanvas = FigureCanvasSVG

class FigureManagerSVG(FigureManagerBase):
pass

Expand Down
2 changes: 2 additions & 0 deletions lib/matplotlib/backends/backend_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,8 @@ def print_foo(self, filename, *args, **kwargs):
def get_default_filetype(self):
return 'foo'

FigureCanvas = FigureCanvasTemplate

class FigureManagerTemplate(FigureManagerBase):
"""
Wrap everything up into a window for the pylab interface
Expand Down
2 changes: 2 additions & 0 deletions lib/matplotlib/backends/backend_tkagg.py
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,8 @@ def stop_event_loop(self):
FigureCanvasBase.stop_event_loop_default(self)
stop_event_loop.__doc__=FigureCanvasBase.stop_event_loop_default.__doc__

FigureCanvas = FigureCanvasTkAgg

class FigureManagerTkAgg(FigureManagerBase):
"""
Public attributes
Expand Down
1 change: 1 addition & 0 deletions lib/matplotlib/backends/backend_wx.py
Original file line number Diff line number Diff line change
Expand Up @@ -1400,6 +1400,7 @@ def _onEnter(self, evt):
"""Mouse has entered the window."""
FigureCanvasBase.enter_notify_event(self, guiEvent = evt)

FigureCanvas = FigureCanvasWx

########################################################################
#
Expand Down
2 changes: 2 additions & 0 deletions lib/matplotlib/backends/backend_wxagg.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,8 @@ def print_figure(self, filename, *args, **kwargs):
if self._isDrawn:
self.draw()

FigureCanvas = FigureCanvasWxAgg

class NavigationToolbar2WxAgg(NavigationToolbar2Wx):
def get_canvas(self, frame, fig):
return FigureCanvasWxAgg(frame, -1, fig)
Expand Down
10 changes: 9 additions & 1 deletion lib/matplotlib/figure.py
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ def __init__(self,
self.patch.set_aa(False)

self._hold = rcParams['axes.hold']
self.canvas = None
self.canvas = self._setup_canvas()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change means that I now get two TK widows popping up (one empty, one with a figure) with the following code:

import matplotlib
matplotlib.use('tkagg')
import matplotlib.pyplot as plt

plt.plot(range(10))
plt.show()

Presumably this is true of all other backends too. Looks like we might have to implement @astrofrog 's suggestion of making this togglable (and have pyplot toggle that toggler).


if subplotpars is None:
subplotpars = SubplotParams()
Expand All @@ -330,6 +330,14 @@ def __init__(self,
self.clf()
self._cachedRenderer = None

def _setup_canvas(self):
"""
Return the FigureCanvas instance defined by the currently loaded backend.
"""
import matplotlib.backends as mbackends # lazy import
backend_mod = mbackends.pylab_setup()[0]
return backend_mod.FigureCanvas(self)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@verbit made a comment on this line on the commit 8bd1d57. @verbit : Would you mind re-iterating your comments here?

Thanks

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if the module from pylab_setup()[0] doesn't have a FigureCanvas class. Then the line return backend_mod.FigureCanvas(self) would result in an error. So it does with IPython that uses his own backend module but without a FigureCanvas class.

The old def _current_figure_canvas(self)works because in case it doesn't find the right FigureCanvas it returns None.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@verbit Line 508 of lib/matplotlib/backends/backend_tkagg is

FigureCanvas = FigureCanvasTkAgg

so the return value of pylab_setup[0] does indeed have a FigureCanvas for this backend. Do you see this behaviour with qt4agg or gtk3agg?

Perhaps this is actually a bug in the tkagg backend?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I saw this behaviour with IPython's custom backend (see: backend_inline.py) that doesn't return a FigureCanvas.
I'm just concerned about the fact, that this new _setup_canvas function might break other applications that don't provide a FigureCanvas class as they are used to the old way.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in #1214.


def _get_axes(self):
return self._axstack.as_list()

Expand Down
0