How to Access Multiple dynamic number of data sources passed via args in CustomJS?

Hello,

I’m learning Bokeh and have some issues trying to access args dict from CustomJS code. I’m working with a Bokeh plot that involves multiple ColumnDataSource objects. I need to dynamically access these data sources within a CustomJS callback, but the number of sources and variable names of these sources can vary.
(The code below is the extension of the solution I found in community regarding hover tool dynamic fields.)
https://discourse.bokeh.org/t/hover-tool-dynamic-fields/9513

from bokeh.layouts import column
from bokeh.plotting import figure, curdoc, show
from bokeh.models import ColumnDataSource, HoverTool, CustomJSHover, CustomJS

import numpy as np

data = {
	"x": [1,2,3,4],
	"y": [1,2,3,4],
	"extra_info": ["abc", None, None, 'cba'],
}
data2 = {
	"x": [5,4,6,5],
	"y": [1,2,3,4],
	"extra_info": ["abc", None, None, 'cba'],
}


TOOLTIPS = [[
    ("x", "@x"),
    ("y", "@y"),
], [
    ("x", "@x"),
    ("y", "@y"),
    ("extra_info", "@extra_info"),
]]

src = ColumnDataSource(data=data)
src1 = ColumnDataSource(data=data2)
data_sources = {"data": src, "data2": src1} #it is currently static dict but expected to be dynamic 
f = figure()
r = f.scatter(x='x',y='y', source=src)
r1 = f.scatter(x='x', y='y', source=src1)
r_list = [src, src1]
hvr = HoverTool()
#create args dict to parse to CustomJS
customjs_arg = dict(hover_tool=hvr, tooltips=TOOLTIPS)
properties_data = list(data_sources.keys())
#update args dict with dynamic data_sources dict
for key, v in data_sources.items():
    customjs_arg[key] = v
customjs_arg.update(dict(properties_data=properties_data))
dynamic_hover_tooltips = CustomJS(args=customjs_arg,code='''
               let tooltips_to_use = tooltips[0];  // Default tooltip
                for (let i = 0; i < properties_data.length; i++) {
                    let source_name = properties_data[i];
                  let source = this.properties.args._value.source_name
                    console.log(this.properties.args._value.source_name)
                if (source.inspected.indices.length > 0) {
                    let index = source.inspected.indices[0];

                    // Check if the 'extra_info' field exists and is not null
                    if (source.data['extra_info'][index] != null) {
                        tooltips_to_use = tooltips[1];  // Use the tooltip with "Path"
                        break;  // Exit loop if condition met
                    }
                }
            }

            // Update the hover tool's tooltips
            hover_tool.tooltips = tooltips_to_use
              ''')

hvr.callback = dynamic_hover_tooltips
f.add_tools(hvr)

show(f)

The source code above is a simplified version of what I’m working on. The data_sources is expected to have a dictionary of multiple key-value pair of ColumnDataSources which can varies.

Is there anyway to access args dict in CustomJS code? I’ve tried to use ‘this.properties.args._value.source_name’ but it does not work

Thanks in advance

Everything from the Python-side args dict is dumped into a named variable in code on the JS side. So the short answer, is no, there is no way to access the args dict itself in the JS code.

However there is no reason you can’t pass another dict, e.g. the data_sources you already have, inside the args dict:

args = {"sources": data_sources, ...}

cb = CustomJS(args=args, code='''
    // access sources["some_key"], etc.
''')

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.