Issue
I have a plot of data points with 2 GUI buttons. I want to click one button and then select points on the plot which will be stored in one array. I then want to click the other button and select additional points in the plot to store in a different array.
My initial attempt was to combine the code provide in these two links:
Select n data points from plot
https://matplotlib.org/3.1.1/gallery/widgets/buttons.html
Clicking the first button and selecting points functions as expected. However, selecting the second button and clicking addition points does not close the connection from the first button.
I've attempted to use .canvas.mpl_diconnect(cid) various ways but to no avail. I cannot seem to figure out how to initialize the cid and pass it through the class.
Below is sample output data from selection, and toy code to replicate.
SAMPLE OUTPUT FROM SELECTION:
# After clicking 'Buy' Button
# data point selections correctly stored in manual_buy array
Select Buy Points
Buy onpick point: ((736551.0, 12.12),)
Buy onpick point: ((736562.0, 12.05),)
# After clicking 'Sell' Button
# data points incorrectly being stored in manual_buy array and manual_sell array
Select Sell Points
Buy onpick point: ((736556.0, 13.02),)
Sell onpick point: ((736556.0, 13.02),)
Buy onpick point: ((736573.0, 13.19),)
Sell onpick point: ((736573.0, 13.19),)
Toy Code:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Button
from datetime import datetime
x = np.arange(0, 10, 1)
y = np.sin(x)
fig_3 = plt.figure()
ax1 = fig_3.add_subplot(111)
plt.subplots_adjust(bottom=0.2)
# Candlestick
ax1.plot(x, y, '-o', picker=1) # 5 points tolerance
ax1.grid(True)
ax1.set_axisbelow(True)
ax1.set_title('Manual Buy / Sell Selection: ', color='white')
ax1.set_facecolor('black')
ax1.figure.set_facecolor('#121212')
ax1.tick_params(axis='x', colors='white')
ax1.tick_params(axis='y', colors='white')
manual_buy = []
manual_sell = []
#https://matplotlib.org/3.1.3/users/event_handling.html
def buy_onpick(event):
thisline = event.artist
xdata = thisline.get_xdata()
ydata = thisline.get_ydata()
ind = event.ind
point = tuple(zip(xdata[ind], ydata[ind]))
dt = datetime.fromordinal(xdata[ind])
buy_str = "BUY"
buy_num = 1
point_data = np.array([[dt, buy_str, buy_num]])
manual_buy.append(point_data)
print('Buy onpick point:', point)
def sell_onpick(event):
thisline = event.artist
xdata = thisline.get_xdata()
ydata = thisline.get_ydata()
ind = event.ind
point = tuple(zip(xdata[ind], ydata[ind]))
dt = datetime.fromordinal(xdata[ind])
sell_str = "SELL"
sell_num = 0.5
point_data = np.array([[dt, sell_str, sell_num]])
manual_buy.append(point_data)
print('Sell onpick point:', point)
class Buy_Sell:
def Buy(self, event):
print('\nSelect Buy Points')
fig_3.canvas.mpl_connect('pick_event', buy_onpick)
def Sell(self, event):
print('\nSelect Sell Points')
fig_3.canvas.mpl_connect('pick_event', sell_onpick)
def Save(self, event):
print('Would have saved data')
#Add functionality to save data
print('Saved')
callback = Buy_Sell()
axbuy = plt.axes([0.59, 0.05, 0.1, 0.075])
axsell = plt.axes([0.7, 0.05, 0.1, 0.075])
axsave = plt.axes([0.81, 0.05, 0.1, 0.075])
bbuy = Button(axbuy, 'Buy')
bbuy.on_clicked(callback.Buy)
bsell = Button(axsell, 'Sell')
bsell.on_clicked(callback.Sell)
bsave = Button(axsave, 'Save')
bsave.on_clicked(callback.Save)
Solution
You should switch modes, which is not in code. Pls see folowing code:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Button
from datetime import datetime
class Buy_Sell:
def __init__(self, fig, x, y):
self.fig = fig
self.ax = fig.axes[0]
self.x = x
self.y = y
self.ax.plot(x, y, '-o', picker=1) # 5 points tolerance
self.ax.grid(True)
self.ax.set_axisbelow(True)
self.ax.set_title('Manual Buy / Sell Selection: ', color='white')
self.ax.set_facecolor('black')
self.ax.figure.set_facecolor('#121212')
self.ax.tick_params(axis='x', colors='white')
self.ax.tick_params(axis='y', colors='white')
self.manual_buy = []
self.manual_sell = []
self.mode = 'buy'
self.pick1 = self.fig.canvas.mpl_connect('pick_event', buy_onpick)
self.pick2 = self.fig.canvas.mpl_connect('pick_event', sell_onpick)
self.fig.canvas.draw()
def buy_onpick(self, event):
print(self.mode)
if self.mode == 'buy':
thisline = event.artist
xdata = thisline.get_xdata()
ydata = thisline.get_ydata()
ind = event.ind
point = tuple(zip(xdata[ind], ydata[ind]))
dt = datetime.fromordinal(xdata[ind])
buy_str = "BUY"
buy_num = 1
point_data = np.array([[dt, buy_str, buy_num]])
self.manual_buy.append(point_data)
print('Buy onpick point:', point)
def sell_onpick(self, event):
print(self.mode)
if self.mode == 'sell':
thisline = event.artist
xdata = thisline.get_xdata()
ydata = thisline.get_ydata()
ind = event.ind
point = tuple(zip(xdata[ind], ydata[ind]))
dt = datetime.fromordinal(xdata[ind])
sell_str = "SELL"
sell_num = 0.5
point_data = np.array([[dt, sell_str, sell_num]])
self.manual_sell.append(point_data)
print('Sell onpick point:', point)
def Save(self, event):
print('Would have saved data')
#Add functionality to save data
print('Saved')
def mode_buy(self, event):
self.mode = 'buy'
print(self.mode)
print('entering buy mode')
self.pick1 = self.fig.canvas.mpl_connect('pick_event', buy_onpick)
self.fig.canvas.mpl_disconnect(self.pick2)
def mode_sell(self, event):
self.mode = 'sell'
print(self.mode)
print('entering sell mode')
self.pick2 = self.fig.canvas.mpl_connect('pick_event', sell_onpick)
self.fig.canvas.mpl_disconnect(self.pick1)
def mode_save(self, event):
self.mode = 'save'
print('entering save mode')
x = np.arange(0, 10, 1)
y = np.sin(x)
fig = plt.figure()
ax1 = fig.add_subplot(111)
plt.subplots_adjust(bottom=0.2)
callback = Buy_Sell(fig, x, y)
axbuy = plt.axes([0.59, 0.05, 0.1, 0.075])
axsell = plt.axes([0.7, 0.05, 0.1, 0.075])
axsave = plt.axes([0.81, 0.05, 0.1, 0.075])
bbuy = Button(axbuy, 'Buy')
bbuy.on_clicked(callback.mode_buy)
bsell = Button(axsell, 'Sell')
bsell.on_clicked(callback.mode_sell)
bsave = Button(axsave, 'Save')
bsave.on_clicked(callback.mode_save)
Key points:
- Create function calls to disconnect buy and sell mode.
buy_onpick
andsell_onpick
only do picking data stuff, switching mode is managed by your button callback functions, in this example aremode_buy
andmode_sell
.
Answered By - ted930511
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.