Closed magland closed 2 years ago
Does this require special functionality that makes it distinct from issue #172?
@jsoules - you're right - this is a duplicate. I will close this one and add my comment/link to the other one.
Actually I decided to keep this one open and closed the other.
Have been working on this. Testing some things now.
Testing using sha1://2102690caa2db411bc9cca4178270810e5a74f9a/Jaq_03_12_visualization_data2.npy?manifest=c38d157da18611aed00a092a938447a78d8292df for the jaq data with ripple events.
Loaded as per https://github.com/scratchrealm/sortingview-dev/blob/main/examples/load_jaq_03_12_data2.py and https://github.com/magland/sortingview/blob/main/sortingview/SpikeSortingView/create_spike_raster_plot.py to generate a raster plot with highlighted spans. The overall code is as follows:
import numpy as np
import figurl as fig
import kachery_client as kc
from math import ceil, floor
def create_spike_raster_plot_data(*, times: np.array, labels: np.array, label: str):
unit_ids = np.sort(np.unique(labels))
plots = []
for unit_id in unit_ids:
inds = np.where(labels == unit_id)[0]
spike_times_sec = times[inds]
plots.append({
'unitId': unit_id,
'spikeTimesSec': spike_times_sec.astype(np.float32)
})
data = {
'type': 'RasterPlot',
'startTimeSec': np.min(times),
'endTimeSec': np.max(times),
'plots': plots
}
return data
data_uri = 'sha1://2102690caa2db411bc9cca4178270810e5a74f9a/Jaq_03_12_visualization_data2.npy?manifest=c38d157da18611aed00a092a938447a78d8292df'
fname = kc.load_file(data_uri)
jaq_data = np.load(fname, allow_pickle=True)
spikes = jaq_data[2]
assert spikes['type'] == 'spikes'
spike_times = spikes['spike_times'].astype(np.float32)
cell_ids = spikes['cell_id'].astype(np.int32)
data = create_spike_raster_plot_data(
times=spike_times,
labels=cell_ids,
label='Spikes'
)
# add ripples to data object
ripples = jaq_data[-1]
assert ripples['type'] == 'ripple_times'
np_starts = ripples['start_times'].to_numpy(dtype=np.float32)
np_ends = ripples['end_times'].to_numpy(dtype=np.float32)
assert len(np_starts) == len(np_ends)
for start, end in zip(np_starts, np_ends):
assert start <= end
data['highlightIntervals'] = [{
'intervalStarts': np_starts,
'intervalEnds': np_ends
}]
figure = fig.Figure(
view_url='http://localhost:3000/',
data=data
)
print(figure.url(label='SPANS_TEST', channel='flatiron1'))
This yields https://figurl.org/f?v=http://localhost:3000/&d=3efdf652e24633ba8345fb6a02af9d01fc67e5d1&channel=flatiron1&label=SPANS_TEST as of this writing.
EDIT 2/23/22: Updated to ensure that the 'highlightIntervals' key points to a list, as I'd originally intended, not just an object. Regenerated FigURL.
I've already merged the PR, but...
There is something off with the highlighted intervals. The location of the highlights changes relative to the spike events as you zoom in/out.
Looks like more is computed at the TimeScrollView level than I realized! That's where the offset for the toolbar (and in the case of the raster plot, the unit labels) is accounted for. So there was a margin alteration that I wasn't realizing.
Submitting a new PR on the same branch that should correct this issue.
In the process, I also discovered that I was painting the highlight bars too far downward in the composite view. This is also fixed.
Example: Click on the 40-minute mark in https://www.figurl.org/f?v=gs://figurl/spikesortingview-1&d=a5128490421d100de4f469ac%5B%E2%80%A6%5De042e2e&channel=flatiron1&label=Jaq_03_12_visualization_data2 and zoom in. The first interval to the left of the 40-minute mark will move to the right (opposite of the direction it should move for a proper zoom) and eventually pass the 40-minute mark.
This corresponds to a span that begins at second 16799.615 and ends at 16799.732.
This example is now fixed.
Closed by SpikeSortingView PRs #33 and #34.
This dataset provided by Eric has ripple times:
https://github.com/scratchrealm/sortingview-dev/blob/main/examples/load_jaq_03_12_data2.py