☰Read-only archive⌕
Looking for help with Bokeh?

This is a read-only archive. Ask questions and join the conversation on GitHub.

Visit Community Support on GitHub →
Archived discussions · Captured October 28, 2026

What is the best way to stream text?

Community Support
Nicholas_Schiraldi
Nicholas_Schiraldi

I’m trying to determine what the best way to stream text updates to a figure via bokeh server. I’m currently streaming text updates via ColumnDataSource, but since the text is not first cleared before updating, it becomes unreadable (as you would expect).

Here is a self contained example (with some unused imports)…

Thanks,

Nick

from bokeh.server.server import Server
from bokeh.application import Application
from bokeh.application.handlers.function import FunctionHandler
from bokeh.plotting import figure, ColumnDataSource, show
from bokeh.models.tickers import FixedTicker
import bokeh.models.glyphs as glyphs

import numpy as np
import matplotlib.pyplot as plt

class random_integration(object):
def init(self):
self.x = np.arange(100)
self.y = sorted(np.random.randn(100))
self.counter = 0.
self.text = [‘Integration Number: {0:03.0f}’.format(self.counter)]

def integrate_foward(self):
    self.x = np.arange(100)
    self.y = sorted(np.random.randn(100))        
    self.counter += 1        
    self.text = randi.text

randi = random_integration()
def make_document(doc):

def update():
    randi.integrate_foward()
   
    # Set up model data for streaming
    new_data={}
    new_data['x']=randi.x
    new_data['y']=randi.y
    source.stream(new_data, rollover = 100)
   
    # Set up text data for streaming
    text_data=dict(
        x=[50],
        y=[-2],
        text=['Iteration Number: {0:03.0f}'.format(randi.counter)]
    )
    text_source.stream(text_data,rollover = 100)

# intialize the figure
p = figure(
    plot_width=500,
    plot_height=600,
    x_range = [0, 100],
    y_range = [-3, 3],
    y_axis_type="linear",
)

# ColumnDataSources give us a nice way to update the data quickly in the plot
source = ColumnDataSource(
    data=dict(
        x=randi.x,
        y=randi.y,
    )
)
text_source=ColumnDataSource(
    data=dict(
        x=[50],
        y=[-2],
        text=randi.text
    )
)

# This is the line that will be updated
p.line(x = 'x', y = 'y',source = source, line_width = 2, legend = 'Random CDF')

# Add a text renderer
p.text(x=50, y=-2, text='text', text_color='black', text_font_size="10pt",
       text_baseline="middle", text_align="center",source = text_source)
   
doc.title = "Random Distribution"
doc.add_root(p)

doc.add_periodic_callback(update, 100)

apps = {’/’: Application(FunctionHandler(make_document))}

server = Server(apps, port=5000)
server.start()

``

⌁   Link to post
Nicholas_Schiraldi
Nicholas_Schiraldi

Solution
FYI for anyone else running into this issue, rollover should be set to 1 when streaming “1” text data point.

i.e.

text_source.stream(text_data,rollover = 1)

···

On Tuesday, June 26, 2018 at 2:41:11 PM UTC-4, Nicholas Schiraldi wrote:

I’m trying to determine what the best way to stream text updates to a figure via bokeh server. I’m currently streaming text updates via ColumnDataSource, but since the text is not first cleared before updating, it becomes unreadable (as you would expect).

Here is a self contained example (with some unused imports)…

Thanks,

Nick

from bokeh.server.server import Server
from bokeh.application import Application
from bokeh.application.handlers.function import FunctionHandler
from bokeh.plotting import figure, ColumnDataSource, show
from bokeh.models.tickers import FixedTicker
import bokeh.models.glyphs as glyphs

import numpy as np
import matplotlib.pyplot as plt

class random_integration(object):
def init(self):
self.x = np.arange(100)
self.y = sorted(np.random.randn(100))
self.counter = 0.
self.text = [‘Integration Number: {0:03.0f}’.format(self.counter)]

def integrate_foward(self):
    self.x = np.arange(100)
    self.y = sorted(np.random.randn(100))        
    self.counter += 1        
    self.text = randi.text

randi = random_integration()
def make_document(doc):

def update():
    randi.integrate_foward()
   
    # Set up model data for streaming
    new_data={}
    new_data['x']=randi.x
    new_data['y']=randi.y
    source.stream(new_data, rollover = 100)
   
    # Set up text data for streaming
    text_data=dict(
        x=[50],
        y=[-2],
        text=['Iteration Number: {0:03.0f}'.format(randi.counter)]
    )
    text_source.stream(text_data,rollover = 100)

# intialize the figure
p = figure(
    plot_width=500,
    plot_height=600,
    x_range = [0, 100],
    y_range = [-3, 3],
    y_axis_type="linear",
)

# ColumnDataSources give us a nice way to update the data quickly in the plot
source = ColumnDataSource(
    data=dict(
        x=randi.x,
        y=randi.y,
    )
)
text_source=ColumnDataSource(
    data=dict(
        x=[50],
        y=[-2],
        text=randi.text
    )
)

# This is the line that will be updated
p.line(x = 'x', y = 'y',source = source, line_width = 2, legend = 'Random CDF')

# Add a text renderer
p.text(x=50, y=-2, text='text', text_color='black', text_font_size="10pt",
       text_baseline="middle", text_align="center",source = text_source)
   
doc.title = "Random Distribution"
doc.add_root(p)


doc.add_periodic_callback(update, 100)

apps = {‘/’: Application(FunctionHandler(make_document))}

server = Server(apps, port=5000)
server.start()

``

⌁   Link to post
Bryan
Bryan

Hi,

I feel compelled to add that the .stream API is for efficiently adding one (or a few) points to an already existing large data source, without having to re-send all the data needlessly. If your column only has 1 item to begin with, and you only want to update that 1 item, there is no reason to use .stream at all, just send the entire new (tiny) .data property.

Thanks,

Bryan

···

On Jul 17, 2018, at 08:06, Nicholas Schiraldi nschiraldi@gmail.com wrote:

Solution
FYI for anyone else running into this issue, rollover should be set to 1 when streaming “1” text data point.

i.e.

text_source.stream(text_data,rollover = 1)

On Tuesday, June 26, 2018 at 2:41:11 PM UTC-4, Nicholas Schiraldi wrote:

I’m trying to determine what the best way to stream text updates to a figure via bokeh server. I’m currently streaming text updates via ColumnDataSource, but since the text is not first cleared before updating, it becomes unreadable (as you would expect).

Here is a self contained example (with some unused imports)…

Thanks,

Nick

from bokeh.server.server import Server
from bokeh.application import Application
from bokeh.application.handlers.function import FunctionHandler
from bokeh.plotting import figure, ColumnDataSource, show
from bokeh.models.tickers import FixedTicker
import bokeh.models.glyphs as glyphs

import numpy as np
import matplotlib.pyplot as plt

class random_integration(object):
def init(self):
self.x = np.arange(100)
self.y = sorted(np.random.randn(100))
self.counter = 0.
self.text = [‘Integration Number: {0:03.0f}’.format(self.counter)]

def integrate_foward(self):
    self.x = np.arange(100)
    self.y = sorted(np.random.randn(100))        
    self.counter += 1        
    self.text = randi.text

randi = random_integration()
def make_document(doc):

def update():
    randi.integrate_foward()
    
    # Set up model data for streaming
    new_data={}
    new_data['x']=randi.x
    new_data['y']=randi.y
    source.stream(new_data, rollover = 100)
    
    # Set up text data for streaming
    text_data=dict(
        x=[50],
        y=[-2],
        text=['Iteration Number: {0:03.0f}'.format(randi.counter)]
    )
    text_source.stream(text_data,rollover = 100)

# intialize the figure
p = figure(
    plot_width=500,
    plot_height=600,
    x_range = [0, 100],
    y_range = [-3, 3],
    y_axis_type="linear",
)

# ColumnDataSources give us a nice way to update the data quickly in the plot
source = ColumnDataSource(
    data=dict(
        x=randi.x,
        y=randi.y,
    )
)
text_source=ColumnDataSource(
    data=dict(
        x=[50],
        y=[-2],
        text=randi.text
    )
)

# This is the line that will be updated
p.line(x = 'x', y = 'y',source = source, line_width = 2, legend = 'Random CDF')

# Add a text renderer
p.text(x=50, y=-2, text='text', text_color='black', text_font_size="10pt",
       text_baseline="middle", text_align="center",source = text_source)
    
doc.title = "Random Distribution"
doc.add_root(p)


doc.add_periodic_callback(update, 100)

apps = {‘/’: Application(FunctionHandler(make_document))}

server = Server(apps, port=5000)
server.start()

``

–
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+unsubscribe@continuum.io.
To post to this group, send email to bokeh@continuum.io.
To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/365c3b5f-8537-4be4-9feb-217cb67c5501%40continuum.io.
For more options, visit https://groups.google.com/a/continuum.io/d/optout.

⌁   Link to post

End of archived discussion · Replies are disabled