Y-axis not updating after altering children

Hi all,

I have a script that displays several plots side by side. The plots are on different scales, so I have a toggle that changes them from using the same y_range to an auto updating y_range. There are also different version of the plots, which replace the initial plots via another toggle.

All of this works initially, but the y_range stops auto updating after changing the plots >1 time.

I.e. 1) the y-axis toggle works, 2) you change plots, 3) the y-axis toggle works, 4) you change plots, 5) the y-axis toggle no longer works.

There aren’t any messages when it stops working, so I’m not sure if this is a bug or if my method is just bad. I’d really appreciate it if anyone could help me out with this.

I’ve included a minimal working script below that highlights the problem.


Python: 3.6.4
Bokeh: 1.2.0
OS: Windows 10 / Ubuntu 16.04
Browser: Chrome 76.0.3809.132 (Official Build) (64-bit)

import numpy as np
import pandas as pd

from bokeh.io import curdoc
from bokeh.plotting import figure
from bokeh.layouts import row, column
from bokeh.models.widgets import Toggle
from bokeh.models import ColumnDataSource

def initialize_data(n):

    x = np.arange(10)

    return ColumnDataSource(pd.DataFrame({
        'x': x,
        'y': x*n

def initialize_figures(d1, d2, ymax):

    p1 = figure(sizing_mode='scale_width', tools='', toolbar_location=None, plot_width=4, plot_height=3)
    p1.circle('x', 'y', source=d1, color='red', size=15)
    p1.circle('x', 'y', source=ymax, color='black', size=15)

    p2 = figure(sizing_mode='scale_width', tools='', toolbar_location=None, plot_width=4, plot_height=3)
    p2.circle('x', 'y', source=d2, color='blue', size=15)
    p2.circle('x', 'y', source=ymax, color='black', size=15)

    return row(p1, p2)

def change_plots(self):
    r1.children, r2.children = r2.children, r1.children

def change_y_axis(self):

    global N

    ymax1.patch({'y': [(0, ymax1.data['y'][0] / N)]})
    ymax2.patch({'y': [(0, ymax2.data['y'][0] / N)]})

    N = 1/N

N = 1000

d11 = initialize_data(1)
d12 = initialize_data(2)

d21 = initialize_data(1)
d22 = initialize_data(.5)

ymax1 = ColumnDataSource({'x': [0], 'y': [max(d11.data['y'].max(), d12.data['y'].max())]})
ymax2 = ColumnDataSource({'x': [0], 'y': [max(d21.data['y'].max(), d22.data['y'].max())]})

r1 = initialize_figures(d11, d12, ymax1)
r2 = initialize_figures(d21, d22, ymax2)

toggle1 = Toggle(label='change plots', height=30, width=500, sizing_mode='scale_width')

toggle2 = Toggle(label='change y-axis', height=30, width=500, sizing_mode='scale_width')

toggles = row(toggle1, toggle2, sizing_mode='scale_width')

c = column(toggles, r1, sizing_mode='scale_width')