tylerthemiler
tylerthemiler

Reputation: 5746

Error using matplotlib.figure vs pylab when using ginput

I am trying to get user selected points (to get a polygon) from an image. I have already embedded a matplotlib.figure in a lot of my code, so I would MUCH prefer to use this style over pylab's figure. I am trying to do the follow:

import pylab
from matplotlib.figure import Figure

x1 = pylab.rand(103, 53) 
figure = Figure(figsize=(4, 4), dpi=100)
axes = figure.add_subplot(111)
axes.imshow(x1) 
x = figure.ginput(2) 

print(x)

But I get the following error:

Traceback (most recent call last):
  File "ginput_demo.py", line 17, in <module>
    x = figure.ginput(2)
  File "C:\Python27\lib\site-packages\matplotlib\figure.py", line 1177, in ginpu
t
    show_clicks=show_clicks)
  File "C:\Python27\lib\site-packages\matplotlib\blocking_input.py", line 282, i
n __call__
    BlockingInput.__call__(self,n=n,timeout=timeout)
  File "C:\Python27\lib\site-packages\matplotlib\blocking_input.py", line 94, in
 __call__
    self.fig.show()
AttributeError: 'Figure' object has no attribute 'show'

The original pylab code that works that I am trying to more or less reproduce is from here:

import pylab 

x1 = pylab.rand(103, 53) 
fig1 = pylab.figure(1) 
ax1 = fig1.add_subplot(111) 
ax1.imshow(x1) 
ax1.axis('image') 
ax1.axis('off') 
x = fig1.ginput(2) 

fig1.show() 

So basically, is there a way to get pylab.ginput to work with a matplotlib.figure or matplotlib.axes reference??

Thanks,

tylerthemiler

Upvotes: 3

Views: 2976

Answers (2)

user2033095
user2033095

Reputation: 1

I couldn't get the suggested solution to work properly when using an embedded plot in a GUI (Pyqt4) - my quick&dirty working solution was to put a Try/Catch into blocking_input.py. Note -this would probably be overwritten when you update matplotlib so you may want to save associations using unique name(s)

 # TRY TO "Ensure that the figure is shown" in the standard way
    try:
        self.fig.show()
    except AttributeError:
        pass

Upvotes: 0

joaquin
joaquin

Reputation: 85613

You should use pylab.ginput instead of myfigure.ginput. After changing this, you will realize that axes.imshow is not plotting, you can fix it using pylab.imshow. And finally you will find that after clicking and getting the position numbers, the figure disappears, so you want to add a pylab.show at the end.

This works, trying to follow as close as possible your prefered way of coding mpl:

from pylab import show, ginput, rand, imshow
from matplotlib.figure import Figure

x1 = rand(103, 53) 
figure = Figure(figsize=(4, 4), dpi=100)
axes = figure.add_subplot(111)

imshow(x1)
x = ginput(2) 
print(x)
show()

I think the problem here comes from mixing different modules (coding styles) from matplotlib.
Your myfigure.ginput() complaints about its Figure class not having a show method. However it works with pylab.figure.ginput().
In fact, pylab.figure, that is actually the one defined in the pyplot module:

>>> import pylab
>>> import matplotlib.pyplot as plt 
>>> pylab.figure is plt.figure
True

although being of the class matplotlib.figure.Figure is not the same as the Figure instance

myfigure = matplotlib.figure.Figure()

pyplot.figure implements a couple of additional methods, one of them show():

>>> from matplotlib import pyplot
>>> from matplotlib.figure import Figure
>>> pfig = set(dir(pyplot.figure()))
>>> Ffig = set(dir(Figure()))
>>> pfig.difference(Ffig)
set(['number', 'show'])

that's why you got the AttributeError with the Figure instance.

Upvotes: 3

Related Questions