我有三维x,y和z的数据。我将它们显示为散景网格图,其中三个单独的图形彼此相同。 x轴是链接的,因此如果我在其中一个图形中平移,则更新其他图形:
time = np.arange(len(data))
labels = ["x","y","z"]
plots = []
for i in range(3):
if i != 0:
fig = figure(plot_width=900, plot_height=150, x_range=first.x_range)
else:
fig = figure(plot_width=900, plot_height=150)
# First figure is saved as other figures are linked to this one
first = fig
source = ColumnDataSource({'x': time, 'y': data[:,i]})
fig.line('x','y', source=source)
fig.yaxis.axis_label = labels[i]
plots.append([fig])
p = gridplot(([plots[0], plots[1], plots[2]]))
show(p)
我还实现了x轴范围的回调,每次x范围变化时都会更新图形,以便绘图填充y轴上的完整图形:
fig.x_range.callback = CustomJS(args=dict(source=source, xrange=fig.x_range,
yrange=fig.y_range), code=adjust_y_range_js)
在此代码中,范围对象使用新计算的范围进行设置,这会触发源自回调的图形中的更新。即如果我放大三个图形中的第一个图形,第一个图形的y范围将被更新,以便填充图形。由于与其他图的联系,其他两个图的x范围也将改变。但是,他们的x_ranges不会触发回调。我尝试在回调JS代码中传递其他范围并以下面的方式更新它们,但是没有成功:
xrange_other.trigger('change');
这会使盒子选择工具因某种原因而冻结,即它将永久地尝试进行选择。任何想法如何以另一种方式更新整个情节?
回调的代码如下(取自某人的github,但遗憾的是无法找到原始来源):
adjust_y_range_js = """
function isNumeric(n) {
return !isNaN(parseFloat(n)) && isFinite(n);
}
var data = source.get('data');
var start = yrange.get('start');
var end = yrange.get('end');
var time_start = xrange.get('start');
var time_end = xrange.get('end');
var pre_max_old = end;
var pre_min_old = start;
var time = data['x'];
var pre = data['y'];
t_idx_start = time.filter(function(st){return st>=time_start})[0];
t_idx_start = time.indexOf(t_idx_start);
t_idx_end = time.filter(function(st){return st>=time_end})[0];
t_idx_end = time.indexOf(t_idx_end);
var pre_interval = pre.slice(t_idx_start, t_idx_end);
pre_interval = pre_interval.filter(function(st){return !isNaN(st)});
var pre_max = Math.max.apply(null, pre_interval);
var pre_min = Math.min.apply(null, pre_interval);
var ten_percent = (pre_max-pre_min)*0.1;
pre_max = pre_max + ten_percent;
pre_min = pre_min - ten_percent;
if((!isNumeric(pre_max)) || (!isNumeric(pre_min))) {
pre_max = pre_max_old;
pre_min = pre_min_old;
}
yrange.set('start', pre_min);
yrange.set('end', pre_max);
// This is what I tried. When using these variables, I passed them in the CustomJS args dict, of course.
//yrange_other1.trigger('change');
//yrange_other2.trigger('change');
//xrange_other1.trigger('change');
//xrange_other2.trigger('change');
//soure_other1.trigger('change');
//soure_other2.trigger('change');
"""
我使用的是python 2.7.10和Bokeh版本0.12.3。