Skip to content

Commit 0f518f1

Browse files
authored
Merge pull request #116 from JaerongA/ephys_test
modify build_electrodes function
2 parents 61cb23a + 59c72c4 commit 0f518f1

File tree

5 files changed

+86
-84
lines changed

5 files changed

+86
-84
lines changed

CHANGELOG.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,17 @@
33
Observes [Semantic Versioning](https://semver.org/spec/v2.0.0.html) standard and
44
[Keep a Changelog](https://keepachangelog.com/en/1.0.0/) convention.
55

6-
## [0.2.1] - Unreleased
6+
## [0.2.1] - 2022-01-06
77

8+
+ Add - `build_electrode_layouts` function in `probe.py` to compute the electrode layout for all types of probes.
89
+ Update - parameterize run_CatGT step from parameters retrieved from `ClusteringParamSet` table
910
+ Update - clustering step, update duration for "median_subtraction" step
1011
+ Bugfix - handles single probe recording in "Neuropix-PXI" format
1112
+ Update - safeguard in creating/inserting probe types upon probe activation
1213
+ Add - quality control metric dashboard
1314
+ Update & fix docstrings
1415
+ Update - `ephys_report.UnitLevelReport` to add `ephys.ClusterQualityLabel` as a foreign key reference
15-
+ Add `.pre-commit-config.yaml`
16-
16+
+ Add - `.pre-commit-config.yaml`
1717

1818
## [0.2.0] - 2022-10-28
1919

element_array_ephys/ephys_acute.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -680,7 +680,7 @@ class ClusterQualityLabel(dj.Lookup):
680680
681681
Attributes:
682682
cluster_quality_label (foreign key, varchar(100) ): Cluster quality type.
683-
cluster_quality_description (varchar(4000) ): Description of the cluster quality type.
683+
cluster_quality_description ( varchar(4000) ): Description of the cluster quality type.
684684
"""
685685

686686
definition = """
@@ -704,7 +704,7 @@ class ClusteringTask(dj.Manual):
704704
Attributes:
705705
EphysRecording (foreign key): EphysRecording primary key.
706706
ClusteringParamSet (foreign key): ClusteringParamSet primary key.
707-
clustering_outdir_dir (varchar (255) ): Relative path to output clustering results.
707+
clustering_output_dir ( varchar (255) ): Relative path to output clustering results.
708708
task_mode (enum): `Trigger` computes clustering or and `load` imports existing data.
709709
"""
710710

@@ -793,7 +793,7 @@ class Clustering(dj.Imported):
793793
Attributes:
794794
ClusteringTask (foreign key): ClusteringTask primary key.
795795
clustering_time (datetime): Time when clustering results are generated.
796-
package_version (varchar(16) ): Package version used for a clustering analysis.
796+
package_version ( varchar(16) ): Package version used for a clustering analysis.
797797
"""
798798

799799
definition = """
@@ -918,10 +918,10 @@ class Curation(dj.Manual):
918918
Clustering (foreign key): Clustering primary key.
919919
curation_id (foreign key, int): Unique curation ID.
920920
curation_time (datetime): Time when curation results are generated.
921-
curation_output_dir (varchar(255) ): Output directory of the curated results.
921+
curation_output_dir ( varchar(255) ): Output directory of the curated results.
922922
quality_control (bool): If True, this clustering result has undergone quality control.
923923
manual_curation (bool): If True, manual curation has been performed on this clustering result.
924-
curation_note (varchar(2000) ): Notes about the curation task.
924+
curation_note ( varchar(2000) ): Notes about the curation task.
925925
"""
926926

927927
definition = """

element_array_ephys/ephys_no_curation.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
from element_interface.utils import dict_to_uuid, find_full_path, find_root_directory
1212

1313
from . import ephys_report, get_logger, probe
14-
1514
from .readers import kilosort, openephys, spikeglx
1615

1716
log = get_logger(__name__)

element_array_ephys/probe.py

Lines changed: 77 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,9 @@ class Electrode(dj.Part):
7878
---
7979
shank: int # shank index, starts at 0, advance left to right
8080
shank_col: int # column index, starts at 0, advance left to right
81-
shank_row: int # row index, starts at 0, advance tip to tail
82-
x_coord=NULL: float # (um) x coordinate of the electrode within the probe, (0, 0) is the bottom left corner of the probe
83-
y_coord=NULL: float # (um) y coordinate of the electrode within the probe, (0, 0) is the bottom left corner of the probe
81+
shank_row: int # row index, starts at 0.
82+
x_coord=NULL: float # (um) x coordinate of the electrode within the probe.
83+
y_coord=NULL: float # (um) y coordinate of the electrode within the probe.
8484
"""
8585

8686
@staticmethod
@@ -100,114 +100,59 @@ def create_neuropixels_probe(probe_type: str = "neuropixels 1.0 - 3A"):
100100

101101
neuropixels_probes_config = {
102102
"neuropixels 1.0 - 3A": dict(
103-
site_count=960,
103+
site_count_per_shank=960,
104104
col_spacing=32,
105105
row_spacing=20,
106106
white_spacing=16,
107-
col_count=2,
107+
col_count_per_shank=2,
108108
shank_count=1,
109109
shank_spacing=0,
110110
),
111111
"neuropixels 1.0 - 3B": dict(
112-
site_count=960,
112+
site_count_per_shank=960,
113113
col_spacing=32,
114114
row_spacing=20,
115115
white_spacing=16,
116-
col_count=2,
116+
col_count_per_shank=2,
117117
shank_count=1,
118118
shank_spacing=0,
119119
),
120120
"neuropixels UHD": dict(
121-
site_count=384,
121+
site_count_per_shank=384,
122122
col_spacing=6,
123123
row_spacing=6,
124124
white_spacing=0,
125-
col_count=8,
125+
col_count_per_shank=8,
126126
shank_count=1,
127127
shank_spacing=0,
128128
),
129129
"neuropixels 2.0 - SS": dict(
130-
site_count=1280,
130+
site_count_per_shank=1280,
131131
col_spacing=32,
132132
row_spacing=15,
133133
white_spacing=0,
134-
col_count=2,
134+
col_count_per_shank=2,
135135
shank_count=1,
136136
shank_spacing=250,
137137
),
138138
"neuropixels 2.0 - MS": dict(
139-
site_count=1280,
139+
site_count_per_shank=1280,
140140
col_spacing=32,
141141
row_spacing=15,
142142
white_spacing=0,
143-
col_count=2,
143+
col_count_per_shank=2,
144144
shank_count=4,
145145
shank_spacing=250,
146146
),
147147
}
148148

149-
def build_electrodes(
150-
site_count: int,
151-
col_spacing: float,
152-
row_spacing: float,
153-
white_spacing: float,
154-
col_count: int,
155-
shank_count: int,
156-
shank_spacing: float,
157-
) -> dict:
158-
"""Builds electrode layouts.
159-
160-
Args:
161-
site_count (int): site count per shank
162-
col_spacing (float): (um) horizontal spacing between sites
163-
row_spacing (float): (um) vertical spacing between columns
164-
white_spacing (float): (um) offset spacing
165-
col_count (int): number of column per shank
166-
shank_count (int): number of shank
167-
shank_spacing (float): spacing between shanks
168-
"""
169-
row_count = int(site_count / col_count)
170-
x_coords = np.tile(
171-
np.arange(0, col_spacing * col_count, col_spacing), row_count
172-
)
173-
y_coords = np.repeat(np.arange(row_count) * row_spacing, col_count)
174-
175-
if white_spacing:
176-
x_white_spaces = np.tile(
177-
[white_spacing, white_spacing, 0, 0], int(row_count / 2)
178-
)
179-
x_coords = x_coords + x_white_spaces
180-
181-
shank_cols = np.tile(range(col_count), row_count)
182-
shank_rows = np.repeat(range(row_count), col_count)
183-
184-
npx_electrodes = []
185-
for shank_no in range(shank_count):
186-
npx_electrodes.extend(
187-
[
188-
{
189-
"electrode": (site_count * shank_no) + e_id,
190-
"shank": shank_no,
191-
"shank_col": c_id,
192-
"shank_row": r_id,
193-
"x_coord": x + (shank_no * shank_spacing),
194-
"y_coord": y,
195-
}
196-
for e_id, (c_id, r_id, x, y) in enumerate(
197-
zip(shank_cols, shank_rows, x_coords, y_coords)
198-
)
199-
]
200-
)
201-
202-
return npx_electrodes
203-
204-
electrodes = build_electrodes(**neuropixels_probes_config[probe_type])
205149
probe_type = {"probe_type": probe_type}
150+
electrode_layouts = build_electrode_layouts(
151+
**{**neuropixels_probes_config[probe_type["probe_type"]], **probe_type}
152+
)
206153
with ProbeType.connection.transaction:
207154
ProbeType.insert1(probe_type, skip_duplicates=True)
208-
ProbeType.Electrode.insert(
209-
[{**probe_type, **e} for e in electrodes], skip_duplicates=True
210-
)
155+
ProbeType.Electrode.insert(electrode_layouts, skip_duplicates=True)
211156

212157

213158
@schema
@@ -217,7 +162,7 @@ class Probe(dj.Lookup):
217162
Attributes:
218163
probe (foreign key, varchar(32) ): Unique ID for this model of the probe.
219164
ProbeType (dict): ProbeType entry.
220-
probe_comment (varchar(1000) ): Comment about this model of probe.
165+
probe_comment ( varchar(1000) ): Comment about this model of probe.
221166
"""
222167

223168
definition = """
@@ -236,7 +181,7 @@ class ElectrodeConfig(dj.Lookup):
236181
Attributes:
237182
electrode_config_hash (foreign key, uuid): unique index for electrode configuration.
238183
ProbeType (dict): ProbeType entry.
239-
electrode_config_name (varchar(4000) ): User-friendly name for this electrode configuration.
184+
electrode_config_name ( varchar(4000) ): User-friendly name for this electrode configuration.
240185
"""
241186

242187
definition = """
@@ -259,3 +204,61 @@ class Electrode(dj.Part):
259204
-> master
260205
-> ProbeType.Electrode
261206
"""
207+
208+
209+
def build_electrode_layouts(
210+
probe_type: str,
211+
site_count_per_shank: int,
212+
col_spacing: float = None,
213+
row_spacing: float = None,
214+
white_spacing: float = None,
215+
col_count_per_shank: int = 1,
216+
shank_count: int = 1,
217+
shank_spacing: float = None,
218+
y_origin="bottom",
219+
) -> list[dict]:
220+
221+
"""Builds electrode layouts.
222+
223+
Args:
224+
probe_type (str): probe type (e.g., "neuropixels 1.0 - 3A").
225+
site_count_per_shank (int): site count per shank.
226+
col_spacing (float): (um) horizontal spacing between sites. Defaults to None (single column).
227+
row_spacing (float): (um) vertical spacing between columns. Defaults to None (single row).
228+
white_spacing (float): (um) offset spacing. Defaults to None.
229+
col_count_per_shank (int): number of column per shank. Defaults to 1 (single column).
230+
shank_count (int): number of shank. Defaults to 1 (single shank).
231+
shank_spacing (float): (um) spacing between shanks. Defaults to None (single shank).
232+
y_origin (str): {"bottom", "top"}. y value decrements if "top". Defaults to "bottom".
233+
"""
234+
row_count = int(site_count_per_shank / col_count_per_shank)
235+
x_coords = np.tile(
236+
np.arange(0, (col_spacing or 1) * col_count_per_shank, (col_spacing or 1)),
237+
row_count,
238+
)
239+
y_coords = np.repeat(np.arange(row_count) * (row_spacing or 1), col_count_per_shank)
240+
241+
if white_spacing:
242+
x_white_spaces = np.tile(
243+
[white_spacing, white_spacing, 0, 0], int(row_count / 2)
244+
)
245+
x_coords = x_coords + x_white_spaces
246+
247+
shank_cols = np.tile(range(col_count_per_shank), row_count)
248+
shank_rows = np.repeat(range(row_count), col_count_per_shank)
249+
250+
return [
251+
{
252+
"probe_type": probe_type,
253+
"electrode": (site_count_per_shank * shank_no) + e_id,
254+
"shank": shank_no,
255+
"shank_col": c_id,
256+
"shank_row": r_id,
257+
"x_coord": x + (shank_no * (shank_spacing or 1)),
258+
"y_coord": {"top": -y, "bottom": y}[y_origin],
259+
}
260+
for shank_no in range(shank_count)
261+
for e_id, (c_id, r_id, x, y) in enumerate(
262+
zip(shank_cols, shank_rows, x_coords, y_coords)
263+
)
264+
]

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
setup(
1818
name=pkg_name.replace("_", "-"),
19-
version=__version__, # noqa F821
19+
version=__version__, # noqa F821
2020
description="DataJoint Element for Extracellular Array Electrophysiology",
2121
long_description=long_description,
2222
long_description_content_type="text/markdown",

0 commit comments

Comments
 (0)