Hi! I am trying to solve a problem with axis synchronization in Bokeh.
The following code snippet produces an interactive chart with twin axes, bar chart and line chart on the same figure. Bar chart is on the left axes and line chart on the right axes.
The first slider called “Bar” multiplies the values for the bar chart by slider’s value. The other slider called ‘Line’ does the same for the line chart.
I explicitly specified how ranges of both axis should behave in callback function. When I use the ‘Line’ slider both axis range changes. IT
Could you please help?
from bokeh.models import LinearAxis, Range1d
from bokeh.io import curdoc
from bokeh.models import Slider, ColumnDataSource, WidgetBox
from bokeh.plotting import figure, output_file, show
from os.path import dirname, join
import numpy as np
import sqlite3 as sql
from bokeh.plotting import figure
from bokeh.layouts import layout, widgetbox
from bokeh.models import ColumnDataSource, HoverTool, Div
from bokeh.models.widgets import Slider, Select, TextInput
from bokeh.io import curdoc
import numpy as np
from bokeh.layouts import row
from bokeh.layouts import widgetbox
from bokeh.models.widgets import Slider
sources
source_bar = ColumnDataSource({‘x’:[1,2,3], ‘y’:[1,3,1]})
source_line = ColumnDataSource({‘x’:[1,2,3], ‘y’:[1,2,3]})
figure
p1 = figure(plot_height=600, plot_width=700, title="", toolbar_location=None)
bar
p1.vbar(source = source_bar, x = ‘x’, top = ‘y’, width = 0.5)
line
p1.extra_y_ranges = {“line”: Range1d(0, 10)}
p1.add_layout(LinearAxis(y_range_name=“line”), ‘right’)
p1.line(x=‘x’, y=‘y’, color=“blue”, line_width = 5, source = source_line, y_range_name=“line”)
slider = Slider(start=0, end=10, value=1, step=.1, title=“Bar”)
slider2 = Slider(start=0, end=10, value=1, step=.1, title=“Line”)
Add callback to widgets
def callback(attr, old, new):
source_bar.data = {‘x’:[1,2,3], ‘y’:[x * slider.value for x in [1,3,1]]}
source_line.data = {‘x’:[1,2,3], ‘y’:[x * slider2.value for x in [1,2,3]]}
p1.y_range.start = 0
p1.y_range.end = np.max(source_bar.data[‘y’])
print(p1.y_range.start, p1.y_range.end)
p1.extra_y_ranges[‘line’].start = np.min(source_line.data[‘y’])
p1.extra_y_ranges[‘line’].end = np.max(source_line.data[‘y’])
slider.on_change(‘value’, callback)
slider2.on_change(‘value’, callback)
layout = row(p1, widgetbox(slider, slider2))
curdoc().add_root(layout)
``