2

I would like to edit the coordinates plotted on my graph based on the coordinates of a mouse click. Specifically, I would like the points I click on to disappear. Right now, my code switches between two graphs, on the second graph I would like to remove the points closest to the click, and then show the new graph.

I figure I need something like this? I also want to be able to save the new array, with the points removed.

* EDIT * I have gotten it to work so when I click it removes the point, however, I would like to get rid of more than one point and to save the array with the points removed.

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

here it is integrated into my whole code

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 Answer 1

1

changing your function to

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

should fix it I think ... but since you dont rewrite points_x or points_y it wont permanently remove them (ie the next click will remove the clicked point, but render all the rest of the ORIGINAL points)

its arguably better to convert your points_x and points_y to mousecoordinates and compare against event.x and event.y, instead of comparing mapcoordinates

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you! Your top few lines didn't work for me, I got an index error: IndexError: too many indices for array. I'm not sure how to convert my points_x and points_y to mousecoordinates as you suggested
edited ... change to array = np.asarray(list(zip(points_x,points_y))) see repl.it/@JoranBeasley/RotatingElaborateCopycat

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.