如何正确为Plotly中的单个轨迹添加回调?
下面的代码尝试用三种不同的方法在Plotly的图形上注册一个回调函数。
- 方法'a'是在将图形添加到图表之前,直接在图形对象上注册回调函数。
- 方法'b'是在将图形添加到图表后,通过从图表的数据列表中获取对象来注册回调函数。
- 方法'c'是方法'a'的一种变体,其中回调函数是局部的(也就是说,它不是一个成员函数)。
以下是我尝试添加回调函数的三种方法的代码。如果你在Jupyter Notebook中运行这段代码,你应该能看到三个图表,点击任意一个图表上的点应该会打印一条消息,但似乎只有使用方法'b'的图表能够正常工作。
import ipywidgets as widgets
import plotly.graph_objects as go
line = {'name': 'line','data': ((1,1), (2,2), (3,3)), 'color':'red', 'dash':'solid'}
squared = {'name': 'squared','data': ((1,1), (2,2**2), (3,3**2)), 'color':'blue', 'dash':'4,4'}
cubed = {'name': 'cubed','data': ((1,1), (2,2**3), (3,3**3)), 'color':'green', 'dash':'solid'}
n4 = {'name': 'n4','data': ((1,1), (2,2**4), (3,3**4)), 'color':'purple', 'dash':'solid'}
traces = (line, squared, cubed, n4)
class MyPlot:
def __init__(self, traces, use_callback):
self.traces = traces
self.use_callback = use_callback
def get_values(self, func, index):
return [e[index] for e in func['data']]
def callback_a(self, trace, points, state):
print(f"in callback_a with trace = {trace}, points = {points}, state = {state}")
def callback_b(self, trace, points, state):
if len(points.point_inds) < 1:
return
print(f"in callback_b with trace = {trace}, points = {points}, state = {state}")
def display(self):
def callback_c(trace, points, state):
print(f"in callback_c with trace = {trace}, points = {points}, state = {state}")
fig = go.FigureWidget()
for t in traces:
s = go.Scatter(mode="lines", name=t['name'], x=self.get_values(t, 0), y=self.get_values(t, 1), line=dict(width=2, color=t['color'], dash=t['dash']))
if self.use_callback == 'a': s.on_click(self.callback_a)
if self.use_callback == 'c': s.on_click(callback_c)
fig.add_trace(s)
if self.use_callback == 'b': fig.data[-1].on_click(self.callback_b)
fig.layout.title = f"Plot using callback {self.use_callback}"
display(fig)
my_plot_a = MyPlot(traces, 'a')
my_plot_b = MyPlot(traces, 'b')
my_plot_c = MyPlot(traces, 'c')
my_plot_a.display()
my_plot_b.display()
my_plot_c.display()
正如我之前所说,似乎只有方法'b'能够正常工作。然而,这种方法有一个不太好的“特性”。当我点击任意一个图形上的点时,每个图形的回调函数都会被调用,即使我并没有点击那个图形。为了解决这个问题,我通过检查points.point_inds
属性的长度来进行处理,只有在我想要的回调中这个长度才会大于0。虽然这样可以解决问题,但感觉有点多余,而我想要的方法'a'似乎是文档中推荐的做法,但我却无法让它正常工作。
这是来自Plotly的一个文档的例子。我觉得我在方法'a'和'c'中都遵循了这个例子。我是不是做错了什么?
0 个回答
暂无回答