matplotlib show() doesn't work twice

23,069

Solution 1

At the start of your code, enable interactive mode via plt.ion()

Solution 2

I have new information about this that a google search turned up

This is from the writer of matplotlib. This came from http://old.nabble.com/calling-show%28%29-twice-in-a-row-td24276907.html

Hi Ondrej,

I'm not sure where to find a good explanation of that, but let me give you some hints. It is intended to use show only once per program. Namely 'show' should be the last line in your script. If you want interactive plotting you may consider interactive mode (pyplot.ion-ioff) like in the example below.

Furthermore for dynamic plotting all animation demos might be useful.

Maybe you want to have also a look at http://matplotlib.sourceforge.net/users/shell.html .

best regards Matthias

So it seems it is an undocumented "feature" (bug?).

Edit: here is his code block:

from pylab import *

t = linspace(0.0, pi, 100)
x = cos(t)
y = sin(t)

ion()  # turn on interactive mode
figure(0)
subplot(111, autoscale_on=False, xlim=(-1.2, 1.2), ylim=(-.2, 1.2))

point = plot([x[0]], [y[0]], marker='o', mfc='r', ms=3)

for j in arange(len(t)):
    # reset x/y-data of point
    setp(point[0], data=(x[j], y[j]))
    draw() # redraw current figure

ioff() # turn off interactive mode
show()

So maybe by using draw() you can get what you want. I haven't tested this code, I'd like to know its behavior.

Solution 3

I had the same issue with show() only working the first time. Are you still on version 0.99.3 or thereabouts? I was able to resolve my problem recently, if you're still interested in changing the behaviour of show(), try this:


I noticed this paragraph titled multiple calls to show supported on the what's new part of the matplotlib download site.

A long standing request is to support multiple calls to show(). This has been difficult because it is hard to get consistent behavior across operating systems, user interface toolkits and versions. Eric Firing has done a lot of work on rationalizing show across backends, with the desired behavior to make show raise all newly created figures and block execution until they are closed. Repeated calls to show should raise newly created figures since the last call. Eric has done a lot of testing on the user interface toolkits and versions and platforms he has access to, but it is not possible to test them all, so please report problems to the mailing list and bug tracker.

This was 'what's new' for version 1.0.1, at time of writing the version in synaptic was still on 0.99.3. I was able to download and build from source v1.0.1. The additional packages I also required to satisfy dependencies were libfreetype6-dev tk-dev tk8.5-dev tcl8.5-dev python-gtk2-dev; your mileage may vary.

Now that i have matplotlib.__version__ == 1.0.1 , the following code works how I would expect:

from matplotlib import pyplot as p
from scipy import eye
p.imshow(eye(3))
p.show()
print 'a' 
p.imshow(eye(6))
p.show()
print 'b' 
p.imshow(eye(9))
p.show()
print 'c' 
Share:
23,069

Related videos on Youtube

Sangi
Author by

Sangi

Updated on September 09, 2020

Comments

  • Sangi
    Sangi over 3 years

    I have a strange problem, with matplotlib. If I run this program, I'm able to open and close several time the same figure.

    import numpy
    from pylab import figure, show
    
    
    X = numpy.random.rand(100, 1000)
    xs = numpy.mean(X, axis=1)
    ys = numpy.std(X, axis=1)
    
    fig = figure()
    ax = fig.add_subplot(111)
    ax.set_title('click on point to plot time series')
    line, = ax.plot(xs, ys, 'o', picker=5)  # 5 points tolerance
    
    
    def onpick(event):
    
        figi = figure()
        ax = figi.add_subplot(111)
        ax.plot([1,2,3,4])        
        figi.show()
    
    fig.canvas.mpl_connect('pick_event', onpick)
    
    show()
    

    On the contrary, if I use the same code of onpick function into my custom widget it opens the figure only the first time, into the other events it enters into the functions but doesn't display the figure:

    from PyQt4 import QtGui, QtCore
    from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
    from matplotlib.figure import Figure
    import numpy as np
    import matplotlib.pyplot as plt
    from matplotlib.backends.backend_qt4 import NavigationToolbar2QT as NavigationToolbar
    import time
    
    STEP = 0.000152 
    
    class MplCanvas(FigureCanvas):
    
        def __init__(self):
    
            # initialization of the canvas
            FigureCanvas.__init__(self, Figure())
    
            self.queue = []
            self.I_data = np.array([])
            self.T_data = np.array([])
    
            self.LvsT = self.figure.add_subplot(111)
            self.LvsT.set_xlabel('Time, s')
            self.LvsT.set_ylabel('PMT Voltage, V')
            self.LvsT.set_title("Light vs Time")
            self.LvsT.grid(True)
    
            self.old_size = self.LvsT.bbox.width, self.LvsT.bbox.height
            self.LvsT_background = self.copy_from_bbox(self.LvsT.bbox)
    
            self.LvsT_plot, = self.LvsT.plot(self.T_data,self.I_data)
            #self.LvsT_plot2, = self.LvsT.plot(self.T_data2,self.I_data2) 
    
            self.mpl_connect('axes_enter_event', self.enter_axes)
            self.mpl_connect('button_press_event', self.onpick)
            self.count = 0
            self.draw()
    
        def enter_axes(self,event):
    
            print "dentro"
    
        def onpick(self,event):
            print "click"
            print 'you pressed', event.canvas
    
            a = np.arange(10)
            print a
            print self.count
    
            fig = plt.figure()
            ax = fig.add_subplot(111)
            ax.plot(a)    
            fig.show()
    
    
    
        def Start_Plot(self,q,Vmin,Vmax,ScanRate,Cycles):
            self.queue = q
    
            self.LvsT.clear()
            self.LvsT.set_xlim(0,abs(Vmin-Vmax)/ScanRate*Cycles)
            self.LvsT.set_ylim(-3, 3)
            self.LvsT.set_autoscale_on(False)
            self.LvsT.clear()
            self.draw()
    
            self.T_data = np.array([])
            self.I_data = np.array([])
    
            # call the update method (to speed-up visualization)
            self.timerEvent(None)
            # start timer, trigger event every 1000 millisecs (=1sec)
            self.timerLvsT = self.startTimer(3)
    
        def timerEvent(self, evt):
    
            current_size = self.LvsT.bbox.width, self.LvsT.bbox.height
            if self.old_size != current_size:
                self.old_size = current_size
                self.LvsT.clear()
                self.LvsT.grid()
                self.draw()
                self.LvsT_background = self.copy_from_bbox(self.LvsT.bbox)
    
            self.restore_region(self.LvsT_background, bbox=self.LvsT.bbox)
    
            result = self.queue.get()
    
            if result == 'STOP': 
                self.LvsT.draw_artist(self.LvsT_plot)
                self.killTimer(self.timerLvsT)
                print "Plot finito LvsT"
    
            else:
                # append new data to the datasets
                self.T_data = np.append(self.T_data,result[0:len(result)/2])
                self.I_data = np.append(self.I_data,result[len(result)/2:len(result)])
    
                self.LvsT_plot.set_data(self.T_data,self.I_data)#L_data
                #self.LvsT_plot2.set_data(self.T_data2,self.I_data2)#L_data
    
                self.LvsT.draw_artist(self.LvsT_plot)
    
                self.blit(self.LvsT.bbox)
    
    
    class LvsT_MplWidget(QtGui.QWidget):
        def __init__(self, parent = None):
            QtGui.QWidget.__init__(self, parent)        
            self.canvas = MplCanvas()
            self.vbl = QtGui.QVBoxLayout()
            self.vbl.addWidget(self.canvas)
            self.setLayout(self.vbl)
    

    This widget is needed for an animation plot and when the experiment is finished if I click on the plot it should appear a figure, that appears only the first time.

    Do you have any clue?

    Thank you very much.

  • Sangi
    Sangi about 13 years
    It doesn't work. I know that show() blocks the entire loop but when I close the figure the GUI loop continues to work. The problem is that when I click again into the figure, show() doesn't work anymore.
  • Sangi
    Sangi about 13 years
    It is a sort of workaround, I would rather prefer to solve the issue in a correct way. Nevertheless if no one can help me I'll do as you said.
  • fabrizioM
    fabrizioM about 13 years
    You should not be using .show to display it. Post a working example so we can test it
  • Sangi
    Sangi about 13 years
    Unluckily I can't post the entire project because it is too big, there are a lot of widget in separate files. I also tried with draw() but it doesn't show anything. Moreover, why the example I posted on the top works with multiple show()?
  • Garrett Berg
    Garrett Berg about 13 years
    I agree. I would also like to know a better answer.
  • Sangi
    Sangi about 13 years
    As my first example, it works perfectly in a separate script but into my function it works only the first time but not the second one. The problem is the final show() that can be called only once. It's so strange, I just need to open and close a figure several time, it should not be so difficult. I guess that somehow the inclusion into a qt widget can lead to this behavior. By the way, using only draw() without show() doesn't display anything.
  • La Cordillera
    La Cordillera almost 4 years
    This is definitely the right and uncomplicated answer!

Related