[英]Using events with matplotlib in a for loop
很抱歉,因為我之前已經打開了另一個與相關主題相關的票證。 多虧了我現在得到的答案,我可以更加具體。 我也收到了一些基於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
編輯2:
我認為我沒有正確地解釋自己,數據的種類可能被誤解了。 就我而言,我正在讀取海量數據表,每一行都是不同的來源。 我正在嘗試繪制的Whay是列的信息。 我是物理學家,所以我對時尚編程或其他方面不了解很多。 問題是...如果無法通過for循環執行此操作,有人可以向我解釋一下如果沒有它怎么做這種工作?
您不需要循環。 使用命令fig.canvas.draw()
在事件函數ontype
新圖。
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()
下一個塊是您要使用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
直到它擊中了yield
。 然后它將返回產生的值(在本示例中為np.random.random
)。 下次調用fun.next()
時,它將在循環中保留的位置繼續運行,直到再次達到yield
為止。 因此,它正是您想要的。
然后從Holger大量借款:
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')
任何可迭代的方法都需要一些技巧:
test_array = np.arange(100).reshape(10,10)
pta.add_step_through(test_array.__iter__(), 'b')
這使我感到很有趣,我將其保存為要點 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.