I am learning how to use click events to trigger specific actions in matplotlib, specifically multiple draggable points.
I want to have something similar to what has been done here with a draggable marker. Nonetheless, this specific example only works for one marker. I have two markers, and I want to move them individually.
I tried different approaches based from here, here, here and a matplotlib tutorial, but I wasn't successful when trying to disconnect one of the markers and update the position of the other marker.
This is the image of what I'm looking for. The marker located at x=367 does not move and I would like to move it as well.
This is my code so far, and I'm running it on a jupyter notebook. I'm a bit new to using classes in Python, my apologies if I missed something pretty obvious.
%matplotlib notebook
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.pyplot import figure
class DraggableMarker():
def __init__(self, lines, ax, mark_x, mark_y):
self.lines = lines
self.ax = ax
self.mark_x = mark_x
self.mark_y = mark_y
self.lines = self.lines[:]
self.tx = [self.ax.text(0,0,"") for l in self.lines]
self.marker = [self.ax.plot(mark_x, mark_y, marker="o", color="red")[0] for l in self.lines]
self.draggable=False
def click(self,event):
# trying to add another marker
# if event.dblclick:
# if event.button==3:
# self.tx = [self.ax.text(0,0,"") for l in self.lines]
# self.marker1 = [self.ax.plot([0], [0], marker="o", color="red")[0] for l in self.lines]
if event.button==2:
#leftclick
self.draggable=True
self.update(event)
elif event.button==3:
self.draggable=False
[tx.set_visible(self.draggable) for tx in self.tx]
[m.set_visible(self.draggable) for m in self.marker]
ax.figure.canvas.draw_idle()
def drag(self, event):
if self.draggable:
self.update(event)
ax.figure.canvas.draw_idle()
def release(self,event):
self.draggable=False
def update(self, event):
for i, line in enumerate(self.lines):
x,y = self.get_closest(line, event.xdata)
self.tx[i].set_position((x,y))
self.tx[i].set_text("x:{}\ny:{}".format(x,y))
self.marker[i].set_data([x],[y])
def get_closest(self,line, mx):
x,y = line.get_data()
mini = np.argmin(np.abs(x-mx))
return x[mini], y[mini]
def connect(self):
self.c1 = self.ax.figure.canvas.mpl_connect("button_press_event", self.click)
self.c2 = self.ax.figure.canvas.mpl_connect("button_release_event", self.release)
self.c3 = self.ax.figure.canvas.mpl_connect("motion_notify_event", self.drag)
self.lines
def disconnect(self):
'disconnect all the stored connection ids'
self.ax.figure.canvas.mpl_disconnect(self.c1)
self.ax.figure.canvas.mpl_disconnect(self.c2)
self.ax.figure.canvas.mpl_disconnect(self.c3)
markers_loc = [(367, 1.246216), (425, 1.297134)]
data_df = pd.read_csv('event_number_1.csv')
x = data_df.index
y = data_df['Skin conductance']
fig, ax = plt.subplots()
plots = [ax.plot(x,y, markevery=[markers_loc[0][0], markers_loc[0][1]]),
ax.plot(x,y, markevery=[markers_loc[1][0], markers_loc[1][1]])]
cnt=0
for plot in plots:
plots[cnt]
ax = plt.gca()
lines = ax.lines
dm = DraggableMarker(lines, ax, markers_loc[cnt][0], markers_loc[cnt][1])
dm.connect()
cnt+=1
Also, if you could give me some advice regarding how to add a new marker, it would be highly appreciated. Thank you!