@@ -466,8 +466,6 @@ def check_field(self, field):
466
466
raise ValueError ("The 'sample' field must only contain non-negative integers" )
467
467
if min (sampdiffs ) < 0 :
468
468
raise ValueError ("The 'sample' field must contain monotonically increasing sample numbers" )
469
- if max (sampdiffs ) > 2147483648 :
470
- raise ValueError ('WFDB annotation files cannot store sample differences greater than 2**31' )
471
469
472
470
elif field == 'label_store' :
473
471
if min (item ) < 1 or max (item ) > 49 :
@@ -1370,19 +1368,30 @@ def field2bytes(field, value):
1370
1368
# sample difference
1371
1369
sd = value [0 ]
1372
1370
1373
- # Add SKIP element if value is too large for single byte
1374
- if sd > 1023 :
1375
- # 8 bytes in total:
1376
- # - [0, 59>>2] indicates SKIP
1377
- # - Next 4 gives sample difference
1378
- # - Final 2 give 0 and sym
1379
- data_bytes = [0 , 236 , (sd & 16711680 )>> 16 , (sd & 4278190080 )>> 24 , sd & 255 , (sd & 65280 )>> 8 , 0 , 4 * typecode ]
1380
- # Just need samp and sym
1381
- else :
1382
- # - First byte stores low 8 bits of samp
1383
- # - Second byte stores high 2 bits of samp
1384
- # and sym
1385
- data_bytes = [sd & 255 , ((sd & 768 ) >> 8 ) + 4 * typecode ]
1371
+ data_bytes = []
1372
+
1373
+ # Add SKIP element(s) if the sample difference is too large to
1374
+ # be stored in the annotation type word.
1375
+ #
1376
+ # Each SKIP element consists of three words (6 bytes):
1377
+ # - Bytes 0-1 contain the SKIP indicator (59 << 10)
1378
+ # - Bytes 2-3 contain the high 16 bits of the sample difference
1379
+ # - Bytes 4-5 contain the low 16 bits of the sample difference
1380
+ # If the total difference exceeds 2**31 - 1, multiple skips must
1381
+ # be used.
1382
+ while sd > 1023 :
1383
+ n = min (sd , 0x7fffffff )
1384
+ data_bytes += [0 , 59 << 2 ,
1385
+ (n >> 16 ) & 255 ,
1386
+ (n >> 24 ) & 255 ,
1387
+ (n >> 0 ) & 255 ,
1388
+ (n >> 8 ) & 255 ]
1389
+ sd -= n
1390
+
1391
+ # Annotation type itself is stored as a single word:
1392
+ # - bits 0 to 9 store the sample difference (0 to 1023)
1393
+ # - bits 10 to 15 store the type code
1394
+ data_bytes += [sd & 255 , ((sd & 768 ) >> 8 ) + 4 * typecode ]
1386
1395
1387
1396
elif field == 'num' :
1388
1397
# First byte stores num
@@ -1653,8 +1662,11 @@ def rdann(record_name, extension, sampfrom=0, sampto=None, shift_samps=False,
1653
1662
subtype , chan , num , aux_note )
1654
1663
1655
1664
# Convert lists to numpy arrays dtype='int'
1656
- (sample , label_store , subtype ,
1657
- chan , num ) = lists_to_int_arrays (sample , label_store , subtype , chan , num )
1665
+ (label_store , subtype ,
1666
+ chan , num ) = lists_to_int_arrays (label_store , subtype , chan , num )
1667
+
1668
+ # Convert sample numbers to a numpy array of 'int64'
1669
+ sample = np .array (sample , dtype = 'int64' )
1658
1670
1659
1671
# Try to get fs from the header file if it is not contained in the
1660
1672
# annotation file
@@ -1748,8 +1760,8 @@ def load_byte_pairs(record_name, extension, pn_dir):
1748
1760
1749
1761
Returns
1750
1762
-------
1751
- filebytes : str
1752
- The input filestream converted to bytes.
1763
+ filebytes : ndarray
1764
+ The input filestream converted to an Nx2 array of unsigned bytes.
1753
1765
1754
1766
"""
1755
1767
# local file
@@ -1769,8 +1781,8 @@ def proc_ann_bytes(filebytes, sampto):
1769
1781
1770
1782
Parameters
1771
1783
----------
1772
- filebytes : str
1773
- The input filestream converted to bytes.
1784
+ filebytes : ndarray
1785
+ The input filestream converted to an Nx2 array of unsigned bytes.
1774
1786
sampto : int
1775
1787
The maximum sample number for annotations to be returned.
1776
1788
@@ -1852,8 +1864,8 @@ def proc_core_fields(filebytes, bpi):
1852
1864
1853
1865
Parameters
1854
1866
----------
1855
- filebytes : str
1856
- The input filestream converted to bytes.
1867
+ filebytes : ndarray
1868
+ The input filestream converted to an Nx2 array of unsigned bytes.
1857
1869
bpi : int
1858
1870
The index to start the conversion.
1859
1871
@@ -1869,31 +1881,28 @@ def proc_core_fields(filebytes, bpi):
1869
1881
The index to start the conversion.
1870
1882
1871
1883
"""
1872
- label_store = filebytes [ bpi , 1 ] >> 2
1884
+ sample_diff = 0
1873
1885
1874
1886
# The current byte pair will contain either the actual d_sample + annotation store value,
1875
1887
# or 0 + SKIP.
1876
-
1877
- # Not a skip - it is the actual sample number + annotation type store value
1878
- if label_store != 59 :
1879
- sample_diff = filebytes [bpi , 0 ] + 256 * (filebytes [bpi , 1 ] & 3 )
1880
- bpi = bpi + 1
1881
- # Skip. Note: Could there be another skip after the first?
1882
- else :
1888
+ while filebytes [bpi , 1 ] >> 2 == 59 :
1883
1889
# 4 bytes storing dt
1884
- sample_diff = 65536 * filebytes [bpi + 1 ,0 ] + 16777216 * filebytes [bpi + 1 ,1 ] \
1885
- + filebytes [bpi + 2 ,0 ] + 256 * filebytes [bpi + 2 ,1 ]
1890
+ skip_diff = ((int (filebytes [bpi + 1 , 0 ]) << 16 )
1891
+ + (int (filebytes [bpi + 1 , 1 ]) << 24 )
1892
+ + (int (filebytes [bpi + 2 , 0 ]) << 0 )
1893
+ + (int (filebytes [bpi + 2 , 1 ]) << 8 ))
1886
1894
1887
1895
# Data type is long integer (stored in two's complement). Range -2**31 to 2**31 - 1
1888
- if sample_diff > 2147483647 :
1889
- sample_diff = sample_diff - 4294967296
1896
+ if skip_diff > 2147483647 :
1897
+ skip_diff = skip_diff - 4294967296
1890
1898
1891
- # After the 4 bytes, the next pair's samp is also added
1892
- sample_diff = sample_diff + filebytes [ bpi + 3 , 0 ] + 256 * ( filebytes [ bpi + 3 , 1 ] & 3 )
1899
+ sample_diff += skip_diff
1900
+ bpi = bpi + 3
1893
1901
1894
- # The label is stored after the 4 bytes. Samples here should be 0.
1895
- label_store = filebytes [bpi + 3 , 1 ] >> 2
1896
- bpi = bpi + 4
1902
+ # Not a skip - it is the actual sample number + annotation type store value
1903
+ label_store = filebytes [bpi , 1 ] >> 2
1904
+ sample_diff += int (filebytes [bpi , 0 ] + 256 * (filebytes [bpi , 1 ] & 3 ))
1905
+ bpi = bpi + 1
1897
1906
1898
1907
return sample_diff , label_store , bpi
1899
1908
0 commit comments