在for循环中将事件与matplotlib一起使用 [英] Using events with matplotlib in a for loop

查看:67
本文介绍了在for循环中将事件与matplotlib一起使用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

很抱歉,因为我之前打开过另一个与相关主题相关的票证.感谢我现在得到的答案,我可以更具体.我还收到了一些基于Tkinter的解决方案,但是我想通过事件和循环解决我的问题.

I apologize since I have open another ticket before on a related topic. Thanks to the answers I got now I can be more specific. I have also received some solutions based on Tkinter, but I would like to solve my problems with events and loops.

我正在处理的特殊情况如下:我有一个数组数组.我希望matplotlib绘制它的第一个元素,让我按一个键(带有相关事件),然后程序绘制第二个数组,相同的行为,依此类推.

The particular case I am dealing with is as follows: I have an array of arrays. I want matplotlib to plot the first element of it, allow me to press one key (with an associated event), and the program plots the second array, same behaviour, and so on.

作为一个简单的例子:

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 时该数字已清除,并通过终端显示它正在工作".我需要程序来绘制第一个元素,并在按下某个键后移至下一个元素.有什么暗示吗?我在做什么错了?

I would expect to get a first plot (the first time the loop runs), and that it is left open until I press 1. However, what I get is an figure with the ten vectors plotted, and when I press 1 the figure is cleared and it says "It is working" via terminal. I need the program to plot the first one, and move to the next element once a key has been pressed. Any hint on this? What am I doing wrong?

谢谢你们!

请记住,原则上程序的结构不能改变,在绘制任何东西之前需要for循环来计算不同的东西.因此,程序应该去

Please keep in mind that in principle, the structure of the program can not be varied, and the for loop is needed to compute different things before plotting anything. Hence, the program should go

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:

我认为我没有正确地解释自己,数据的类型可能已经被误解了.就我而言,我正在读取海量数据表,每一行都是不同的来源.我试图绘制的是列的信息.我是物理学家,所以我对时尚编程或其他方面不了解很多.问题是...如果无法通过for循环执行此操作,有人可以向我解释一下如果没有它怎么做这种工作?

I think I didn't explained myself properly and the kind of data might have been missunderstood. In my case, I am reading a huge table of data, and each line is a different source. Whay I am trying to plot is the information of the columns. I am a physicist, so I don't have much knowledge about stylish programming or anything. The problem is...if there is no way to do this with a for loop, could anyone explain me how to do this kind of work without it?

推荐答案

下一个块是您想要的 for 循环的作用.

This next block is what does what you want with the for loop.

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 之后的内容.请参阅收益"是什么?Python 中的关键字 do? .简而言之, yield 将带有循环的函数转换为生成器工厂.

Your for loop goes into the function ugly_math, and what you want plotted is what goes after yield. see What does the "yield" keyword do in Python? . In short, yield turns a function with a loop into a generator factory.

fun = ugly_math()

那么就是一个生成器.当您调用 fun.next()时,它将运行函数 ugly_math ,直到达到 yield .然后它将返回产生的值(在本例中为 np.random.random ).下次您调用 fun.next() 时,它会从循环中停止的地方继续运行,直到再次达到 yield.因此,它完全符合您的要求.

is then a generator. When you call fun.next() it will run the function ugly_math until it hits the yield. It will then return the value yielded (in this example, np.random.random). The next time you call fun.next() it will pick up where it left off in the loop and run until it hits yield again. Hence it does exactly what you want.

然后从Holger大量借钱:

Then borrowing heavily from 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 ,这样我们就可以在用尽生成器之后删除回调.

The cid_dict is there so that we can remove the call-back after we have exhausted the generator.

我们可以把这一切都包装成一个类

We can wrap this all up into a class as such

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

任何可迭代的方法都需要一些技巧:

Any iterable will work with a bit of finessing:

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

这让我很开心,我把它保存为 gist.

This amused me enough I saved it as a gist.

这篇关于在for循环中将事件与matplotlib一起使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆