Image plotting using the OO interface

David Goldsmith <d_l_goldsmith@...9...> 06/19/08 9:39 AM >>>

Hi! I'm having trouble figuring out how to plot an array as an image with the OO interface - please help (e.g., w/ an example). Thanks,

DG

From the examples http://matplotlib.sourceforge.net/matplotlib_examples_0.98.0.zip

../examples/api/agg_oo.py

···

--------------------------------------------
#!/usr/bin/env python
"""
A pure OO (look Ma, no pylab!) example using the agg backend
"""
from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
from matplotlib.figure import Figure

fig = Figure()
canvas = FigureCanvas(fig)
ax = fig.add_subplot(111)
ax.plot([1,2,3])
ax.set_title('hi mom')
ax.grid(True)
ax.set_xlabel('time')
ax.set_ylabel('volts')
canvas.print_figure('test')
--------------------------------------------

You can replace the call to ax.plot() with a call to ax.imshow() or ax.pcolor()

Hope that gets you going.

Cheers,
Scott

Please find our Email Disclaimer here: http://www.ukzn.ac.za/disclaimer/

What is the relationship between a figure and a canvas?

My impression is the following. You can do all your
drawing on a figure. When you want to render the figure
(e.g., to screen, or printing to file), and not until then,
you need a canvas. A canvas will therefore always be
associated with a particular backend.

But when one creates a figure canvas, the canvas registers
itself with the figure. What does the figure get out of this?
(E.g., if we want the figure to draw itself to the canvas,
the canvas could always pass itself to the figure. Right?)

Thank you,
Alan Isaac

···

On Thu, 19 Jun 2008, Scott Sinclair apparently wrote:

canvas = FigureCanvas(fig)

The Figure is the top level matplotlib artist container that contains
all the other matplotlib.artist.Artist instances (Axes, Line2D,
etc..). Artists don't know anything about output formats (GDK, PS,
SVG) but they do know about renderers
(matplotlib.backend_bases.RendererBase) which have methods like
draw_line, draw_rectangle, and draw_text. The renderer subclasses
know the various output languages like postscript or svg. The canvas
is the target of the drawing by the renderer, and the canvas puts all
the pieces together. The canvas contains a renderer that knows how to
draw on the canvas, and it also contains the figure instance to be
drawn. The canvas calls

  fig.draw(renderer)

and then the figure instance in turn calls

  self.figurePatch.draw(renderer)

and then the figurePatch, a matplotlib.patches.Rectangle instance, calls

  renderer.draw_rectangle(graphicscontext, 25, 40)

So the renderer doesn't know anything about the matplotlib artist
Rectangle, but the Rectangle knows how to tell the renderer to draw
itself. This design decouples the functionality to make it possible
to change the artists w/o affecting the renderers, so the drawing API
is not affected by the matplotlib artist classes. This is covered
somewhat in Chapter 10 of the user's guide
http://matplotlib.sourceforge.net/users_guide_0.98.0.pdf

JDH

···

On Thu, Jun 19, 2008 at 8:58 AM, Alan G Isaac <aisaac@...310...> wrote:

On Thu, 19 Jun 2008, Scott Sinclair apparently wrote:

canvas = FigureCanvas(fig)

What is the relationship between a figure and a canvas?

Your post was helpful.
I still do not see why a figure has a canvas as data.
I'll read that chapter.
Thanks!
Alan

···

On Thu, 19 Jun 2008, John Hunter apparently wrote:

This is covered somewhat in Chapter 10 of the user's guide
http://matplotlib.sourceforge.net/users_guide_0.98.0.pdf

This is just a convenience so the child can see the parent. If I have
a function that gets a line, I can do line.axes.figure.canvas and walk
backwards up the containment hierarchy to get what I need. This is
backwards because a canvas holds a figure which holds an axes which
holds a line, but everybody stores a reference to their parent. A
side effect of having so many cyclic references is that we cannot use
__del__ anywhere in the mpl class hierarchy since this breaks garbage
collection with cyclic references.

···

On Thu, Jun 19, 2008 at 3:37 PM, Alan G Isaac <aisaac@...310...> wrote:

On Thu, 19 Jun 2008, John Hunter apparently wrote:

This is covered somewhat in Chapter 10 of the user's guide
http://matplotlib.sourceforge.net/users_guide_0.98.0.pdf

Your post was helpful.
I still do not see why a figure has a canvas as data.
I'll read that chapter.

That example doesn't do anything on my computer...

DG

···

--- On Thu, 6/19/08, Scott Sinclair <sinclaird@...1522...> wrote:

From: Scott Sinclair <sinclaird@...1522...>
Subject: Re: [Matplotlib-users] Image plotting using the OO interface
To: Matplotlib-users@lists.sourceforge.net
Date: Thursday, June 19, 2008, 3:58 AM
>>> David Goldsmith <d_l_goldsmith@...9...>
06/19/08 9:39 AM >>>
Hi! I'm having trouble figuring out how to plot an
array as an image with the OO interface - please help
(e.g., w/ an example). Thanks,

DG
>>>

>From the examples
http://matplotlib.sourceforge.net/matplotlib_examples_0.98.0.zip

../examples/api/agg_oo.py

--------------------------------------------
#!/usr/bin/env python
"""
A pure OO (look Ma, no pylab!) example using the agg
backend
"""
from matplotlib.backends.backend_agg import FigureCanvasAgg
as FigureCanvas
from matplotlib.figure import Figure

fig = Figure()
canvas = FigureCanvas(fig)
ax = fig.add_subplot(111)
ax.plot([1,2,3])
ax.set_title('hi mom')
ax.grid(True)
ax.set_xlabel('time')
ax.set_ylabel('volts')
canvas.print_figure('test')
--------------------------------------------

You can replace the call to ax.plot() with a call to
ax.imshow() or ax.pcolor()

Hope that gets you going.

Cheers,
Scott

Please find our Email Disclaimer here:
http://www.ukzn.ac.za/disclaimer/

-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://sourceforge.net/services/buy/index.php
_______________________________________________
Matplotlib-users mailing list
Matplotlib-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-users

Look again :slight_smile: It created a file called test.png in the directory in
which you ran the example. As long as you include the last line in
the example (the print_figure" line) it will save a figure.

JDH

···

On Fri, Jun 20, 2008 at 2:26 AM, David Goldsmith <d_l_goldsmith@...9...> wrote:

That example doesn't do anything on my computer...

Thanks for the explanation!
Alan
PS If anyone wants to share an example where it is useful
to work "backwards" like that, I'm sure I would learn
from it.

···

On Thu, Jun 19, 2008 at 3:37 PM, Alan G Isaac <aisaac@...310...> wrote:

I still do not see why a figure has a canvas as data.

On Thu, 19 Jun 2008, John Hunter apparently wrote:

This is just a convenience so the child can see the parent. If I have
a function that gets a line, I can do line.axes.figure.canvas and walk
backwards up the containment hierarchy to get what I need. This is
backwards because a canvas holds a figure which holds an axes which
holds a line, but everybody stores a reference to their parent. A
side effect of having so many cyclic references is that we cannot use
__del__ anywhere in the mpl class hierarchy since this breaks garbage
collection with cyclic references.

Take a look at the draggable rectangle code in the example below. The
rDraggableRectangle class needs to be able to update the canvas with a
draw, but rather than having to pass in the canvas instance
explicitly, we can just get it from the rectangle. Ie, the artist
knows what canvas he is in even though the canvas contains the
rectangle. The PDF event handling tutorial which contains this
example is at http://matplotlib.sourceforge.net/pycon/event_handling_tut.pdf
if you want some context.

import numpy as np
import matplotlib.pyplot as plt

class DraggableRectangle:
    def __init__(self, rect):
        self.rect = rect
        self.press = None

    def connect(self):
        'connect to all the events we need'
        self.cidpress = self.rect.figure.canvas.mpl_connect(
            'button_press_event', self.on_press)
        self.cidrelease = self.rect.figure.canvas.mpl_connect(
            'button_release_event', self.on_release)
        self.cidmotion = self.rect.figure.canvas.mpl_connect(
            'motion_notify_event', self.on_motion)

    def on_press(self, event):
        'on button press we will see if the mouse is over us and store
some data'
        if event.inaxes != self.rect.axes: return

        contains, attrd = self.rect.contains(event)
        if not contains: return
        print 'event contains', self.rect.xy
        x0, y0 = self.rect.xy
        self.press = x0, y0, event.xdata, event.ydata

    def on_motion(self, event):
        'on motion we will move the rect if the mouse is over us'
        if self.press is None: return
        if event.inaxes != self.rect.axes: return
        x0, y0, xpress, ypress = self.press
        dx = event.xdata - xpress
        dy = event.ydata - ypress
        #print 'x0=%f, xpress=%f, event.xdata=%f, dx=%f,
x0+dx=%f'%(x0, xpress, event.xdata, dx, x0+dx)
        self.rect.set_x(x0+dx)
        self.rect.set_y(y0+dy)

        self.rect.figure.canvas.draw()

    def on_release(self, event):
        'on release we reset the press data'
        self.press = None
        self.rect.figure.canvas.draw()

    def disconnect(self):
        'disconnect all the stored connection ids'
        self.rect.figure.canvas.mpl_disconnect(self.cidpress)
        self.rect.figure.canvas.mpl_disconnect(self.cidrelease)
        self.rect.figure.canvas.mpl_disconnect(self.cidmotion)

fig = plt.figure()
ax = fig.add_subplot(111)
rects = ax.bar(range(10), 20*np.random.rand(10))
drs = []
for rect in rects:
    dr = DraggableRectangle(rect)
    dr.connect()
    drs.append(dr)

plt.show()

···

On Fri, Jun 20, 2008 at 8:41 AM, Alan G Isaac <aisaac@...310...> wrote:

On Thu, Jun 19, 2008 at 3:37 PM, Alan G Isaac <aisaac@...310...> wrote:

I still do not see why a figure has a canvas as data.

On Thu, 19 Jun 2008, John Hunter apparently wrote:

This is just a convenience so the child can see the parent. If I have
a function that gets a line, I can do line.axes.figure.canvas and walk
backwards up the containment hierarchy to get what I need. This is
backwards because a canvas holds a figure which holds an axes which
holds a line, but everybody stores a reference to their parent. A
side effect of having so many cyclic references is that we cannot use
__del__ anywhere in the mpl class hierarchy since this breaks garbage
collection with cyclic references.

Thanks for the explanation!
Alan
PS If anyone wants to share an example where it is useful
to work "backwards" like that, I'm sure I would learn
from it.

Ah, I'm learning more than I bargained for!
But very usefully as it turns out.
Thanks!
Alan

···

On Fri, Jun 20, 2008 at 8:41 AM, Alan G Isaac <aisaac@...310...> wrote:

If anyone wants to share an example where it is useful to
work "backwards" like that, I'm sure I would learn from
it.

On Fri, 20 Jun 2008, John Hunter wrote:

Take a look at the draggable rectangle code in the example below.
... The PDF event handling tutorial which contains this
example is at
http://matplotlib.sourceforge.net/pycon/event_handling_tut.pdf