-
-
Notifications
You must be signed in to change notification settings - Fork 403
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
Subcoordinate y-range from RangeXY stream with DynamicMap #6136
Comments
Also, dragging the bounding box doesn't exactly work either; using holoviews main. |
Had a look at it with @hoxbro and saw two issues:
|
Similar lack of y-dim control was documented here with combined overlay and dmap: #6010 |
@ahuang11 , below is dummy data and plotting for something closer to the intended use-case. I think it captures what @maximlt is asking for above and the bug you are reporting, but please confirm! Code for example that's closer to intended use-caseimport numpy as np
import holoviews as hv
from bokeh.models import HoverTool
from holoviews.plotting.links import RangeToolLink
from scipy.stats import zscore
from holoviews.operation.datashader import rasterize
hv.extension('bokeh')
N_CHANNELS = 10
N_SECONDS = 5
SAMPLING_RATE = 200
INIT_FREQ = 2 # Initial frequency in Hz
FREQ_INC = 5 # Frequency increment
AMPLITUDE = 1
total_samples = N_SECONDS * SAMPLING_RATE
time = np.linspace(0, N_SECONDS, total_samples)
channels = [f'EEG {i}' for i in range(N_CHANNELS)]
data = np.array([AMPLITUDE * np.sin(2 * np.pi * (INIT_FREQ + i * FREQ_INC) * time)
for i in range(N_CHANNELS)])
hover = HoverTool(tooltips=[
("Channel", "@channel"),
("Time", "$x s"),
("Amplitude", "$y µV")
])
def show_curves(x_range, y_range):
# when y_range for subcoords is fixed, we could try to also drop out of view channels
print(y_range)
if x_range is None: # Fallback if no range is selected
x_range = (0, N_SECONDS)
# Calculate indices for slicing data based on x_range
start_idx = max(int((x_range[0] / N_SECONDS) * total_samples), 0)
end_idx = min(int((x_range[1] / N_SECONDS) * total_samples), total_samples)
channel_curves = []
for channel, channel_data in zip(channels, data):
sliced_time = time[start_idx:end_idx]
sliced_data = channel_data[start_idx:end_idx]
ds = hv.Dataset((sliced_time, sliced_data, channel), ["Time", "Amplitude", "channel"])
curve = hv.Curve(ds, "Time", ["Amplitude", "channel"], label=channel).opts(
color="black", line_width=1, tools=[hover], responsive=True,
height=400, show_legend=False,subcoordinate_y=True,
)
channel_curves.append(curve)
return hv.Overlay(channel_curves)
range_stream = hv.streams.RangeXY(x_range=(0, N_SECONDS), y_range=(0, 1))
curves = hv.DynamicMap(show_curves, streams=[range_stream])
y_positions = range(N_CHANNELS)
yticks = [(i, ich) for i, ich in enumerate(channels)]
z_data = zscore(data, axis=1)
minimap = rasterize(hv.Image((time, y_positions, z_data), ["Time (s)", "Channel"], "Amplitude (uV)")).opts(
cmap="RdBu_r", xlabel='Time (s)', alpha=.5, yticks=[yticks[0], yticks[-1]],
height=150, responsive=True, default_tools=[], clim=(-z_data.std(), z_data.std())
)
RangeToolLink(minimap, curves, axes=["x", "y"], boundsx=(None, 2), boundsy=(None, 6.5))
(curves + minimap).opts(merge_tools=False).cols(1) Screen.Recording.2024-02-28.at.1.10.33.PM.mov |
Yes that's it! Thanks for coming up with the proper MRE. |
Yes! |
@maximlt, if you have time for CZI next week, please prioritize this |
Okay, unlike #6010 this issue makes sense to me. The hope is to link the outer y-range of the subcoordinate-y instead of linking the internal subcoordinates. I'll work on that now. |
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. |
It gives scaled / unscaled values I think, and does it twice.
I also tried playing around with subcoordinate_y as a tuple, but it makes the curves way too spread apart.
The text was updated successfully, but these errors were encountered: