-
Notifications
You must be signed in to change notification settings - Fork 34
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
No curation ephys AND kilosort triggering #54
Changes from 101 commits
f740aef
042cc46
a39a9b1
590310e
adfad95
b7c0845
de84ce0
4397dd7
5420ae0
70e93b3
a7e7554
0d56456
047bfa1
60105da
a9326ea
149ef3f
9f98195
a24bd1a
ba28637
5cdc994
6c646bb
dd01fd2
f699ce7
6bf0eb1
6788180
d63561f
375e437
c593baf
69c5e51
a6cae12
a0ea9f7
acdab12
38c5be6
28c4452
94aade7
ae966aa
b9f4e92
044c389
0f0c212
67341d8
c2ee64f
dc7ddd9
408532c
55bec01
f34e95d
19b704b
beaf765
74e3ead
e8ffe17
d07f830
19616ef
09c1e60
3ebdf23
b25f065
49ca0be
199a2ba
58b5984
ddc3b94
df599fb
819ff19
81d99c8
96931a4
b6f8f99
4250220
af2b18b
e325a30
db3027b
f55a6a7
d105419
0d16e7e
c213325
adffe34
43d6614
da10c66
02069c9
142459d
1c39568
2022e91
02c4b67
8dff08b
6107e8e
dae36d1
8657d58
aa47c8a
31bba8c
f9a4754
f2881ca
c56cd18
9dd6b42
4951b39
b4832ea
d66368c
779b2fb
f4052cc
03cab02
cb1a041
7320f9f
f0b3d4a
bdcfa46
83649f5
c2f8aea
e0a9a4f
769de13
39c8579
85c7c8b
11a12ba
cd5fe70
af864d7
47babf3
7fecff1
ddd4095
a578d85
f4b917d
f11e016
07604e2
4e367d7
67039ac
9a59e57
b97566e
3f1ee37
0c77826
b71b459
a3c5c2f
fd331bd
b2bd0ee
97f3d21
d8aea04
f9f18d0
5905392
987231b
aed42ca
fbdbe24
35da39b
c33d1b0
f60ba3d
71d87ae
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import datajoint as dj | ||
import logging | ||
import os | ||
|
||
|
||
dj.config['enable_python_native_blobs'] = True | ||
|
||
|
||
def get_logger(name): | ||
log = logging.getLogger(name) | ||
log.setLevel(os.getenv('LOGLEVEL', 'INFO')) | ||
return log | ||
|
||
import ephys_acute as ephys | ||
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
@@ -18,7 +18,7 @@ def activate(schema_name, *, create_schema=True, create_tables=True): | |||||||||
schema.activate(schema_name, create_schema=create_schema, create_tables=create_tables) | ||||||||||
|
||||||||||
# Add neuropixels probes | ||||||||||
for probe_type in ('neuropixels 1.0 - 3A', 'neuropixels 1.0 - 3B', | ||||||||||
for probe_type in ('neuropixels 1.0 - 3A', 'neuropixels 1.0 - 3B', 'neuropixels UHD', | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Minor fix. Phase 3A is different than Neuropixels 1.0 which is also called Phase 3B. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Source: cortex-lab/neuropixels wiki |
||||||||||
'neuropixels 2.0 - SS', 'neuropixels 2.0 - MS'): | ||||||||||
ProbeType.create_neuropixels_probe(probe_type) | ||||||||||
|
||||||||||
|
@@ -46,15 +46,38 @@ class Electrode(dj.Part): | |||||||||
def create_neuropixels_probe(probe_type='neuropixels 1.0 - 3A'): | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||
""" | ||||||||||
Create `ProbeType` and `Electrode` for neuropixels probes: | ||||||||||
1.0 (3A and 3B), 2.0 (SS and MS) | ||||||||||
+ neuropixels 1.0 - 3A | ||||||||||
+ neuropixels 1.0 - 3B | ||||||||||
Comment on lines
+49
to
+50
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||
+ neuropixels UHD | ||||||||||
+ neuropixels 2.0 - SS | ||||||||||
+ neuropixels 2.0 - MS | ||||||||||
|
||||||||||
For electrode location, the (0, 0) is the | ||||||||||
bottom left corner of the probe (ignore the tip portion) | ||||||||||
Electrode numbering is 1-indexing | ||||||||||
""" | ||||||||||
|
||||||||||
neuropixels_probes_config = { | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am trying to double check these numbers. I have been going through the manuscripts. Do you have a source that compiles all of these numbers? Thanks. |
||||||||||
'neuropixels 1.0 - 3A': dict(site_count=960, col_spacing=32, row_spacing=20, | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||
white_spacing=16, col_count=2, | ||||||||||
shank_count=1, shank_spacing=0), | ||||||||||
'neuropixels 1.0 - 3B': dict(site_count=960, col_spacing=32, row_spacing=20, | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||
white_spacing=16, col_count=2, | ||||||||||
shank_count=1, shank_spacing=0), | ||||||||||
'neuropixels UHD': dict(site_count=384, col_spacing=6, row_spacing=6, | ||||||||||
white_spacing=0, col_count=8, | ||||||||||
shank_count=1, shank_spacing=0), | ||||||||||
'neuropixels 2.0 - SS': dict(site_count=1280, col_spacing=32, row_spacing=15, | ||||||||||
white_spacing=0, col_count=2, | ||||||||||
shank_count=1, shank_spacing=250), | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||
'neuropixels 2.0 - MS': dict(site_count=1280, col_spacing=32, row_spacing=15, | ||||||||||
white_spacing=0, col_count=2, | ||||||||||
shank_count=4, shank_spacing=250) | ||||||||||
} | ||||||||||
|
||||||||||
def build_electrodes(site_count, col_spacing, row_spacing, | ||||||||||
white_spacing, col_count=2, | ||||||||||
shank_count=1, shank_spacing=250): | ||||||||||
white_spacing, col_count, | ||||||||||
shank_count, shank_spacing): | ||||||||||
""" | ||||||||||
:param site_count: site count per shank | ||||||||||
:param col_spacing: (um) horrizontal spacing between sites | ||||||||||
|
@@ -66,14 +89,15 @@ def build_electrodes(site_count, col_spacing, row_spacing, | |||||||||
:return: | ||||||||||
""" | ||||||||||
row_count = int(site_count / col_count) | ||||||||||
x_coords = np.tile([0, 0 + col_spacing], row_count) | ||||||||||
x_white_spaces = np.tile([white_spacing, white_spacing, 0, 0], int(row_count / 2)) | ||||||||||
x_coords = np.tile(np.arange(0, col_spacing * col_count, col_spacing), row_count) | ||||||||||
y_coords = np.repeat(np.arange(row_count) * row_spacing, col_count) | ||||||||||
|
||||||||||
x_coords = x_coords + x_white_spaces | ||||||||||
y_coords = np.repeat(np.arange(row_count) * row_spacing, 2) | ||||||||||
if white_spacing: | ||||||||||
x_white_spaces = np.tile([white_spacing, white_spacing, 0, 0], int(row_count / 2)) | ||||||||||
x_coords = x_coords + x_white_spaces | ||||||||||
|
||||||||||
shank_cols = np.tile([0, 1], row_count) | ||||||||||
shank_rows = np.repeat(range(row_count), 2) | ||||||||||
shank_cols = np.tile(range(col_count), row_count) | ||||||||||
shank_rows = np.repeat(range(row_count), col_count) | ||||||||||
|
||||||||||
npx_electrodes = [] | ||||||||||
for shank_no in range(shank_count): | ||||||||||
|
@@ -88,51 +112,12 @@ def build_electrodes(site_count, col_spacing, row_spacing, | |||||||||
|
||||||||||
return npx_electrodes | ||||||||||
|
||||||||||
# ---- 1.0 3A ---- | ||||||||||
if probe_type == 'neuropixels 1.0 - 3A': | ||||||||||
electrodes = build_electrodes(site_count=960, col_spacing=32, row_spacing=20, | ||||||||||
white_spacing=16, col_count=2) | ||||||||||
|
||||||||||
probe_type = {'probe_type': 'neuropixels 1.0 - 3A'} | ||||||||||
with ProbeType.connection.transaction: | ||||||||||
ProbeType.insert1(probe_type, skip_duplicates=True) | ||||||||||
ProbeType.Electrode.insert([{**probe_type, **e} for e in electrodes], | ||||||||||
skip_duplicates=True) | ||||||||||
|
||||||||||
# ---- 1.0 3B ---- | ||||||||||
if probe_type == 'neuropixels 1.0 - 3B': | ||||||||||
electrodes = build_electrodes(site_count=960, col_spacing=32, row_spacing=20, | ||||||||||
white_spacing=16, col_count=2) | ||||||||||
|
||||||||||
probe_type = {'probe_type': 'neuropixels 1.0 - 3B'} | ||||||||||
with ProbeType.connection.transaction: | ||||||||||
ProbeType.insert1(probe_type, skip_duplicates=True) | ||||||||||
ProbeType.Electrode.insert([{**probe_type, **e} for e in electrodes], | ||||||||||
skip_duplicates=True) | ||||||||||
|
||||||||||
# ---- 2.0 Single shank ---- | ||||||||||
if probe_type == 'neuropixels 2.0 - SS': | ||||||||||
electrodes = build_electrodes(site_count=1280, col_spacing=32, row_spacing=15, | ||||||||||
white_spacing=0, col_count=2, | ||||||||||
shank_count=1, shank_spacing=250) | ||||||||||
|
||||||||||
probe_type = {'probe_type': 'neuropixels 2.0 - SS'} | ||||||||||
with ProbeType.connection.transaction: | ||||||||||
ProbeType.insert1(probe_type, skip_duplicates=True) | ||||||||||
ProbeType.Electrode.insert([{**probe_type, **e} for e in electrodes], | ||||||||||
skip_duplicates=True) | ||||||||||
|
||||||||||
# ---- 2.0 Multi shank ---- | ||||||||||
if probe_type == 'neuropixels 2.0 - MS': | ||||||||||
electrodes = build_electrodes(site_count=1280, col_spacing=32, row_spacing=15, | ||||||||||
white_spacing=0, col_count=2, | ||||||||||
shank_count=4, shank_spacing=250) | ||||||||||
|
||||||||||
probe_type = {'probe_type': 'neuropixels 2.0 - MS'} | ||||||||||
with ProbeType.connection.transaction: | ||||||||||
ProbeType.insert1(probe_type, skip_duplicates=True) | ||||||||||
ProbeType.Electrode.insert([{**probe_type, **e} for e in electrodes], | ||||||||||
skip_duplicates=True) | ||||||||||
electrodes = build_electrodes(**neuropixels_probes_config[probe_type]) | ||||||||||
probe_type = {'probe_type': probe_type} | ||||||||||
with ProbeType.connection.transaction: | ||||||||||
ProbeType.insert1(probe_type, skip_duplicates=True) | ||||||||||
ProbeType.Electrode.insert([{**probe_type, **e} for e in electrodes], | ||||||||||
skip_duplicates=True) | ||||||||||
|
||||||||||
|
||||||||||
@schema | ||||||||||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -12,7 +12,7 @@ | |||||
|
||||||
class Kilosort: | ||||||
|
||||||
kilosort_files = [ | ||||||
_kilosort_core_files = [ | ||||||
'params.py', | ||||||
'amplitudes.npy', | ||||||
'channel_map.npy', | ||||||
|
@@ -22,47 +22,60 @@ class Kilosort: | |||||
'similar_templates.npy', | ||||||
'spike_templates.npy', | ||||||
'spike_times.npy', | ||||||
'spike_times_sec.npy', | ||||||
'spike_times_sec_adj.npy', | ||||||
'template_features.npy', | ||||||
'template_feature_ind.npy', | ||||||
'templates.npy', | ||||||
'templates_ind.npy', | ||||||
'whitening_mat.npy', | ||||||
'whitening_mat_inv.npy', | ||||||
'spike_clusters.npy', | ||||||
'spike_clusters.npy' | ||||||
] | ||||||
|
||||||
_kilosort_additional_files = [ | ||||||
'spike_times_sec.npy', | ||||||
'spike_times_sec_adj.npy', | ||||||
'cluster_groups.csv', | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
'cluster_KSLabel.tsv' | ||||||
] | ||||||
|
||||||
# keys to self.files, .data are file name e.g. self.data['params'], etc. | ||||||
kilosort_keys = [path.splitext(kilosort_file)[0] for kilosort_file in kilosort_files] | ||||||
kilosort_files = _kilosort_core_files + _kilosort_additional_files | ||||||
|
||||||
def __init__(self, kilosort_dir): | ||||||
self._kilosort_dir = pathlib.Path(kilosort_dir) | ||||||
self._files = {} | ||||||
self._data = None | ||||||
self._clusters = None | ||||||
|
||||||
params_filepath = kilosort_dir / 'params.py' | ||||||
|
||||||
if not params_filepath.exists(): | ||||||
raise FileNotFoundError(f'No Kilosort output found in: {kilosort_dir}') | ||||||
self.validate() | ||||||
|
||||||
params_filepath = kilosort_dir / 'params.py' | ||||||
self._info = {'time_created': datetime.fromtimestamp(params_filepath.stat().st_ctime), | ||||||
'time_modified': datetime.fromtimestamp(params_filepath.stat().st_mtime)} | ||||||
|
||||||
@property | ||||||
def data(self): | ||||||
if self._data is None: | ||||||
self._stat() | ||||||
self._load() | ||||||
return self._data | ||||||
|
||||||
@property | ||||||
def info(self): | ||||||
return self._info | ||||||
|
||||||
def _stat(self): | ||||||
def validate(self): | ||||||
""" | ||||||
Check if this is a valid set of kilosort outputs - i.e. all crucial files exist | ||||||
""" | ||||||
missing_files = [] | ||||||
for f in Kilosort._kilosort_core_files: | ||||||
full_path = self._kilosort_dir / f | ||||||
if not full_path.exists(): | ||||||
missing_files.append(f) | ||||||
if missing_files: | ||||||
raise FileNotFoundError(f'Kilosort files missing in ({self._kilosort_dir}):' | ||||||
f' {missing_files}') | ||||||
|
||||||
def _load(self): | ||||||
self._data = {} | ||||||
for kilosort_filename in Kilosort.kilosort_files: | ||||||
kilosort_filepath = self._kilosort_dir / kilosort_filename | ||||||
|
@@ -91,16 +104,18 @@ def _stat(self): | |||||
self._data[base] = (np.reshape(d, d.shape[0]) | ||||||
if d.ndim == 2 and d.shape[1] == 1 else d) | ||||||
|
||||||
self._data['channel_map'] = self._data['channel_map'].flatten() | ||||||
|
||||||
# Read the Cluster Groups | ||||||
for cluster_pattern, cluster_col_name in zip(['cluster_groups.*', 'cluster_KSLabel.*'], | ||||||
for cluster_pattern, cluster_col_name in zip(['cluster_group.*', 'cluster_KSLabel.*'], | ||||||
['group', 'KSLabel']): | ||||||
try: | ||||||
cluster_file = next(self._kilosort_dir.glob(cluster_pattern)) | ||||||
except StopIteration: | ||||||
pass | ||||||
else: | ||||||
cluster_file_suffix = cluster_file.suffix | ||||||
assert cluster_file_suffix in ('.csv', '.tsv', '.xlsx') | ||||||
assert cluster_file_suffix in ('.tsv', '.xlsx') | ||||||
break | ||||||
else: | ||||||
raise FileNotFoundError( | ||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.