在 Bokeh 图中使用滑块动态更改注释的坐标和文本

Dynamically change the coordinates and the text of annotation with slider in Bokeh plot

我有一个散景图,其中有一个滑块。我想改变滑块画线的坐标,如图screenshot of the figure. When I change the slider, the line changes its coordinates.

我尝试将滑块小部件与列数据源一起使用。但是,由于我是 Python 的新手,我无法使用滑块移动标签的位置和文本。有办法吗?

我的代码如下:

import math
import numpy as np
from bokeh.io import output_file
from bokeh.plotting import figure, show
from bokeh.layouts import column, row
from bokeh.models import CustomJS, Slider, Label, LabelSet
from bokeh.plotting import ColumnDataSource, figure, show
from bokeh.models import Arrow, OpenHead, NormalHead, VeeHead

theta = 0 #input the value here
theta = np.radians(-theta)

#Inputs to be made text boxes
sig_x = 10

# line
x=[1,1]
y=[-1,1]

x1=[1,1]
y1=[1,1]

我想介绍一个变量,它也会随着滑块的变化而变化,现在这里是 10。

sig_1 = 10*sig_x

然后我介绍了词典,以及 x=xy=y x1=x1y1=y1.

source = ColumnDataSource(data=dict(x=x, y=y))

fig = figure(title = 'Test of Text Rotation',
        plot_height = 300, plot_width = 300,
        x_range = (-3,3), y_range=(-3,3),
        toolbar_location = None)

我找不到向行添加标签的方法,所以我添加了布局(来自教程示例)。但是,与 fig.line 命令不同的是,'x''y' 不能作为变量添加(请原谅我使用的术语不正确)。

citation = Label(x=1, y=1, text = str(sig_1))

fig.line('x', 'y',source=source, line_width = 2)     # Main Stress block
fig.add_layout(citation)

amp_slider = Slider(start=0, end=360, value=theta, step=1, title="theta")
# Adding callback code,
callback = CustomJS(args=dict(source=source ,val=amp_slider),
                code="""
const data = source.data;

 var x = data['x'];
 var y = data['y'];
 var pi = Math.PI;
 var theta = -1*(val.value) * (pi/180);
 x[0]=(1*Math.cos(theta))-(1*Math.sin(theta)); // addition
 x[1]=(1*Math.cos(theta))+(1*Math.sin(theta)); // addition
      
 y[0]=(-1*Math.sin(theta))-(1*Math.cos(theta)); // addition
 y[1]=(-1*Math.sin(theta))+(1*Math.cos(theta)); // addition
 
source.change.emit();
""")

amp_slider.js_on_change('value', callback)

layout = row(fig, column(amp_slider),)

show(layout)

我添加了 x1[0]=(1*Math.cos(theta))-(1*Math.sin(theta))x1[1]=(1*Math.cos(theta))+(1*Math.sin(theta));y[0]=(-1*Math.sin(theta))-(1*Math.cos(theta));y[1]=(-1*Math.sin(theta))+(1*Math.cos(theta));

正如预期的那样,此代码不会随行移动标签。对我做错了什么的任何解释,以及这样做的可能性都会非常有帮助。

您也可以将 Lable 传递给 CustomJS-回调,并像对 ColumnDataSource 一样修改此模型的值。不要忘记致电 lable.change.emit();.

请参阅下面的完整示例。

import numpy as np
from bokeh.plotting import figure, show, output_notebook
from bokeh.layouts import row
from bokeh.models import CustomJS, Slider, Label, ColumnDataSource
output_notebook()

theta = 0 #input the value here
theta = np.radians(-theta)

#Inputs to be made text boxes
sig_x = 10

source = ColumnDataSource(data=dict(x=[1,1], y=[-1,1]))

fig = figure(
    title = 'Test of Text Rotation',
    plot_height = 300,
    plot_width = 300,
    x_range = (-3,3),
    y_range=(-3,3),
    toolbar_location = None
)
fig.line('x', 'y',source=source, line_width = 2)

citation = Label(x=1, y=1, text = str(10*sig_x))
fig.add_layout(citation)

amp_slider = Slider(start=0, end=360, value=theta, step=1, title="theta")

# Adding callback code
callback = CustomJS(args=dict(source=source ,val=amp_slider, lable=citation),
                code="""
const data = source.data;

var x = data['x'];
var y = data['y'];
var pi = Math.PI;
var theta = -1*(val.value) * (pi/180);
x[0]=(1*Math.cos(theta))-(1*Math.sin(theta));
x[1]=(1*Math.cos(theta))+(1*Math.sin(theta));
y[0]=(-1*Math.sin(theta))-(1*Math.cos(theta));
y[1]=(-1*Math.sin(theta))+(1*Math.cos(theta));
source.change.emit();

lable['x'] = x[1]
lable['y'] = y[1]
lable.change.emit();
"""
)
amp_slider.js_on_change('value', callback)
layout = row(fig, amp_slider)
show(layout)

结果

如果要修改标签的文字,可以使用类似的方法。