<jupyter_start><jupyter_text>The Bokeh Server, a minimal programmatic example================This notebook show how to start a *very simple* bokeh server application *programmatically*.  For more complex examples, or for the more standard command line interface, see the [Bokeh documentation](http://bokeh.pydata.org/en/latest/docs/user_guide/server.html).Motivation---------Many people know Bokeh as a tool for building web visualizations from languages like Python.  However I find that Bokeh's true value is in serving live-streaming, interactive visualizations that update with real-time data.  I personally use Bokeh to serve real-time diagnostics for a distributed computing system.  In this case I embed Bokeh directly into my library.  I've found it incredibly useful and easy to deploy sophisticated and beaufitul visualizations that help me understand the deep inner-workings of my system.Most of the (excellent) documentation focuses on stand-alone applications using the Bokeh server    $ bokeh serve myapp.py    However I mostly deal with programmers who would prefer to execute things programmatically.  I thought I'd provide some examples on how to do this within a Jupyter notebook. Launch Bokeh Servers from a Notebook------------------------------------The code below starts a Bokeh server running on port 5000 that provides a single route to `/` that serves a single figure with a line-plot.  The imports are a bit wonky, but the amount of code necessary here is relatively small.<jupyter_code>from bokeh.server.server import Server
from bokeh.application import Application
from bokeh.application.handlers.function import FunctionHandler
from bokeh.plotting import figure, ColumnDataSource

def make_document(doc):
    fig = figure(title='Line plot!', sizing_mode='scale_width')
    fig.line(x=[1, 2, 3], y=[1, 4, 9])

    doc.title = "Hello, world!"
    doc.add_root(fig)
    
apps = {'/': Application(FunctionHandler(make_document))}

server = Server(apps, port=5000)
server.start()<jupyter_output><empty_output><jupyter_text>We make a function `make_document` which is called every time someone visits our website.  This function can create plots, call functions, and generally do whatever it wants.  Here we make a simple line plot and register that plot with the document with the `doc.add_root(...)` method.  This starts a Tornado web server and creates a new image whenever someone connects, similar to libraries like Tornado, or Flaskimage to bokeh-server-line-plot.png Live Updates--------------I find that Bokeh's real strength comes when you want to stream live data into the browser.  Doing this by hand generally means serializing your data on the server, figuring out how web sockets work, sending the data to the client/browser and then updating plots in the browser.Bokeh handles this by keeping a synchronized table of data on the client and the server.  This is the `ColumnDataSource`.  If you define plots around the column data source and then push more data into the source then Bokeh will handle the rest, synchronizing the plots on the screen with the data that you provide.In the example below every time someone connects to our server we make a new `ColumnDataSource`, make a function that will add a new record into it, and set up a calllback to call that function every 100ms.  We then make a plot around that data source to render the data as colored circles.Because this is a new Bokeh server we start this on a new port, though in practice if we had multiple pages we would just add them as multiple routes in the `apps` variable.<jupyter_code>import random

def make_document(doc):
    source = ColumnDataSource({'x': [], 'y': [], 'color': []})

    def update():
        new = {'x': [random.random()],
               'y': [random.random()],
               'color': [random.choice(['red', 'blue', 'green'])]}
        source.stream(new)

    doc.add_periodic_callback(update, 100)

    fig = figure(title='Streaming Circle Plot!', sizing_mode='scale_width',
                 x_range=[0, 1], y_range=[0, 1])
    fig.circle(source=source, x='x', y='y', color='color', size=10)

    doc.title = "Now with live updating!"
    doc.add_root(fig)
    
apps = {'/': Application(FunctionHandler(make_document))}

server = Server(apps, port=5001)
server.start()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.09027938120526437, 'fraction_numerical': 0.0069268067420918955, 'mean_word_length': 4.181818181818182, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '2', 'dir': 'jupyter-structured-clean-dedup', 'id': '210720', 'license': 'MIT', 'n_tokens_mistral': 1163, 'n_tokens_neox': 1112, 'n_words': 543, 'path': '_archive/visual/simple-bokeh-server.ipynb', 'repo_name': 'myxie/topsim', 'size': '4331'}