2

I am trying to plot several graphs in Bokeh, but I get the following error:

RuntimeError: Models must be owned by only a single document, Selection(id='1057', ...) is already in a doc.

I know that this is caused when trying to use the same objects in multiple docs, but I don't understand where I am doing that. Here is the entire (simplified) code.

I'm using Bokeh 1.4.0.

from bokeh.plotting import figure, show
from bokeh.layouts import row, gridplot
from bokeh.models import ColumnDataSource
from bokeh.io import output_file
import pandas as pd

feature_groups  = [['ciao'],['bye']]


df = pd.DataFrame.from_dict({'x':[0,1,2,3,4], 'y':[2,3,4,5,6]})
x_test = [0,1,2,3,4]
y_test = [2,3,4,5,6]
source = ColumnDataSource(df)


for features_columns in feature_groups:
    output_file('features_labels' + features_columns[0] +'.html')
    p = []

    for k,f in enumerate(features_columns):
        p_k = figure(title=f)
        p_k.circle(x=f, y='ki', line_width=2, source=source,fill_alpha=0.5,line_alpha=0.5)
        p_k.circle_cross( x=x_test, y=y_test, color='red',fill_alpha=0.5,line_alpha=0.5)
        p_k.circle_cross( x = x_test, y = y_test, color='green',fill_alpha=0.5,line_alpha=0.5)
        p_k.xaxis.axis_label = f
        p_k.yaxis.axis_label = 'ki'
        p.append(p_k)
    grid = gridplot(p, ncols=2)
    show(grid)

thank you in advance

Bruno
  • 632
  • 3
  • 10
  • 24
  • I just posted an answer to a similar question [here](https://stackoverflow.com/questions/39735710/bokeh-models-must-be-owned-by-only-a-single-document/67047128#67047128) that may be helpful. – Brian Larsen Apr 11 '21 at 16:01

2 Answers2

3

1) like the error says each Bokeh model (in this case instance of ColumnDataSource) can be added to the Bokeh Document only once so just move source = ColumnDataSource(df) to the for loop.

EDIT (thanks to bigreddot): Apparently you can share the same source only between glyphs and plots in the same Bokeh Document and not between different documents. Methods like output_file, save and show implicitly create a new Bokeh Document so using the same source in combination with two output_file statements in your original code will always cause a problem

2) you refer to fields that don't exist in your ColumnDataSource like 'ki' etc. I replaced them with x='x' and y='y'

See below corrected and working code:

from bokeh.plotting import figure, show
from bokeh.layouts import row, gridplot
from bokeh.models import ColumnDataSource
from bokeh.io import output_file
import pandas as pd

feature_groups  = [['ciao'],['bye']]

df = pd.DataFrame.from_dict({'x':[0,1,2,3,4], 'y':[2,3,4,5,6]})
x_test = [0,1,2,3,4]
y_test = [2,3,4,5,6]

for features_columns in feature_groups:
    output_file('features_labels' + features_columns[0] +'.html')
    p = []
    source = ColumnDataSource(df)

    for k,f in enumerate(features_columns):
        p_k = figure(title=f)
        p_k.circle(x='x', y='y', line_width=2, source=source,fill_alpha=0.5,line_alpha=0.5)
        p_k.circle_cross( x=x_test, y=y_test, color='red',fill_alpha=0.5,line_alpha=0.5)
        p_k.circle_cross( x = x_test, y = y_test, color='green',fill_alpha=0.5,line_alpha=0.5)
        p_k.xaxis.axis_label = f
        p_k.yaxis.axis_label = 'ki'
        p.append(p_k)
    grid = gridplot(p, ncols=2)
    show(grid)
Tony
  • 7,767
  • 2
  • 22
  • 51
  • You can share CDS objects on different plots, as long as they are the same `Document`. But `output_file`, `show` etc implicitly create new documents under the covers which why the original code triggers this condition. – bigreddot Nov 05 '19 at 16:05
  • @Tony Won't this create 2 separate HTMLs? – Coddy Jul 30 '20 at 15:32
0

Use this function show_bokeh(grid)

def show_bokeh(plot_fig):
    try:
        bpl.reset_output()
        bpl.output_notebook()
        bpl.show(plot_fig)
    except:
        bpl.output_notebook()
        bpl.show(plot_fig) 

instead of show()