Repository navigation
Expand file tree
/
Copy pathraster.py
More file actions
87 lines (67 loc) · 2.93 KB
/
Copy pathraster.py
File metadata and controls
87 lines (67 loc) · 2.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
"""
NDWidget Spike Raster
=====================
Browse a spike raster with an ``NDWidget``. The array is ``[raster, spike, xy]``, where the value dim holds the
spike time in seconds and the raster index of each spike, so each of the 20 rasters is a separate scatter in the
collection.
The datapoints dim is time, so the one slider scrubs along it and ``display_window`` sets how many seconds of
spikes are rendered at a time. That window is what keeps a long recording viewable, only the spikes in view are
read and uploaded.
``x_range_mode="auto"`` couples the camera to that window in both directions: the x-range follows the slider,
and panning or zooming sets the display window to the new width and the index to the new center. The linear
selector marks the current time.
"""
# test_example = false
# sphinx_gallery_pygfx_docs = 'animate 6s 20fps'
import numpy as np
import fastplotlib as fpl
n_rasters = 10
n_spikes = 2_000 # spikes per raster
duration = 120.0 # seconds
rng = np.random.default_rng(0)
# a shared sequence of population events, each raster fires near every event with its own jitter
events = np.sort(rng.uniform(0, duration, n_spikes))
# [raster, spike, xy], the value dim holds the spike time in seconds and the raster index
data = np.empty((n_rasters, n_spikes, 2), dtype=np.float32)
data[:, :, 0] = events + rng.normal(0, 0.05, (n_rasters, n_spikes))
data[:, :, 1] = np.arange(n_rasters)[:, None]
data2 = np.empty((n_rasters, n_spikes, 2), dtype=np.float32)
data2[:, :, 0] = events + rng.normal(0, 0.05, (n_rasters, n_spikes))
data2[:, :, 1] = np.arange(n_rasters)[:, None]
# reference space is seconds, one step per 60 Hz frame
ranges = {"time": (0, duration, 1 / 60)}
ndw = fpl.NDWidget(ranges=ranges, size=(700, 700), shape=(2, 1))
ndw[0, 0].add_nd_timeseries(
data,
dims=("raster", "time", "xy"),
display_dims=("raster", "time", "xy"),
graphic_type=fpl.ScatterCollection,
slider_maps={"time": events}, # seconds -> index into the spike list
display_window=5.0, # seconds of spikes to render
max_display_datapoints=1_000_000, # spikes are cheap points, never decimate them
x_range_mode="auto",
cmap="viridis", # one color per raster
sizes=4,
name="raster",
)
ndw[1, 0].add_nd_timeseries(
data2,
dims=("raster", "time", "xy"),
display_dims=("raster", "time", "xy"),
graphic_type=fpl.ScatterCollection,
slider_maps={"time": events}, # seconds -> index into the spike list
display_window=5.0, # seconds of spikes to render
max_display_datapoints=1_000_000, # spikes are cheap points, never decimate them
x_range_mode="auto",
cmap="viridis", # one color per raster
sizes=4,
name="raster",
)
subplot = ndw.figure[0, 0]
ndw.show(maintain_aspect=False)
figure = ndw.figure
# NOTE: fpl.loop.run() should not be used for interactive sessions
# See the "JupyterLab and IPython" section in the user guide
if __name__ == "__main__":
print(__doc__)
fpl.loop.run()