I have been mainly working in VS code to create a bokeh dashboard and I now need to get it to run within a Jupyter notebook. I know that some transformations in the code are required to push the code to a Jupyter notebook and for it to update interactively with widgets.
I have referred to this documentation:-
https://docs.bokeh.org/en/latest/docs/user_guide/jupyter.html#userguide-jupyter-notebook
But it is either too simplistic for my code, or that I have not used the push_notebook
commands properly (or both).
Here is the code that I am trying to run in the notebook:-
################################### Code chunk 1##########################
from ipywidgets import interact
import pandas as pd
import numpy as np
import math
from bokeh.models import HoverTool
from bokeh.io import curdoc, output_notebook, push_notebook
from bokeh.plotting import figure, ColumnDataSource
from bokeh.layouts import layout, row, column, gridplot
from bokeh.models.widgets import RangeSlider
#https://discourse.bokeh.org/t/interactive-histograms-not-updating-with-sliders/3779/25
#clustering packages
from operator import index
from bokeh.models.widgets.markups import Div
import numpy as np
from numpy.lib import source
import pandas as pd
from bokeh.io import curdoc
from bokeh.layouts import column, row, gridplot, Column, Row
from bokeh.models import ColumnDataSource, Select, Slider, BoxSelectTool, LassoSelectTool, Tabs, Panel, LinearColorMapper, ColorBar, BasicTicker, PrintfTickFormatter, MultiSelect, DataTable, TableColumn
from bokeh.plotting import figure, curdoc, show
from bokeh.palettes import viridis, gray, cividis, Category20
from bokeh.transform import factor_cmap
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import classification_report, confusion_matrix, mean_squared_error, r2_score, recall_score, f1_score
from sklearn.preprocessing import StandardScaler, PolynomialFeatures
from sklearn.cluster import KMeans
from sklearn.svm import SVC
from sklearn.decomposition import PCA
#tables
from time import time
output_notebook()
################################# Code chunk 2 ###########################################
#define the categorical variable
category_a = ['A','B','C']
category_b = ['X','Y','Z']
print("step 2")
df = pd.DataFrame({
'id': np.arange(0, 100),
'date': pd.date_range(start='1/1/2021', periods=100, freq='D'),
'month':np.random.randint(1, 12, 100),
'sensor_1': np.random.uniform(0, 1,100),
'sensor_2': np.random.uniform(10, 150, 100),
'sensor_3': np.random.randint(0, 90, 100),
'sensor_4': np.random.randint(0, 450, 100),
'sensor_5': np.random.randint(0, 352, 100),
'categorya': np.random.choice(category_a, 100, p=[0.2, 0.4, 0.4]),
'categoryb': np.random.choice(category_b, 100, p=[0.6, 0.2, 0.2]),
})
source = ColumnDataSource(data=df)
################################### Code chunk 3##############################
class hist_data:
def __init__(self, df, col, n_bins, bin_range):
self.sensor1_lwr = min(df['sensor_1'])#duration millisecond
self.sensor1_upr = max(df['sensor_1'])#duration millisecond
self.sensor2_lwr = min(df['sensor_2'])#count watch
self.sensor2_upr = max(df['sensor_2'])#count_watch
self.sensor3_lwr = min(df['sensor_3'])#count idle
self.sensor3_upr = max(df['sensor_3'])#count idle
self.sensor4_lwr = min(df['sensor_4'])#count inter and watch
self.sensor4_upr = max(df['sensor_4'])#count inter and watch
self.sensor5_lwr = min(df['sensor_5'])#count inter
self.sensor5_upr = max(df['sensor_5'])#count inter
self.col = col
self.n_bins = n_bins
self.bin_range = bin_range
self.original_df = df
self.source = ColumnDataSource(self.create_hist_data(df))
def filt_df(self):
filt = (pd.DataFrame(self.original_df[(self.original_df.sensor_1 >=self.sensor1_lwr) &
(self.original_df.sensor_1 <= self.sensor1_upr) &
(self.original_df.sensor_2 >= self.sensor2_lwr) &
(self.original_df.sensor_2 <= self.sensor2_upr) &
(self.original_df.sensor_3 >= self.sensor3_lwr) &
(self.original_df.sensor_3 <= self.sensor3_upr) &
(self.original_df.sensor_4 >= self.sensor4_lwr) &
(self.original_df.sensor_4 <= self.sensor4_upr) &
(self.original_df.sensor_5 >= self.sensor5_lwr) &
(self.original_df.sensor_5 <= self.sensor5_upr)]))
print(f'{self.sensor1_lwr} {self.sensor1_upr} {self.sensor2_lwr} {self.sensor2_upr} {self.sensor3_lwr} {self.sensor3_upr} {self.sensor4_lwr} {self.sensor4_upr} {self.sensor5_lwr} {self.sensor5_upr}')
filt.shape
return ColumnDataSource(self.create_hist_data(filt))
def create_hist_data(self,df):
arr_hist, edges = np.histogram(df[self.col],bins=self.n_bins, range=self.bin_range)
arr_df = pd.DataFrame({'count': arr_hist, 'left': edges[:-1], 'right': edges[1:]})
arr_df['f_count'] = ['%d' % count for count in arr_df['count']]
arr_df['f_interval'] = ['%d to %d ' % (left, right) for left, right in zip(arr_df['left'], arr_df['right'])]
return (arr_df)
df = df
########################histograms
hist_data_A = hist_data(df,'sensor_1',math.floor(math.sqrt(df['sensor_1'].nunique())),[min(df['sensor_1']),max(df['sensor_1'])])
hist_data_B = hist_data(df,'sensor_2',math.floor(math.sqrt(df['sensor_2'].nunique())),[min(df['sensor_2']),max(df['sensor_2'])])
hist_data_C = hist_data(df,'sensor_3',math.floor(math.sqrt(df['sensor_3'].nunique())),[min(df['sensor_3']),max(df['sensor_3'])])
hist_data_D = hist_data(df,'sensor_4',math.floor(math.sqrt(df['sensor_4'].nunique())),[min(df['sensor_4']),max(df['sensor_4'])])
hist_data_E = hist_data(df,'sensor_5',math.floor(math.sqrt(df['sensor_5'].nunique())),[min(df['sensor_5']),max(df['sensor_5'])])
############################slider
A_Slider= RangeSlider(start=min(df['sensor_1']), end=max(df['sensor_1']), value=(min(df['sensor_1']),max(df['sensor_1'])), step=1, title='sensor_1')
B_Slider = RangeSlider(start=min(df['sensor_2']), end=max(df['sensor_2']), value=(min(df['sensor_2']),max(df['sensor_2'])), step=1, title='sensor_2')
C_Slider = RangeSlider(start=min(df['sensor_3']), end=max(df['sensor_3']), value=(min(df['sensor_3']),max(df['sensor_3'])), step=1, title='sensor_3')
D_Slider = RangeSlider(start=min(df['sensor_4']), end=max(df['sensor_4']), value=(min(df['sensor_4']),max(df['sensor_4'])), step=1, title='sensor_4')
E_Slider = RangeSlider(start=min(df['sensor_5']), end=max(df['sensor_5']), value=(min(df['sensor_5']),max(df['sensor_5'])), step=1, title='sensor_5')
def callback_A(attr,new,old):
hist_data_A.sensor1_lwr = new[0]
hist_data_A.sensor1_upr = new[1]
hist_data_A.source = hist_data_A.filt_df()
Graphs1.children[0] = plot_data_A()
push_notebook(handle=grid)
def callback_B(attr,new,old):
hist_data_B.sensor2_lwr = new[0]
hist_data_B.sensor2_upr = new[1]
hist_data_B.source = hist_data_B.filt_df()
Graphs1.children[1] = plot_data_B()
push_notebook(handle=grid)
def callback_C(attr,new,old):
hist_data_C.sensor3_lwr = new[0]
hist_data_C.sensor3_upr = new[1]
hist_data_C.source = hist_data_C.filt_df()
Graphs1.children[2] = plot_data_C()
push_notebook(handle=grid)
def callback_D(attr,new,old):
hist_data_D.sensor4_lwr = new[0]
hist_data_D.sensor4_upr = new[1]
hist_data_D.source = hist_data_D.filt_df()
Graphs2.children[0] = plot_data_D()
push_notebook(handle=grid)
def callback_E(attr,new,old):
hist_data_E.sensor5_lwr = new[0]
hist_data_E.sensor5_upr = new[1]
hist_data_E.source = hist_data_E.filt_df()
Graphs2.children[1] = plot_data_E()
push_notebook(handle=grid)
A_Slider.on_change("value",callback_A)
B_Slider.on_change("value",callback_B)
C_Slider.on_change("value",callback_C)
D_Slider.on_change("value",callback_D)
E_Slider.on_change("value",callback_E)
(df,'sensor_1',df['sensor_1'].nunique(),[min(df['sensor_1']),max(df['sensor_1'])])
(df,'sensor_2',df['sensor_2'].nunique(),[min(df['sensor_2']),max(df['sensor_2'])])
(df,'sensor_3',df['sensor_3'].nunique(),[min(df['sensor_3']),max(df['sensor_3'])])
(df,'sensor_4',df['sensor_4'].nunique(),[min(df['sensor_4']),max(df['sensor_4'])])
(df,'sensor_5',df['sensor_5'].nunique(),[min(df['sensor_5']),max(df['sensor_5'])])
# Histogram
def interactive_histogram( hist_data, title,x_axis_label,x_tooltip):
source = hist_data
# Set up the figure same as before
toollist = ['lasso_select', 'tap', 'reset', 'save','crosshair','wheel_zoom','pan','hover','box_select']
p = figure(plot_width = 400,
plot_height = 400,
title = title,
x_axis_label = x_axis_label,
y_axis_label = 'Count',tools=toollist)
# Add a quad glyph with source this time
p.quad(bottom=0,
top='count',
left='left',
right='right',
source=source,
fill_color='red',
hover_fill_alpha=0.7,
hover_fill_color='blue',
line_color='black')
# Add style to the plot
p.title.align = 'center'
p.title.text_font_size = '18pt'
p.xaxis.axis_label_text_font_size = '12pt'
p.xaxis.major_label_text_font_size = '12pt'
p.yaxis.axis_label_text_font_size = '12pt'
p.yaxis.major_label_text_font_size = '12pt'
# Add a hover tool referring to the formatted columns
hover = HoverTool(tooltips = [(x_tooltip, '@f_interval'),
('Count', '@f_count')])
# Add the hover tool to the graph
p.add_tools(hover)
return p
push_notebook(handle=grid)
#binsize = 10
binzise = 100
def plot_data_A():
A_hist = interactive_histogram(hist_data_A.source, 'sensor_1','sensor_1','sensor_1')
return A_hist
def plot_data_B():
B_hist = interactive_histogram(hist_data_B.source, 'sensor_2','sensor_2','sensor_2')
return B_hist
#
def plot_data_C():
C_hist = interactive_histogram(hist_data_C.source, 'sensor_3','sensor_3','sensor_3')
return C_hist
#
def plot_data_D():
D_hist = interactive_histogram(hist_data_D.source, 'sensor_4','sensor_4','sensor_4')
return D_hist
#
def plot_data_E():
E_hist = interactive_histogram(hist_data_E.source, 'sensor_5','sensor_5','sensor_5')
return E_hist
#
Graphs1 = row([plot_data_A(), plot_data_B(), plot_data_C()])
Graphs2 = row([plot_data_D(), plot_data_E()])
Controls1= column([A_Slider,B_Slider,C_Slider,D_Slider,E_Slider])
#grid = gridplot([[Graphs1],
# [Controls1]])
grid = gridplot([[Controls1,Graphs1],[None,Graphs2]])
show(grid)
But the widgets do not update the plots. Can someone kindly show me what I am missing?