6363from neo .rawio .neuralynxrawio .ncssections import NcsSection , NcsSectionsFactory
6464from neo .rawio .neuralynxrawio .nlxheader import NlxHeader
6565
66+ # Named tuple for stream identification keys
67+ StreamKey = namedtuple ('StreamKey' , ['sampling_rate' , 'input_range' , 'filter_params' ])
68+
6669
6770class NeuralynxRawIO (BaseRawIO ):
6871 """
@@ -203,7 +206,7 @@ def __init__(
203206 def _source_name (self ):
204207 return self .dirname
205208
206- def _build_stream_key (self , header_info , chan_index , gain ):
209+ def _build_stream_key (self , header_info , chan_index ):
207210 """
208211 Build stream key based on acquisition parameters only.
209212
@@ -217,14 +220,12 @@ def _build_stream_key(self, header_info, chan_index, gain):
217220 Header information from NlxHeader
218221 chan_index : int
219222 Channel index for multi-channel parameters
220- gain : float
221- Channel gain value (bit_to_microVolt)
222223
223224 Returns
224225 -------
225- tuple
226- Hashable stream key containing acquisition parameters:
227- (sampling_rate, input_range, gain, filter_params_tuple )
226+ StreamKey
227+ Named tuple containing acquisition parameters:
228+ (sampling_rate, input_range, filter_params )
228229 """
229230 # Core acquisition parameters (already normalized by NlxHeader)
230231 sampling_rate = float (header_info ["sampling_rate" ])
@@ -236,21 +237,21 @@ def _build_stream_key(self, header_info, chan_index, gain):
236237 input_range = input_range [chan_index ] if chan_index < len (input_range ) else input_range [0 ]
237238 # Already converted to int by NlxHeader._normalize_types()
238239
239- gain = float (gain )
240-
240+ # Note: gain is not included in stream key as it's derived from InputRange (gain = InputRange / 32768)
241+ # Note: input_inverted is not included in stream key as it's a whole-dataset property
242+ # that never differentiates streams (all channels have the same value)
241243
242244 # Build filter parameters tuple (already normalized by NlxHeader)
243245 filter_params = []
244246 for key in self ._filter_keys :
245247 if key in header_info :
246248 filter_params .append ((key , header_info [key ]))
247249
248- # Create hashable stream key
249- stream_key = (
250- sampling_rate ,
251- input_range ,
252- gain ,
253- tuple (sorted (filter_params )),
250+ # Create hashable stream key using namedtuple for readability
251+ stream_key = StreamKey (
252+ sampling_rate = sampling_rate ,
253+ input_range = input_range ,
254+ filter_params = tuple (sorted (filter_params )),
254255 )
255256
256257 return stream_key
@@ -340,7 +341,7 @@ def _parse_header(self):
340341 gain *= - 1
341342
342343 # Build stream key from acquisition parameters only
343- stream_key = self ._build_stream_key (info , idx , gain )
344+ stream_key = self ._build_stream_key (info , idx )
344345
345346 if stream_key not in stream_props :
346347 stream_props [stream_key ] = {
@@ -464,7 +465,7 @@ def _parse_header(self):
464465 if signal_channels .size > 0 :
465466 # Build DSP filter configuration registry: filter_id -> filter parameters dict
466467 # Extract unique filter configurations from stream keys
467- unique_filter_tuples = {stream_key [ 3 ] for stream_key in stream_props .keys ()} # stream_key[3] is filter_params_tuple
468+ unique_filter_tuples = {stream_key . filter_params for stream_key in stream_props .keys ()}
468469 _dsp_filter_configurations = {i : dict (filt ) for i , filt in enumerate (sorted (unique_filter_tuples ))}
469470
470471 # Create reverse mapping for looking up filter IDs during stream name construction
@@ -475,18 +476,17 @@ def _parse_header(self):
475476 self ._dsp_filter_configurations = _dsp_filter_configurations
476477
477478 # Order streams by sampling rate (high to low)
478- ordered_stream_keys = sorted (stream_props .keys (), reverse = True , key = lambda x : x [ 0 ] )
479+ ordered_stream_keys = sorted (stream_props .keys (), reverse = True , key = lambda x : x . sampling_rate )
479480
480481 stream_names = []
481482 stream_ids = []
482483 buffer_ids = []
483484
484485 for stream_id , stream_key in enumerate (ordered_stream_keys ):
485- # Unpack stream_key and format stream name
486- sampling_rate , input_range , gain , filter_params_tuple = stream_key
487- dsp_filter_id = seen_filters [filter_params_tuple ]
488- voltage_mv = int (input_range / 1000 ) if input_range is not None else 0
489- stream_name = f"stream{ stream_id } _{ int (sampling_rate )} Hz_{ voltage_mv } mVRange_DSPFilter{ dsp_filter_id } "
486+ # Format stream name using namedtuple fields
487+ dsp_filter_id = seen_filters [stream_key .filter_params ]
488+ voltage_mv = int (stream_key .input_range / 1000 ) if stream_key .input_range is not None else 0
489+ stream_name = f"stream{ stream_id } _{ int (stream_key .sampling_rate )} Hz_{ voltage_mv } mVRange_DSPFilter{ dsp_filter_id } "
490490
491491 stream_names .append (stream_name )
492492 stream_ids .append (str (stream_id ))
0 commit comments