|
33 | 33 | from .mdf import _open_mdf, dataField, descriptionField, unitField, \ |
34 | 34 | masterField, masterTypeField, idField, _convert_name |
35 | 35 |
|
| 36 | +try: |
| 37 | + from dataRead import SymBufReader as _SymBufReader |
| 38 | + _SYMBUF_AVAILABLE = True |
| 39 | +except ImportError: |
| 40 | + _SYMBUF_AVAILABLE = False |
| 41 | + |
36 | 42 | # datatypes |
37 | 43 | _LINK = '<Q' |
38 | 44 | _REAL = '<d' |
@@ -1793,10 +1799,10 @@ def decompress_data_block(block, zip_type, zip_parameter, org_data_length): |
1793 | 1799 | M = org_data_length // zip_parameter |
1794 | 1800 | aligned = M * zip_parameter |
1795 | 1801 | tail = block[aligned:] |
1796 | | - # frombuffer avoids a copy; .T.copy() materialises the transposed layout |
1797 | | - transposed = frombuffer(block[:aligned], dtype='u1').reshape(zip_parameter, M).T.copy() |
| 1802 | + # reshape as (zip_parameter, M), use Fortran-contiguous copy to get row-major of transpose |
| 1803 | + arr = frombuffer(block[:aligned], dtype='u1').reshape(zip_parameter, M) |
1798 | 1804 | del block |
1799 | | - block = (transposed.tobytes() + bytes(tail)) if tail else transposed.tobytes() |
| 1805 | + block = (arr.T.tobytes() + bytes(tail)) if tail else arr.T.tobytes() |
1800 | 1806 | return block |
1801 | 1807 |
|
1802 | 1808 | def write(self, fid, data, record_length): |
@@ -1902,7 +1908,7 @@ def write(self, fid, data): |
1902 | 1908 |
|
1903 | 1909 |
|
1904 | 1910 | class Info4(dict): |
1905 | | - __slots__ = ['fileName', 'fid', 'filterChannelNames', 'zipfile'] |
| 1911 | + __slots__ = ['fileName', 'fid', 'filterChannelNames', 'zipfile', '_si_cache'] |
1906 | 1912 | """ information block parser fo MDF file version 4.x |
1907 | 1913 |
|
1908 | 1914 | Attributes |
@@ -1961,21 +1967,24 @@ def __init__(self, file_name=None, fid=None, filter_channel_names=False, minimal |
1961 | 1967 | self['AT'] = {} # Attachment block |
1962 | 1968 | self['allChannelList'] = set() # all channels |
1963 | 1969 | self['masters'] = dict() # channels grouped by master |
| 1970 | + self._si_cache = {} # SI block cache: pointer → dict |
1964 | 1971 | self.filterChannelNames = filter_channel_names |
1965 | 1972 | self.fileName = file_name |
1966 | 1973 | self.fid = None |
1967 | 1974 | if fid is None and file_name is not None: |
1968 | 1975 | # Open file |
1969 | 1976 | (self.fid, self.fileName, self.zipfile) = _open_mdf(self.fileName) |
1970 | 1977 | if self.fileName is not None and fid is None: |
1971 | | - self.read_info(self.fid, minimal) |
| 1978 | + reader = _SymBufReader(self.fid) if _SYMBUF_AVAILABLE else self.fid |
| 1979 | + self.read_info(reader, minimal) |
1972 | 1980 | # Close the file |
1973 | 1981 | self.fid.close() |
1974 | 1982 | if self.zipfile: # temporary uncompressed file, to be removed |
1975 | 1983 | remove(file_name) |
1976 | 1984 | elif self.fileName is None and fid is not None: |
1977 | 1985 | # called by mdfreader.mdfinfo |
1978 | | - self.read_info(fid, minimal) |
| 1986 | + reader = _SymBufReader(fid) if _SYMBUF_AVAILABLE else fid |
| 1987 | + self.read_info(reader, minimal) |
1979 | 1988 |
|
1980 | 1989 | def read_info(self, fid, minimal): |
1981 | 1990 | """ read all file blocks except data |
@@ -2252,12 +2261,15 @@ def read_cn_block(self, fid, pointer, dg, cg, mlsd_channels, vlsd, minimal, chan |
2252 | 2261 | fid, self['CN'][dg][cg][cn]['cn_cc_conversion']) |
2253 | 2262 | if not channel_name_list: |
2254 | 2263 | if not minimal: |
2255 | | - # reads Channel Source Information |
2256 | | - temp = SIBlock() |
2257 | | - temp.read_si(fid, self['CN'][dg][cg][cn]['cn_si_source']) |
2258 | | - if temp: |
2259 | | - self['CN'][dg][cg][cn]['SI'] = dict() |
2260 | | - self['CN'][dg][cg][cn]['SI'].update(temp) |
| 2264 | + # reads Channel Source Information (cached by pointer to avoid duplicate file reads) |
| 2265 | + si_pointer = self['CN'][dg][cg][cn]['cn_si_source'] |
| 2266 | + if si_pointer and si_pointer not in self._si_cache: |
| 2267 | + temp = SIBlock() |
| 2268 | + temp.read_si(fid, si_pointer) |
| 2269 | + self._si_cache[si_pointer] = dict(temp) if temp else None |
| 2270 | + cached_si = self._si_cache.get(si_pointer) |
| 2271 | + if cached_si: |
| 2272 | + self['CN'][dg][cg][cn]['SI'] = dict(cached_si) |
2261 | 2273 |
|
2262 | 2274 | # keep original non unique channel name |
2263 | 2275 | self['CN'][dg][cg][cn]['orig_name'] = self['CN'][dg][cg][cn]['name'] |
|
0 commit comments