pythonplotbokehrangesliderpython-interactive

Separate range sliders for multiple y axes in bokeh


I have multiple line plots to draw on a single figure and I am doing this using bokeh.plotting. Using

p0.line(), 

p0.extra_y_ranges(),

and

p0.add_layout(LinearAxes())

p0 being 1 bokeh figure.

Example plot attached for reference.

I would like to have range_sliders for each y axis separately on the right. Would this be possible using bokeh?

For the primary y axis, the range slider works fine using

# set up RangeSlider y_counts
range_slider_c = RangeSlider(
    title="c",
    start=-10,
    end=400,
    step=1,
    value=(-1, 300),
    height = 250,
    orientation='vertical',
    show_value= False,
    direction = 'rtl'
)
range_slider_c.js_link("value", p0.y_range, "start", attr_selector=0)
range_slider_c.js_link("value", p0.y_range, "end", attr_selector=1)

But I am unclear about how to call the additional y axes's ranges like I did for p0.y_range in js.link.

I hope I have been able to explain my requirements properly.


Solution

  • This answers is based on the answer on your previous question.

    As it is mentioned there, the extra y-ranges are saved in a dictionary with the keyword extra_y_ranges. Therefor you only have to change the js_link using extra_y_ranges with a valid name. For example range_slider_c.js_link("value", p0.extra_y_ranges["c", "start", attr_selector=0).

    Complete minimal example

    from bokeh.layouts import column
    from bokeh.models import LinearAxis, Range1d, CustomJS, RangeSlider
    from bokeh.plotting import figure, show, output_notebook
    output_notebook()
    
    data_x = [1,2,3,4,5]
    data_y = [1,2,3,4,5]
    color = ['red', 'green', 'magenta', 'black']
    p = figure(plot_width=500, plot_height=300)
    p.line(data_x, data_y, color='blue')
    
    range_sliders = []
    for i, c in enumerate(color, start=1):
        name = f'extra_range_{i}'
        lable = f'extra range {i}'
        p.extra_y_ranges[name] = Range1d(start=0, end=10*i)
    
        p.add_layout(LinearAxis(axis_label=lable, y_range_name=name), 'right')
        p.line(data_x, data_y, color=c, y_range_name=name)
    
        range_slider = RangeSlider(start=0, end=10*i, value=(1,9*i), step=1, title=f"Slider {lable}")
        range_slider.js_link("value", p.extra_y_ranges[name] , "start", attr_selector=0)
        range_slider.js_link("value", p.extra_y_ranges[name] , "end", attr_selector=1)
    
        range_sliders.append(range_slider)
    
    show(column(range_sliders+[p]))
    

    Output

    multiple y-ranges with multiple sliders

    Comment

    To stack the sliders and the figure i use the column layout, which takes a list of bokeh objects. Other layouts are available.