Search code examples
pythonbokeh

Bokeh highlight values in second plot and show data table


I have two plots and a data table. I want to select a value in plot 1 and then the corresponding value of plot two should be highlighted in plot 2. In addition I would like to show a data table under both plots with the selected values. Here is what I have so far:

from bokeh.plotting import figure
from bokeh.models import ColumnDataSource
from bokeh.io import show
import numpy as np
import pandas as pd
from bokeh.layouts import row
from bokeh.models.widgets import DataTable, TableColumn


df2 = pd.DataFrame(np.array([[1, 3.280, 3.3925], [2, 3.3012, 3.4303], [3, 3.5972, 3.8696]]),
                   columns=['abspos', 'val1', 'val1_q'])

source = ColumnDataSource(data=df2)

p1 = figure(title="Plot1",
            plot_width=1500,
            plot_height=900,
            x_range=[0, 5],
            y_range=[0, 5])

p1.circle('abspos', 'val1', source=source, line_color=None, color='red', size=6)

pq1 = figure(title="Plot2",plot_width=900, plot_height=900)
pq1.circle('val1_q', 'val1', source=source, line_color=None, size=6)

columns = [
        TableColumn(field="abspos", title="abspos"),
        TableColumn(field="val1", title="val1"),
        TableColumn(field="val1_q", title="val1_q")
    ]
data_table = DataTable(source=source, columns=columns, width=300, height=280)


def plot_both(plot1, plot2):
    show(row(plot1, plot2))
    
    
plot_both(p1, pq1)

If I select the data point [2, 3.3012] in plot 1, the data point [3.3012, 3.4303] should be highlighted in plot 2. The data table underneath should show [2, 3.3012, 3.4303].

Question 1: How to achieve a highlight in plot 2 according to selected point in plot 1 (and vice versa).

Question 2: How to display a Table under both plots which shows the data of the selected data points.


Solution

  • The simplest way would be to use the tap tool (code below works for Bokeh v2.1.1)

    from bokeh.plotting import show, figure
    from bokeh.models import ColumnDataSource, Row, Column, CustomJS, DataTable, TableColumn
    import numpy as np
    import pandas as pd
    
    df2 = pd.DataFrame(np.array([[1, 3.280, 3.3925], [2, 3.3012, 3.4303], [3, 3.5972, 3.8696]]),
                       columns=['abspos', 'val1', 'val1_q'])
    
    source = ColumnDataSource(data=df2)
    
    p1 = figure(title="Plot1",plot_width=900, plot_height=500, tools="tap,pan,box_zoom,wheel_zoom,save,reset")
    p1.circle('abspos', 'val1', source=source, line_color=None, color='blue', size=10)
    
    p2 = figure(title="Plot2",plot_width=900, plot_height=500, tools="tap,pan,box_zoom,wheel_zoom,save,reset")
    p2.circle('val1_q', 'val1', source=source, line_color=None, color='blue', size=10)
    
    columns = [
            TableColumn(field="abspos", title="abspos"),
            TableColumn(field="val1", title="val1"),
            TableColumn(field="val1_q", title="val1_q")
        ]
    dt1 = DataTable(source=source, columns=columns, width=900, height=300)
    dt2 = DataTable(source=source, columns=columns, width=900, height=300)
    
    show(Column(Row(p1, p2), Row(dt1, dt2)))
    

    If you need more functionality you would need to add a JS callback like p1.js_on_event('tap', CustomJS(args={...}, code="..."))