в matplotlib есть ли способ вывести фигуру асинхронно? - PullRequest
13 голосов
/ 19 февраля 2011

Есть ли в matplotlib простой способ построения фигуры без прерывания потока управления сценария?

Используя псевдокод для ясности, вот что я пытаюсь достичь:

fig1 = figure()
fig1.plot_a_figure(datasets)

for dataset in datasets:
   results = analyze(dataset)    # this takes several minutes
   update(fig1)
   pop_up_another_figure(results) # would like to have a look at this one
                                  # while the next dataset is being processed

Конечно, я могу просто сохранить значения () этих промежуточных цифр, но мне нужно только быстро взглянуть на них, и было бы лучше, чтобы они просто появлялись на экране в реальном времени.

РЕДАКТИРОВАТЬ: работоспособный пример:

#!/usr/bin/python
import pylab as plb
import matplotlib.pyplot as plt

fig1=plt.figure(1)
ax = fig1.add_subplot(1,1,1)

ax.plot([1,2,3],[4,5,6],'ro-')

#fig1.show()  # this does not show a figure if uncommented
plt.show()    # until the plot window is closed, the next line is not executed

print "doing something else now"

Я что-то упустил очень простой?

Ответы [ 2 ]

13 голосов
/ 12 сентября 2011

Перво-наперво, не забудьте простую альтернативу - просто создать новые окна с рисунками с помощью plt.figure(2), plt.figure(3) и т. Д. Если вы действительно хотите обновить существующее окно с рисунками, вам лучше держать ручку на своем объект линии с

h = ax.plot([1,2,3],[4,5,6],'ro-')

А потом вы будете делать что-то вроде:

h[0].set_data(some_new_results)
ax.figure.canvas.draw()

Что касается настоящего вопроса, если вы все еще боретесь с этим, читайте дальше ...


Вам нужно включить интерактивный режим, если вы хотите, чтобы plt.show() был неблокирующим. Чтобы изменить ваш исполняемый пример так, чтобы «делая что-то еще сейчас» печатался немедленно, в отличие от ожидания закрытия окна рисунка, было бы следующее:

#!/usr/bin/python
import pylab as plb
import matplotlib.pyplot as plt

fig1=plt.figure(1)
ax = fig1.add_subplot(1,1,1)

ax.plot([1,2,3],[4,5,6],'ro-')

#fig1.show()  # this does not show a figure if uncommented
plt.ion()     # turns on interactive mode
plt.show()    # now this should be non-blocking

print "doing something else now"
raw_input('Press Enter to continue...')

Тем не менее, это просто царапает поверхность вещей - есть много сложностей, когда вы начинаете хотеть выполнять фоновую работу при взаимодействии с графиками. Это естественное следствие рисования с использованием, по сути, конечного автомата, оно плохо сочетается с многопоточностью и программированием в объектно-ориентированной среде.

  • Дорогие вычисления должны будут идти в рабочие потоки (или, альтернативно, в подпроцессы), чтобы избежать зависания графического интерфейса.
  • Queue должен использоваться для передачи входных данных и получения результатов из рабочих функций потокобезопасным способом.
  • По моему опыту, вызывать draw() в рабочем потоке небезопасно, поэтому вам также нужно настроить способ планирования перерисовки.
  • Различные бэкэнды могут начать делать странные вещи, и TkAgg кажется единственным, который работает на 100% (см. здесь ).

Самое простое и лучшее решение - не использовать интерпретатор vanilla python, а использовать ipython -pylab (как справедливо предположил ianalis), потому что они уже выяснили большинство приемов, необходимых для плавной работы интерактивных материалов. Это можно сделать без ipython / pylab, но это значительный объем дополнительной работы.

Примечание: Мне все еще часто нравится работать на ферме вне рабочих потоков, используя окна GUI ipython и pyplot, и для обеспечения бесперебойной работы потоков мне также нужно использовать другой аргумент командной строки ipython -pylab -wthread. Я на python 2.7.1+ с matplotlib v1.1.0, ваш пробег может отличаться. Надеюсь, это поможет!

Примечание для пользователей Ubuntu : репозитории все еще возвращаются к v0.99 в течение достаточно долгого времени, стоит обновить ваш matplotlib, потому что было много улучшения по сравнению с выпуском v1.0, включая марафон Bugfix и серьезные изменения в поведении show().

2 голосов
/ 19 февраля 2011

Вероятно, самое простое решение - использовать IPython в качестве оболочки Python. Запустите его с параметром -pylab.

ipython -pylab
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...