44
55Note:
66 * the centre of the first left columns and the first bottom row is our reference (x=0, y=0)
7- * "oe_x_shift" is a global shift on x axis to make spikeglx and openephys compatible.
87
98"""
109
8180 "lf_gains" ,
8281 "ap_hp_filters" ,
8382 ),
84- "oe_x_shift" : - 11 ,
8583 },
8684 # Neuropixels 2.0 - Single Shank - Prototype
8785 "21" : {
9795 "contour_description" : "np70" ,
9896 "contour_shift" : [- 27 , - 11 ],
9997 "fields_in_imro_table" : ("channel_ids" , "banks" , "references" , "elec_ids" ),
100- "oe_x_shift" : - 8 ,
10198 },
10299 # Neuropixels 2.0 - Four Shank - Prototype
103100 "24" : {
119116 "references" ,
120117 "elec_ids" ,
121118 ),
122- "oe_x_shift" : - 8 ,
123119 },
124120 # Neuropixels 2.0 - Single Shank - Commercial without metal cap
125121 "2003" : {
135131 "contour_description" : "np70" ,
136132 "contour_shift" : [- 27 , - 11 ],
137133 "fields_in_imro_table" : ("channel_ids" , "banks" , "references" , "elec_ids" ),
138- "oe_x_shift" : - 8 ,
139134 },
140135 # Neuropixels 2.0 - Single Shank - Commercial with metal cap
141136 "2004" : {
151146 "contour_description" : "np70" ,
152147 "contour_shift" : [- 27 , - 11 ],
153148 "fields_in_imro_table" : ("channel_ids" , "banks" , "references" , "elec_ids" ),
154- "oe_x_shift" : - 8 ,
155149 },
156150 # Neuropixels 2.0 - Four Shank - Commercial without metal cap
157151 "2013" : {
173167 "references" ,
174168 "elec_ids" ,
175169 ),
176- "oe_x_shift" : - 8 ,
177170 },
178171 # Neuropixels 2.0 - Four Shank - Commercial with metal cap
179172 "2014" : {
195188 "references" ,
196189 "elec_ids" ,
197190 ),
198- "oe_x_shift" : - 8 ,
191+ },
192+ # Neuropixels 2.0 Quad Base
193+ "2020" : {
194+ "model_name" : "Neuropixels 2.0 Quad Base" ,
195+ "x_pitch" : 32 ,
196+ "y_pitch" : 15 ,
197+ "contact_width" : 12 ,
198+ "stagger" : 0.0 ,
199+ "shank_pitch" : 250 ,
200+ "shank_number" : 4 ,
201+ "ncols_per_shank" : 2 ,
202+ "nrows_per_shank" : 640 ,
203+ "contour_description" : "np70" ,
204+ "contour_shift" : [- 27 , - 11 ],
205+ "fields_in_imro_table" : (
206+ "channel_ids" ,
207+ "shank_id" ,
208+ "banks" ,
209+ "references" ,
210+ "elec_ids" ,
211+ ),
199212 },
200213 # Experimental probes previous to 1.0
201214 "Phase3a" : {
217230 "ap_gains" ,
218231 "lf_gains" ,
219232 ),
220- "oe_x_shift" : - 11 ,
221233 },
222234 # Neuropixels 1.0-NHP Short (10mm)
223235 "1015" : {
240252 "lf_gains" ,
241253 "ap_hp_filters" ,
242254 ),
243- "oe_x_shift" : - 11 ,
244255 },
245256 #################
246257 # Neuropixels 1.0-NHP Medium (25mm)
264275 "lf_gains" ,
265276 "ap_hp_filters" ,
266277 ),
267- "oe_x_shift" : - 11 ,
268278 },
269279 # Neuropixels 1.0-NHP Medium (25mm)
270280 "1021" : {
287297 "lf_gains" ,
288298 "ap_hp_filters" ,
289299 ),
290- "oe_x_shift" : - 11 ,
291300 },
292301 #################
293302 # Neuropixels 1.0-NHP Medium (25mm)
311320 "lf_gains" ,
312321 "ap_hp_filters" ,
313322 ),
314- "oe_x_shift" : - 11 ,
315323 },
316324 # Neuropixels 1.0-NHP 45mm SOI90 - NHP long 90um wide, staggered contacts
317325 "1030" : {
334342 "lf_gains" ,
335343 "ap_hp_filters" ,
336344 ),
337- "oe_x_shift" : - 11 ,
338345 },
339346 # Neuropixels 1.0-NHP 45mm SOI125 - NHP long 125um wide, staggered contacts
340347 "1031" : {
357364 "lf_gains" ,
358365 "ap_hp_filters" ,
359366 ),
360- "oe_x_shift" : - 11 ,
361367 },
362368 # 1.0-NHP 45mm SOI115 / 125 linear - NHP long 125um wide, linear contacts
363369 "1032" : {
380386 "lf_gains" ,
381387 "ap_hp_filters" ,
382388 ),
383- "oe_x_shift" : - 11 ,
384389 },
385390 # Ultra probes 1 bank
386391 "1100" : {
403408 "lf_gains" ,
404409 "ap_hp_filters" ,
405410 ),
406- "oe_x_shift" : - 8 ,
407411 },
408412 # Ultra probes 16 banks
409413 "1110" : {
426430 "lf_gains" ,
427431 "ap_hp_filters" ,
428432 ),
429- "oe_x_shift" : - 8 ,
430433 },
431434 "1121" : {
432435 "model_name" : "Neuropixels Ultra - Type 2" ,
448451 "lf_gains" ,
449452 "ap_hp_filters" ,
450453 ),
451- "oe_x_shift" : 18 ,
452454 },
453455 # NP-Opto
454456 "1300" : {
471473 "lf_gains" ,
472474 "ap_hp_filters" ,
473475 ),
474- "oe_x_shift" : - 11 ,
475476 },
476477}
477478
506507 "NP2004" : "2004" ,
507508 "PRB2_1_2_0640_0" : "21" ,
508509 "PRB2_4_2_0640_0" : "24" ,
510+ # NXT
511+ "NP2020" : "2020" ,
509512 # Ultra
510513 "NP1100" : "1100" , # Ultra probe - 1 bank
511514 "NP1110" : "1110" , # Ultra probe - 16 banks no handle beacuse
@@ -1065,7 +1068,9 @@ def read_openephys(
10651068
10661069 # check if shank ids is present
10671070 if all (":" in val for val in channel_values ):
1068- shank_ids = np .array ([int (val [val .find (":" ) + 1 :]) for val in channel_values ])
1071+ shank_ids = np .array ([int (val .split (":" )[1 ]) for val in channel_values ])
1072+ elif all ("_" in val for val in channel_names ):
1073+ shank_ids = np .array ([int (val .split ("_" )[1 ]) for val in channel_names ])
10691074 else :
10701075 shank_ids = None
10711076
@@ -1084,13 +1089,16 @@ def read_openephys(
10841089 if probe_part_number not in probe_part_number_to_probe_type :
10851090 raise NotImplementedError (f"Probe part number { probe_part_number } is not supported yet" )
10861091 ptype = probe_part_number_to_probe_type [probe_part_number ]
1087- x_shift = npx_descriptions [ptype ]["oe_x_shift" ] if ptype is not None else 0
10881092
10891093 if fix_x_position_for_oe_5 and oe_version < parse ("0.6.0" ) and shank_ids is not None :
10901094 positions [:, 1 ] = positions [:, 1 ] - npx_descriptions [ptype ]["shank_pitch" ] * shank_ids
10911095
1092- # x offset
1093- positions [:, 0 ] += x_shift
1096+ # x offset so that the first column is at 0x
1097+ offset = np .min (positions [:, 0 ])
1098+ # if some shanks are not used, we need to adjust the offset
1099+ if shank_ids is not None :
1100+ offset -= np .min (shank_ids ) * npx_descriptions [ptype ]["shank_pitch" ]
1101+ positions [:, 0 ] -= offset
10941102
10951103 contact_ids = []
10961104 for i , pos in enumerate (positions ):
@@ -1135,6 +1143,7 @@ def read_openephys(
11351143 # now select correct probe (if multiple)
11361144 if len (np_probes ) > 1 :
11371145 found = False
1146+ probe_names = [p ["name" ] for p in np_probes_info ]
11381147
11391148 if stream_name is not None :
11401149 assert probe_name is None and serial_number is None , (
@@ -1179,8 +1188,8 @@ def read_openephys(
11791188 return None
11801189 else :
11811190 raise Exception (
1182- "More than one probe found. Use one of 'stream_name', 'probe_name', or 'serial_number' "
1183- "to select the right probe"
1191+ f "More than one probe found. Use one of 'stream_name', 'probe_name', or 'serial_number' "
1192+ f "to select the right probe. \n Probe names: { probe_names } "
11841193 )
11851194 else :
11861195 # in case of a single probe, make sure it is consistent with optional
@@ -1218,7 +1227,6 @@ def read_openephys(
12181227 np_probe = np_probes [probe_idx ]
12191228 positions = np_probe_info ["positions" ]
12201229 shank_ids = np_probe_info ["shank_ids" ]
1221- pname = np_probe_info ["name" ]
12221230
12231231 ptype = np_probe_info ["ptype" ]
12241232 if ptype in npx_descriptions :
@@ -1270,6 +1278,7 @@ def read_openephys(
12701278 probe .set_contact_ids (contact_ids )
12711279
12721280 polygon = polygon_contour_description [contour_description ]
1281+ contour_shift = np .array (npx_descriptions [ptype ]["contour_shift" ])
12731282 if shank_ids is None :
12741283 contour = polygon
12751284 else :
@@ -1278,7 +1287,7 @@ def read_openephys(
12781287 contour += list (np .array (polygon ) + [shank_pitch * i , 0 ])
12791288
12801289 # shift
1281- contour = np .array (contour ) - x_shift
1290+ contour = np .array (contour ) + contour_shift
12821291 probe .set_planar_contour (contour )
12831292
12841293 # wire it
0 commit comments