Построение графика неблокирующим способом с помощью 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. Я забыл сказать, что хотел бы обновлять существующее окно каждый раз, когда я что-то строю, вместо того, чтобы создавать новое.

767   3  

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()

простой трюк, который работает для меня является следующее:

  1. использовать block = False аргумент внутри показать: plt.показать (block = False)
  2. использовать еще один 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()

результат:

Sine animation

отказ от ответственности: я сопровождающий для pyformulas.

ссылки: Matplotlib: сохранить участок в массив numpy

Comments

    Ничего не найдено.