построение графиков в matplotlib при выполнении измерения, которое требует времени - PullRequest
3 голосов
/ 18 марта 2012

Я хотел бы выполнить измерение и построить график, пока измерение Бег. Это измерение занимает довольно много времени в Python (он должен получать данные по медленному соединению). Проблема в том, что график замерзает при измерении. Измерение состоит из установки центральной длины волны, а затем измерения некоторого сигнала.

Моя программа выглядит примерно так:

# this is just some arbitrary library that has the functions set_wavelength and
# perform_measurement
from measurement_module import set_wavelength, perform_measurement
from pylab import *

xdata = np.linspace(600,1000,30) # this will be the x axis
ydata = np.zeros(len(xdata)) # this will be the y data. It will
for i in range(len(xdata)):
  # this call takes approx 1 s
  set_wavelength(xdata[i])
  # this takes approx 10 s
  ydata[i] = perform_measurement(xdata)
  # now I would like to plot the measured data
  plot(xdata,ydata)
  draw()

Это будет работать при запуске в IPython с включенным модулем -pylab, но во время измерения фигура замерзнет. Как можно изменить поведение, чтобы иметь интерактивный график при измерении?

Вы не можете просто использовать pylab.ion (), потому что python занят во время измерений.

С уважением,

Dirk

Ответы [ 4 ]

1 голос
/ 19 марта 2012

Я рекомендую буферизовать данные большими кусками и рендерить / повторно рендерить, когда буфер заполняется. Если вы хотите, чтобы он был неблокирующим, посмотрите на гринлеты.

from gevent.greenlet import Greenlet
import copy
def render(buffer):
    '''
    do rendering stuff
    '''
    pass

buff = ''
while not_finished:
    buff = connection.read()
    g = Greenlet(render, copy.deepcopy(buff))
    g.start()
1 голос
/ 19 марта 2012

Вы можете, хотя, возможно, немного неловко, запустить сбор данных как отдельный процесс. Я нахожу Popen в модуле подпроцесса весьма удобным. Затем позвольте этому сценарию сбора данных сохранить то, что он делает где-то на диске, и вы используете

Popen.poll()

Чтобы проверить, завершено ли оно.

Это должно работать.

0 голосов
/ 21 марта 2012

Взгляните на Черты и Чако , систему типов Enthought и библиотеку графиков. Они обеспечивают хорошую абстракцию для решения проблемы, с которой вы сталкиваетесь. График Chaco будет обновляться каждый раз, когда меняется какая-либо из его зависимостей.

0 голосов
/ 20 марта 2012

Медленный ввод и вывод - идеальное время для использования потоков и очередей в Python. У потоков есть свои ограничения, но это тот случай, когда они работают легко и эффективно.

Описание того, как это сделать:
Обычно графический интерфейс пользователя (например, окно matplotlib) должен находиться в основном потоке, поэтому сбор данных выполняется во втором потоке. В потоке данных проверьте, поступают ли новые данные (и если вы делаете это в каком-то бесконечном цикле опроса, вставьте короткий time.sleep, чтобы время от времени освобождать поток). Затем, при необходимости, сообщите основному потоку, что есть некоторые новые данные для обработки / отображения. Как именно это сделать, зависит от деталей вашей программы, вашего графического интерфейса и т. Д. Вы можете просто использовать флаг в потоке данных, который вы проверяете в основном потоке, или theading.Event, или, например, если у вас есть wx бэкэнд для matplotlib wx.CallAfter легко. Я рекомендую просмотреть одно из многих учебных пособий по многопоточности Python, чтобы понять его, а также многопоточность с помощью графического интерфейса пользователя, как правило, тоже имеет несколько проблем, так что просто сделайте быстрый поиск по потокам с вашим конкретным бэкэндом. Это звучит громоздко, поскольку я объясняю это так кратко, но на самом деле это довольно просто и мощно, и будет более плавным, чем, например, чтение и запись в один и тот же файл из разных процессов.

...