Skip to content

Correctly infer length of record when unspecified #323

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Sep 10, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions sample-data/a103l-no-len.hea
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
a103l-no-len 3 250
a103l.mat 16+24 7247/mV 16 0 -171 -27403 0 II
a103l.mat 16+24 1.052e+04/mV 16 0 9127 -301 0 V
a103l.mat 16+24 1.253e+04/NU 16 0 6042 -17391 0 PLETH
#Asystole
#False alarm
6 changes: 6 additions & 0 deletions sample-data/drive02-no-len.hea
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
drive02-no-len 5 15.5
drive02.dat 16x32 1000 16 0 -1236 14736 0 ECG
drive02.dat 16x2 1000 16 0 1802 13501 0 foot GSR
drive02.dat 16 1.0001/bpm 16 0 75 -19070 0 HR
drive02.dat 16 100 16 0 0 -9226 0 marker
drive02.dat 16x2 500 16 0 5804 -14191 0 RESP
12 changes: 9 additions & 3 deletions tests/test_record.py
Original file line number Diff line number Diff line change
Expand Up @@ -701,9 +701,15 @@ def test_infer_sig_len(self):
Read two headers. The records should be the same.
"""

record = wfdb.rdrecord('sample-data/100')
record_2 = wfdb.rdrecord('sample-data/100-no-len')
record_2.record_name = '100'
record = wfdb.rdrecord('sample-data/drive02')
record_2 = wfdb.rdrecord('sample-data/drive02-no-len')
record_2.record_name = record.record_name

assert record_2.__eq__(record)

record = wfdb.rdrecord('sample-data/a103l')
record_2 = wfdb.rdrecord('sample-data/a103l-no-len')
record_2.record_name = record.record_name

assert record_2.__eq__(record)

Expand Down
18 changes: 12 additions & 6 deletions wfdb/io/_signal.py
Original file line number Diff line number Diff line change
Expand Up @@ -2059,7 +2059,8 @@ def describe_list_indices(full_list):
return unique_elements, element_indices


def _infer_sig_len(file_name, fmt, n_sig, dir_name, pn_dir=None):
def _infer_sig_len(file_name, fmt, tsamps_per_frame, byte_offset,
dir_name, pn_dir=None):
"""
Infer the length of a signal from a dat file.

Expand All @@ -2069,8 +2070,10 @@ def _infer_sig_len(file_name, fmt, n_sig, dir_name, pn_dir=None):
Name of the dat file.
fmt : str
WFDB fmt of the dat file.
n_sig : int
Number of signals contained in the dat file.
tsamps_per_frame : int
Total number of samples per frame contained in the dat file.
byte_offset : int or None
The byte offset of the dat file. None is equivalent to zero.
dir_name : str
The full directory where the dat file(s) are located, if the dat
file(s) are local.
Expand All @@ -2081,11 +2084,11 @@ def _infer_sig_len(file_name, fmt, n_sig, dir_name, pn_dir=None):
Returns
-------
sig_len : int
The length of the signal.
The length of the signal file in frames.

Notes
-----
sig_len * n_sig * bytes_per_sample == file_size
sig_len * tsamps_per_frame * bytes_per_sample == file_size

"""
if pn_dir is None:
Expand All @@ -2094,7 +2097,10 @@ def _infer_sig_len(file_name, fmt, n_sig, dir_name, pn_dir=None):
file_size = download._remote_file_size(file_name=file_name,
pn_dir=pn_dir)

sig_len = int(file_size / (BYTES_PER_SAMPLE[fmt] * n_sig))
if byte_offset is None:
byte_offset = 0
data_size = file_size - byte_offset
sig_len = int(data_size / (BYTES_PER_SAMPLE[fmt] * tsamps_per_frame))

return sig_len

Expand Down
12 changes: 11 additions & 1 deletion wfdb/io/record.py
Original file line number Diff line number Diff line change
Expand Up @@ -3441,9 +3441,19 @@ def rdrecord(record_name, sampfrom=0, sampto=None, channels=None,
if record.n_sig == 0:
record.sig_len = 0
else:
# Calculate total number of samples per frame in the
# first dat file.
tsamps_per_frame = 0
for fname, spf in zip(record.file_name,
record.samps_per_frame):
if fname == record.file_name[0]:
tsamps_per_frame += spf

# Calculate length from size of the dat file.
record.sig_len = _signal._infer_sig_len(
file_name=record.file_name[0], fmt=record.fmt[0],
n_sig=record.file_name.count(record.file_name[0]),
tsamps_per_frame=tsamps_per_frame,
byte_offset=record.byte_offset[0],
dir_name=dir_name, pn_dir=pn_dir)
sampto = record.sig_len

Expand Down