From 76a03b3525b260d396c312d1cf13539d14894115 Mon Sep 17 00:00:00 2001 From: Benjamin Moody Date: Mon, 9 Aug 2021 17:46:25 -0400 Subject: [PATCH] _rd_dat_signals: optimize construction of expanded arrays. When reading signal data with smooth_frames = False, we want to return a one-dimensional array of samples for each signal, which means extracting a range of samples from each frame and concatenating those ranges into a single numpy array. Previously this was done by constructing an array of all the desired sample indices, and using that array as a subscript into the input sig_data array. This is inefficient in both time and memory. Instead, extract the desired samples as a slice of a two-dimensional array, and reshape that slice to obtain a 1D array. (Using reshape(-1) instead of flatten() means that if samps_per_frame is 1, the array does not need to be copied. If the array does need to be copied, the reshape operation is still faster than any Python loop and doesn't require additional memory.) --- wfdb/io/_signal.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/wfdb/io/_signal.py b/wfdb/io/_signal.py index f6a95ec6..3c895613 100644 --- a/wfdb/io/_signal.py +++ b/wfdb/io/_signal.py @@ -1193,12 +1193,13 @@ def _rd_dat_signals(file_name, dir_name, pn_dir, fmt, n_sig, sig_len, # List of 1d numpy arrays signal = [] # Transfer over samples + sig_frames = sig_data.reshape(-1, tsamps_per_frame) + ch_start = 0 for ch in range(n_sig): - # Indices of the flat signal that belong to the channel - ch_indices = np.concatenate([np.array(range(samps_per_frame[ch])) - + sum([0] + samps_per_frame[:ch]) - + tsamps_per_frame * framenum for framenum in range(int(len(sig_data)/tsamps_per_frame))]) - signal.append(sig_data[ch_indices]) + ch_end = ch_start + samps_per_frame[ch] + ch_signal = sig_frames[:, ch_start:ch_end].reshape(-1) + signal.append(ch_signal) + ch_start = ch_end # Skew the signal signal = _skew_sig(signal, skew, n_sig, read_len, fmt, nan_replace, samps_per_frame)