@@ -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+ ]
0 commit comments