Update value using dropdown widget

import pandas as pd
import numpy as np
import matplotlib.colors as pltc

from pymongo import MongoClient

from datetime import timedelta
from datetime import datetime
import yaml

from bokeh.themes import Theme
from bokeh.io import show, output_notebook
from bokeh.plotting import figure, output_file, show
from bokeh.models import ColumnDataSource
from bokeh.models.tools import HoverTool
from bokeh.models.widgets import Panel
from bokeh.models.widgets import Tabs
from bokeh.models import Slider
from bokeh.models import Legend, FixedTicker
from bokeh.io import curdoc
from bokeh.layouts import widgetbox
import bokeh.palettes
from bokeh.layouts import column, row


client = MongoClient('mongodb://localhost')
db = client['test']
dataUsage = db.deviceDataUsage

d1 =[]
for usage in dataUsage.find({'appDataUsageModels':{'$exists':True,'$ne' : None}},{"_id": 0,'deviceDUDay':1,"activationCode":1,"deviceId":1,'appDataUsageModels':1}):

device = []

for i,v in enumerate(d1):
        for j in d1[i]['appDataUsageModels']:
            app = {}
            app['deviceDUDay'] = d1[i]['deviceDUDay']
            app['appName'] = j['appName']
            app['appBGDU'] = j['appBGDU']
            app['appFGDU'] = j['appFGDU']
            app['deviceId'] = d1[i]['deviceId']

    except KeyError:

df = pd.DataFrame(device)
df['deviceDUDay'] =  pd.to_datetime(df['deviceDUDay'])

d = 30
right_now = datetime.now()
glanceback = timedelta(days=d)
one = right_now - glanceback

a2 = right_now.strftime("%m-%d-%Y")
a1 = one.strftime("%m/%d/%Y")
df = df[a1: a2]

dfo = df.groupby(['deviceDUDay', 'deviceId']).sum()/1000000000
dfo['totalDataUsage'] = dfo['appBGDU']+dfo['appFGDU']
dfo = round(dfo.drop(columns =['appBGDU', 'appFGDU']),2)

df_device = df.groupby(['deviceId']).sum()/1000000000
df_device = df_device.reset_index()
df_device['totalDataUsage'] = df_device['appBGDU']+df_device['appFGDU']
df_device = df_device.drop(columns =['appBGDU', 'appFGDU'])

dfo = dfo.unstack()

dfo.columns = dfo.columns.droplevel()
dfo = dfo.fillna(0)

df_device = df_device.sort_values('totalDataUsage', ascending = False)

col = list(df_device['deviceId'])
ind = list(dfo.index)
source = ColumnDataSource(data=dfo)
all_colors = [k for k,v in pltc.cnames.items()]
colors = all_colors[:numlines]

legend_it = []
p = figure(width=1250, height=1100, x_axis_type="datetime", title="Monthly Data Usage", title_location='above')
p.xaxis.axis_label = 'Date Range'
p.yaxis.axis_label = 'Data Used'

for (cl, color) in zip(col, colors):
    c = p.line(x='deviceDUDay', y=cl, line_width=2, alpha=0.8, source=source, color = color )
    legend_it.append((cl, [c]))
            tooltips=[('datetime','@deviceDUDay{%Y-%m-%d}'),(cl, f'@{cl}')],
            formatters={'deviceDUDay': 'datetime'}))
# p.add_tools(crosshair)
legend = Legend(items=legend_it, location=(300, 0), spacing = 5)
p.add_layout(legend, 'right')

p.legend.label_text_font_size = '10px'

menu = Select(options=['30', '60', '90'], value='30', title='days')

def callback(attr, old, new):
    d = menu.value

menu.on_change('value', callback)

layout = column(menu, p)

In the above code I am trying to update the value of variable d(which default to 30) in line 55 using the dropdown widget. When we change the value of d, the dataframe slices based on its value.
Do I need to update the columndatasource as well in the callback function of the widget?

All I want is when I change the days, i.e., the d value, I want the plot to be updated as well. Please any help would be appreciated. Thank You!

Do I need to update the columndatasource as well in the callback function of the widget?

Of course. Right now, you just change a single variable’s value. But you also need to recompute everything that depends on d (so you probably want to avoid statements like df = df[a1: a2] that overwrite variables), including the data attribute of all relevant instances of ColumnDataSource.