Search code examples
pythonplotbokehmultiple-axes

Bokeh Server with 3 y axes doesn't plot,but does for 2 y axes.Why?


My objective is to plot live data on multiple y axes(different ranges). The following code worked with 2 y axes but when I added a 3rd one, the browser was just blank.An earlier basic bokeh plot with 4 y axes worked fine but this server version is not working.I dont know what mistake I am doing,please guide me.

The follwing code plots 2 temporary points then a 3rd permanent point. Uses 'patch' and 'stream' from ColumnDataSource to achieve this.

from bokeh.io import curdoc
from bokeh.models import ColumnDataSource
from bokeh.plotting import figure
from bokeh.models import LinearAxis, Range1d
import numpy as np

def plotcharts(source,x,a,b,c):
    fig=figure(y_range=(0, 500))
    fig.circle(source=source, x=x,y=a,size=12,color='red')

    fig.extra_y_ranges = {"foo1": Range1d(start=0, end=50)}
    fig.circle(source=source,x=x, y=b, size=12, color="blue", 
    y_range_name="foo1")
    fig.add_layout(LinearAxis(y_range_name="foo1"), 'left')

    # configure 3rd axis
    fig.extra_y_ranges = {"foo2": Range1d(start=0, end=25)}
    fig.circle(source=source, x=x, y=c, color="magenta", 
    y_range_name="foo2")
    fig.add_layout(LinearAxis(y_range_name="foo2"), 'right')

    return fig

count=(-1)
dct=dict(x=[],a=[],b=[],c=[])  
#Just a and b work fine but when 3rd axis c was added it doesnt !
source=ColumnDataSource(dct)
fig=plotcharts(source,'x','a','b','c') #c==3rd axis

def update_data():
    global count
    count=count+1
    y1 = np.random.randint(low=0, high=500)
    y2 = np.random.randint(low=0, high=50)
    y3 = np.random.randint(low=0, high=25) #y3==3rd axis

    if count%3==0:
        new_data = {
            'x': [count/3],
            'a': [y1],
            'b': [y2],
            'c': [y3]  #c==3rd axis
        }
        source.stream(new_data,rollover=20)

    else:
        l = len(df['a'])
        new_data = {
            'a': [(l - 1,y1)],
            'b': [(l - 1, y2)],
            'c': [(l - 1, y3)]  #c==3rd axis
        }
        source.patch(new_data)

curdoc().add_root(fig)
curdoc().add_periodic_callback(update_data,1000)

Solution

  • You have these two lines in your code:

    fig.extra_y_ranges = {"foo1": Range1d(start=0, end=50)}
    [...]
    fig.extra_y_ranges = {"foo2": Range1d(start=0, end=25)}
    

    Bokeh doesn't try to do some special magic on setting these fields, so with the latter statement, you just override the former. Instead, you should just write one line:

    fig.extra_y_ranges = {"foo1": Range1d(start=0, end=50), "foo2": Range1d(start=0, end=25)}