On Jul 29, 2018, at 15:04, Robert Deng <[email protected]> wrote:
Thank you Bryan, you are a Godsend
For now, I'm going to continue with the JS standalone route. Would you or anyone help me as I have the code that should theoretically work, but there's a small disconnect?
I start plotting my gmaps image and creating a widget for multi_select. I create tooltip_values as the metric values that pass into hover tooltip. I mask it in a ColumnDataSource function because the callback function likes it in a Dict(String, Instance(Model)) format. (I'm open to a slicker way to skip the CDS function). Note that source is used as a list comprehension for the actual tooltips with labels and values. It's also first defined, and used only once right after within the tooltip values.
I make the callback JS function by taking in source2 and multi_select values, and simply replace the source2 values with the selected values. The console logs show that the values check out. Apparently, source values are only updating correctly within the JS, but not back out to hover tooltip's source. Do I need to call a function to replot within after the initial JS callback?
import pickle
import numpy as np
import pandas as pd
import geopandas as gpd
import bokeh
from bokeh.io import output_notebook, show
from bokeh.plotting import figure
from bokeh.models import ColumnDataSource, HoverTool, LogColorMapper, GMapOptions, GMapPlot, Patches, HoverTool, CustomJS
from bokeh.palettes import YlGn as palette
from bokeh.layouts import Column, widgetbox, Row
from bokeh.models.widgets import Slider, Button, CheckboxButtonGroup, CheckboxGroup, TableColumn, Panel, DataTable, DateFormatter, TableColumn, MultiSelect, Select
from bokeh.io import output_file, show, curdoc, save
from bokeh.plotting import gmap
from shapely.geometry import Polygon, Point
import matplotlib.pyplot as plt
from matplotlib.pyplot import *
from gmplot import gmplot
palette = palette[9]
palette.reverse()
color_mapper = LogColorMapper(palette=palette)
%matplotlib inline
output_file("combinedplot.html")
map_options = GMapOptions(lat=32.88, lng=-118.460745, map_type="roadmap", zoom=8)
#Gmaps API key: Use API Keys | Maps JavaScript API | Google for Developers
p = gmap("YOUR_OWN_KEY", map_options, title="CA Kelp Areas - Big Squares, Combined Data", height = 600, width = 600)
source = ColumnDataSource(data=dict(
x = xs,
y = ys,
kelp = biomass_kg,
bathymetry = water_depth_m,
sst = sst,
species = species,
critical_species_distance = critical_species_distance,
county = county,
county_distance = county_distance,
pretected_areas = pretected_areas,
pretected_areas_distance = pretected_areas_distance,
estab = estab,
avg_emp = avg_emp,
qcew = qcew,
unemployment = unemployment,
ndvi = ndvi,
min_light = min_light,
mixed_l = mixed_l,
floor_temp = floor_temp,
viable = viable,
boat_launches = boat_launches,
boat_launches_distance = boat_launches_distance,
shoretype = shoretype,
shoretype_distance = shoretype_distance,
shoretype2 = shoretype2,
shoretype2_distance = shoretype2_distance,
aerial_kelp = aerial_kelp,
admin_kelp = admin_kelp))
patched = Patches(xs="x", ys="y", fill_color= {"field": "kelp", "transform":color_mapper},
fill_alpha=0.8, line_color = "white", line_width = 0.7)
p.add_glyph(source, patched)
tooltip_values = ['@kelp',
'@bathymetry',
'@sst',
'@species',
'@species_distance',
'@county',
'@county_distance',
'@pretected_areas',
'@pretected_areas_distance',
'@estab',
'@avg_emp',
'@qcew',
'@unemployment',
'@ndvi',
'@min_light',
'@mixed_l',
'@floor_temp',
'@viable',
'@boat_launches',
'@boat_launches_distance',
'@shoretype',
'@shoretype_distance',
'@shoretype2',
'@shoretype2_distance',
'@aerial_kelp',
'@admin_kelp']
source2 = ColumnDataSource(data = dict(value = tooltip_values))
p.add_tools(HoverTool(tooltips=[(i.replace("@", ""), i) for i in source2.data["value"]]))
multi_select = MultiSelect(title="Metrics Hover:",
value=["@kelp"],
options=tooltip_values)
callback_m = CustomJS(args=dict(source2=source2, multi_select=multi_select), code="""
var tt = source2.data.value;
console.log("tt", tt)
var value = cb_obj.value;
console.log("ms value", value)
tt = value;
console.log("post change", tt)
console.log("source2 emitting", source2)
source2.change.emit();
""")
multi_select.js_on_change('value', callback_m)
show(Column(multi_select, p))
On Sunday, July 29, 2018 at 1:04:40 PM UTC-7, Bryan Van de ven wrote:
Hi,
By calling show, you are creating a standalone HTML/JS document that is not connected to any persistent python process. So there is nothing to run your Python update callback. Use of real python callbacks requires running on the Bokeh server (that is the purpose of the Bokeh server, to be the thing that runs real Python callbacks). You can find more information about the bokeh server here:
Bokeh server — Bokeh 3.3.2 Documentation
If you don't want to use the Bokeh server then you will be limited to CustomJS callbacks, which only execute JavaScript code in the browser.
Thanks,
Bryan
> On Jul 29, 2018, at 12:56, deng....@gmail.com wrote:
>
> Hi Bokeh Community,
>
> Originally, I'm trying to create a multi-select widget with metrics options to toggle on the hover over on a gmap plot. I was inspired by this:
> Redirecting to Google Groups
>
> I follow the examples pretty much function by function with the exception of curdoc as I'm just trying to show a working example and not add to a bokeh server (?) I'm not sure if that has any bearing on this situation. Basically it plots and the values are read in well, but I don't think the javascript is working beneath it.
>
> Hopefully this loads for you guys, if anything breaks, lmk. Would really appreciate this as I'm doing this for a big graduating project for my masters!
>
> Here's my code
> import pickle
> import numpy as np
> import pandas as pd
> import geopandas as gpd
>
> import bokeh
> from bokeh.io import output_notebook, show
> from bokeh.plotting import figure
> from bokeh.models import ColumnDataSource, HoverTool, LogColorMapper, GMapOptions, GMapPlot, Patches, HoverTool, CustomJS
> from bokeh.palettes import YlGn as palette
> from bokeh.layouts import Column, widgetbox, Row
> from bokeh.models.widgets import Slider, Button, CheckboxButtonGroup, CheckboxGroup, TableColumn, Panel, DataTable, DateFormatter, TableColumn, MultiSelect, Select
> from bokeh.io import output_file, show, curdoc, save
> from bokeh.plotting import gmap
> from shapely.geometry import Polygon, Point
> import matplotlib.pyplot as plt
> from matplotlib.pyplot import *
> from gmplot import gmplot
> palette = palette[9]
> palette.reverse()
> color_mapper = LogColorMapper(palette=palette)
> %matplotlib inline
>
> df = pickle.load(open("pickles/grid_df.pkl", "rb"))
> df.drop(["halibut_trawl_sites", "marinas", "oil_platforms", "piers"], axis = 1, inplace = True)
>
> #Convert columns to lists for column data source
> xs = [df["geometry"][i].exterior.xy[0].tolist() for i in range(df.shape[0])]
> ys = [df["geometry"][i].exterior.xy[1].tolist() for i in range(df.shape[0])]
> biomass_kg = df.biomass.tolist()
> water_depth_m = df.depth.tolist()
> sst = df.mean_sst.tolist()
> species = [df.critical_species[i][0][1] for i in range(df.shape[0])]
> critical_species_distance = [df.critical_species[i][0][2] for i in range(df.shape[0])]
> county = [df.county[i][0][1] for i in range(df.shape[0])]
> county_distance = [df.county[i][0][2] for i in range(df.shape[0])]
> pretected_areas = [df.pretected_areas[i][0][1] for i in range(df.shape[0])]
> pretected_areas_distance = [df.pretected_areas[i][0][2] for i in range(df.shape[0])]
> estab = [df.nes_estab_pct[i][0][1] for i in range(df.shape[0])]
> estab_perc = [df.nes_estab_pct[i][0][2] for i in range(df.shape[0])]
> avg_emp = [df.annual_avg_emplvl[i][0][1] for i in range(df.shape[0])]
> avg_emp_perc = [df.annual_avg_emplvl[i][0][2] for i in range(df.shape[0])]
> qcew = [df.qcew_emp_pct[i][0][1] for i in range(df.shape[0])]
> qcew_perc = [df.qcew_emp_pct[i][0][2] for i in range(df.shape[0])]
> unemployment = [df.unemployment_rate[i][0][1] for i in range(df.shape[0])]
> ndvi = df.ndvi.tolist()
> min_light = df.z_min_light.tolist()
> mixed_l = df.z_mixedl.tolist()
> floor_temp = df.floor_temp.tolist()
> viable = df.viable.tolist()
> boat_launches = [df.boat_launches[i][0][1] for i in range(df.shape[0])]
> boat_launches_distance = [df.boat_launches[i][0][2] for i in range(df.shape[0])]
> shoretype = [df.shoretype[i][0][1] for i in range(df.shape[0])]
> shoretype_distance = [df.shoretype[i][0][2] for i in range(df.shape[0])]
> shoretype2 = [df.shoretype2[i][0][1] for i in range(df.shape[0])]
> shoretype2_distance = [df.shoretype2[i][0][2] for i in range(df.shape[0])]
> aerial_kelp = [df.aerial_kelp[i][0][2] for i in range(df.shape[0])]
> admin_kelp = df.admin_kelp_bed.tolist()
>
> #Gmap plotting - I'm hiding my google api key, but you could easily get one here: Use API Keys | Maps JavaScript API | Google for Developers
>
> def create_plot():
> p = gmap("YOUR_OWN_GOOGLE_API_KEY", map_options, title="Combined Data", height = 600, width = 600)
>
> source = ColumnDataSource(data=dict(
> x = xs,
> y = ys,
> kelp = biomass_kg,
> bathymetry = water_depth_m,
> sst = sst,
> species = species,
> critical_species_distance = critical_species_distance,
> county = county,
> county_distance = county_distance,
> pretected_areas = pretected_areas,
> pretected_areas_distance = pretected_areas_distance,
> estab = estab,
> avg_emp = avg_emp,
> qcew = qcew,
> unemployment = unemployment,
> ndvi = ndvi,
> min_light = min_light,
> mixed_l = mixed_l,
> floor_temp = floor_temp,
> viable = viable,
> boat_launches = boat_launches,
> boat_launches_distance = boat_launches_distance,
> shoretype = shoretype,
> shoretype_distance = shoretype_distance,
> shoretype2 = shoretype2,
> shoretype2_distance = shoretype2_distance,
> aerial_kelp = aerial_kelp,
> admin_kelp = admin_kelp))
>
> v = ms.value
> patched = Patches(xs="x", ys="y", fill_color= {"field": "kelp", "transform":color_mapper},
> fill_alpha=0.8, line_color = "white", line_width = 0.7)
> p.add_glyph(source, patched)
> tooltip_ms = [(x.replace("@", ""), x) for x in v]
> p.add_tools(HoverTool(tooltips=tooltip_ms))
> return p
>
> def update(attribute, old, new):
> l.children[1] = None
> l.children[1] = create_plot()
>
> #Help! Still won't update
> ms.on_change('value', update)
> l = Column(ms, create_plot())
> show(l)
>
>
>
>
>
> --
> You received this message because you are subscribed to the Google Groups "Bokeh Discussion - Public" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to bokeh+un...@continuum.io.
> To post to this group, send email to bo...@continuum.io.
> To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/602d6872-60fa-4739-9691-81c8ed066923%40continuum.io\.
> For more options, visit https://groups.google.com/a/continuum.io/d/optout\.
> <grid_df.pkl>
--
You received this message because you are subscribed to the Google Groups "Bokeh Discussion - Public" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/86c40ff0-2c68-4bcf-b550-831489e02ce6%40continuum.io\.
For more options, visit https://groups.google.com/a/continuum.io/d/optout\.