@@ -246,12 +246,20 @@ def _parse_header(self):
246246 chan_name = local_chan
247247 chan_id = f"{ stream_name } #{ chan_name } "
248248 event_channels .append ((chan_name , chan_id , "event" ))
249- # add events_memmap
250- data = np .memmap (info ["bin_file" ], dtype = "int16" , mode = "r" , offset = 0 , order = "C" )
251- data = data .reshape (- 1 , info ["num_chan" ])
252- # The digital word is usually the last channel, after all the individual analog channels
253- extracted_word = data [:, len (info ["analog_channels" ])]
254- self ._events_memmap = np .unpackbits (extracted_word .astype (np .uint8 )[:, None ], axis = 1 )
249+ # Create memmap for digital word but defer unpacking until needed
250+ # The digital word is stored as the last channel, after all the individual analog channels
251+ # For example: if there are 8 analog channels (indices 0-7), the digital word is at index 8
252+ num_samples = info ["sample_length" ]
253+ num_channels = info ["num_chan" ]
254+ data = np .memmap (
255+ info ["bin_file" ],
256+ dtype = "int16" ,
257+ mode = "r" ,
258+ shape = (num_samples , num_channels ),
259+ order = "C" ,
260+ )
261+ digital_word_channel_index = len (info ["analog_channels" ])
262+ self ._events_memmap_digital_word = data [:, digital_word_channel_index ]
255263 event_channels = np .array (event_channels , dtype = _event_channel_dtype )
256264
257265 # No spikes
@@ -342,7 +350,9 @@ def _get_event_timestamps(self, block_index, seg_index, event_channel_index, t_s
342350 info = self .signals_info_dict [0 , "nidq" ] # There are no events that are not in the nidq stream
343351 dig_ch = info ["digital_channels" ]
344352 if len (dig_ch ) > 0 :
345- event_data = self ._events_memmap
353+ # Unpack bits on-demand - this is when memory allocation happens
354+ event_data = np .unpackbits (self ._events_memmap_digital_word .astype (np .uint8 )[:, None ], axis = 1 )
355+
346356 channel = dig_ch [event_channel_index ]
347357 ch_idx = 7 - int (channel [2 :]) # They are in the reverse order
348358 this_stream = event_data [:, ch_idx ]
@@ -682,7 +692,12 @@ def extract_stream_info(meta_file, meta):
682692 info ["sampling_rate" ] = float (meta [k ])
683693 info ["num_chan" ] = num_chan
684694
685- info ["sample_length" ] = int (meta ["fileSizeBytes" ]) // 2 // num_chan
695+ # Calculate sample_length from actual file size instead of metadata to handle stub/modified files
696+ # The metadata fileSizeBytes may not match the actual .bin file (e.g., in test stub files)
697+ # Original calculation (only correct for unmodified files):
698+ # info["sample_length"] = int(meta["fileSizeBytes"]) // 2 // num_chan
699+ actual_file_size = Path (meta_file ).with_suffix (".bin" ).stat ().st_size
700+ info ["sample_length" ] = actual_file_size // 2 // num_chan # 2 bytes per int16 sample
686701 info ["gate_num" ] = gate_num
687702 info ["trigger_num" ] = trigger_num
688703 info ["device" ] = device
0 commit comments