4
4
5
5
6
6
"""
7
- OpenEphys plug-in for Neuropixels recording saves data in binary format the following the directory structure:
7
+ The Open Ephys Record Node saves Neuropixels data in binary format according to the following the directory structure:
8
8
(https://open-ephys.github.io/gui-docs/User-Manual/Recording-data/Binary-format.html)
9
9
10
10
Record Node 102
14
14
-- continuous
15
15
-- Neuropix-PXI-100.0 (probe0 ap)
16
16
-- Neuropix-PXI-100.1 (probe0 lf)
17
- -- Neuropix-PXI-101.0 (probe1 ap)
18
- -- Neuropix-PXI-101.1 (probe1 lf)
17
+ -- Neuropix-PXI-100.2 (probe1 ap)
18
+ -- Neuropix-PXI-100.3 (probe1 lf)
19
19
...
20
20
-- events
21
21
-- spikes
@@ -46,8 +46,8 @@ def __init__(self, experiment_dir):
46
46
47
47
def load_probe_data (self ):
48
48
"""
49
- Loop through all OpenEphys "processors", identify the processor for
50
- neuropixels probe, extract probe info
49
+ Loop through all Open Ephys "processors", identify the processor for
50
+ the Neuropixels probe(s) , extract probe info
51
51
Loop through all recordings, associate recordings to
52
52
the matching probes, extract recording info
53
53
@@ -58,53 +58,65 @@ def load_probe_data(self):
58
58
probes = {}
59
59
for processor in self .experiment .settings ['SIGNALCHAIN' ]['PROCESSOR' ]:
60
60
if processor ['@pluginName' ] in ('Neuropix-PXI' , 'Neuropix-3a' ):
61
- oe_probe = Probe (processor )
62
- for rec in self .experiment .recordings :
63
- for cont_info , analog_signal in zip (rec ._oebin ['continuous' ],
64
- rec .analog_signals ):
65
- if cont_info ['source_processor_id' ] != oe_probe .processor_id :
66
- continue
67
-
68
- if cont_info ['source_processor_sub_idx' ] == 0 : # ap data
69
- assert cont_info ['sample_rate' ] == analog_signal .sample_rate == 30000
70
- cont_type = 'ap'
71
-
72
- oe_probe .recording_info ['recording_count' ] += 1
73
- oe_probe .recording_info ['recording_datetimes' ].append (
74
- rec .datetime )
75
- oe_probe .recording_info ['recording_durations' ].append (
76
- float (rec .duration ))
77
- oe_probe .recording_info ['recording_files' ].append (
78
- rec .absolute_foldername / 'continuous' / cont_info ['folder_name' ])
79
-
80
- elif cont_info ['source_processor_sub_idx' ] == 1 : # lfp data
81
- assert cont_info ['sample_rate' ] == analog_signal .sample_rate == 2500
82
- cont_type = 'lfp'
83
-
84
- if getattr (oe_probe , cont_type + '_meta' ) is None :
85
- cont_info ['channels_ids' ] = analog_signal .channel_ids
86
- cont_info ['channels_names' ] = analog_signal .channel_names
87
- cont_info ['channels_gains' ] = analog_signal .gains
88
- setattr (oe_probe , cont_type + '_meta' , cont_info )
89
-
90
- oe_probe .__dict__ [f'{ cont_type } _analog_signals' ].append (analog_signal )
91
-
92
- probes [oe_probe .probe_SN ] = oe_probe
61
+ if processor ['@pluginName' ] == 'Neuropix-3a' :
62
+ oe_probe = Probe (processor )
63
+ probes [oe_probe .probeSN ] = oe_probe
64
+ else :
65
+ for probe_index in range (len (processor ['EDITOR' ]['NP_PROBE' ])):
66
+ oe_probe = Probe (processor , probe_index )
67
+ probes [oe_probe .probe_SN ] = oe_probe
68
+
69
+ for probe_index , probe_SN in enumerate (probes .keys ()):
70
+
71
+ oe_probe = probes [probe_SN ]
72
+
73
+ for rec in self .experiment .recordings :
74
+ for cont_info , analog_signal in zip (rec ._oebin ['continuous' ],
75
+ rec .analog_signals ):
76
+ if cont_info ['source_processor_id' ] != oe_probe .processor_id :
77
+ continue
78
+
79
+ if cont_info ['source_processor_sub_idx' ] == probe_index * 2 : # ap data
80
+ assert cont_info ['sample_rate' ] == analog_signal .sample_rate == 30000
81
+ cont_type = 'ap'
82
+
83
+ oe_probe .recording_info ['recording_count' ] += 1
84
+ oe_probe .recording_info ['recording_datetimes' ].append (
85
+ rec .datetime )
86
+ oe_probe .recording_info ['recording_durations' ].append (
87
+ float (rec .duration ))
88
+ oe_probe .recording_info ['recording_files' ].append (
89
+ rec .absolute_foldername / 'continuous' / cont_info ['folder_name' ])
90
+
91
+ elif cont_info ['source_processor_sub_idx' ] == probe_index * 2 + 1 : # lfp data
92
+ assert cont_info ['sample_rate' ] == analog_signal .sample_rate == 2500
93
+ cont_type = 'lfp'
94
+
95
+ if getattr (oe_probe , cont_type + '_meta' ) is None :
96
+ cont_info ['channels_ids' ] = analog_signal .channel_ids
97
+ cont_info ['channels_names' ] = analog_signal .channel_names
98
+ cont_info ['channels_gains' ] = analog_signal .gains
99
+ setattr (oe_probe , cont_type + '_meta' , cont_info )
100
+
101
+ oe_probe .__dict__ [f'{ cont_type } _analog_signals' ].append (analog_signal )
93
102
94
103
return probes
95
104
96
105
97
106
class Probe :
98
107
99
- def __init__ (self , processor ):
108
+ def __init__ (self , processor , probe_index = 0 ):
100
109
self .processor_id = int (processor ['@NodeId' ])
101
- self .probe_info = processor ['EDITOR' ]['PROBE' ]
102
- self .probe_SN = self .probe_info ['@probe_serial_number' ]
103
-
104
- # Determine probe-model (TODO: how to determine npx 2.0 SS and MS?)
105
- self .probe_model = {
106
- "Neuropix-PXI" : "neuropixels 1.0 - 3B" ,
107
- "Neuropix-3a" : "neuropixels 1.0 - 3A" }[processor ['@pluginName' ]]
110
+
111
+ if processor ['@pluginName' ] == 'Neuropix-3a' :
112
+
113
+ self .probe_info = processor ['EDITOR' ]['PROBE' ]
114
+ self .probe_SN = self .probe_info ['@probe_serial_number' ]
115
+ self .probe_model = "Neuropixels 3A"
116
+ else :
117
+ self .probe_info = processor ['EDITOR' ]['NP_PROBE' ][probe_index ]
118
+ self .probe_SN = self .probe_info ['@probe_serial_number' ]
119
+ self .probe_model = self .probe_info ['@probe_name' ]
108
120
109
121
self .ap_meta = None
110
122
self .lfp_meta = None
0 commit comments