Streaming Plot Won't Update in Browser

I have a time series setup that should check for a data update every 5 seconds. My issue is the web browser plot does not seem to update from the server callback. I assume I am missing something obvious somewhere.

The file test.txt is the data file and will contain any data updates.

import pandas as pd
from bokeh.plotting import figure, show, ColumnDataSource, output_file
from bokeh.models import ColumnDataSource, HoverTool, WheelZoomTool, BoxAnnotation, Select, CrosshairTool, Span, Range1d
from bokeh.palettes import Spectral3
from bokeh.io import output_notebook, curdoc, reset_output
from bokeh.layouts import column
import numpy as np
reset_output()
output_notebook()

output_file('/home/awips/time_series_update.html')
df = pd.read_csv(('/tmp/app/time_series/data/test.txt'))

def update():
    new_data = pd.read_csv(('/tmp/app/time_series/data/test.txt'))
    result = {'DATE': new_data['DATE'], 'WS': new_data['WS'], 'WSMAX': new_data['WSMAX'], 'P': new_data['P'], 'T': new_data['T'], 'RH': new_data['RH'], 'WD': new_data['WD']}
    print(result)
    source.stream(result, 5)
    print("Check to see if update is working")
    return

df['DATE'] = pd.to_datetime(df['DATE'], format='%Y-%m-%d %H:%M:%S')
df['WS'] = df['WS']*1.94384
df['WSMAX'] = df['WSMAX']*1.94384
                                  
grouped = df.groupby('DATE').sum()
source = ColumnDataSource(grouped)

p1 = figure(x_axis_type='datetime', title='NAM 0-30mb AGL Forecast Wind Speed', plot_width=800, plot_height=400)
p1.y_range=Range1d(0,30)
p1.line(x='DATE', y='WS', line_width=2, source=source, color='black')
p1.triangle(x='DATE', y='WS', size=12, source=source, line_color='black', fill_color='red')
p1.yaxis.axis_label = 'Wind Speed (knots)'
p1.axis.axis_label_text_font_style = "bold"

high_box = BoxAnnotation(bottom=15.0, fill_alpha=0.1, fill_color='red')
p1.add_layout(high_box)


p1.add_tools(HoverTool(show_arrow=True, line_policy='nearest', tooltips=[
    ('Date', '@DATE'),('Wind Speed', '@WS')
]))
p1.add_tools(CrosshairTool())
p1.toolbar.active_scroll = p1.select_one(WheelZoomTool)
p1.toolbar.logo = None
p1.toolbar_location = None
new = Span(location=15.0, dimension='width', line_color='red',line_dash='dashed', line_width=3)
p1.add_layout(new)

#show(p1)
curdoc().add_root(p1)
curdoc().add_periodic_callback(update, 5000)
curdoc().title = "METAR DATA"

Is this in the notebook? Or are your running it with bokeh serve?

I am running it with bokeh serve.

Here is an updated script. It does not utilize the streaming function because the streaming function didn’t seem to update the graphic when plotting. The issue with this script is it keeps copying over itself. I have not found a way to basically just refresh the graphic with new data when it arrives.

import os.path, time
import pandas as pd
from bokeh.plotting import figure, show, ColumnDataSource, output_file
from bokeh.models import ColumnDataSource, HoverTool, WheelZoomTool, BoxAnnotation, Select, CrosshairTool, Span, Range1d
from bokeh.io import output_notebook, curdoc, reset_output
from bokeh.layouts import column
import numpy as np
reset_output()
output_notebook()

#output_file('/home/awips/time_series_update.html')

p1 = figure(x_axis_type='datetime', title='NAM 0-30mb AGL Forecast Wind Speed', plot_width=800, plot_height=400)
p1.y_range=Range1d(0,30)
p1.yaxis.axis_label = 'Wind Speed (knots)'
p1.axis.axis_label_text_font_style = "bold"
high_box = BoxAnnotation(bottom=15.0, fill_alpha=0.1, fill_color='red')
p1.add_layout(high_box)
p1.add_tools(CrosshairTool())
p1.toolbar.active_scroll = p1.select_one(WheelZoomTool)
p1.toolbar.logo = None
p1.toolbar_location = None

#hover = (HoverTool(show_arrow=True, line_policy='nearest', tooltips=[
#('Date', '@DATE{%Y-%m-%d %H:%M}'),('Wind Speed', '@WS{%2.1f} kts')], 
#    formatters={'DATE': 'datetime','WS': 'printf',}))
#p1.add_tools(hover)

def plotgraph():
     df = pd.read_csv(('/tmp/app/time_series/data/test.txt'))
     df['WS'] = df['WS']*1.94384
     df['WSMAX'] = df['WSMAX']*1.94384
     df['DATE'] = pd.to_datetime(df['DATE'], format='%Y-%m-%d %H:%M:%S')
     #hover = HoverTool(tooltips=[("Date", "@DATE{%Y-%m-%d %H:%M}"),("Wind Speed", "@WS{%2.1f} kts")])
     source = ColumnDataSource(df)
     p1.line(x='DATE', y='WS', line_width=2, source=source, color='black')
     p1.triangle(x='DATE', y='WS', size=12, source=source, line_color='black', fill_color='red')
     hover = (HoverTool(show_arrow=True, line_policy='nearest', tooltips=[('Date', '@DATE{%Y-%m-%d %H:%M}'),('Wind Speed', '@WS{%2.1f} kts')], 
        formatters={
            'DATE': 'datetime',
            'WS': 'printf',
        }))
     p1.add_tools(hover)
     hover.mode = "vline"
    #    hover.mode = "vline"

def update():
     global current
     newtime = time.ctime(os.path.getmtime("/tmp/app/time_series/data/test.txt"))
     if current < newtime: #File has been modified so plot the new points
        plotgraph()
        current = newtime

current = time.ctime(os.path.getmtime("/tmp/app/time_series/data/test.txt"))
plotgraph() #plot graph for the first time before iterating the update loop
curdoc().add_root(p1)
curdoc().add_periodic_callback(update, 1000)
curdoc().title = "METAR DATA"

It definitely does do that, if it is used correctly, as you can verify by running the OHLC example locally. There are also many unit and integration tests that continuously maintain the stream method functionality.

Since the example above is not complete (the data it relies on has not been provided), I can’t run it myself to experiment and determine the exact source of the usage error. However one certain problem is this:

result = {'DATE': new_data['DATE'], 'WS': new_data['WS'], 'WSMAX': new_data['WSMAX'], 'P': new_data['P'], 'T': new_data['T'], 'RH': new_data['RH'], 'WD': new_data['WD']}

All the values in this dict must be columns, i.e. lists, series, or arrays. That’s true even if you are streaming only a single new value—the values should be lists/arrays of length one. But your dict values are not columns, as expected, they are single numbers.