情节条件 on_click
Plotly Conditional on_click
有没有办法为控制另一个的函数 `on_click 设置条件语句?我打算执行以下操作:
- 引入散点数据(目前有效)
- Select 我的散点数据中有 2 个点(目前有效 - 图片上的蓝点)
- 在 2 个散点之间创建新线(目前有效 - 图片上的黑线)
- Select 创建的新线上的一个点(目前有效 - 图片上的绿点)
- 将新行上的点限制为 1(我一直在尝试进行条件语句)
- Select 我的散点图中没有线的第 3 个点(我正在等待这样做,直到我可以修复上一步。我将有另一个数据集,我'我从那里拉出来,我将允许 select 从 - 图片上的红点)
- 根据我已经select编辑的点创建新线(图片上的橙色线)
我原以为使用条件 fake_click_check
语句会起作用,但它什么也没做。我想一旦我可以修复当前的条件语句(以及如何将它们与 on_click
一起使用),我就可以完成其余的步骤。
@out.capture()
def update_point(trace, points, selector):
x = list(line.x) + points.xs
y = list(line.y) + points.ys
line.update(x=x, y=y)
clicks=len(fig.to_dict()['data'][2]['x'])
c = list(scatter.marker.color)
s = list(scatter.marker.size)
for i in points.point_inds:
c[i] = '#bae2be'
s[i] = 20
with fig.batch_update():
scatter.marker.color = c
scatter.marker.size = s
if (clicks==2):
fict_x1=float(fig.to_dict()['data'][2]['x'][0])
fict_x2=float(fig.to_dict()['data'][2]['x'][2])
fict_x_start=np.minimum(fict_x1,fict_x2)
fict_x_end=np.maximum(fict_x1,fict_x2)
fict_x=np.arange(fict_x_start,fict_x_end,0.1)
x_len=fict_x.size
fict_y1=float(fig.to_dict()['data'][2]['y'][0])
fict_y2=float(fig.to_dict()['data'][2]['y'][2])
fict_y_start=np.minimum(fict_y1,fict_y2)
fict_y_end=np.maximum(fict_y1,fict_y2)
fict_y_tick=(fict_y_end-fict_y_start)/x_len
fict_y=np.arange(fict_y_start,fict_y_end,fict_y_tick)
new_point.update(x=fict_x,y=fict_y)
fake_click_check=1
if (clicks > 2):
line.update(x=[],y=[])
scatter.marker.color=['#a3a7e4']*100
scatter.marker.size=[10]*100
out.clear_output
@out.capture()
def set_new_point(trace,points,selector):
fake_click=len(fig.to_dict()['data'][2]['x'])
if (fake_click_check < 1):
if (fake_click>1):
c = list(new_point.marker.color)
s = list(new_point.marker.size)
fake_click_check=fake_click_check+1
for i in points.point_inds:
c[i]='#bae2be'
s[i]=20
with fig.batch_update():
new_point.marker.color = c
new_point.marker.size = s
scatter.on_click(update_point)
if (fake_click_check==1):
new_point.on_click(set_new_point)
- 一切都是关于如何系统地建立能力
- 我发现的一个限制:https://community.plotly.com/t/detecting-click-only-on-the-point-or-line-possible/8452 因此在前两个选定点之间创建了一组插值点,以便可以点击第三个点
import numpy as np
import plotly.express as px
import plotly.graph_objects as go
import ipywidgets as widgets
x = np.random.uniform(-10, 10, size=50)
y = np.sin(x)
# construct figure that has holders for points, interpolated line and final lines
fig = go.FigureWidget(
[
go.Scatter(x=x, y=y, mode="markers", name="base_points"),
go.Scatter(name="points", mode="markers", marker={"size": 20}),
go.Scatter(name="interp", showlegend=False),
go.Scatter(name="lines", line={"color": "orange"}, mode="lines"),
]
)
fig.update_layout(template="simple_white")
out = widgets.Output(layout={"border": "1px solid black"})
out.append_stdout("Output appended with append_stdout\n")
# interpolated line between first two selected points
@out.capture()
def line_click(trace, points, selector):
# print(trace.name, points.xs, points.ys)
if len(points.xs) == 1 and len(fig.data[1].x) == 2:
t = fig.data[1]
t.update(x=list(t.x) + points.xs, y=list(t.y) + points.ys)
# create our callback function
@out.capture()
def base_click(trace, points, selector):
# print(trace.name, points.xs, points.ys)
if len(points.xs) == 0:
return
if fig.data[1].x is None: # first point
t = fig.data[1]
t.update(x=points.xs, y=points.ys)
elif len(fig.data[1].x) in [1, 3]: # second and fourth point
t = fig.data[1]
t.update(x=list(t.x) + points.xs, y=list(t.y) + points.ys)
if len(fig.data[1].x) == 2:
# need a set of points so click events work on second points
xx = np.linspace(*fig.data[1].x, 20)
yy = np.interp(xx, fig.data[1].x, fig.data[1].y)
t = fig.data[2]
t.update(x=xx, y=yy, marker={"size": 2}, mode="markers")
else: # fourth point create the lines
# use order of points to construct wanted lines
fig.data[3].update(
x=np.array(fig.data[1].x)[[0, 3, 3, 2, 3, 1]],
y=np.array(fig.data[1].y)[[0, 3, 3, 2, 3, 1]],
)
fig.data[0].on_click(base_click)
fig.data[2].on_click(line_click)
reset = widgets.Button(description="Reset")
@out.capture()
def on_reset_clicked(b):
# line.update(x=[], y=[])
fig.data[1].update(x=None, y=None)
fig.data[2].update(x=None, y=None)
fig.data[3].update(x=None, y=None)
out.clear_output()
reset.on_click(on_reset_clicked)
widgets.VBox([widgets.HBox([reset]), widgets.HBox([fig, out])])
有没有办法为控制另一个的函数 `on_click 设置条件语句?我打算执行以下操作:
- 引入散点数据(目前有效)
- Select 我的散点数据中有 2 个点(目前有效 - 图片上的蓝点)
- 在 2 个散点之间创建新线(目前有效 - 图片上的黑线)
- Select 创建的新线上的一个点(目前有效 - 图片上的绿点)
- 将新行上的点限制为 1(我一直在尝试进行条件语句)
- Select 我的散点图中没有线的第 3 个点(我正在等待这样做,直到我可以修复上一步。我将有另一个数据集,我'我从那里拉出来,我将允许 select 从 - 图片上的红点)
- 根据我已经select编辑的点创建新线(图片上的橙色线)
我原以为使用条件 fake_click_check
语句会起作用,但它什么也没做。我想一旦我可以修复当前的条件语句(以及如何将它们与 on_click
一起使用),我就可以完成其余的步骤。
@out.capture()
def update_point(trace, points, selector):
x = list(line.x) + points.xs
y = list(line.y) + points.ys
line.update(x=x, y=y)
clicks=len(fig.to_dict()['data'][2]['x'])
c = list(scatter.marker.color)
s = list(scatter.marker.size)
for i in points.point_inds:
c[i] = '#bae2be'
s[i] = 20
with fig.batch_update():
scatter.marker.color = c
scatter.marker.size = s
if (clicks==2):
fict_x1=float(fig.to_dict()['data'][2]['x'][0])
fict_x2=float(fig.to_dict()['data'][2]['x'][2])
fict_x_start=np.minimum(fict_x1,fict_x2)
fict_x_end=np.maximum(fict_x1,fict_x2)
fict_x=np.arange(fict_x_start,fict_x_end,0.1)
x_len=fict_x.size
fict_y1=float(fig.to_dict()['data'][2]['y'][0])
fict_y2=float(fig.to_dict()['data'][2]['y'][2])
fict_y_start=np.minimum(fict_y1,fict_y2)
fict_y_end=np.maximum(fict_y1,fict_y2)
fict_y_tick=(fict_y_end-fict_y_start)/x_len
fict_y=np.arange(fict_y_start,fict_y_end,fict_y_tick)
new_point.update(x=fict_x,y=fict_y)
fake_click_check=1
if (clicks > 2):
line.update(x=[],y=[])
scatter.marker.color=['#a3a7e4']*100
scatter.marker.size=[10]*100
out.clear_output
@out.capture()
def set_new_point(trace,points,selector):
fake_click=len(fig.to_dict()['data'][2]['x'])
if (fake_click_check < 1):
if (fake_click>1):
c = list(new_point.marker.color)
s = list(new_point.marker.size)
fake_click_check=fake_click_check+1
for i in points.point_inds:
c[i]='#bae2be'
s[i]=20
with fig.batch_update():
new_point.marker.color = c
new_point.marker.size = s
scatter.on_click(update_point)
if (fake_click_check==1):
new_point.on_click(set_new_point)
- 一切都是关于如何系统地建立能力
- 我发现的一个限制:https://community.plotly.com/t/detecting-click-only-on-the-point-or-line-possible/8452 因此在前两个选定点之间创建了一组插值点,以便可以点击第三个点
import numpy as np
import plotly.express as px
import plotly.graph_objects as go
import ipywidgets as widgets
x = np.random.uniform(-10, 10, size=50)
y = np.sin(x)
# construct figure that has holders for points, interpolated line and final lines
fig = go.FigureWidget(
[
go.Scatter(x=x, y=y, mode="markers", name="base_points"),
go.Scatter(name="points", mode="markers", marker={"size": 20}),
go.Scatter(name="interp", showlegend=False),
go.Scatter(name="lines", line={"color": "orange"}, mode="lines"),
]
)
fig.update_layout(template="simple_white")
out = widgets.Output(layout={"border": "1px solid black"})
out.append_stdout("Output appended with append_stdout\n")
# interpolated line between first two selected points
@out.capture()
def line_click(trace, points, selector):
# print(trace.name, points.xs, points.ys)
if len(points.xs) == 1 and len(fig.data[1].x) == 2:
t = fig.data[1]
t.update(x=list(t.x) + points.xs, y=list(t.y) + points.ys)
# create our callback function
@out.capture()
def base_click(trace, points, selector):
# print(trace.name, points.xs, points.ys)
if len(points.xs) == 0:
return
if fig.data[1].x is None: # first point
t = fig.data[1]
t.update(x=points.xs, y=points.ys)
elif len(fig.data[1].x) in [1, 3]: # second and fourth point
t = fig.data[1]
t.update(x=list(t.x) + points.xs, y=list(t.y) + points.ys)
if len(fig.data[1].x) == 2:
# need a set of points so click events work on second points
xx = np.linspace(*fig.data[1].x, 20)
yy = np.interp(xx, fig.data[1].x, fig.data[1].y)
t = fig.data[2]
t.update(x=xx, y=yy, marker={"size": 2}, mode="markers")
else: # fourth point create the lines
# use order of points to construct wanted lines
fig.data[3].update(
x=np.array(fig.data[1].x)[[0, 3, 3, 2, 3, 1]],
y=np.array(fig.data[1].y)[[0, 3, 3, 2, 3, 1]],
)
fig.data[0].on_click(base_click)
fig.data[2].on_click(line_click)
reset = widgets.Button(description="Reset")
@out.capture()
def on_reset_clicked(b):
# line.update(x=[], y=[])
fig.data[1].update(x=None, y=None)
fig.data[2].update(x=None, y=None)
fig.data[3].update(x=None, y=None)
out.clear_output()
reset.on_click(on_reset_clicked)
widgets.VBox([widgets.HBox([reset]), widgets.HBox([fig, out])])