Toggle synchronization of x axes of multiple figures

I have a Bokeh (3.4.3) server application with multiple figures, and I want to toggle on/off synchronization of their x axes. I am able to successfully synchronize them but not un-synchronize them. Is this possible?

from bokeh.models import CheckboxGroup, ColumnDataSource, DataRange1d, Range1d
from bokeh.plotting import figure, show
from bokeh.layouts import column
from bokeh.io import curdoc

# Sample data
x = list(range(10))
y1 = [i**2 for i in x]
y2 = [i**1.5 for i in x]

source1 = ColumnDataSource(data=dict(x=x, y=y1))
source2 = ColumnDataSource(data=dict(x=x, y=y2))

fig1 = figure(title="Figure 1", width=400, height=400)
fig1.line('x', 'y', source=source1, line_width=2)

fig2 = figure(title="Figure 2", width=400, height=400)
fig2.line('x', 'y', source=source2, line_width=2)

# Initialize with synchronized x-range
fig1.x_range = DataRange1d()
fig2.x_range = fig1.x_range

sync_checkbox = CheckboxGroup(labels=["Synchronize x-axes"], active=[0])

def toggle_sync(attr, old, new):
    if sync_checkbox.active:
        # Synchronize x-axis
        common_x_range = fig1.x_range
        fig2.x_range = common_x_range
    else:
        # Unsynchronize x-axis
        fig1.x_range = DataRange1d()
        fig2.x_range = DataRange1d()

sync_checkbox.on_change('active', toggle_sync)

layout = column(sync_checkbox, fig1, fig2)

curdoc().add_root(layout)

There are so many events and connections to ranges that replacing them entirely is not really supported [1]. Since linking ranges on plots means sharing ranges, there’s not really a good way to “undo” linking. In this case I’d actually suggest just making two versions of same plot, one linked and one not, and “swapping” them out by toggling their visibility as necessary.


  1. In fact I think I will propose making this official by making ranges read only for 4.0. ↩︎

Hi Bryan,

Thanks for the suggestion.

Just to confirm, you are saying that in 4.0 users will be prevented from replacing a Range object entirely, but will we still be able to dynamically update the start and end parameters for Range1d objects? We have multiple Bokeh server applications where we manually scale our x axes by dynamically updating the start and end parameters of the underlying Range1d objects.

@ah7149407 Yes that is exactly correct. Summarizing:


plot.x_range.start = 0  # still OK
plot.y_range.end = 10   # still OK

plot.x_range = Range1D(...)  # will possibly be disallowed

Excellent. Thanks, Bryan!

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.