Редактировать график на основе ввода мышью - PullRequest
0 голосов
/ 17 апреля 2020

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

Я полагаю, что мне нужно что-то подобное? Я также хочу иметь возможность сохранить новый массив с удаленными точками.

* РЕДАКТИРОВАТЬ * Я заставил его работать, поэтому, когда я щелкаю по нему, удаляется точка, однако я хотел бы избавиться от более чем одной точки и сохранить массив с удаленными точками.

    def on_button_press(self, event):
        print('xdata, ydata:', event.xdata, event.ydata)
        #find the x index closest to the mouse click
        array = np.asarray((points_x))
        idx = (np.abs(array - event.xdata)).argmin()

        #remove those points from points_x and points_y
        points_x_adjust = np.delete(points_x, idx)
        points_y_adjust = np.delete(points_y, idx)

        #replot
        self.canvas.flush_events()
        self.ax.clear()
        self.ax.plot(Z_filt_2)
        self.ax.set(title='Points removed')
        # self.ax.set(xlim=(touchdown_cut_adj[-11]-500,toeoff_cut_adj[-1]+500))
        # self.ax.plot(toeoff_cut_adj,plt_TOy_adj, marker='o', linestyle='none')
        # x,y = zip(*new_points)
        self.ax.plot(points_x_adjust,points_y_adjust, marker='x', linestyle='none')
        self.canvas.draw()

здесь он интегрирован в весь мой код

from tkinter import * 

import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import (
    FigureCanvasTkAgg, NavigationToolbar2Tk)
from matplotlib.figure import Figure


# (not so) random data
# (not so) random data
Z_filt_1 = [0,1,2,3,4,5,6,7,8,9,10]
Z_filt_2 = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14]

points_x = [2,4,6,8,10]
points_y = [2,4,6,8,10]


class MatPlotLibSwitchGraphs:

    def __init__(self, master):
        self.master = master

        self.frame = Frame(self.master)
        self.frame.pack(expand=YES, fill=BOTH)

        self.fig = Figure(figsize=(5, 4), dpi=100)
        self.ax = self.fig.gca() #config_plot()

        self.canvas = FigureCanvasTkAgg(self.fig, self.master)  
        self.config_window()

        self.graphIndex = 0
        self.draw_graph_one()

    def config_window(self):
        toolbar = NavigationToolbar2Tk(self.canvas, self.master)
        toolbar.update()

        self.canvas.get_tk_widget().pack(side=TOP, fill=BOTH, expand=1)

        print('connect')
        self.canvas.mpl_connect("key_press_event", self.on_key_press)
        self.canvas.mpl_connect("button_press_event", self.on_button_press)

        self.button = Button(self.master, text="QUIT", command=self._quit)
        self.button.pack(side=BOTTOM)
        self.button_switch = Button(self.master, text="CHANGE PLOT", command=self.switch_graphs)
        self.button_switch.pack(side=BOTTOM)

    def draw_graph_one(self):
        self.ax.clear()
        self.ax.plot(Z_filt_1)
        self.ax.plot(points_x,points_y, marker='x', linestyle='none')
        self.ax.set(title='First Plot')
        self.canvas.draw()

    def draw_graph_two(self):
        self.ax.clear()
        self.ax.plot(Z_filt_2)
        self.ax.plot(points_x,points_y, marker='x', linestyle='none')
        self.ax.set(title='Second Plot')
        self.canvas.draw()

    def on_key_press(self, event):
        print('key:', event.key)

    def on_button_press(self, event):
        print('xdata, ydata:', event.xdata, event.ydata)
        #find the x index closest to the mouse click
        array = np.asarray((points_x))
        idx = (np.abs(array - event.xdata)).argmin()

        #remove those points from points_x and points_y
        points_x_adjust = np.delete(points_x, idx)
        points_y_adjust = np.delete(points_y, idx)

        #replot
        self.canvas.flush_events()
        self.ax.clear()
        self.ax.plot(Z_filt_2)
        self.ax.set(title='Points removed')
        # self.ax.set(xlim=(touchdown_cut_adj[-11]-500,toeoff_cut_adj[-1]+500))
        # self.ax.plot(toeoff_cut_adj,plt_TOy_adj, marker='o', linestyle='none')
        # x,y = zip(*new_points)
        self.ax.plot(points_x_adjust,points_y_adjust, marker='x', linestyle='none')
        self.canvas.draw()

    def _quit(self):
        #self.master.quit()  # stops mainloop
        self.master.destroy() # works better then `quit()` (at least on Linux)

    def switch_graphs(self):
        # Need to call the correct draw, whether we're on graph one or two
        self.graphIndex = (self.graphIndex + 1 ) % 2
        if self.graphIndex == 0:
            self.draw_graph_one()
        else:
            self.draw_graph_two()

def main():
    root = Tk()
    MatPlotLibSwitchGraphs(root)
    root.mainloop()

if __name__ == '__main__':
    main()

1 Ответ

0 голосов
/ 17 апреля 2020

изменение вашей функции на

def on_button_press(self, event):
    array = np.asarray(list(zip(points_x,points_y)))
    dist = (array[:,0] - event.xdata)**2 + (array[:,1]-event.ydata)**2
    idx = dist.argmin()
    CLOSENESS_THRESHOLD = 0.1
    if dist[idx] > CLOSENESS_THRESHOLD:
        return
    new_points = np.delete(array,idx,0)

    self.canvas.flush_events()
    self.ax.clear()
    self.ax.plot(Z_filt_1)
    self.ax.set(title='Click to remove points')
    # self.ax.set(xlim=(touchdown_cut_adj[-11]-500,toeoff_cut_adj[-1]+500))
    # self.ax.plot(toeoff_cut_adj,plt_TOy_adj, marker='o', linestyle='none')
    x,y = zip(*new_points)
    self.ax.plot(x,y, marker='x', linestyle='none')
    self.canvas.draw()

должно исправить это, я думаю ... но так как вы не перезаписывает points_x или points_y, они не будут удалены навсегда (ie следующий щелчок удалит точку щелчка, но рендеринг всех остальных ОРИГИНАЛЬНЫХ точек)

возможно, лучше конвертировать ваши points_x и points_y в координаты мыши и сравнивать их с event.x и event.y вместо сравнения mapcoordinates

...