Использование событий с matplotlib в цикле for

Прошу прощения, так как я открыл еще один билет раньше по соответствующей теме. Благодаря ответам, которые я получил, я могу быть более конкретным. Я также получил некоторые решения на основе Tkinter, но я хотел бы решить свои проблемы с событиями и циклами.

В частном случае я имею дело с следующим: у меня есть массив массивов. Я хочу, чтобы matplotlib нарисовал первый его элемент, позвольте мне нажать одну клавишу (со связанным событием), и программа отображает второй массив, такое же поведение и т. Д.

В качестве краткого примера:

import matplotlib.pyplot as plt import numpy as np # Define the event def ontype(event): if event.key == '1': print 'It is working' plt.clf() # Create figure an connect the event to it fig=plt.figure(figsize=(16,8)) plt.gcf().canvas.mpl_connect('key_press_event',ontype) # Loop for element in xrange(10): #This mimicks the "array of arrays" generating a random array in each loop vector = np.random.random(10) plt.plot(vector) plt.show() 

Я бы ожидал получить первый график (первый раз, когда цикл работает), и что он остается открытым до тех пор, пока я не нажму 1. Однако я получаю цифру с десятью векторами, и когда я нажимаю 1, очищается, и он говорит: «Он работает» через терминал. Мне нужна программа для построения первой и перейдите к следующему элементу после нажатия клавиши. Любой намек на это? Что я делаю не так?

Спасибо вам, ребята!

РЕДАКТИРОВАТЬ:

Пожалуйста, имейте в виду, что в принципе структура программы не может быть изменена, и цикл for необходим для вычисления разных вещей перед построением чего-либо. Следовательно, программа должна идти

 def ontype(event): define event Some stuff elements = array of arrays for element in elements: do more stuff plot element and "stay" in this plot untill any event key is pressed. And then, go to the next element in elements and do the same 

EDIT 2:

Я думаю, что я не объяснил себя должным образом, и данные, возможно, были пропущены. В моем случае я читаю огромную таблицу данных, и каждая строка – другой источник. Я пытаюсь зарисовать данные столбцов. Я физик, поэтому у меня мало знаний о стильном программировании или что-то еще. Проблема в том, что … если нет способа сделать это с помощью цикла for, может ли кто-нибудь объяснить мне, как делать такую ​​работу без нее?

2 Solutions collect form web for “Использование событий с matplotlib в цикле for”

Следующий блок – это то, что вы хотите с циклом for .

 def ugly_math(): print 'you will hit this once' for j in range(10): print 'loop ', j # insert math here yield np.random.random(10) * j 

Ваш цикл for переходит в функцию ugly_math , и то, что вы хотите построить, это то, что идет после yield . см. Что делает ключевое слово yield в Python? , Короче говоря, yield превращает функцию с петлей в завод генератора.

 fun = ugly_math() 

тогда является генератором. Когда вы вызываете fun.next() он будет запускать функцию ugly_math пока не достигнет ugly_math . Затем он вернет полученное значение (в этом примере np.random.random ). В следующий раз, когда вы fun.next() он заберет там, где он остановился в цикле, и запустится до тех пор, пока он снова не fun.next() . Следовательно, он делает именно то, что вы хотите.

Затем сильно заимствуя у Хольгера:

 fun = ugly_math() cid_dict = {} # Define the event def ontype(event): if event.key == '1': print 'It is working' try: vector = fun.next() plt.plot(vector) fig.canvas.draw() except StopIteration: plt.gcf().canvas.mpl_disconnect(cid_dict['cid']) del cid_dict['cid'] # Create figure an connect the event to it fig=plt.figure(figsize=(16,8)) cid_dict['cid'] = plt.gcf().canvas.mpl_connect('key_press_event',ontype) vector = np.random.random(10) plt.plot(vector) plt.show() 

cid_dict существует, так что мы можем удалить обратный вызов после того, как мы исчерпали генератор.

Мы можем объединить все это в класс как таковой

 class push_to_advance(object): def __init__(self): self.fig = plt.figure() self.ax = self.fig.gca() self.bound_keys = [] self.bound_cid = {} def add_step_through(self, gen, key): key = key[0] # make a single char if key in self.bound_keys: raise RuntimeError("key %s already bound"%key) first_data = gen.next() self.ax.plot(first_data) self.fig.canvas.draw() self.bound_keys.append(key) def ontype(event): if event.key == key: try: self.ax.plot(gen.next()) self.fig.canvas.draw() except StopIteration: self.fig.canvas.mpl_disconnect(self.bound_cid[key]) del self.bound_cid[key] self.bound_keys.remove(key) self.bound_cid[key] = self.fig.canvas.mpl_connect('key_press_event', ontype) 

Это используется как таковое:

  pta = push_to_advance() gen = ugly_math() pta.add_step_through(gen,'a') 

Любой iterable будет работать с немного изяществом:

  test_array = np.arange(100).reshape(10,10) pta.add_step_through(test_array.__iter__(), 'b') 

Это меня так забавляло, что я спас его как сущность .

Вам не нужен цикл. Переделайте новые сюжеты в ontype функции ontype с помощью команды fig.canvas.draw() .

 import matplotlib.pyplot as plt import numpy as np # Define the event def ontype(event): if event.key == '1': print 'It is working' vector = np.random.random(10) plt.plot(vector) fig.canvas.draw() # Create figure an connect the event to it fig=plt.figure(figsize=(16,8)) plt.gcf().canvas.mpl_connect('key_press_event',ontype) vector = np.random.random(10) plt.plot(vector) plt.show() 
  • Графики Matplotlib, не отображаемые в сублиметре
  • Построение 2D-массива с помощью Matplotlib
  • Pandas, отображающий тайм-ауты, с вертикальными линиями в выбранные даты
  • Построение панды timedelta
  • Реализация многопроцессорности pyqtgraph в виджет pyqt
  • Групповые этикетки в barplart matplotlib с использованием Pandas MultiIndex
  • Matplotlib - Как установить ylim () для серии графиков?
  • Как получить экземпляр Axs matplotlib для построения графика?
  • Python - лучший язык программирования в мире.