简体   繁体   中英

Change plotted data in a figure when x_range of another figure linked to the other one is changed in Bokeh

I have two figures in which data source is linked in Bokeh. The left figure show (x, y) and the right figure shows (v, z) and the other shows (x, y). I want to re-draw the left figure when the x_range of the right figure is changed so that the data points not shown in the right panel are removed from the left panel. I thought I should use a callback feature of Bokeh, but I'm not familiar with it. I tried to write the following code, but it does not work. It would be great if someone tell me how to do it.

import numpy as np

from bokeh.io import output_notebook, show, save, output_file
from bokeh.models import ColumnDataSource, HoverTool, CustomJS
from bokeh.models.formatters import DatetimeTickFormatter
from bokeh.palettes import brewer, all_palettes, viridis
from bokeh.plotting import figure
from bokeh.models import WMTSTileSource
from bokeh.layouts import column, row, gridplot

x = np.random.randn(100)
y = np.random.randn(100)
z = x**2
v = np.exp(-0.5 * x**2)
colors = np.array(viridis(x.size))

source_all = ColumnDataSource(
    data=dict(x=x,
              y=y,
              z=z,
              v=v,
              colors=colors,
              index=np.arange(x.size, dtype=np.int)))

source_plot = ColumnDataSource(
    data=dict(x=x,
              y=y,
              z=z,
              v=v,
              colors=colors))

left = figure(plot_width=300, plot_height=300, title=None, 
              x_range=(-3, 3),
              y_range=(-3, 3),
             tools=['reset', 'save', 'pan', 'wheel_zoom', 'tap', 'box_select'])
left.circle('x', 'y', source=source_plot, color='colors')

right = figure(plot_width=300, plot_height=300, title=None, # x_range=(),
              tools=['reset', 'save', 'pan', 'wheel_zoom', 'tap', 'box_select'])
right.circle('v', 'z', source=source_plot, color='colors')

def callback(left=left, right=right, source=source_plot, source_all=source_all, window=None):

    x_range = right.x_range
    x_range.have_updated_interactively = False

    xmin = x_range[0]
    xmax = x_range[1]

    data = source.data
    data_all = source_all.data

    x, y, z, v, color = data['x'], data['y'], data['z'], data['v'], data['colors']
    xa, ya, za, va, colora = data_all['x'], data_all['y'], data_all['z'], data_all['v'], data_all['colors']

    for i in range(len(v)):
        if v[i] < xmin or v[i] > xmax:
            x[i] = np.nan
            y[i] = np.nan
            z[i] = np.nan
            color[i] = None
        else:
            x[i] = xa[i]
            y[i] = ya[i]
            z[i] = za[i]
            color[i] = colora[i]
    Bokeh.index[left.id].plot_canvas_view.update_dataranges()
    source.change.emit()

callback = CustomJS.from_py_func(callback)


right.x_range.js_on_change('start', callback)

p = gridplot([[left, right]])

show(p)

You could work that with a callback but isn't a lasso_select or box_select doing more or less what you want? 在此处输入图片说明

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM