@@ -24,17 +24,17 @@ def get_neuropixels_sample_shifts_from_probe(probe: Probe, stream_name: str = "a
2424 sample_shifts : np.ndarray
2525 Array of relative phase shifts for each channel.
2626 """
27- # get inter-sample shifts based on the probe information and mux channels
28- model_description = probe .annotations .get ("description" , None )
27+ # get inter-sample shifts based on the probe information and ADC sampling pattern
2928 num_channels_per_adc = probe .annotations .get ("num_channels_per_adc" , None )
30- mux_channels = probe .contact_annotations .get ("mux_channels" , None )
31- num_readouts_channels = probe .annotations .get ("num_readout_channels" , None )
29+ adc_sample_order = probe .contact_annotations .get ("adc_sample_order" , None )
30+ ap_sample_frequency_hz = probe .annotations .get ("ap_sample_frequency_hz" , None )
31+ lf_sample_frequency_hz = probe .annotations .get ("lf_sample_frequency_hz" , None )
3232
3333 if (
34- model_description is None
35- or num_channels_per_adc is None
36- or mux_channels is None
37- or num_readouts_channels is None
34+ num_channels_per_adc is None
35+ or adc_sample_order is None
36+ or ap_sample_frequency_hz is None
37+ or lf_sample_frequency_hz is None
3838 ):
3939 warning_message = (
4040 "Unable to find inter-sample shifts in the Neuropixels probe metadata. "
@@ -43,17 +43,18 @@ def get_neuropixels_sample_shifts_from_probe(probe: Probe, stream_name: str = "a
4343 warnings .warn (warning_message , UserWarning , stacklevel = 2 )
4444 return None
4545
46- if "2.0" in model_description :
47- # for Neuropixels 2.0 ( and newer), the number of cycles in ADC is equal to the number of channels per ADC
48- num_cycles_in_adc = num_channels_per_adc
49- else :
50- # for Neuropixels 1.0 technology, the number of cycles for the AP stream is +1 because
51- # the last cycle is used for the LFP stream
52- num_cycles_in_adc = num_channels_per_adc + 1 if "ap" in stream_name . lower () else num_channels_per_adc
46+ # The number of cycles is determined by the number of channels per ADC times 1 + the ratio
47+ # between the lf and ap sample rate.
48+ # For NP 1.0, this gives 13 cycles: 12 * (1 + 2500 / 30000) = 13
49+ # For NP 2.0, the lf sample rate is 0 and so the number of cycles is equal to the number of
50+ # channels per ADC.
51+ # see: https://github.com/billkarsh/ProbeTable/issues/3#issuecomment-3438263027
52+ num_cycles_in_adc = int ( num_channels_per_adc * ( 1 + lf_sample_frequency_hz / ap_sample_frequency_hz ))
5353
54- sample_shifts = np .zeros_like (mux_channels , dtype = float )
55- for mux_channel in mux_channels :
56- sample_shifts [mux_channels == mux_channel ] = np .arange (num_channels_per_adc ) / num_cycles_in_adc
54+ # The inter-sample shifts are given by the adc sample order divided by the number of cycles in ADC
55+ # This makes sure we also handle cases where only a subset of channels are recorded
56+ # see: https://github.com/SpikeInterface/spikeinterface/issues/4144
57+ sample_shifts = adc_sample_order / num_cycles_in_adc
5758
5859 return sample_shifts
5960
@@ -157,7 +158,7 @@ def get_neuropixels_channel_groups(num_channels=384, num_channels_per_adc=12):
157158 """
158159 warnings .warn (
159160 "`get_neuropixels_channel_groups` is deprecated and will be removed in 0.104.0. "
160- "Use the `mux_channels ` contact annotation from the `Probe` instead." ,
161+ "Use the `adc_group ` contact annotation from the `Probe` instead." ,
161162 DeprecationWarning ,
162163 stacklevel = 2 ,
163164 )
0 commit comments