Linking data between patches, slider and vbar plot

I’ve been trying to link a slider and vbar plot to a set of patches on a map. The intention would be to have patches in a plot alongside a vbar chart which could be selected with a linking brush interaction. When bars on the vbar chart are selected I’d like the corresponding patches to be darker, or vice-versa. As the data is also a time series I would like a slider to allow selection of a day in the dataset which would change the vbar and patches.

At the moment I’m hindered by not knowing how to let a geojson data source power all elements. I’ve seen tutorials about this working with a column data source. I’m also not a JS oriented coder and would be interested in advice or examples of it working.

# plot interactively in Bokeh

from bokeh.io import curdoc

from bokeh.layouts import column, gridplot, widgetbox
from bokeh.palettes import brewer

import json

from bokeh.models import (GeoJSONDataSource, HoverTool, LinearColorMapper, 
                          Slider, CDSView, ColorBar, ColumnDataSource, 
                          CustomJS, CustomJSFilter)

from bokeh.plotting import figure

# from bokeh.tile_providers import CARTODBPOSITRON, get_provider

# tile_provider = get_provider(CARTODBPOSITRON)

with open('../geojson/aus_110.json') as aus:
    ausmap = GeoJSONDataSource(geojson=aus.read())
    
with open('./junedata.json') as forchart:
  fc = forchart.read()
  geosource = GeoJSONDataSource(geojson=fc) 

sp_list = ['PL 491', 'PL 183', 'PL 91', 'EP 129 R6', 'PL 444', 'PL 494', 'PL 1085', 'PL 228', 'PL 403', 'PL 67', 'PL 273', 'PL 53', 'PL 266', 'PL 1022', 'PL 219', 'L 20', 'PL 1049', 'PL 436', 'PL 1019', 'PL 81', 'PL 1038', 'PL 1027', 'PL 276', 'PL 492', 'PL 80', 'PL 237', 'control area south of Roma', 'PL 60', 'PL 188', 'PL 61', 'PL 313', 'EP 413 R3', 'PL 116', 'PL 450', 'PL 42', 'PL 469', 'PL 11', 'PL 512', 'PL 90', 'PL 417', 'PL 263', 'EP 426 R1', 'PL 1077', 'PL 34', 'L 8 R1', 'PL 249', 'L 17', 'PL 205', 'PL 68', 'PL 1024', 'PL 49', 'PL 265', 'PL 1', 'PL 209', 'PL 82', 'PL 493', 'PL 278', 'PL 1044', 'PL 323', 'PL 1040', 'PL 66', 'PL 451', 'EP 432 R1', 'PL 318', 'EP 389 R3', 'PL 439', 'PL 152', 'PL 1065', 'PL 316', 'PL 21', 'PL 193', 'PL 474', 'PL 179', 'PL 229', 'PL 272', 'PL 299', 'PL 94', 'PL 1079', 'PL 1023', 'PL 211', 'PL 50', 'PL 397', 'PL 39', 'PL 1010', 'L 19', 'PL 253', 'PL 1020', 'PL 502', 'PL 446', 'PL 30', 'PL 497', 'PL 40', 'PL 95', 'PL 1067', 'PL 43', 'PL 315', 'PL 180', 'PL 234', 'PL 225', 'Control area 2 - W of Gold Coast', 'PL 36', 'PL 513', 'PL 131', 'PL 226', 'PL 408', 'PL 115', 'EP 498', 'PL 213', 'PL 411', 'PL 438', 'PL 216', 'EP 416 R2', 'PL 1064', 'EP 431 R1', 'PL 57', 'PL 89', 'PL 471', 'L 21', 'PL 9', 'PL 184', 'EP 480', 'PL 407', 'PL 233', 'PL 507', 'PL 8', 'PL 288', 'PL 1034', 'PL 63', 'PL 204', 'PL 254', 'PL 220', 'PL 1036', 'PL 1088', 'PL 185', 'PL 98', 'PL 302', 'PL 506', 'PL 154', 'PL 416', 'PL 99', 'PL 140', 'EP 493', 'PL 503', 'PL 15', 'PL 1073', 'PL 1051', 'PL 1089', 'PL 25', 'PL 145', 'PL 187', 'PL 437', 'PL 1016', 'PL 1066', 'PL 136', 'PL 282', 'L 9 R1', 'PL 1030', 'PL 24', 'PL 1061', 'PL 1060', 'PL 214', 'PL 305', 'PL 319', 'PL 92', 'PL 322', 'PL 14', 'PL 155', 'PL 1081', 'PL 54', 'PL 176', 'PL 45', 'PL 1031', 'PL 218', 'PL 88', 'PL 65', 'PL 458', 'PL 1069', 'PL 1026', 'PL 1009', 'PL 1011', 'PL 32', 'PL 79', 'PL 26', 'PL 108', 'Darwin LNG', 'PL 111', 'PL 419', 'PL 1055', 'PL 62', 'PL 22', 'PL 83', 'PL 320', 'PL 508', 'PL 1021', 'PL 399', 'PL 157', 'PL 301', 'PL 23', 'PL 132', 'PL 495', 'PL 1071', 'PL 413', 'PL 169', 'PL 1059', 'PL 101', 'PL 485', 'PL 147', 'PL 505', 'Control Point 4 - S of Darwin LNG', 'EP 428 R1', 'PL 6', 'PL 279', 'PL 27', 'PL 482', 'PL 406', 'PL 1056', 'PL 398', 'PL 470', 'PL 223', 'PL 52', 'PL 51', 'PL 227', 'PL 177', 'PL 420', 'PL 1076', 'PL 93', 'EP 481', 'PL 153', 'PL 295', 'PL 158', 'EP 494', 'PL 1033', 'PL 415', 'PL 1047', 'PL 142', 'PL 441', 'PL 129', 'EP 440 R1', 'PL 146', 'PL 464', 'PL 75', 'PL 148', 'PL 496', 'PL 1048', 'PL 1037', 'PL 510', 'PL 1028', 'PL 78', 'PL 297', 'PL 143', 'PL 1062', 'PL 405', 'PL 268', 'PL 3', 'PL 418', 'PL 1075', 'PL 71', 'PL 244', 'PL 77', 'PL 48', 'PL 69', 'PL 100', 'PL 324', 'PL 28', 'PL 1014', 'PL 509', 'PL 231', 'PL 141', 'PL 195', 'L 18', 'PL 484', 'PL 1057', 'PL 314', 'PL 200', 'EP 391 R3', 'PL 224', 'PL 1087', 'PL 35', 'PL 412', 'PL 156', 'L 6 R1', 'PL 1046', 'PL 414', 'PL 202', 'PL 1078', 'PL 85', 'PL 303', 'PL 498', 'EP 371 R2', 'PL 235', 'PL 421', 'EP 408 R2', 'PL 321', 'PL 38', 'PL 59', 'PL 1012', 'PL 1032', 'PL 1013', 'PL 1050', 'PL 445', 'PL 1017', 'PL 281', 'PL 1084', 'PL 267', 'PL 192', 'PL 33', 'PL 212', 'PL 134', 'PL 17', 'PL 440', 'PL 1070', 'PL 133', 'PL 18', 'PL 264', 'PL 511', 'PL 41', 'PL 1072', 'EP 447 R1', 'EP 496', 'PL 29', 'PL 317', 'PL 1035', 'PL 1008', 'EP 457 R1', 'PL 245', 'PL 170', 'PL 76', 'PL 457', 'PL 137', 'PL 467', 'PL 232', 'PL 12', 'EP 104 R6', 'PL 442', 'PL 196', 'EP 436 R1', 'PL 1029', 'PL 435', 'PL 159', 'PL 1068', 'PL 1082', 'PL 191', 'PL 1083', 'PL 434', 'PL 277', 'PL 304', 'PL 44', 'PL 194', 'PL 110', 'PL 114', 'PL 275', 'Blacktip Single Point Mooring (SPM) Condensate Export Buoy', 'PL 1045', 'EP 458 R1', 'PL 86', 'PL 247', 'PL 31', 'PL 466', 'PL 401', 'PL 46', 'PL 2', 'EP 487', 'PL 58', 'PL 404', 'PL 236', 'PL 215', 'PL 138', 'PL 201']

palette = brewer['YlOrRd'][7]
palette = palette[::-1]

color_mapper = LinearColorMapper(palette = palette, low = 1700, high = 1900)
tick_labels = {'1700':'1700', 
              '1730':'1730', 
              '1760':'1760',
              '1800':'1800', 
              '1830':'1830', 
              '1860':'1860', 
              '1900':'1900'}

color_bar = ColorBar(color_mapper = color_mapper, 
                    label_standoff = 8,
                    width = 500, height = 20,
                    border_line_color = None,
                    location = (0,0),
                    orientation = 'horizontal', 
                    major_label_overrides = tick_labels
                    )

tools = ['box_select, lasso_select', 'tap', 'pan', 'reset']
ttips = [('Name', '@sample_point')]

map_ = figure(background_fill_color="white", tools=tools)
# map_.add_tile(tile_provider)

map_.xgrid.grid_line_color=None
map_.ygrid.grid_line_color=None

bg = map_.patches('xs', 'ys', 
            source=ausmap,
            fill_color = '#f5f5f5',
            line_width=0.25,
            line_color = None,
            fill_alpha = 1
              )

slider = Slider(title = 'Day', 
              start = 1, end = 30, 
              step = 1, value = 1)


# This callback triggers the filter when the slider changes
callback = CustomJS(args = dict(source=geosource), 
                    code = """source.change.emit();""")

slider.js_on_change('value', callback)

# Creates custom filter that selects the rows of the month based on the value in the slider
custom_filter = CustomJSFilter(args = dict(slider = slider, 
                                          source = geosource), 
                              code = """
                                    console.log(source.get_length())
                                    var indices = [];
                                    // iterate through rows of data source and see if each satisfies some constraint
                                    for (var i = 0; i < source.get_length(); i++){
                                    if (source.data[‘day’][i] == slider.value){
                                    indices.push(true);
                                    } else {
                                    indices.push(false);
                                    }
                                    }
                                    return indices;
                                    """)

# Uses custom_filter to determine which set of sites are visible
view = CDSView(source = geosource, filters = [custom_filter])

pls = map_.patches("xs", "ys", 
            source=geosource,
            fill_color = {'field': 'max', 
                    'transform': color_mapper},
                    view=view)

varis = figure(background_fill_color="white", tooltips=ttips, 
              tools=tools, width = 1200, height = 400, x_range=sp_list)

varis.vbar(width=0.5, bottom=1750, x='sample_point',
          top='max', source=geosource,
                    view=view)

# map_.add_tools(HoverTool(renderers = [bg], 
#                      tooltips = [('Name', '@STATE_NAME')]))

map_.add_tools(HoverTool(renderers = [pls], 
                    tooltips = [('Name', '@Name'), 
                                ("Max PPB: ", "@max"), 
                                ("Day: ", "@day")]))

map_.add_layout(color_bar, 'above')

p = gridplot([[column(slider)], [map_], [varis]])

curdoc().add_root(p)