Overloading of terms is a common and often-discussed situation for software in general. The select
method is for selecting objects out of the Bokeh document object-graph. The selected
property records UX selections on plots. They both, for better or worse, relate to “selections”, just in different contexts.
I don’t understand what “Hit testing” means?
Hit-testing is a check for geometric intersection:
- Does a single point (e.g. coordinate of a mouse tap) intersect with any vbar glyphs?
- Does a rectangle (e.g. drawn by a box-select tool) intersect with any scatter plot markers?
- Does a polygon (e.g. drawn by a lasso-select tool) intersect with patches glyphs?
Etc. And if there is an intersection, what are the indices of the specific things that were “hit”? As a concrete example: If I draw 200 circles and tap-tool click on the 117th one, then the selection is the list [117]. If I lasso tool draw around thirty scatter points, then the selection is a list with those thirty indices.
Now, not all glyphs support every kind of hit testing. That might be because it doesn’t make sense at all for some combinations, or because there is just not enough interest to justify the effort, or as I mentioned above, because there are open questions about the best approach. Lines currently only support “point” hit testing (“tap tool”) and “span” hit testing (there is no span selection tool, but hover tools can be configured with a “vline” or “hline” mode that uses span hit-testing).
However, finally, and importantly for you: Lines are special and different. Almost all bokeh glyphs, e.g. scatter markers, bars, patches, etc. are all “vectorized”. You supply a table of 200 data coordinates and you get 200 circles drawn, and each of those can be selected individually or in groups. But line glyphs are not like that at all, in a very fundamental way. A line has a connected topology. You give 200 data coordinates, but only have one single line as a result. That means line selections don’t (can’t) fit neatly in the scheme I described above.
When a tap tool “hits” a line, regardless of which point, it has to record that the entire line glyph as a whole is selected. However, it also reports the nearest points in the line in line_indices
. It does this because this is often useful information to report to callbacks. But for lines specifically, setting line_indices
is not sufficient to programmatically trigger a visual selection “on the entire line”. When you set line_indices = [0]
that does not mean select the “first line”. When a given Line
glyph renders, there is just the one line, so line_indices = [0]
means the first point of that one line. That is not what will cause a “visual” selected appearance for an entire line.
FWIW, I was also specific and careful about this in my wording above:
Selection.line_indicies
are set when a point or span hit-test is registered.
i.e., it works in one direction (UX selection on a line → Bokeh sets line_indices
for you), but not in the opposite direction. Instead you would need to set the selected.selected_glyph
property to be the line glyph model. That is what indicates that the “entire line” is selected, as can be seen in the actual code that checks for this:
Selecting lines programmatically is not really documented anywhere because:
- it is unavoidably complicated and in the weeds compared to most glyphs, and
- without any exaggeration, you are the very first person to ever ask about it
In any case, to programatically cause an entire line to display as “visually selected”, the callback should look something like this (untested):
line = plot.line(...)
cb = CustomJS(args=dict(glyph=line.glyph, source=line.data_source), code="""
source.selected.selected_glyph = glyph
""")