在python中循环可点击的图 [英] Looping over clickable plot in python
问题描述
我打算使用以下类来标记时间序列的特定部分.
I have the following class which I intend to use in labelling specific parts of a time series.
class Labeler(object):
def __init__(self, accel_data, vline=0):
self.fig = plt.figure(figsize=(10,2))
self.accel_data = accel_data
x_ = np.arange(len(self.accel_data))
self.plot, = plt.plot(x_, self.accel_data, picker=100)
plt.xlim(0, len(self.accel_data)-1)
self.final_loc = 0
self.vline_loc = 0
self.vline = plt.axvline(self.vline_loc, color='red')
self.fig.canvas.mpl_connect('button_press_event', self._onclick)
self.button_next = Button(plt.axes([0.85, 0.78, 0.05, 0.1]), 'Next', color='#32CD32')
self.button_next.on_clicked(self._nextbutton)
self.button_done = Button(plt.axes([0.85, 0.65, 0.05, 0.1]), 'Done', color='orange')
self.button_done.on_clicked(self._donebutton)
plt.show(block=True)
self.starts = []
def _onclick(self, event):
self.final_loc = self.vline_loc
self.vline_loc = int(event.xdata)
self.vline.set_xdata(self.vline_loc)
def _nextbutton(self, event):
self.starts.append(['code', self.final_loc])
n = np.random.randint(1000)
self.plot.set_xdata(np.arange(n))
self.plot.set_ydata(np.random.rand(n))
self.plot.set_title(str(n))
def _donebutton(self, event):
plt.close() # close to stop plot
现在,我想在 ipython 笔记本中使用它,以便我可以在这样的循环中使用它:
Now, I want to use this in an ipython notebook so that I can use it in a loop like this:
for i in range(5):
l = Labeler(np.random.rand(1000))
print(l.starts) # print the locs of vertical lines
cont = input("Press any key to continue")
我的问题是,当我循环绘图时,它会等到循环完成后再显示绘图.我要它做的是打开一个图,用红线确定零件,然后进行下一个图.请让我知道如何实现.谢谢!
My problem is that when I loop over the plot, it waits until the loop is finished before displaying the plot. What I want it to do is open a single plot, determine parts using the red line, and then proceed to the next plot. Please let me know how this can be accomplished. Thanks!
推荐答案
jupyter notebook 解决方案
笔记本中的问题是交互式图形阻止了进一步的代码被执行.我能想到的唯一解决方案是让该角色接管对更新的控制.
下面是一个示例(我确定这不是您真正想要的,但是我在理解某些代码的目的时遇到了问题,因此它执行了类似的操作).这个想法是向类提供所有数据,然后类可以循环遍历它.
Solution for jupyter notebook
The problem in a notebook is that the interactive figure prevents further code from being executed. The only solution I can think of is to let the figure take over control over the updates.
The following would be an example (I'm sure it's not what you actually wanted, but I had problems understanding the purpose of some of the code, so it does something similar). The idea would be to provide all the data already to the class, which can then loop through it.
%matplotlib notebook
import matplotlib.pyplot as plt
from matplotlib.widgets import Button
import numpy as np
class Labeler(object):
def __init__(self, data, vline=0):
self.fig = plt.figure(figsize=(10,2))
self.ax = self.fig.gca()
self.i = 0
self.data = data
self.fig.canvas.mpl_connect('button_press_event', self._onclick)
self.button_next = Button(plt.axes([0.85, 0.78, 0.05, 0.1]), 'Next', color='#32CD32')
self.button_next.on_clicked(self._nextbutton)
self.button_done = Button(plt.axes([0.85, 0.65, 0.05, 0.1]), 'Done', color='orange')
self.button_done.on_clicked(self._donebutton)
self.starts = []
plt.show()
def _nextbutton(self, event):
self.i
self.final_loc = 0
self.vline_loc = 0
self.accel_data = self.data[self.i % len(data)]
self.x = np.arange(len(self.accel_data))
plt.xlim(0, len(self.accel_data)-1)
self.plot, = self.ax.plot(self.x, self.accel_data, picker=100)
self.vline = self.ax.axvline(self.vline_loc, color='red')
self.starts.append(['code', self.final_loc])
self.ax.set_title(str(self.i))
self.i += 1
self.fig.canvas.draw()
def _onclick(self, event):
self.final_loc = self.vline_loc
self.vline_loc = int(event.xdata)
self.vline.set_xdata(self.vline_loc)
self.fig.canvas.draw()
def _donebutton(self, event):
#plt.close() # close to stop plot
self.ax.clear()
pass
data = []
for i in range(5):
data.append(np.random.rand(60+10*i))
l = Labeler(data)
以下代码对我来说运行良好.
The following code runs fine for me.
import matplotlib.pyplot as plt
from matplotlib.widgets import Button
import numpy as np
class Labeler(object):
def __init__(self, accel_data, vline=0):
self.fig = plt.figure(figsize=(10,2))
self.ax = self.fig.gca()
self.accel_data = accel_data
x_ = np.arange(len(self.accel_data))
self.plot, = plt.plot(x_, self.accel_data, picker=100)
plt.xlim(0, len(self.accel_data)-1)
self.final_loc = 0
self.vline_loc = 0
self.vline = plt.axvline(self.vline_loc, color='red')
self.fig.canvas.mpl_connect('button_press_event', self._onclick)
self.button_next = Button(plt.axes([0.85, 0.78, 0.05, 0.1]), 'Next', color='#32CD32')
self.button_next.on_clicked(self._nextbutton)
self.button_done = Button(plt.axes([0.85, 0.65, 0.05, 0.1]), 'Done', color='orange')
self.button_done.on_clicked(self._donebutton)
self.starts = []
plt.show(block=True)
def _onclick(self, event):
self.final_loc = self.vline_loc
self.vline_loc = int(event.xdata)
self.vline.set_xdata(self.vline_loc)
def _nextbutton(self, event):
self.starts.append(['code', self.final_loc])
n = np.random.randint(1000)
self.plot.set_xdata(np.arange(n))
self.plot.set_ydata(np.random.rand(n))
self.ax .set_title(str(n))
def _donebutton(self, event):
plt.close() # close to stop plot
for i in range(5):
l = Labeler(np.random.rand(1000))
print(l.starts) # print the locs of vertical lines
cont = raw_input("Press any key to continue")
这篇关于在python中循环可点击的图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!