ограничение данных до желаемых значений - PullRequest
3 голосов
/ 02 августа 2011

У меня есть код, отображающий линии на изображении слева вверху.Я хотел бы выбрать область (прямоугольник, показанный справа на изображении выше) и выяснить, какие линии соответствуют этой области.

Код, изображающий изображение слева:

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 Ответ

2 голосов
/ 02 августа 2011

Это не слишком просто, но и не невероятно сложно.В общем, вы бы хотели использовать для этого полноценный графический инструментарий (например, Qt, wx, GTK, TK и т. Д.), Но вы можете сделать это с помощью «чистого» matplotlib.(Matplotlib, конечно, просто использует любой графический интерфейс, который ваша установка настроена для использования за кулисами.)

Ваша первая проблема заключается в том, что вы нигде не храните идентификаторы дорожек.

Это может быть просто:

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 Опять же, более гибко использовать полнофункциональный графический интерфейс, но виджеты 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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...