簡體   English   中英

Plotly 有條件的 on_click

[英]Plotly Conditional on_click

有沒有辦法為控制另一個的 function `on_click 設置條件語句? 我打算做以下事情:

  1. 引入分散數據(目前有效)
  2. Select 我的散點數據中有 2 個點(目前有效 - 圖片上的藍點)
  3. 在 2 個散點之間創建新線(當前有效 - 圖片上的黑線)
  4. Select 創建的新行上的一個點(當前有效 - 圖片上的綠點)
  5. 將新行上的點限制為 1(我一直在嘗試做出條件語句)
  6. Select 從我的散點 plot 的第 3 點沒有線(我正在等待這樣做,直到我可以修復上一步。我將有另一個數據集,我將從中提取我將允許select 來自-圖片上的紅點)
  7. 根據我已經選擇的點創建新線(圖片上的橙色線)

在此處輸入圖像描述

我原以為使用條件fake_click_check語句會起作用,但它沒有做任何事情。 我想一旦我可以修復這個當前的條件語句(以及如何將它們與on_click一起使用),我將能夠執行 rest 的步驟。

@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)
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])])

在此處輸入圖像描述

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM