Skip to content

Commit e69ab7b

Browse files
authored
Merge pull request #356 from alejoe91/add-more-np-metadata
Add num_adcs, num_channels_per_adc, num_readout_channels, adc_bit_depth annotations to NP probes
2 parents 03bae61 + 86d088e commit e69ab7b

File tree

1 file changed

+26
-14
lines changed

1 file changed

+26
-14
lines changed

src/probeinterface/neuropixels_tools.py

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -128,15 +128,19 @@ def make_mux_table_array(mux_information) -> np.array:
128128

129129
# mux_information looks like (num_adcs num_channels_per_adc)(int int int ...)(int int int ...)...(int int int ...)
130130
# First split on ')(' to get a list of the information in the brackets, and remove the leading data
131+
adc_info = mux_information.split(")(")[0]
131132
split_mux = mux_information.split(")(")[1:]
132133

134+
# The first element is the number of ADCs and the number of channels per ADC
135+
num_adcs, num_channels_per_adc = map(int, adc_info[1:].split(","))
136+
133137
# Then remove the brackets, and split using " " to get each integer as a list
134138
mux_channels = [
135139
np.array(each_mux.replace("(", "").replace(")", "").split(" ")).astype("int") for each_mux in split_mux
136140
]
137141
mux_channels_array = np.transpose(np.array(mux_channels))
138142

139-
return mux_channels_array
143+
return num_adcs, num_channels_per_adc, mux_channels_array
140144

141145

142146
def get_probe_contour_vertices(shank_width, tip_length, probe_length) -> list:
@@ -225,7 +229,7 @@ def read_imro(file_path: Union[str, Path]) -> Probe:
225229
return _read_imro_string(imro_str, imDatPrb_pn)
226230

227231

228-
def _make_npx_probe_from_description(probe_description, model_name, elec_ids, shank_ids, mux_table=None) -> Probe:
232+
def _make_npx_probe_from_description(probe_description, model_name, elec_ids, shank_ids, mux_info=None) -> Probe:
229233
# used by _read_imro_string and for generating the NP library
230234

231235
# compute position
@@ -302,14 +306,23 @@ def _make_npx_probe_from_description(probe_description, model_name, elec_ids, sh
302306
# wire it
303307
probe.set_device_channel_indices(np.arange(positions.shape[0]))
304308

309+
# set other key metadata annotations
310+
probe.annotate(
311+
adc_bit_depth=probe_description["adc_bit_depth"],
312+
num_readout_channels=probe_description["num_readout_channels"],
313+
)
314+
305315
# annotate with MUX table
306-
if mux_table is not None:
316+
if mux_info is not None:
307317
# annotate each contact with its mux channel
318+
num_adcs, num_channels_per_adc, mux_table = make_mux_table_array(mux_info)
308319
num_contacts = positions.shape[0]
309320
mux_channels = np.zeros(num_contacts, dtype="int64")
310321
for adc_idx, mux_channels_per_adc in enumerate(mux_table):
311322
mux_channels_per_adc = mux_channels_per_adc[mux_channels_per_adc < num_contacts]
312323
mux_channels[mux_channels_per_adc] = adc_idx
324+
probe.annotate(num_adcs=num_adcs)
325+
probe.annotate(num_channels_per_adc=num_channels_per_adc)
313326
probe.annotate_contacts(mux_channels=mux_channels)
314327

315328
return probe
@@ -343,7 +356,7 @@ def _read_imro_string(imro_str: str, imDatPrb_pn: Optional[str] = None) -> Probe
343356
probe_type = probe_type_num_chans.split(",")[0][1:]
344357

345358
probe_features = _load_np_probe_features()
346-
pt_metadata, fields, mux_table = get_probe_metadata_from_probe_features(probe_features, imDatPrb_pn)
359+
pt_metadata, fields, mux_info = get_probe_metadata_from_probe_features(probe_features, imDatPrb_pn)
347360

348361
# fields = probe_description["fields_in_imro_table"]
349362
contact_info = {k: [] for k in fields}
@@ -369,7 +382,7 @@ def _read_imro_string(imro_str: str, imDatPrb_pn: Optional[str] = None) -> Probe
369382
else:
370383
shank_ids = None
371384

372-
probe = _make_npx_probe_from_description(pt_metadata, imDatPrb_pn, elec_ids, shank_ids, mux_table)
385+
probe = _make_npx_probe_from_description(pt_metadata, imDatPrb_pn, elec_ids, shank_ids, mux_info)
373386

374387
# scalar annotations
375388
probe.annotate(
@@ -405,9 +418,10 @@ def get_probe_metadata_from_probe_features(probe_features: dict, imDatPrb_pn: st
405418
406419
Returns
407420
-------
408-
probe_metadata, imro_field
421+
probe_metadata, imro_field, mux_information
409422
Dictionary of probe metadata.
410423
Tuple of fields included in the `imro_table_fields`.
424+
Mux table information, if available, as a string.
411425
"""
412426

413427
probe_metadata = probe_features["neuropixels_probes"].get(imDatPrb_pn)
@@ -440,15 +454,13 @@ def get_probe_metadata_from_probe_features(probe_features: dict, imDatPrb_pn: st
440454
imro_fields = tuple(imro_fields_list)
441455

442456
# Read MUX table information
443-
mux_table = None
457+
mux_information = None
444458

445459
if "z_mux_tables" in probe_features:
446460
mux_table_format_type = probe_metadata.get("mux_table_format_type", None)
447461
mux_information = probe_features["z_mux_tables"].get(mux_table_format_type, None)
448-
if mux_information is not None:
449-
mux_table = make_mux_table_array(mux_information)
450462

451-
return probe_metadata, imro_fields, mux_table
463+
return probe_metadata, imro_fields, mux_information
452464

453465

454466
def write_imro(file: str | Path, probe: Probe):
@@ -862,7 +874,7 @@ def read_openephys(
862874
positions = np.array([xpos, ypos]).T
863875

864876
probe_part_number = np_probe.get("probe_part_number", None)
865-
pt_metadata, _, mux_table = get_probe_metadata_from_probe_features(probe_features, probe_part_number)
877+
pt_metadata, _, mux_info = get_probe_metadata_from_probe_features(probe_features, probe_part_number)
866878

867879
shank_pitch = pt_metadata["shank_pitch_um"]
868880

@@ -926,7 +938,7 @@ def read_openephys(
926938
"dock": dock,
927939
"serial_number": probe_serial_number,
928940
"part_number": probe_part_number,
929-
"mux_table": mux_table,
941+
"mux_info": mux_info,
930942
}
931943
# Sequentially assign probe names
932944
if "custom_probe_name" in np_probe.attrib and np_probe.attrib["custom_probe_name"] != probe_serial_number:
@@ -1024,7 +1036,7 @@ def read_openephys(
10241036
shank_ids = np_probe_info["shank_ids"]
10251037
elec_ids = np_probe_info["elec_ids"]
10261038
pt_metadata = np_probe_info["pt_metadata"]
1027-
mux_table = np_probe_info["mux_table"]
1039+
mux_info = np_probe_info["mux_info"]
10281040

10291041
# check if subset of channels
10301042
chans_saved = get_saved_channel_indices_from_openephys_settings(settings_file, stream_name=stream_name)
@@ -1038,7 +1050,7 @@ def read_openephys(
10381050
elec_ids = np.array(elec_ids)[chans_saved]
10391051

10401052
probe = _make_npx_probe_from_description(
1041-
pt_metadata, probe_part_number, elec_ids, shank_ids=shank_ids, mux_table=mux_table
1053+
pt_metadata, probe_part_number, elec_ids, shank_ids=shank_ids, mux_info=mux_info
10421054
)
10431055
probe.serial_number = np_probe_info["serial_number"]
10441056
probe.name = np_probe_info["name"]

0 commit comments

Comments
 (0)