我有一个代码,用于绘制上方左侧图像中的线条。我想选择一个区域(上图中右侧显示的一个矩形),并找出该区域内哪些线对应。
代码绘制左边的图像是:
datfiles = glob.glob("*.dat")
for asc_filename in datfiles:
data = pylab.loadtxt(asc_filename)
x, y = data[:,0], data[:,3]
pylab.plot(x, y)
plt.legend()
pylab.savefig('ts.png')
您建议使用哪些模块进行python以及有关从何处开始使用代码的任何想法?
谢谢!
答案 0 :(得分:2)
这不是太简单,但也不是很难。一般来说,你想要使用某种类型的完整gui工具包(例如Qt,wx,GTK,TK等),但你可以使用“纯”matplotlib。 (Matplotlib当然只是使用你的安装配置为在幕后使用的gui。)
您的第一个问题是您没有在任何地方存储曲目ID。
可以这么简单:
import pylab
txt_files = glob.iglob("*.txt")
for txt_filename in txt_files:
data = pylab.loadtxt(txt_filename)
t, x, y = data[:,0], data[:,1], data[:,2]
line, = pylab.plot(x, y, label=time.ctime(t[0]))
line.track_id = filename[:-4]
然而,你必须将它们存放在某个地方!为每个matplotlib线条艺术家对象添加属性将使以后更容易,但您可以通过其他方式轻松完成。
对于下一部分,matplotlib.widgets
中有一个小部件可以满足您的需求。看看这里的例子:http://matplotlib.sourceforge.net/examples/widgets/rectangle_selector.html同样,使用一个成熟的gui工具包更灵活,但matplotlib小部件可以正常工作。
最后,您需要了解如何确定您刚绘制的框是否与任何行重叠。我不会试图弄清楚顶点之间的线段是否越过框,但是找出一个点是否在其中是很简单的,并且matplotlib已经有很多实用程序来做到这一点。
将所有内容放在一起作为例子:
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.widgets import RectangleSelector
from matplotlib.transforms import Bbox
def main():
# Generate some random data:
data = []
for track_id in xrange(100):
a, b = np.random.random(2)
x = 100 * a + np.random.random(100).cumsum()
y = np.cos(x) + b * np.random.random(100).cumsum()
data.append((track_id, x, y))
# Plot it, keeping track of the "track_id"
fig, ax = plt.subplots()
for track_id, x, y in data:
line, = ax.plot(x,y)
line.track_id = track_id
# Make the selector...
selector = RectangleSelector(ax, onselect, drawtype='box')
# We could set up a button or keyboard shortcut to activate this, instead...
selector.set_active(True)
plt.show()
def onselect(eclick, erelease):
"""Get the lines in an axis with vertices inside the region selected.
"eclick" and "erelease" are matplotlib button_click and button_release
events, respectively."""
# Make a matplotlib.transforms.Bbox from the selected region so that we
# can more easily deal with finding if points are inside it, etc...
left, bottom = min(eclick.x, erelease.x), min(eclick.y, erelease.y)
right, top = max(eclick.x, erelease.x), max(eclick.y, erelease.y)
region = Bbox.from_extents(left, bottom, right, top)
track_ids = []
ax = eclick.inaxes
for line in ax.lines:
bbox = line.get_window_extent(eclick.canvas)
# Start with a rough overlaps...
if region.overlaps(bbox):
# We need the xy data to be in display coords...
xy = ax.transData.transform(line.get_xydata())
# Then make sure that at least one vertex is really inside...
if any(region.contains(x,y) for x,y in xy):
# Highlight the selected line by making it bold
line.set_linewidth(3)
track_ids.append(line.track_id)
print track_ids
eclick.canvas.draw()
if __name__ == '__main__':
main()