Hi guys,
for a university project I use bokeh to visualize patient samples and color them to their corresponding class. the data frame “data” consists of a x, y, color, id (called here “patient”) and class (called here “subgroup”) column:
dimGrey = "#696969" # Used for "Marked" subgroup
[...]
s1 = ColumnDataSource(data)
p1 = figure(tools="lasso_select, wheel_zoom, box_zoom, reset", tooltips=tooltips, title="Interactive Plot for selecting ({}) ".format(names[i]))
p1.circle('x', 'y', source=s1, alpha=0.7, color=plotColors, legend_group='label')
# Initial approach
p1.circle([], [], color='dimGrey', legend_label="Marked")
[...]
p1.add_layout(p1.legend[0], 'right')
# You can ignore t2 and savebutton for that problem
grid = gridplot([[p1, t2], [text_input, savebutton]], sizing_mode='stretch_both')
show(grid)
The result is as expected:
I included a text input widget which takes a list of id’s and colors all given samples to grey (ignore s2 and t2 those are for a different purpose):
text_input = TextInput(value="", title="Patients to mark:", sizing_mode='fixed')
text_input.js_on_change("value", CustomJS(args=dict(s1=s1,s2=s2,t2=t2), code="""
var d1 = s1.data;
var d2 = s2.data;
var numPatients = d1['patient'].length;
var val = this.value.toString().trim();
var tokens = val.split(/\s*,\s*/);
for (var w = 0; w < tokens.length; w++){
for (var i = 0; i < numPatients; i++) {
if (tokens[w] == d1['patient'][i]){
d1['color'][i] = '#696969'; #thats the grey color mentioned
d1['subgroup'][i] = 'Marked';
for (var j = 0; j < d2['patient'].length; j++){ #ignore this, d2 is used for a seperate table
if(tokens[w] == d2['patient'][j]){
d2['subgroup'][j] = 'Marked';
}
}
}
}
}
s1.change.emit();
t2.change.emit();
"""))
My ultimate goal is to add an legend item with the label “Marked” as soon as atleast one samples is colored grey via the text input and to delete the legend item as soon as the marked sample is reseted to it’s original color (I already implemented the reset feature).
I initially tried to implemented a simplified version by adding the extra legend item permanently (which would be fine for now) but it looks like that legend items need a corresponding sample to visualize the colored circle (there is non in the above image for “Marked”), which aren’t their for the marked subgroup at the beginning. So I did the following: Added a pseudo sample with the subgroup/class “Marked” and color “dimGrey” and just put it far away from the other samples and adjusted the ranges of the plot, so the pseudo sample is not seen. With legend_group=‘label’ a correct legenditem is created but I don’t like this solution. With the tool hover wheel you can simply zoom out and see the pseudo sample if you zoom out enough. The code above is my inital approach, not the version with the pseudo sample.
Any ideas how to solve this elegantly?
Thanks in advance.
Peddy