def load(self, ecg_file) -> ECGRecord: if not os.path.isfile(ecg_file): raise FileNotFoundError(f"{ecg_file} is not found") record = Holter(ecg_file) record.load_data() def load_ann(ann_file, annheader): filesize = os.path.getsize(ann_file) headersize = 522 + annheader.var_block_size + 4 record.beat_anns = [] with open(ann_file, 'rb') as f: f.seek(headersize - 4, os.SEEK_SET) first_sample = np.fromfile(f, dtype=np.uint32, count=1)[0] current_sample = first_sample timeout = False # was there a gap in the annotations? for beat in range(int((filesize - headersize) / 4)): # note, the beat at first_sample isn't annotated. so the first beat # in beat_anns is actually the second beat of the recording. ann = chr(np.fromfile(f, dtype=np.uint8, count=1)[0]) internal = chr(np.fromfile(f, dtype=np.uint8, count=1)[0]) toc = np.fromfile(f, dtype=np.int16, count=1)[0] current_sample += toc if ann == '!': timeout = True # there was a few minutes gap in the anns; don't # know how to line them up to rest of recording record.beat_anns.append({'ann': ann, 'internal': internal, 'toc': toc}) if not timeout: record.beat_anns[-1]['samp_num'] = current_sample ann_file = os.path.splitext(ecg_file)[0] + '.ann' ann_header = Holter(ann_file, check_valid=False, annfile=True) load_ann(ann_file, ann_header) time = Time.from_fs_samples(record.sr, len(record.lead[0].data)) record_name = os.path.split(ecg_file)[1] record_name = ".".join(record_name.split(".")[:-1]) new_record = ECGRecord(name=record_name, time=time) for leadi in record.lead: new_record.add_signal(Signal(leadi.data, str(leadi))) ecg_annotation = ECGAnnotation([ECGAnnotationSample(i["samp_num"], i["ann"]) for i in record.beat_anns]) new_record.annotations = ecg_annotation new_record.info = SubjectInfo() new_record.info.race = record.race new_record.info.sex = record.sex new_record.info.birth_date = record.birth_date new_record.info.record_date = record.record_date new_record.info.file_date = record.file_date new_record.info.start_time = record.start_time new_record.info.pm = record.pm return new_record
def load(self, hea_file) -> ECGRecord: base_path = os.path.splitext(hea_file)[0] def load_annotation(ann_ext): return wfdb.rdann(base_path, ann_ext) hea_file = base_path + ".hea" if not os.path.isfile(hea_file): raise FileNotFoundError(f"{hea_file} is not found") record = wfdb.rdrecord(base_path) time = Time.from_fs_samples(record.fs, record.sig_len) new_record = ECGRecord(name=record.record_name, time=time) for signal, lead_name in zip(record.p_signal.T, record.sig_name): new_record.add_signal(Signal(signal, lead_name)) ann = load_annotation("atr") ecg_annotation = ECGAnnotation([ ECGAnnotationSample(samp, symbol) for samp, symbol in zip(ann.sample, ann.symbol) ]) new_record.annotations = ecg_annotation return new_record
def test_len(fs, samples): time = Time.from_fs_samples(fs, samples) assert len(time) == samples
def test_from_time_stamp_not_monotonic(time_stamps): with pytest.raises(ValueError): Time.from_timestamps(time_stamps)
def test_from_time_stamp(time_stamps): time = Time.from_timestamps(time_stamps) assert np.array_equal(time.time, time_stamps)
def test_slicing_single_element(time_stamps): time = Time.from_timestamps(time_stamps) assert time[0] == time_stamps[0]
def test_slicing(time_stamps): time = Time.from_timestamps(time_stamps) assert np.array_equal(time[0:1], time_stamps[0:1])
def test_from_fs_samples(fs, samples): time = Time.from_fs_samples(fs, samples) time_expected = (1 / fs) * np.arange(0, samples) assert np.array_equal(time.time, time_expected)
def test_duration(fs, samples): record = ECGRecord("record_100", time=Time.from_fs_samples(fs, samples)) assert record.duration == (samples - 1) / fs
def test_inconsistent_signal_type(): record = ECGRecord("record_100", time=Time.from_fs_samples(360, 10)) with pytest.raises(TypeError): record.add_signal(electrocardiogram())
def test_inconsistent_signal_len(): record = ECGRecord("record_100", time=Time.from_fs_samples(360, 10)) with pytest.raises(ValueError): record.add_signal(Signal(electrocardiogram(), "MLII"))
def test_length(fs, samples): record = ECGRecord("record_100", time=Time.from_fs_samples(fs, samples)) assert len(record) == samples