我正在尝试可视化传感器输出相对于其路径的变化。
我在一个图中绘制路径为散点图,在第二个图中绘制信号幅度的某个范围。我需要可视化(突出显示)获取特定读数的路径点。
我开始使用bokeh作为后端,并且总体上,我需要的可视化效果非常好。但是我被这种特殊的互动所困扰。
我想在图的中间锚定一些标记,例如垂直线。当我移动/滚动幅度图(底部)时,我想突出显示路径图上最接近标记线的点。
示例代码:
(我想锚定标记线,并在红点和垂直线之间添加交互,以获取信号索引,但未实现。)
import numpy as np
import pandas as pd
from bokeh.io import output_file
from bokeh.models import ColumnDataSource, HoverTool, Span
from bokeh.plotting import figure, show
from bokeh.layouts import gridplot
output_file('interactive_path_sig.html', title="interactive path")
class InteractivePath():
def __init__(self):
x = np.arange(0, 1000, 0.5)
self.df = pd.DataFrame({"x": x,
"y": np.sin(x),
"z": np.cos(x)})
self.source = ColumnDataSource(self.df)
def plot_path(self):
plt = figure(title = "Sensor Path")
plt.scatter(x="x", y="y",source=self.source,
line_color=None, size = 6)
# TODO implement interaction instead of hard coded index
index=500 # this is where I think I need to create working callback
print("x={}, y={}".format(self.df['x'][index], self.df['y'][index]))
plt.circle(x=self.df['x'][index], y=self.df['y'][index],
fill_color="red", size=15)
hover = HoverTool()
hover.tooltips=[("index", "@index"), ("senosr","@z")]
plt.add_tools(hover)
return plt
def plot_signal(self):
plt = figure(x_range=(450, 550), title="Signal Amplitude")
plt.line(x="index", y="z", source=self.source, line_color="black", line_width=2)
# TODO implement interaction instead of hard coded index
index = 500 # I think this needs emit some singal to other plot
vline = Span(location=index, dimension='height', line_color='red', line_width=3)
plt.renderers.extend([vline])
return plt
def get_grid(self):
""" place visualisation in a grid and display"""
grid = gridplot([[self.plot_path()], [self.plot_signal()]],
sizing_mode='stretch_both',)
return grid
def vis_main(self):
""" use all visualisations"""
show(self.get_grid())
if __name__=="__main__":
vis = InteractivePath()
vis.vis_main()
答案 0 :(得分:3)
一些指针:
index
已存在于您的self.df
中,一旦您将其放置在绘图上,它就更易于与之交互,因为您可以使用JS绘图行为来处理它,而不用返回到python变量并重新加载数据。hover_color='red'
可以代替绘制并移动另一类字形。如果您希望保持静态选择状态,以便在屏幕快照中无需鼠标即可生成精美的报告,请使用selected
的内置ColumnDataSource
属性定义回调。我可以用一些更具体的示例发布一些实际的代码块,但是如果这些要点对于您的实际用例来说是很难的,那么它将为您提供解决方案。
编辑:
所以我使用一种类方法非常接近-问题是能够从第一种方法编辑第二个图,而不是对ColumnDataSource
本身的实际更改。
def plot_it(self):
self.plot_signal = figure(x_range=(450, 550), y_range=(-1, 1), title='signal')
self.plot_signal.line(x='index', y='z', source=self.source)
self.plot_signal.segment(x0=500, y0=-2, x1=500, y1=2, source=self.source)
self.plot_path = figure(title='sensor')
self.plot_path.scatter(x='x', y='y', source=self.source, hover_color='red')
jscode='''
var data = source.data;
var plot_signal = plot_signal;
var index = cb_data.index['1d'].indices;
var xmin = 0;
var xmax = 0;
if (index > 0) {
xmin = index[0] - 50;
xmax = index[0] + 50;
plot_signal.x_range.end = xmax;
plot_signal.x_range.start = xmin;
plot_signal.change.emit();
}
hover_callback = CustomJS(args=dict(source=self.source, plot_signal=self.plot_signal), code=jscode)
hover.tooltips = [('index', '@index'), ('sensor', '@z')]
self.plot_path.add_tools(hover)
def get_grid(self):
self.plot_it()
grid = gridplot([[self.plot_path], [self.plot_signal]])
return grid
除了移动线段外,其他所有操作均应执行。我找不到添加plot_signal.SOMEOBJECT.x0
和.x1
的句段命名约定,但是就像使用if (index > 0)
一样,它将被添加到index[0]
块中。我删除了一些样式选项,因为我正在从另一台计算机上转录。
moving a line segment上的这个问题可能会为您提供细分JSON对象的语法。