Построение графика неблокирующим способом с помощью Matplotlib
Я играл с Numpy и matplotlib в последние несколько дней. У меня возникли проблемы с попыткой сделать matplotlib plot функцией без блокировки выполнения. Я знаю, что здесь уже много потоков, поэтому задаю подобные вопросы, и я довольно много гуглил, но не смог сделать эту работу.
Я пробовал использовать show (block=False), как некоторые люди предлагают, но все, что я получаю, это замороженное окно. Если я просто вызываю show (), результат строится правильно, но выполнение блокируется до закрытия окна. Из других потоков, которые я читал, я подозреваю, что работает ли show(block=False) или нет, зависит от бэкэнда. Это правильно? Мой задний конец-Qt4Agg. Не могли бы вы взглянуть на мой код и скажите мне, если вы видите что-то неправильно? Вот мой код. Спасибо за любую помощь.
from math import *
from matplotlib import pyplot as plt
print plt.get_backend()
def main():
x = range(-50, 51, 1)
for pow in range(1,5): # plot x^1, x^2, ..., x^4
y = [Xi**pow for Xi in x]
print y
plt.plot(x, y)
plt.draw()
#plt.show() #this plots correctly, but blocks execution.
plt.show(block=False) #this creates an empty frozen window.
_ = raw_input("Press [enter] to continue.")
if __name__ == '__main__':
main()
PS. Я забыл сказать, что хотел бы обновлять существующее окно каждый раз, когда я что-то строю, вместо того, чтобы создавать новое.
3 ответов:
Я долго искал решения, и нашел ответ.
похоже, чтобы получить то, что вы (и я) хотите, вам нужна комбинация
plt.ion(),plt.show()(неblocking=False, это устарело) и, самое главное,plt.pause(.001)(или в любое время вы хотите). Элемент пауза необходимо, потому что события GUI происходят, когда основной код спит, включая рисование. Возможно, что это реализуется путем сбора времени от a Спящая нить, так что, может быть, Иды с этим связались-я не знаю.вот реализация, которая работает для меня на Python 3.5:
import numpy as np from matplotlib import pyplot as plt def main(): plt.axis([-50,50,0,10000]) plt.ion() plt.show() x = np.arange(-50, 51) for pow in range(1,5): # plot x^1, x^2, ..., x^4 y = [Xi**pow for Xi in x] plt.plot(x, y) plt.draw() plt.pause(0.001) input("Press [enter] to continue.") if __name__ == '__main__': main()
простой трюк, который работает для меня является следующее:
- использовать block = False аргумент внутри показать: plt.показать (block = False)
- использовать еще один plt.показать()в конце из сценария .py.
пример:
import matplotlib.pyplot as plt plt.imshow(add_something) plt.xlabel("x") plt.ylabel("y") plt.show(block=False) #more code here (e.g. do calculations and use print to see them on the screen plt.show()
Примечание:
plt.show()это последняя строка моего скрипта.
вы можете избежать блокировки выполнения путем записи графика в массив, а затем отображения массива в другом потоке. Вот пример одновременного создания и отображения графиков с помощью pf.экран от pyformulas 0.2.8:
import pyformulas as pf import matplotlib.pyplot as plt import numpy as np import time fig = plt.figure() canvas = np.zeros((480,640)) screen = pf.screen(canvas, 'Sinusoid') start = time.time() while True: now = time.time() - start x = np.linspace(now-2, now, 100) y = np.sin(2*np.pi*x) + np.sin(3*np.pi*x) plt.xlim(now-2,now+1) plt.ylim(-3,3) plt.plot(x, y, c='black') # If we haven't already shown or saved the plot, then we need to draw the figure first... fig.canvas.draw() image = np.fromstring(fig.canvas.tostring_rgb(), dtype=np.uint8, sep='') image = image.reshape(fig.canvas.get_width_height()[::-1] + (3,)) screen.update(image) #screen.close()результат:
отказ от ответственности: я сопровождающий для pyformulas.

Comments