开发者

limiting the data to the desired values

开发者 https://www.devze.com 2023-03-25 09:35 出处:网络
I have a code plotting the lines in the image on left hand side above. I would like to select an area (a rectangular showed on the right side of the image above) an开发者_开发知识库d figure out which

I have a code plotting the lines in the image on left hand side above. I would like to select an area (a rectangular showed on the right side of the image above) an开发者_开发知识库d figure out which lines corresponds within that area.

The code plots the image on left is:

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

Which modules you would suggest for python and any ideas on where to start with the code?

Thanks!


It's not too simple, but it's not incredibly hard, either. In general, you'd want to use a full-fledged gui toolkit of some sort (e.g. Qt, wx, GTK, TK, etc) for this, but you can do it with "pure" matplotlib. (Matplotlib is, of course, just using whichever gui your install is configured to use behind-the-scenes.)

Your first problem is that you're not storing the track IDs anywhere.

It can be as simple as:

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]

You have to store them somewhere, however! Adding an attribute to each matplotlib line artist object will make things easier later, but you could just as easily do it in other ways.

For the next part, there's a widget in matplotlib.widgets that will do what you need. Have a look at the example here: http://matplotlib.sourceforge.net/examples/widgets/rectangle_selector.html Again, it's more flexible to use a full-blown gui toolkit, but the matplotlib widgets will work fine for something like this.

Finally, you need to understand how to figure out whether the box you just drew overlaps with any of the lines. I'm not going to mess with trying to figure out whether a line segment between to vertices crosses the box, but finding out if a point is inside it is simple, and matplotlib already has plenty of utilities to do that.

Putting it all together into an example:

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

limiting the data to the desired values

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号