@@ -1577,9 +1577,14 @@ def __init__(self, *arg, **kwargs):
15771577 def _get_signal_size (self , block_index , seg_index , stream_index ):
15781578 buffer_id = self .header ["signal_streams" ][stream_index ]["buffer_id" ]
15791579 buffer_desc = self .get_analogsignal_buffer_description (block_index , seg_index , buffer_id )
1580- # some hdf5 revert teh buffer
1581- time_axis = buffer_desc .get ("time_axis" , 0 )
1582- return buffer_desc ["shape" ][time_axis ]
1580+ # For "raw" type, shape is always (time, channels) regardless of file layout
1581+ # For "hdf5" type, shape can be (time, channels) or (channels, time) based on time_axis
1582+ if buffer_desc ["type" ] == "raw" :
1583+ return buffer_desc ["shape" ][0 ]
1584+ else :
1585+ # some hdf5 revert the buffer
1586+ time_axis = buffer_desc .get ("time_axis" , 0 )
1587+ return buffer_desc ["shape" ][time_axis ]
15831588
15841589 def _get_analogsignal_chunk (
15851590 self ,
@@ -1603,29 +1608,61 @@ def _get_analogsignal_chunk(
16031608
16041609 if buffer_desc ["type" ] == "raw" :
16051610
1606- # open files on demand and keep reference to opened file
1607- if not hasattr (self , "_memmap_analogsignal_buffers" ):
1608- self ._memmap_analogsignal_buffers = {}
1609- if block_index not in self ._memmap_analogsignal_buffers :
1610- self ._memmap_analogsignal_buffers [block_index ] = {}
1611- if seg_index not in self ._memmap_analogsignal_buffers [block_index ]:
1612- self ._memmap_analogsignal_buffers [block_index ][seg_index ] = {}
1613- if buffer_id not in self ._memmap_analogsignal_buffers [block_index ][seg_index ]:
1614- fid = open (buffer_desc ["file_path" ], mode = "rb" )
1615- self ._memmap_analogsignal_buffers [block_index ][seg_index ][buffer_id ] = fid
1616- else :
1617- fid = self ._memmap_analogsignal_buffers [block_index ][seg_index ][buffer_id ]
1611+ time_axis = buffer_desc .get ("time_axis" , 0 )
16181612
1619- num_channels = buffer_desc ["shape" ][1 ]
1613+ if time_axis == 0 :
1614+ # MULTIPLEXED: time_axis=0 means (time, channels) layout
1615+ # open files on demand and keep reference to opened file
1616+ if not hasattr (self , "_memmap_analogsignal_buffers" ):
1617+ self ._memmap_analogsignal_buffers = {}
1618+ if block_index not in self ._memmap_analogsignal_buffers :
1619+ self ._memmap_analogsignal_buffers [block_index ] = {}
1620+ if seg_index not in self ._memmap_analogsignal_buffers [block_index ]:
1621+ self ._memmap_analogsignal_buffers [block_index ][seg_index ] = {}
1622+ if buffer_id not in self ._memmap_analogsignal_buffers [block_index ][seg_index ]:
1623+ fid = open (buffer_desc ["file_path" ], mode = "rb" )
1624+ self ._memmap_analogsignal_buffers [block_index ][seg_index ][buffer_id ] = fid
1625+ else :
1626+ fid = self ._memmap_analogsignal_buffers [block_index ][seg_index ][buffer_id ]
1627+
1628+ num_channels = buffer_desc ["shape" ][1 ]
1629+
1630+ raw_sigs = get_memmap_chunk_from_opened_file (
1631+ fid ,
1632+ num_channels ,
1633+ i_start ,
1634+ i_stop ,
1635+ np .dtype (buffer_desc ["dtype" ]),
1636+ file_offset = buffer_desc ["file_offset" ],
1637+ )
16201638
1621- raw_sigs = get_memmap_chunk_from_opened_file (
1622- fid ,
1623- num_channels ,
1624- i_start ,
1625- i_stop ,
1626- np .dtype (buffer_desc ["dtype" ]),
1627- file_offset = buffer_desc ["file_offset" ],
1628- )
1639+ elif time_axis == 1 :
1640+ # VECTORIZED: time_axis=1 means (channels, time) layout
1641+ # Data is stored as [all_samples_ch1, all_samples_ch2, ...]
1642+ dtype = np .dtype (buffer_desc ["dtype" ])
1643+ num_channels = buffer_desc ["shape" ][1 ]
1644+ num_samples = i_stop - i_start
1645+ total_samples_per_channel = buffer_desc ["shape" ][0 ]
1646+
1647+ # Determine which channels to read
1648+ if channel_indexes is None :
1649+ chan_indices = np .arange (num_channels )
1650+ else :
1651+ chan_indices = np .asarray (channel_indexes )
1652+
1653+ raw_sigs = np .empty ((num_samples , len (chan_indices )), dtype = dtype )
1654+
1655+ for i , chan_idx in enumerate (chan_indices ):
1656+ offset = buffer_desc ["file_offset" ] + chan_idx * total_samples_per_channel * dtype .itemsize
1657+ channel_data = np .memmap (buffer_desc ["file_path" ], dtype = dtype , mode = 'r' ,
1658+ offset = offset , shape = (total_samples_per_channel ,))
1659+ raw_sigs [:, i ] = channel_data [i_start :i_stop ]
1660+
1661+ # Channel slicing already done above, so skip later channel_indexes slicing
1662+ channel_indexes = None
1663+
1664+ else :
1665+ raise ValueError (f"time_axis must be 0 or 1, got { time_axis } " )
16291666
16301667 elif buffer_desc ["type" ] == "hdf5" :
16311668
0 commit comments