diff --git a/atlasview/atlasview.py b/atlasview/atlasview.py
index 07fee99..79d402f 100644
--- a/atlasview/atlasview.py
+++ b/atlasview/atlasview.py
@@ -261,7 +261,7 @@ class ControllerTopView(PgImageController):
"""
TopView ControllerTopView
"""
- def __init__(self, qmain: TopView, res: int = 25, volume='image'):
+ def __init__(self, qmain: TopView, res: int = 25, volume='image', **kwargs):
super(ControllerTopView, self).__init__(qmain)
self.volume = volume
self.atlas = AllenAtlas(res)
diff --git a/setup.py b/setup.py
index fcc00a5..1eca54a 100644
--- a/setup.py
+++ b/setup.py
@@ -12,6 +12,7 @@
entry_points={
'console_scripts': [
'atlas=atlasview.atlasview:main',
+ 'align=atlaselectrophysiology.ephys_atlas_gui:main',
]
},
)
diff --git a/viewspikes/README.md b/viewspikes/README.md
index a7154fc..ad27b2a 100644
--- a/viewspikes/README.md
+++ b/viewspikes/README.md
@@ -12,6 +12,13 @@ Pre-requisites:
```
conda activate iblenv
-pip install easyqc
+pip install viewephys
pip install -U pyqtgraph
```
+
+
+## Roadmap
+- multi-probe displays for sessions with several probes
+- make sure NP2.0 4 shanks is supported
+- display LFP
+- speed up the raster plots in pyqtgraph
diff --git a/viewspikes/data.py b/viewspikes/data.py
deleted file mode 100644
index c0510af..0000000
--- a/viewspikes/data.py
+++ /dev/null
@@ -1,110 +0,0 @@
-from pathlib import Path
-import shutil
-
-from brainbox.io import spikeglx
-from one.webclient import dataset_record_to_url
-
-import numpy as np
-import scipy.signal
-
-from one import alf
-
-
-CHUNK_DURATION_SECS = 1
-OUTPUT_TO_TEST = True
-
-
-def get_ks2_batch(ks2memmap, ibatch):
- BATCH_SIZE = 65600
- NTR = 384
- offset = BATCH_SIZE * NTR * ibatch
- from_to = np.array([0, BATCH_SIZE * NTR])
- slic = slice(from_to[0] + offset, from_to[1] + offset)
-
- ks2 = np.reshape(ks2memmap[slice(from_to[0] + offset, from_to[1] + offset)], (NTR, BATCH_SIZE))
- return ks2
-
-
-# ks2 proc
-def get_ks2(raw, dsets, one):
- kwm = next(dset for dset in dsets if dset['dataset_type'] == 'kilosort.whitening_matrix')
- kwm = np.load(one._download_dataset(kwm))
- channels = [dset for dset in dsets if dset['dataset_type'].startswith('channels')]
- malf_path = next(iter(one._download_datasets(channels))).parent
- channels = alf.io.load_object(malf_path, 'channels')
- _car = raw[channels['rawInd'], :] - np.mean(raw[channels.rawInd, :], axis=0)
- sos = scipy.signal.butter(3, 300 / 30000 / 2, btype='highpass', output='sos')
- ks2 = np.zeros_like(raw)
- ks2[channels['rawInd'], :] = scipy.signal.sosfiltfilt(sos, _car)
- std_carbutt = np.std(ks2)
- ks2[channels['rawInd'], :] = np.matmul(kwm, ks2[channels['rawInd'], :])
- ks2 = ks2 * std_carbutt / np.std(ks2)
- return ks2
-
-
-def get_spikes(dsets, one):
- dtypes_spikes = ['spikes.clusters', 'spikes.amps', 'spikes.times', 'clusters.channels',
- 'spikes.samples', 'spikes.depths']
- dsets_spikes = [dset for dset in dsets if dset['dataset_type'] in dtypes_spikes]
- malf_path = next(iter(one._download_datasets(dsets_spikes))).parent
- channels = alf.io.load_object(malf_path, 'channels')
- clusters = alf.io.load_object(malf_path, 'clusters')
- spikes = alf.io.load_object(malf_path, 'spikes')
- return spikes, clusters, channels
-
-
-def stream(pid, t, one=None, cache=True, dsets=None, typ='ap', tlen=1):
- """
- NB: returned Reader object must be closed after use
- :param pid: Probe UUID
- :param t:
- :param one: An instance of ONE
- :param cache:
- :param dsets:
- :param typ: 'ap' or 'lf'
- :param tlen: no. of seconds to stream
- :return: sr, dsets, t0
- """
-
- assert one
- assert typ in ['lf', 'ap']
- t0 = np.floor(t / CHUNK_DURATION_SECS) * CHUNK_DURATION_SECS
- if cache:
- samples_folder = Path(one.alyx._par.CACHE_DIR).joinpath('cache', typ)
- sample_file_name = Path(f"{pid}_{str(int(t0)).zfill(5)}.meta")
- if dsets is None:
- dsets = one.alyx.rest('datasets', 'list', probe_insertion=pid)
- if cache and samples_folder.joinpath(sample_file_name).exists():
- print(f'loading {sample_file_name} from cache')
- sr = spikeglx.Reader(samples_folder.joinpath(sample_file_name).with_suffix('.bin'),
- open=True)
- return sr, dsets, t0
-
- dset_ch = next(dset for dset in dsets if dset['dataset_type'] == "ephysData.raw.ch" and
- f'.{typ}.' in dset['name'])
- dset_meta = next(dset for dset in dsets if dset['dataset_type'] == "ephysData.raw.meta" and
- f'.{typ}.' in dset['name'])
- dset_cbin = next(dset for dset in dsets if dset['dataset_type'] == f"ephysData.raw.{typ}" and
- f'.{typ}.' in dset['name'])
-
- file_ch, file_meta = one._download_datasets([dset_ch, dset_meta])
-
- first_chunk = int(t0 / CHUNK_DURATION_SECS)
- last_chunk = int((t0 + tlen) / CHUNK_DURATION_SECS) - 1
-
- sr = spikeglx.download_raw_partial(
- one=one,
- url_cbin=dataset_record_to_url(dset_cbin)[0],
- url_ch=file_ch,
- first_chunk=first_chunk,
- last_chunk=last_chunk)
-
- if cache:
- samples_folder.mkdir(exist_ok=True, parents=True)
- out_meta = samples_folder.joinpath(sample_file_name)
- shutil.copy(sr.file_meta_data, out_meta)
- with open(out_meta.with_suffix('.bin'), 'wb') as fp:
- sr.open()
- sr._raw[:].tofile(fp)
-
- return sr, dsets, t0
diff --git a/viewspikes/example_view_ephys_session.py b/viewspikes/example_view_ephys_session.py
new file mode 100644
index 0000000..5e1a78b
--- /dev/null
+++ b/viewspikes/example_view_ephys_session.py
@@ -0,0 +1,15 @@
+from pathlib import Path
+from one.api import ONE
+from brainbox.io.one import EphysSessionLoader, SpikeSortingLoader
+from iblapps.viewspikes.gui import view_raster
+
+PATH_CACHE = Path("/datadisk/Data/NAWG/01_lick_artefacts/openalyx")
+
+one = ONE(base_url="https://openalyx.internationalbrainlab.org", cache_dir=PATH_CACHE)
+
+pid = '5135e93f-2f1f-4301-9532-b5ad62548c49'
+eid, pname = one.pid2eid(pid)
+
+
+self = view_raster(pid=pid, one=one, stream=False)
+
diff --git a/viewspikes/examples_local.py b/viewspikes/examples_local.py
deleted file mode 100644
index bd2ab40..0000000
--- a/viewspikes/examples_local.py
+++ /dev/null
@@ -1,111 +0,0 @@
-from pathlib import Path
-import numpy as np
-import scipy
-import matplotlib.pyplot as plt
-from easyqc.gui import viewseis
-
-import one.alf.io as alfio
-from one.api import ONE
-import spikeglx
-import neuropixel
-from neurodsp import voltage
-from brainbox.plot import driftmap
-
-from needles2 import run_needles2
-from viewspikes.data import stream, get_ks2, get_spikes
-from viewspikes.plots import plot_insertion, show_psd, overlay_spikes
-
-RAW_PATH = Path("/datadisk/Data/spike_sorting/benchmark/raw")
-SORT_PATH = Path("/datadisk/team_drives/WG-Neural-Analysis/Spike-Sorting-Analysis/benchmarks")
-SORTERS = ['ks2','ks3', 'pyks2.5']
-
-"8413c5c6-b42b-4ec6-b751-881a54413628",
-"8ca1a850-26ef-42be-8b28-c2e2d12f06d6",
-"ce24bbe9-ae70-4659-9e9c-564d1a865de8",
-"ce397420-3cd2-4a55-8fd1-5e28321981f4",
-
-# Example 1
-pid, t0 = ("ce24bbe9-ae70-4659-9e9c-564d1a865de8", 810)
-bin_file = next(RAW_PATH.joinpath(pid).rglob("*.ap.bin"))
-sr = spikeglx.Reader(bin_file)
-sel = slice(int(t0 * sr.fs), int((t0 + 4) * sr.fs))
-raw = sr[sel, :-1].T
-
-
-# Example 2: Plot Insertion for a given PID
-av = run_needles2.view(lazy=True)
-av.add_insertion_by_id(pid)
-
-# Example 3: Show the PSD
-fig, ax = plt.subplots()
-fig.set_size_inches(14, 7)
-show_psd(raw, sr.fs, ax=ax)
-
-# Example 4: Display the raw / pre-proc
-h = neuropixel.trace_header()
-sos = scipy.signal.butter(3, 300 / sr.fs / 2, btype='highpass', output='sos')
-butt = scipy.signal.sosfiltfilt(sos, raw)
-fk_kwargs ={'dx': 1, 'vbounds': [0, 1e6], 'ntr_pad': 160, 'ntr_tap': 0, 'lagc': .01, 'btype': 'lowpass'}
-destripe = voltage.destripe(raw, fs=sr.fs, fk_kwargs=fk_kwargs, tr_sel=np.arange(raw.shape[0]))
-eqc_butt = viewseis(butt.T, si=1 / sr.fs, h=h, t0=t0, title='butt', taxis=0)
-eqc_dest = viewseis(destripe.T, si=1 / sr.fs, h=h, t0=t0, title='destr', taxis=0)
-eqc_dest_ = viewseis(destripe.T, si=1 / sr.fs, h=h, t0=t0, title='destr_', taxis=0)
-# Example 5: overlay the spikes on the existing easyqc instances
-from ibllib.plots import color_cycle
-ss = {}
-symbols = 'x+o'
-eqcsort = {}
-for i, sorter in enumerate(SORTERS):
- alf_path = SORT_PATH.joinpath(sorter, pid,'alf')
- ss[sorter] = {}
- for k in ['spikes', 'clusters', 'channels']:
- ss[sorter][k] = alfio.load_object(alf_path, k)
- col = (np.array(color_cycle(i)) * 255).astype(np.uint8)
- eqcsort[sorter] = viewseis(destripe.T, si=1 / sr.fs, h=h, t0=t0, title=sorter, taxis=0)
- _, _, _ = overlay_spikes(
- eqcsort[sorter], ss[sorter]['spikes'], ss[sorter]['clusters'], ss[sorter]['channels'],
- label=sorter, symbol=symbols[i])
- _, _, _ = overlay_spikes(
- eqc_dest_, ss[sorter]['spikes'], ss[sorter]['clusters'], ss[sorter]['channels'],
- rgb=tuple(col), label=sorter, symbol=symbols[i])
- # overlay_spikes(eqc_dest, ss[sorter]['spikes'], ss[sorter]['clusters'], ss[sorter]['channels'])
- # sc.setPen(pg.mkPen((0, 255, 0, 155), width=1))
-
-##
-from ibllib.dsp.fourier import fshift
-from ibllib.dsp.voltage import destripe
-eqc_butt = viewseis(butt.T, si=1 / sr.fs, h=h, t0=t0, title='butt', taxis=0)
-bshift = fshift(butt, h['sample_shift'], axis=1)
-eqc_buts = viewseis(bshift.T, si=1 / sr.fs, h=h, t0=t0, title='shift', taxis=0)
-
-
-
-##
-from one.api import ONE
-pid = "8413c5c6-b42b-4ec6-b751-881a54413628"
-one = ONE()
-
-dtypes = ['spikes.amps', 'spikes.clusters', 'spikes.times',
- 'clusters.channels',
- 'clusters.mlapdv']
-
-from iblatlas import atlas
-from ibllib.pipes import histology
-from ibllib.ephys import neuropixel
-
-import numpy as np
-neuropixel.TIP_SIZE_UM
-neuropixel.SITES_COORDINATES
-
-len(one.alyx.rest('datasets', 'list', insertion=pid))
-
-# if we don't have the data on the flatiron
-pi = one.alyx.rest('insertions', 'read', id=pid)
-traj = one.alyx.rest('trajectories', 'list', probe_insertion=pid)[-1]
-ins = atlas.Insertion.from_dict(traj)
-xyz_channels = histology.interpolate_along_track(
- ins.xyz, (neuropixel.SITES_COORDINATES[:, 1] + neuropixel.TIP_SIZE_UM) / 1e6)
-
-
-
-
diff --git a/viewspikes/examples_reproducible.py b/viewspikes/examples_reproducible.py
deleted file mode 100644
index e1e8f6a..0000000
--- a/viewspikes/examples_reproducible.py
+++ /dev/null
@@ -1,60 +0,0 @@
-from one.api import ONE, alfio
-from atlaselectrophysiology.alignment_with_easyqc import viewer
-
-one = ONE()
-
-
-pids = ['ce397420-3cd2-4a55-8fd1-5e28321981f4',
- 'e31b4e39-e350-47a9-aca4-72496d99ff2a',
- 'f8d0ecdc-b7bd-44cc-b887-3d544e24e561',
- '6fc4d73c-2071-43ec-a756-c6c6d8322c8b',
- 'c17772a9-21b5-49df-ab31-3017addea12e',
- '0851db85-2889-4070-ac18-a40e8ebd96ba',
- 'eeb27b45-5b85-4e5c-b6ff-f639ca5687de',
- '69f42a9c-095d-4a25-bca8-61a9869871d3',
- 'f03b61b4-6b13-479d-940f-d1608eb275cc',
- 'f2ee886d-5b9c-4d06-a9be-ee7ae8381114',
- 'f26a6ab1-7e37-4f8d-bb50-295c056e1062',
- 'c4f6665f-8be5-476b-a6e8-d81eeae9279d',
- '9117969a-3f0d-478b-ad75-98263e3bfacf',
- 'febb430e-2d50-4f83-87a0-b5ffbb9a4943',
- '8413c5c6-b42b-4ec6-b751-881a54413628',
- '8b7c808f-763b-44c8-b273-63c6afbc6aae',
- 'f936a701-5f8a-4aa1-b7a9-9f8b5b69bc7c',
- '63517fd4-ece1-49eb-9259-371dc30b1dd6',
- '8d59da25-3a9c-44be-8b1a-e27cdd39ca34',
- '19baa84c-22a5-4589-9cbd-c23f111c054c',
- '143dd7cf-6a47-47a1-906d-927ad7fe9117',
- '84bb830f-b9ff-4e6b-9296-f458fb41d160',
- 'b749446c-18e3-4987-820a-50649ab0f826',
- '36362f75-96d8-4ed4-a728-5e72284d0995',
- '9657af01-50bd-4120-8303-416ad9e24a51',
- 'dab512bd-a02d-4c1f-8dbc-9155a163efc0']
-
-
-
-INDEX = 2
-pid = pids[INDEX]
-av = viewer(pid, one=one)
-##
-eid, pname = one.pid2eid(pid)
-session_path = one.eid2path(eid)
-probe_path = session_path.joinpath('alf', pname)
-
-from pathlib import Path
-
-local_path = Path("/datadisk/Data/spike_sorting/mic").joinpath(pid, pname)
-spikes = alfio.load_object(probe_path, 'spikes')
-spikes_ = alfio.load_object(local_path, 'spikes')
-
-
-# from ibllib.plots import vertical_lines
-# vertical_lines(rewards, ymin=0, ymax=3800, ax=ax)
-from brainbox.plot import driftmap
-import matplotlib.pyplot as plt
-fig, ax = plt.subplots(nrows=2, ncols=1, sharex=True, sharey=True)
-driftmap(spikes['times'], spikes['depths'], t_bin=0.1, d_bin=5, ax=ax[0])
-driftmap(spikes_['times'], spikes_['depths'], t_bin=0.1, d_bin=5, ax=ax[1])
-
-
-
diff --git a/viewspikes/examples_stream.py b/viewspikes/examples_stream.py
deleted file mode 100644
index 9ecc804..0000000
--- a/viewspikes/examples_stream.py
+++ /dev/null
@@ -1,13 +0,0 @@
-from one.api import ONE
-from atlaselectrophysiology.alignment_with_easyqc import viewer
-
-one = ONE()
-
-
-"da8dfec1-d265-44e8-84ce-6ae9c109b8bd", # SWC_043_2020-09-21_probe00 ok
-"b749446c-18e3-4987-820a-50649ab0f826", # KS023_2019-12-10_probe01 ok
-"f86e9571-63ff-4116-9c40-aa44d57d2da9", # CSHL049_2020-01-08_probe00 a bit stripy but fine
-"675952a4-e8b3-4e82-a179-cc970d5a8b01", # CSH_ZAD_029_2020-09-19_probe01 a bit stripy as well
-
-pid = "af2a0072-e17e-4368-b80b-1359bf6d4647"
-av = viewer(pid, one=one)
diff --git a/viewspikes/gui.py b/viewspikes/gui.py
index c84b766..32313bf 100644
--- a/viewspikes/gui.py
+++ b/viewspikes/gui.py
@@ -2,23 +2,19 @@
import numpy as np
import scipy.signal
-
from PyQt5 import QtWidgets, QtCore, QtGui, uic
import pyqtgraph as pg
-from brainbox.processing import bincount2D
-from easyqc.gui import viewseis
-import one.alf.io as alfio
-from one.alf.files import get_session_path
-from iblutil.numerical import ismember
-import spikeglx
-from neurodsp import voltage
+from iblutil.numerical import bincount2D
+from viewephys.gui import viewephys
+import neurodsp
+from brainbox.io.one import EphysSessionLoader, SpikeSortingLoader
+from iblatlas.atlas import BrainRegions
-import qt
-from brainbox.io.one import SpikeSortingLoader
+regions = BrainRegions()
T_BIN = .007 # time bin size in secs
-D_BIN = 10 # depth bin size in um
+D_BIN = 20 # depth bin size in um
SNS_PALETTE = [(0.12156862745098039, 0.4666666666666667, 0.7058823529411765),
(1.0, 0.4980392156862745, 0.054901960784313725),
@@ -34,23 +30,24 @@
YMAX = 4000
-def view_raster(bin_file):
- bin_file = Path(bin_file)
- pname = bin_file.parent.name
- session_path = get_session_path(bin_file)
- ssl = SpikeSortingLoader(session_path=session_path, pname=pname)
+def view_raster(pid, one, stream=True):
+ ssl = SpikeSortingLoader(one=one, pid=pid)
+ sl = EphysSessionLoader(one=one, eid=ssl.eid)
+ sl.load_trials()
spikes, clusters, channels = ssl.load_spike_sorting(dataset_types=['spikes.samples'])
- trials = alfio.load_object(ssl.session_path.joinpath('alf'), 'trials')
- return RasterView(bin_file, spikes, clusters, trials=trials)
+
+ return RasterView(ssl, spikes, clusters, channels, trials=sl.trials, stream=stream)
class RasterView(QtWidgets.QMainWindow):
- def __init__(self, bin_file, spikes, clusters, channels=None, trials=None, *args, **kwargs):
- self.sr = spikeglx.Reader(bin_file)
+ def __init__(self, ssl, spikes, clusters, channels=None, trials=None, stream=True, *args, **kwargs):
+ self.ssl = ssl
self.spikes = spikes
self.clusters = clusters
self.channels = channels
self.trials = trials
+ # self.sr_lf = ssl.raw_electrophysiology(band='lf', stream=False) that would be cool to also have the LFP
+ self.sr = ssl.raw_electrophysiology(band='ap', stream=stream)
self.eqcs = []
super(RasterView, self).__init__(*args, **kwargs)
# wave by Diana Militano from the Noun Projectp
@@ -68,7 +65,7 @@ def __init__(self, bin_file, spikes, clusters, channels=None, trials=None, *args
iok = ~np.isnan(spikes.depths)
self.raster, self.rtimes, self.depths = bincount2D(
spikes.times[iok], spikes.depths[iok], T_BIN, D_BIN)
- self.imageItem_raster.setImage(np.flip(self.raster.T))
+ self.imageItem_raster.setImage(self.raster.T)
transform = [T_BIN, 0., 0., 0., D_BIN, 0., - .5, - .5, 1.]
self.transform = np.array(transform).reshape((3, 3)).T
self.imageItem_raster.setTransform(QtGui.QTransform(*transform))
@@ -82,13 +79,12 @@ def __init__(self, bin_file, spikes, clusters, channels=None, trials=None, *args
# self.view.layers[label] = {'layer': new_scatter, 'type': 'scatter'}
self.line_eqc = pg.PlotCurveItem()
self.plotItem_raster.addItem(self.line_eqc)
- # self.plotItem_raster.removeItem(new_curve)
################################################## plot trials
if self.trials is not None:
trial_times = dict(
- goCue_times=trials['goCue_times'],
- error_times=trials['feedback_times'][trials['feedbackType'] == -1],
- reward_times=trials['feedback_times'][trials['feedbackType'] == 1])
+ goCue_times=trials['goCue_times'].values,
+ error_times=trials['feedback_times'][trials['feedbackType'] == -1].values,
+ reward_times=trials['feedback_times'][trials['feedbackType'] == 1].values)
self.trial_lines = {}
for i, k in enumerate(trial_times):
self.trial_lines[k] = pg.PlotCurveItem()
@@ -97,7 +93,6 @@ def __init__(self, bin_file, spikes, clusters, channels=None, trials=None, *args
y = np.tile(np.array([0, 1, 1, 0]), int(trial_times[k].shape[0] / 2 + 1))[
:trial_times[k].shape[0] * 2] * YMAX
self.trial_lines[k].setData(x=x.flatten(), y=y.flatten(), pen=pg.mkPen(np.array(SNS_PALETTE[i]) * 256))
-
self.show()
def mouseClick(self, event):
@@ -131,108 +126,26 @@ def keyPressEvent(self, e):
def show_ephys(self, t0, tlen=1):
- first = int(t0 * self.sr.fs)
- last = first + int(self.sr.fs * tlen)
-
- raw = self.sr[first:last, : - self.sr.nsync].T
+ s0 = int(self.ssl.samples2times(t0, direction='reverse'))
+ s1 = s0 + int(self.sr.fs * tlen)
+ raw = self.sr[s0:s1, : - self.sr.nsync].T
butter_kwargs = {'N': 3, 'Wn': 300 / self.sr.fs * 2, 'btype': 'highpass'}
+
sos = scipy.signal.butter(**butter_kwargs, output='sos')
butt = scipy.signal.sosfiltfilt(sos, raw)
- destripe = voltage.destripe(raw, fs=self.sr.fs)
+ destripe = neurodsp.voltage.destripe(raw, fs=self.sr.fs)
- self.eqc_raw = viewephys(butt, self.sr.fs, channels=None, br=None, title='butt', t0=t0, t_scalar=1)
- self.eqc_des = viewephys(destripe, self.sr.fs, channels=None, br=None, title='destripe', t0=t0, t_scalar=1)
+ self.eqc_raw = viewephys(butt, self.sr.fs, channels=self.channels, br=regions, title='butt', t0=t0, t_scalar=1)
+ self.eqc_des = viewephys(destripe, self.sr.fs, channels=self.channels, br=regions, title='destripe', t0=t0, t_scalar=1)
eqc_xrange = [t0 + tlen / 2 - 0.01, t0 + tlen / 2 + 0.01]
self.eqc_des.viewBox_seismic.setXRange(*eqc_xrange)
self.eqc_raw.viewBox_seismic.setXRange(*eqc_xrange)
- # eqc2 = viewephys(butt - destripe, self.sr.fs, channels=None, br=None, title='diff')
- # overlay spikes
- tprobe = self.spikes.samples / self.sr.fs
- slice_spikes = slice(np.searchsorted(tprobe, t0), np.searchsorted(tprobe, t0 + tlen))
- t = tprobe[slice_spikes]
+ # we slice the spikes using the samples according to ephys time, but display in session times
+ slice_spikes = slice(np.searchsorted(self.spikes['samples'], s0), np.searchsorted(self.spikes['samples'], s1))
+ t = self.spikes['times'][slice_spikes]
c = self.clusters.channels[self.spikes.clusters[slice_spikes]]
self.eqc_raw.ctrl.add_scatter(t, c)
self.eqc_des.ctrl.add_scatter(t, c)
-
-
-
-
-def viewephys(data, fs, channels=None, br=None, title='ephys', t0=0, t_scalar=1e3):
- """
- :param data: [nc, ns]
- :param fs:
- :param channels:
- :param br:
- :param title:
- :return:
- """
- width = 40
- height = 800
- nc, ns = data.shape
- # ih = np.linspace(0, nc - 1, height).astype(np.int32)
- # image = br.rgb[channels['ibr'][ih]].astype(np.uint8)
- # image = np.tile(image[:, np.newaxis, :], (1, width, 1))
- # image = np.tile(image[np.newaxis, :, :], (width, 1, 1))
- from ibllib.ephys.neuropixel import trace_header
- if channels is None or br is None:
- channels = trace_header(version = 1)
- eqc = viewseis(data.T, si=1 / fs * t_scalar, h=channels, title=title, taxis=0, t0=t0)
- return eqc
- else:
- _, ir = ismember(channels['atlas_id'], br.id)
- image = br.rgb[ir].astype(np.uint8)
- image = image[np.newaxis, :, :]
-
-
- eqc = viewseis(data.T, si=1 / fs * t_scalar, h=channels, title=title, taxis=0)
- imitem = pg.ImageItem(image)
- eqc.plotItem_header_v.addItem(imitem)
- transform = [1, 0, 0, 0, 1, 0, -0.5, 0, 1.]
- imitem.setTransform(QtGui.QTransform(*transform))
- eqc.plotItem_header_v.setLimits(xMin=-.5, xMax=.5)
- # eqc.comboBox_header.setVisible(False)
-
- return eqc
-
-
-COLOR_PLOTS = (pg.mkColor((31, 119, 180)),)
-
-
-def view2p(tiff_file, title=None):
- qt.create_app()
- v2p = View2p._get_or_create(title=title)
- v2p.update_tiff(tiff_file)
- v2p.show()
- return v2p
-
-
-class View2p(QtWidgets.QMainWindow):
- """
- This is the view in the MVC approach
- """
- layers = None # used for additional scatter layers
-
- @staticmethod
- def _instances():
- app = QtWidgets.QApplication.instance()
- return [w for w in app.topLevelWidgets() if isinstance(w, View2p)]
-
- @staticmethod
- def _get_or_create(title=None):
- v2p = next(filter(lambda e: e.isVisible() and e.windowTitle() == title,
- View2p._instances()), None)
- if v2p is None:
- v2p = View2p()
- v2p.setWindowTitle(title)
- return v2p
-
- def __init__(self, *args, **kwargs):
- super(View2p, self).__init__(*args, **kwargs)
- # wave by Diana Militano from the Noun Projectp
- uic.loadUi(Path(__file__).parent.joinpath('view2p.ui'), self)
-
- def update_tiff(self, tiff_file):
- pass
\ No newline at end of file
diff --git a/viewspikes/main.py b/viewspikes/main.py
deleted file mode 100644
index 6c986e2..0000000
--- a/viewspikes/main.py
+++ /dev/null
@@ -1,93 +0,0 @@
-from pathlib import Path
-
-import scipy.signal
-import numpy as np
-
-import spikeglx
-from neurodsp import voltage
-import neuropixel
-from one.api import ONE
-from easyqc.gui import viewseis
-
-from viewspikes.plots import plot_insertion, show_psd, overlay_spikes
-from viewspikes.data import stream, get_spikes, get_ks2
-
-folder_samples = Path('/datadisk/Data/spike_sorting/short_samples')
-files_samples = list(folder_samples.rglob('*.bin'))
-
-one = ONE()
-SIDE_BY_SIDE = False
-#
-# pins = one.alyx.rest('insertions', 'list', django=('json__extended_qc__alignment_count__gt,0'))
-# pid, t0 = ('3e7618b8-34ca-4e48-ba3a-0e0f88a43131', 1002) # SWC_054_2020-10-10_probe01__ - sync w/ spikes !!!
-# pid, t0 = ('04c9890f-2276-4c20-854f-305ff5c9b6cf', 1002.) # SWC_054_2020-10-10_probe00__04c9890f-2276-4c20-854f-305ff5c9b6cf - sync w/ spikes !!!
-# pid, t0 = ('0925fb1b-cf83-4f55-bfb7-aa52f993a404', 500.) # DY_013_2020-03-06_probe00__0925fb1b-cf83-4f55-bfb7-aa52f993a404
-# pid, t0 = ('0ece5c6a-7d1e-4365-893d-ac1cc04f1d7b', 750.) # CSHL045_2020-02-27_probe01__0ece5c6a-7d1e-4365-893d-ac1cc04f1d7b
-# pid, t0 = ('0ece5c6a-7d1e-4365-893d-ac1cc04f1d7b', 3000.) # CSHL045_2020-02-27_probe01__0ece5c6a-7d1e-4365-893d-ac1cc04f1d7b
-pid, t0 = ('10ef1dcd-093c-4839-8f38-90a25edefb49', 2400.)
-# pid, t0 = ('1a6a17cc-ba8c-4d79-bf20-cc897c9500dc', 5000)
-# pid, t0 = ('2dd99c91-292f-44e3-bbf2-8cfa56015106', 2500) # NYU-23_2020-10-14_probe01__2dd99c91-292f-44e3-bbf2-8cfa56015106
-# pid, t0 = ('2dd99c91-292f-44e3-bbf2-8cfa56015106', 6000) # NYU-23_2020-10-14_probe01__2dd99c91-292f-44e3-bbf2-8cfa56015106
-# pid, t0 = ('30dfb8c6-9202-43fd-a92d-19fe68602b6f', 2400.) # ibl_witten_27_2021-01-16_probe00__30dfb8c6-9202-43fd-a92d-19fe68602b6f
-# pid, t0 = ('31dd223c-0c7c-48b5-a513-41feb4000133', 3000.) # really good one : striping on not all channels
-# pid, t0 = ('39b433d0-ec60-460f-8002-a393d81620a4', 2700.) # ZFM-01577_2020-10-27_probe01 needs FDNAT
-# pid, t0 = ('47da98a8-f282-4830-92c2-af0e1d4f00e2', 2700.)
-
-# 67 frequency spike
-# 458 /datadisk/Data/spike_sorting/short_samples/b45c8f3f-6361-41df-9bc1-9df98b3d30e6_01210.bin ERROR dans le chargement de la whitening matrix
-# 433 /datadisk/Data/spike_sorting/short_samples/8d59da25-3a9c-44be-8b1a-e27cdd39ca34_04210.bin Cortex complètement silencieux.
-# 531 /datadisk/Data/spike_sorting/short_samples/47be9ae4-290f-46ab-b047-952bc3a1a509_00010.bin Sympa pour le spike sorting, un bon example de trace pourrie à enlever avec FDNAT / Cadzow. Il y a du striping à la fin mais pas de souci pour KS2 ou pour le FK.
-# 618 5b9ce60c-dcc9-4789-b2ff-29d873829fa5_03610.bin: gros cabossage plat laissé par le FK !! Tester un filtre K tout bête # spikes tous petits en comparaison. Le spike sorting a l'air décalé
-# 681 /datadisk/Data/spike_sorting/short_samples/eab93ab0-26e3-4bd9-9c53-9f81c35172f4_02410.bin !! Spikes décalés. Superbe example de layering dans le cerveau avec 3 niveaux très clairement définis
-# 739 /datadisk/Data/spike_sorting/short_samples/f03b61b4-6b13-479d-940f-d1608eb275cc_04210.bin: Autre example de layering ou les charactéristiques spectrales / spatiales sont très différentes. Spikes alignés
-# 830 /datadisk/Data/spike_sorting/short_samples/b02c0ce6-2436-4fc0-9ea0-e7083a387d7e_03010.bin, très mauvaise qualité - spikes sont décalés ?!?
-
-
-
-file_ind = np.random.randint(len(files_samples))
-file_ind = 739 # very good quality spike sorting
-print(file_ind, files_samples[file_ind])
-
-pid, t0 = ('47da98a8-f282-4830-92c2-af0e1d4f00e2', 1425.)
-
-pid = files_samples[file_ind]
-# pid, t0 = ("01c6065e-eb3c-49ba-9c25-c1f17b18d529", 500)
-if isinstance(pid, Path):
- file_sample = pid
- pid, t0 = file_sample.stem.split('_')
- t0 = float(t0)
- sr = spikeglx.Reader(file_sample, open=True)
- dsets = one.alyx.rest('datasets', 'list', probe_insertion=pid)
-else:
- sr, dsets, t0 = stream(pid, t0, one=one, samples_folder=folder_samples)
-
-#
-plot_insertion(pid, one)
-
-
-h = neuropixel.trace_header()
-raw = sr[:, :-1].T
-
-sos = scipy.signal.butter(3, 300 / sr.fs / 2, btype='highpass', output='sos')
-butt = scipy.signal.sosfiltfilt(sos, raw)
-# show_psd(butt, sr.fs)
-
-fk_kwargs ={'dx': 1, 'vbounds': [0, 1e6], 'ntr_pad': 160, 'ntr_tap': 0, 'lagc': .01, 'btype': 'lowpass'}
-destripe = voltage.destripe(raw, fs=sr.fs, fk_kwargs=fk_kwargs, tr_sel=np.arange(raw.shape[0]))
-ks2 = get_ks2(raw, dsets, one)
-
-# get the spikes corresponding to current chunk, here needs to go through samples for sync reasons
-spikes, clusters, channels = get_spikes(dsets, one)
-
-if SIDE_BY_SIDE:
- hhh = {k: np.tile(h[k], 3) for k in h}
- eqc_concat = viewseis(np.r_[butt, destripe, ks2], si=1 / sr.fs, h=hhh, t0=t0, title='concat')
- overlay_spikes(eqc_concat, spikes, clusters, channels)
-else:
- eqc_butt = viewseis(butt.T, si=1 / sr.fs, h=h, t0=t0, title='butt', taxis=0)
- eqc_dest = viewseis(destripe.T, si=1 / sr.fs, h=h, t0=t0, title='destr', taxis=0)
- eqc_ks2 = viewseis(ks2.T, si=1 / sr.fs, h=h, t0=t0, title='ks2', taxis=0)
- overlay_spikes(eqc_butt, spikes, clusters, channels)
- overlay_spikes(eqc_dest, spikes, clusters, channels)
- overlay_spikes(eqc_ks2, spikes, clusters, channels)
-sr.close()
diff --git a/viewspikes/view2p.ui b/viewspikes/raster.ui
similarity index 51%
rename from viewspikes/view2p.ui
rename to viewspikes/raster.ui
index f5b6819..a6a6bc7 100644
--- a/viewspikes/view2p.ui
+++ b/viewspikes/raster.ui
@@ -6,54 +6,54 @@
0
0
- 810
- 606
+ 999
+ 656
MainWindow
-
-
-
- -1
- -1
- 801
- 551
-
-
-
- -
-
-
-
-
-
-
-
- -10
- 550
- 799
- 15
-
-
-
- Qt::Horizontal
-
-
+
+ -
+
+
-
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+
+
+
+ open...
+
+