Update glyph color from DataTable

Hi guys,

I am really puzzled by the code below. The goal is to plot different quads depending on the rows that are selected in a DataTable. The shapes of the rectangles look perfectly fine, but I can’t understand the behavior of the quad colors that is pretty random — illustrated in some screenshots below.

I would appreciate any enlightenment and work around about this issue.

Cheers.

import bokeh.layouts as bl
import bokeh.models as bm
import bokeh.plotting as bp

data = {"left": [-1, -2, -3], "right": [1, 2, 3], "color": ["red", "green", "blue"]}

source = bm.ColumnDataSource(data)
index_filter = bm.IndexFilter([])
view = bm.CDSView(source=source, filters=[index_filter])

data_table = bm.DataTable(
    source=source,
    height=120,
    columns=[
        bm.TableColumn(field="left", title="Left"),
        bm.TableColumn(field="right", title="Right"),
        bm.TableColumn(field="color", title="Color"),
    ],
)

p = bp.figure(x_range=(-4, 4), y_range=(-1, 1))
r = p.quad(
    bottom=p.y_range.start,
    top=p.y_range.end,
    left="left",
    right="right",
    fill_color="color",
    line_color=None,
    source=source,
    view=view,
)
p.y_range.js_link("start", r.glyph, "bottom")
p.y_range.js_link("end", r.glyph, "top")

callback = bm.CustomJS(
    args={"source": source, "index_filter": index_filter},
    code="""
    index_filter.indices = source.selected.indices;
    source.change.emit();
    """,
)
source.selected.js_on_change("indices", callback)

bp.show(bl.column(data_table, p))

I think you are running in to

Unortunately I don’t have a workaround to suggest at present except to re-work without CDSView (e.g. you could set alpha=1 for selected indices and alpha=0 for unselected indices (either with an explicit alpha column or by actually setting a selection and using selected/nonselected glyph properties)

Thanks for the info. I therefore used a solution with two sources.
Cheers

import bokeh.layouts as bl
import bokeh.models as bm
import bokeh.plotting as bp

data = {"left": [-1, -2, -3], "right": [1, 2, 3], "color": ["red", "green", "blue"]}


source = bm.ColumnDataSource(data)

data_table = bm.DataTable(
    source=source,
    height=120,
    columns=[
        bm.TableColumn(field="left", title="Left"),
        bm.TableColumn(field="right", title="Right"),
        bm.TableColumn(field="color", title="Color"),
    ],
)

quad_data = {"left": [], "right": [], "color": []}
quad_source = bm.ColumnDataSource(quad_data)

p = bp.figure(x_range=(-4, 4), y_range=(-1, 1))
r = p.quad(
    bottom=p.y_range.start,
    top=p.y_range.end,
    left="left",
    right="right",
    fill_color="color",
    line_color=None,
    source=quad_source,
)
p.y_range.js_link("start", r.glyph, "bottom")
p.y_range.js_link("end", r.glyph, "top")

callback = bm.CustomJS(
    args={"source": source, "quad_source": quad_source},
    code="""
    let indices = source.selected.indices;

    for (let field of ["left", "right", "color"]){
        quad_source.data[field] = indices.map(i => source.data[field][i]);
    }
    quad_source.change.emit();
    """,
)
source.selected.js_on_change("indices", callback)

bp.show(bl.column(data_table, p))