Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support hit-tested group-wise wheel zoom renderers for subcoordinate_y #6268

Closed
droumis opened this issue Jun 7, 2024 · 1 comment · Fixed by #6277
Closed

Support hit-tested group-wise wheel zoom renderers for subcoordinate_y #6268

droumis opened this issue Jun 7, 2024 · 1 comment · Fixed by #6277
Assignees
Labels
TRIAGE Needs triaging

Comments

@droumis
Copy link
Member

droumis commented Jun 7, 2024

Should be tested and work with the HoloViews doc's eeg example

See Bokeh PR for incoming 3.5 functionality and description of behavior: bokeh/bokeh#13826

Pure Bokeh example
from bokeh.layouts import column
from bokeh.plotting import figure, curdoc
import numpy as np

from bokeh.core.properties import field
from bokeh.layouts import column, row
from bokeh.models import (ColumnDataSource, CustomJS, Div, FactorRange, HoverTool,
                          Range1d, Switch, WheelZoomTool, ZoomInTool, ZoomOutTool, GroupByModels)
from bokeh.palettes import Category10
from bokeh.plotting import figure

n_eeg_channels = 7
n_pos_channels = 3
n_channels = n_eeg_channels + n_pos_channels
n_seconds = 15

total_samples = 512*n_seconds
time = np.linspace(0, n_seconds, total_samples)
data = np.random.randn(n_channels, total_samples).cumsum(axis=1)
channels = [f"EEG {i}" for i in range(n_eeg_channels)] + [f"POS {i}" for i in range(n_pos_channels)]

hover = HoverTool(tooltips=[
    ("Channel", "$name"),
    ("Time", "$x s"),
    ("Amplitude", "$y μV"),
])

x_range = Range1d(start=time.min(), end=time.max())
y_range = FactorRange(factors=channels)

p = figure(x_range=x_range, y_range=y_range, lod_threshold=None, tools="pan,reset,xcrosshair")

source = ColumnDataSource(data=dict(time=time))
eeg_renderers = []
pos_renderers = []

for i, channel in enumerate(channels):
    is_eeg = channel.startswith('EEG')
    xy = p.subplot(
        x_source=p.x_range,
        y_source=Range1d(start=data[i].min(), end=data[i].max()),
        x_target=p.x_range,
        y_target=Range1d(start=i, end=i + 1),
    )

    source.data[channel] = data[i]
    if is_eeg:
        line = xy.line(field("time"), field(channel), color='black', source=source, name=channel)
        eeg_renderers.append(line)
    else:
        line = xy.line(field("time"), field(channel), color=Category10[10][i], source=source, name=channel)
        pos_renderers.append(line)
    
all_renderers = eeg_renderers + pos_renderers

level = 1
hit_test = True

behavior = GroupByModels(groups=[eeg_renderers, pos_renderers])

ywheel_zoom = WheelZoomTool(renderers=all_renderers, level=level, hit_test=hit_test, hit_test_mode="hline", hit_test_behavior=behavior, dimensions="height")
xwheel_zoom = WheelZoomTool(renderers=all_renderers, level=level, dimensions="width")
zoom_in = ZoomInTool(renderers=all_renderers, level=level, dimensions="height")
zoom_out = ZoomOutTool(renderers=all_renderers, level=level, dimensions="height")

p.add_tools(ywheel_zoom, xwheel_zoom, zoom_in, zoom_out, hover)
p.toolbar.active_scroll = ywheel_zoom

level_switch = Switch(active=level == 1)
level_switch.js_on_change("active", CustomJS(
    args=dict(tools=[ywheel_zoom, zoom_in, zoom_out]),
    code="""
export default ({tools}, obj) => {
    const level = obj.active ? 1 : 0
    for (const tool of tools) {
        tool.level = level
    }
}
"""))

hit_test_switch = Switch(active=hit_test)
hit_test_switch.js_on_change("active", CustomJS(
    args=dict(tool=ywheel_zoom),
    code="""
export default ({tool}, obj) => {
    tool.hit_test = obj.active
}
"""))

layout = column(
    row(Div(text="Zoom sub-coordinates:"), level_switch),
    row(Div(text="Zoom hit-tested:"), hit_test_switch),
    p,
)

curdoc().add_root(layout)
video1253097405.mp4
Copy link

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Nov 12, 2024
@droumis droumis moved this from WIP to Done in CZI R5 neuro Dec 9, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
TRIAGE Needs triaging
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants