I am designing a Bokeh layout using the Bokeh server. I am defining two main columns (see attached image), and I am attempting to link the x-axis of all plots on the right column. The problems are that:
I am trying to make this app as dynamic as possible, which mean that depending on the case-study, not all the plots will be available, and each individual plot is set from a separate function
Each plot object is stored in a list, and I don't know how to access their properties
The reference plot is not known a priori so I don't see how I can implement the example in the Bokeh doc - in other words, I need to first plot all the subplots to then get the relevant x_range
So I was wondering if it is possible to set the linking behaviour a posteriori once all plots in the column are defined (i.e. the output of plotDataset
below). My intuition is to loop through the objects, get the children and set the x_range
to the first plot, but I don't know how to do that.
Below is a simplified version of what I am trying to achieve. Ideally, I would get the x_range of the first plot of fCol
and apply it to all other plots just before return column(fCol)
Any idea is greatly appreciated! And also, I am fairly beginner with Python so please shout if you see anything else horrible!
Thank you
def plotTS(data, col):
tTmp = []
# A loop that defines each tab of the plot
for i in range(len(col)):
fTmp = figure()
fTmp.circle(data[:]['time'], data[:][col[i]], color=color)
# Append tab
tTmp.append(Panel(child=fTmp))
# Return the tabs
return Tabs(tabs=tTmp)
def plotDataset(data):
col = ['NDVI', 'EVI'] # Name of the tabs
fCol = []
fCol.append(plotTS(data, col))
# NOTE: I use an append approach because in reality plotTS is called more than once
return column(fCol)
# General layout - I did not include the code for the left column
layout = row(leftColumn, plotDataset(data))
See code below (Bokeh v1.1.0).
from bokeh.models import Panel, Tabs, Column, Row
from bokeh.plotting import figure
from tornado.ioloop import IOLoop
from bokeh.server.server import Server
from bokeh.application import Application
from bokeh.application.handlers.function import FunctionHandler
def modify_doc(doc):
leftColumn = Column(figure())
def plotTS(data, col):
tTmp = []
for i in col:
fTmp = figure()
fTmp.circle(data['x'], data['y'], color='black')
tTmp.append(Panel(child=fTmp, title = i))
return Tabs(tabs=tTmp)
def plotDataset(data):
col = ['NDVI', 'EVI']
fCol = plotTS(data, col)
shared_range = None
for panel in fCol.tabs:
fig = panel.child
if shared_range is None:
shared_range = fig.x_range
else:
fig.x_range = shared_range
return Column(fCol)
layout = Row(leftColumn, plotDataset(data = dict(x = [1, 2, 3], y = [1, 2, 3])))
doc.add_root(layout)
io_loop = IOLoop.current()
server = Server(applications = {'/app': Application(FunctionHandler(modify_doc))}, io_loop = io_loop, port = 5002)
server.start()
server.show('/app')
io_loop.start()