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.
At the start of your code, enable interactive mode via plt.ion()
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With