MIT-LCP / wfdb-python

Native Python WFDB package
MIT License
730 stars 298 forks source link

Record.adc: RuntimeWarning: invalid value encountered in cast #480

Closed bemoody closed 2 months ago

bemoody commented 3 months ago

The adc function reports a RuntimeWarning (at least in some cases) if the input array contains NaN values.

I'm currently looking at this case (expanded=True, inplace=False), though it looks like the other cases are also broken in various similar ways:

                d_signal = []
                for ch in range(self.n_sig):
                    # NAN locations for the channel
                    ch_nanlocs = np.isnan(self.e_p_signal[ch])
                    ch_d_signal = self.e_p_signal[ch].copy()
                    np.multiply(ch_d_signal, self.adc_gain[ch], ch_d_signal)
                    np.add(ch_d_signal, self.baseline[ch], ch_d_signal)
                    np.round(ch_d_signal, 0, ch_d_signal)
                    ch_d_signal = ch_d_signal.astype(intdtype, copy=False)
                    ch_d_signal[ch_nanlocs] = d_nans[ch]
                    d_signal.append(ch_d_signal)

The warning occurs here:

                    ch_d_signal = ch_d_signal.astype(intdtype, copy=False)

numpy is complaining, I assume, because you can't cast a NaN to an integer.

(Like many things to do with numpy and with this package), the above looks rather inefficient. Perhaps numpy.nan_to_num could be used instead.

bemoody commented 3 months ago

Perhaps numpy.nan_to_num could be used instead.

Never mind: nan_to_num is not any more intelligently implemented (might even be worse) than what wfdb-python is already doing.

bemoody commented 2 months ago

To reproduce the issue:

import wfdb, numpy
r = wfdb.Record(fs=500, n_sig=1, units=['mV'], sig_name=['ECG'], p_signal=numpy.array([[0], [1], [numpy.nan]]), fmt=['16'], adc_gain=[1], baseline=[0])
r.adc()

or

import wfdb, numpy
r = wfdb.Record(fs=500, n_sig=1, units=['mV'], sig_name=['ECG'], e_p_signal=[numpy.array([0, 1, numpy.nan])], fmt=['16'], adc_gain=[1], baseline=[0])
r.adc(expanded=True)

This is fixed with pull #481.