1

I'm currently trying to plot the average and max of of a dataframe in 2 graphs with shared selection. On selection of in graph 1, I want to plot the data that is being averaged in graph 2. I'm getting the graphs and selection but it doesn't seems to update the graph with a selection in spyder. Below my code.

import pandas as pd
import numpy as np
from bokeh.models import ColumnDataSource
from bokeh.plotting import figure, show
from bokeh.layouts import row
from bokeh.io import curdoc

# data for plot 2
df2 = pd.DataFrame(list([[1,1,2,3],[3,4,4,5]]))

source2 = ColumnDataSource(
        data=dict(
            x=list(df2.index.values),
            y=list(df2.iloc[:,0].values)
        )
    )

# data for plot 1 & 0
df1 = np.mean(df2)
df0 = np.max(df2)
source1 = ColumnDataSource(
        data=dict(
            x=list(range(0,df1.shape[0])),
            y=list(df1.values),
            y1=list(df0.values),
                    )
    )

# Plot graph one with data from df1 and source 1 as barplot
plot1 = figure(plot_height=300, plot_width=400, tools="box_select")
barglyph = plot1.circle(x='x',y='y',source=source1)

# Plot graph one with data from df1 and source 1 as barplot
plot0 = figure(plot_height=300, plot_width=400, tools="box_select")
barglyph = plot0.circle(x='x',y='y1',source=source1)



# Plot graph two with data from df2 and source 2 as line
plot2 = figure(plot_height=300, plot_width=400, title="myvalues", 
              tools="box_zoom,reset,save,wheel_zoom,hover")    
r1 = plot2.line(x='x',y='y',source =source2, line_alpha = 1, line_width=1)
# safe data from plot 2 for later change in subroutine
ds1 = r1.data_source

def callback(attr, old, new):
    patch_name =  source1.data['colnames'][new['1d']['indices'][0]]
    ds1.data['y'] = df2[patch_name].values

barglyph.data_source.on_change('selected',callback)
show(row(plot0,plot1,plot2))
curdoc().add_root(row(plot0,plot1,plot2))

If I run this in jupyter I get the error: AttributeError: 'Document' object has no attribute 'references'

5
  • Are you just running this as a regular python script? It has to be run on a Bokeh Server, the Bokeh Server is the persistent python process that connects to a viewers browser and executes the callbacks, i.e. when a slider changes. If you just run a bokeh app as a "regular" python script, then it runs and the python process exists and there is no python process left to execute your callbacks. See bokeh.pydata.org/en/latest/docs/user_guide/server.html Commented Jul 2, 2018 at 15:52
  • Thanks for tip! Running via de bokeh server works! Commented Jul 3, 2018 at 12:07
  • I have a second question related to the callback function. I would like to have select 1 or more points and used this selection as indices in the table for multiplot. I cant find any documenation. So this function patch_name = source1.data['colnames'][new['1d']['indices'][0]] with multi select. Commented Jul 3, 2018 at 12:13
  • Different questions should go in separate posts Commented Jul 3, 2018 at 13:40
  • I've expanded the comment as an answer, it would be appreciated if you could accept it so that it is easier for others to find. Commented Jul 3, 2018 at 14:46

1 Answer 1

1

Using real Python callbacks, e.g. with on_change requires running the code as a Bokeh server application, in a Bokeh server. A browser has no ability to run ability to run Python code. If you just run the code as a "regular" Python script python app.py then Python runs the code, generates output in your browser, then the Python interpreter exits at the end–at which point there is no Python process to run your callback code. So, the Bokeh server is the persistent, long-running Python process that exists to run real Python callbacks in Bokeh apps.

There are a few ways to run Bokeh server applications:

  • As a separate process. Typically, if your app code is in app.py this means executing a command line command similar to:

    bokeh serve --show app.py
    

    This will open up a session of the application in a browser locally.

  • Embedded in a Jupyter notebook. In this case you define your app code in a function like myapp(doc) that accepts a Bokeh Document and adds all the things you want (plots, widgets, tools, callbacks, etc.) to that document. Then in the notebook, you execute:

    show(myapp) 
    

    and the app will display and run inline in the notebook. You can download and run this complete example notebook locally for more details.

  • As a library, e.g. in Flask app. For more information on this option see Embedding the Bokeh Server as a Library in the User's Guide.

Otherwise, if you can't or don't want to run a Bokeh server, it is possible to implement many interactive features using Javascript Callbacks, which function in standalone (non-server) Bokeh documents.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.