Функция matplotlib show() не работает дважды
У меня странная проблема, с matplotlib. Если я запустил эту программу, я могу открыть и закрыть несколько раз одну и ту же цифру.
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()
Наоборот, если я использую один и тот же код функции onpick в своем пользовательском виджетах, он открывается только в первый раз, в другие события, которые он вводит в функции, но не отображает цифру:
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)
Этот виджет необходим для графика анимации, и когда эксперимент закончен, если я нажимаю на график, он должен появиться на фигуре, которая появляется только в первый раз.
Есть ли у вас какие-либо подсказки?
Большое спасибо.
Ответы
Ответ 1
У меня есть новая информация об этом, что поиск google появился
Это от писателя matplotlib. Это произошло от http://old.nabble.com/calling-show%28%29-twice-in-a-row-td24276907.html
Hi Ondrej,
Я не уверен, где найти хорошее объяснение этого, но позвольте мне дать вы некоторые намеки. Он предназначен для использования показывать только один раз для каждой программы. а именно "показать" должна быть последней строкой в вашем script. Если вы хотите вы можете рассмотреть интерактивные mode (pyplot.ion-ioff), как в пример ниже.
Кроме того, для динамического построения всех анимационные демонстрации могут быть полезными.
Возможно, вы хотите также взглянуть на http://matplotlib.sourceforge.net/users/shell.html.
С наилучшими пожеланиями Маттиас
Так кажется, что это недокументированная "функция" (ошибка?).
Изменить: вот его блок кода:
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()
Итак, возможно, используя draw(), вы можете получить то, что хотите. Я не тестировал этот код, я бы хотел узнать его поведение.
Ответ 2
В начале вашего кода включите интерактивный режим через plt.ion()
Ответ 3
У меня была такая же проблема, когда show() работал только в первый раз. Вы все еще на версии 0.99.3 или около того? Недавно мне удалось решить проблему, если вы все еще заинтересованы в изменении поведения show(), попробуйте следующее:
Я заметил этот абзац под названием несколько вызовов, чтобы показать поддерживаемый, что новая часть сайта загрузки matplotlib.
Долгостоящий запрос заключается в поддержке нескольких вызовов show(). Это было сложно, потому что трудно добиться последовательного поведения в разных операционных системах, наборах пользовательских интерфейсов и версиях. Эрик Файринг проделал большую работу по рационализации шоу через бэкэнды, с желаемым поведением, чтобы показать, что все поднятые фигуры поднимают и блокируют исполнение до тех пор, пока они не будут закрыты. Повторные вызовы для показа должны поднимать вновь созданные цифры с момента последнего вызова. Эрик провел много испытаний на инструментах пользовательского интерфейса и версиях и платформах, к которым у него есть доступ, но их невозможно протестировать, поэтому сообщайте о проблемах в список рассылки и отслеживать ошибки.
Это было "что нового" для версии 1.0.1, на момент написания версии в синаптической версии все еще было 0.99.3. Я смог загрузить и построить из источника v1.0.1. Дополнительные пакеты, которые мне также необходимы для удовлетворения зависимостей, были libfreetype6-dev tk-dev tk8.5-dev tcl8.5-dev python-gtk2-dev
; ваш пробег может отличаться.
Теперь, когда у меня есть matplotlib.__version__ == 1.0.1
, следующий код работает так, как я ожидал бы:
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'
Ответ 4
Мое обходное решение этой проблемы - никогда не звонить close
.
Я уверен, что вы можете контролировать прозрачность виджета в PyQt. Вы можете попробовать контролировать видимость с помощью Qt вместо matplotlib. Я уверен, что кто-то, кто знает больше о matplotlib, может дать лучший ответ, чем это: D
Ответ 5
def onpick(self,event):
print "click"
print 'you pressed', event.canvas
...
ax.plot(a)
fig.show() # <--- this blocks the entire loop
Try:
def onpick(self,event):
print "click"
print 'you pressed', event.canvas
...
ax.plot(a)
self.draw()
self.update()
Ответ 6
Вы можете создать экземпляр фигуры с помощью:
fig = plt.figure(0)
И нарисуйте свои вещи, манипулируя этим рис.
Вы можете использовать fig.show()
в любое время, чтобы показать свою цифру.