From e013d5b49620bfc02a5fc528947f90d1e5d5134e Mon Sep 17 00:00:00 2001 From: Benjamin Moody Date: Thu, 18 Apr 2024 14:23:45 -0400 Subject: [PATCH] adc: optimize replacement of NaNs. When converting physical to digital sample arrays, we must replace NaN values with the appropriate invalid-sample sentinel value. To do this, we need to call np.isnan and use the result as a mask to replace entries in the output array. (Although the function np.nan_to_num also exists, it's less efficient: it literally does just this, but also handles infinities.) What we don't need to do is to call any() to check whether there are any true entries - that just means we're iterating through the same array three times rather than once. Furthermore, np.copyto can broadcast d_nans across the rows of p_signal, so all the channels can be handled at once. Also use copyto in adc_inplace_1d for consistency. --- wfdb/io/_signal.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/wfdb/io/_signal.py b/wfdb/io/_signal.py index 67bb6d68..843aeaa1 100644 --- a/wfdb/io/_signal.py +++ b/wfdb/io/_signal.py @@ -539,7 +539,7 @@ def adc_inplace_1d(ch_p_signal, adc_gain, baseline, d_nan): np.multiply(ch_p_signal, adc_gain, ch_p_signal) np.add(ch_p_signal, baseline, ch_p_signal) np.round(ch_p_signal, 0, ch_p_signal) - ch_p_signal[ch_nanlocs] = d_nan + np.copyto(ch_p_signal, d_nan, where=ch_nanlocs) ch_d_signal = ch_p_signal.astype(intdtype, copy=False) return ch_d_signal @@ -550,10 +550,7 @@ def adc_inplace_2d(p_signal): np.multiply(p_signal, self.adc_gain, p_signal) np.add(p_signal, self.baseline, p_signal) np.round(p_signal, 0, p_signal) - if nanlocs.any(): - for ch in range(p_signal.shape[1]): - if nanlocs[:, ch].any(): - p_signal[nanlocs[:, ch], ch] = d_nans[ch] + np.copyto(p_signal, d_nans, where=nanlocs) d_signal = p_signal.astype(intdtype, copy=False) return d_signal