将数据限制为所需的值

时间:2011-08-02 00:44:26

标签: python matplotlib

我有一个代码,用于绘制上方左侧图像中的线条。我想选择一个区域(上图中右侧显示的一个矩形),并找出该区域内哪些线对应。

代码绘制左边的图像是:

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以及有关从何处开始使用代码的任何想法?

谢谢!

1 个答案:

答案 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()

An example of some data being selected