|
1 | 1 | import math |
2 | 2 | import os |
| 3 | +import sys |
3 | 4 |
|
4 | 5 | import numpy as np |
5 | 6 |
|
|
10 | 11 | MAX_I32 = 2147483647 |
11 | 12 | MIN_I32 = -2147483648 |
12 | 13 |
|
13 | | -# Formats in which all samples align with byte boundaries |
14 | | -ALIGNED_FMTS = ['8', '16', '24', '32', '61', '80', '160'] |
15 | | -# Formats in which not all samples align with byte boundaries |
16 | | -UNALIGNED_FMTS = ['212', '310', '311'] |
| 14 | +# Formats in which all samples align with integer (power-of-two) boundaries |
| 15 | +ALIGNED_FMTS = ['8', '16', '32', '61', '80', '160'] |
| 16 | +# Formats in which not all samples align with integer boundaries |
| 17 | +UNALIGNED_FMTS = ['212', '310', '311', '24'] |
17 | 18 | # Formats which are stored in offset binary form |
18 | 19 | OFFSET_FMTS = ['80', '160'] |
19 | 20 | # All WFDB dat formats - https://www.physionet.org/physiotools/wag/signal-5.htm |
|
29 | 30 | '160': 16, '212': 12, '310': 10, '311': 10} |
30 | 31 |
|
31 | 32 | # Numpy dtypes used to load dat files of each format. |
32 | | -DATA_LOAD_TYPES = {'8': '<i1', '16': '<i2', '24': '<i3', '32': '<i4', |
| 33 | +DATA_LOAD_TYPES = {'8': '<i1', '16': '<i2', '24': '<u1', '32': '<i4', |
33 | 34 | '61': '>i2', '80': '<u1', '160': '<u2', '212': '<u1', |
34 | 35 | '310': '<u1', '311': '<u1'} |
35 | 36 |
|
@@ -1398,6 +1399,9 @@ def _rd_dat_file(file_name, dir_name, pn_dir, fmt, start_byte, n_samp): |
1398 | 1399 | elif fmt in ['310', '311']: |
1399 | 1400 | byte_count = _required_byte_num('read', fmt, n_samp) |
1400 | 1401 | element_count = byte_count |
| 1402 | + elif fmt == '24': |
| 1403 | + byte_count = n_samp * 3 |
| 1404 | + element_count = byte_count |
1401 | 1405 | else: |
1402 | 1406 | element_count = n_samp |
1403 | 1407 | byte_count = n_samp * BYTES_PER_SAMPLE[fmt] |
@@ -1535,6 +1539,26 @@ def _blocks_to_samples(sig_data, n_samp, fmt): |
1535 | 1539 | # Loaded values as un_signed. Convert to 2's complement form. |
1536 | 1540 | # Values > 2^9-1 are negative. |
1537 | 1541 | sig[sig > 511] -= 1024 |
| 1542 | + |
| 1543 | + elif fmt == '24': |
| 1544 | + # The following is equivalent to: |
| 1545 | + # sig = (sig_data[2::3].view('int8').astype('int32') * 65536 |
| 1546 | + # + sig_data[1::3].astype('uint16') * 256 |
| 1547 | + # + sig_data[0::3]) |
| 1548 | + |
| 1549 | + # Treat the high byte as signed and shift it by 16 bits. |
| 1550 | + sig = np.left_shift(sig_data[2::3].view('int8'), 16, dtype='int32') |
| 1551 | + |
| 1552 | + # Directly copy the low and middle bytes. |
| 1553 | + if sys.byteorder == 'little': |
| 1554 | + sig.view('uint8')[0::4] = sig_data[0::3] |
| 1555 | + sig.view('uint8')[1::4] = sig_data[1::3] |
| 1556 | + elif sys.byteorder == 'big': |
| 1557 | + sig.view('uint8')[3::4] = sig_data[0::3] |
| 1558 | + sig.view('uint8')[2::4] = sig_data[1::3] |
| 1559 | + else: |
| 1560 | + raise NotImplementedError |
| 1561 | + |
1538 | 1562 | return sig |
1539 | 1563 |
|
1540 | 1564 |
|
|
0 commit comments