Signal.welch function: f and pxx outcome is 0

Question:

I have an array of BOLD activity of length 240. A recording took place every 2 seconds (you can download a part of the data here (the file can be opend normally with a .txt editor). I want to analyse this time series with the signal.welch function.

f, pxx = signal.welch(data, fs=0.5, window='hanning', nperseg=50, noverlap=25, scaling='density', average='mean')

It gives me the following error

ValueError: noverlap must be less than nperseg.

When I set noverlap = None , no error shows up, but f equals 0 and pxx is an array of 0s.

Thank you very much for your suggestions!!

Asked By: Ang

||

Answers:

If I read the data file with, for example,

data = np.loadtxt('rest1_LeftInsula.1D')

data will be a 1-d numpy array with shape (240,), and the call

f, pxx = signal.welch(data, fs=0.5, window='hanning', nperseg=50, noverlap=25, scaling='density', average='mean')

works with no errors.

If I reshape data to be an array with shape (240, 1), and pass that to welch (which can be done by indexing it as data[:, None] or with the reshape method data.reshape((240, 1))), I get the same error that you reported:

In [11]: f, pxx = signal.welch(data[:,None], fs=0.5, window='hanning', nperseg=5, 0, noverlap=25, scaling='density', average='mean')
[...]/scipy/signal/spectral.py:1964: UserWarning: nperseg = 50 is greater than input length  = 1, using nperseg = 1
  warnings.warn('nperseg = {0:d} is greater than input length '
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-11-0e5235350cfd> in <module>
----> 1 f, pxx = signal.welch(data[:,None], fs=0.5, window='hanning', nperseg=50, noverlap=25, scaling='density', average='mean')

[...]/scipy/signal/spectral.py in welch(x, fs, window, nperseg, noverlap, nfft, detrend, return_onesided, scaling, axis, average)
    446 
    447     """
--> 448     freqs, Pxx = csd(x, x, fs=fs, window=window, nperseg=nperseg,
    449                      noverlap=noverlap, nfft=nfft, detrend=detrend,
    450                      return_onesided=return_onesided, scaling=scaling,

[...]/scipy/signal/spectral.py in csd(x, y, fs, window, nperseg, noverlap, nfft, detrend, return_onesided, scaling, axis, average)
    580 
    581     """
--> 582     freqs, _, Pxy = _spectral_helper(x, y, fs, window, nperseg, noverlap, nfft,
    583                                      detrend, return_onesided, scaling, axis,
    584                                      mode='psd')

[...]/scipy/signal/spectral.py in _spectral_helper(x, y, fs, window, nperseg, noverlap, nfft, detrend, return_onesided, scaling, axis, mode, boundary, padded)
   1756         noverlap = int(noverlap)
   1757     if noverlap >= nperseg:
-> 1758         raise ValueError('noverlap must be less than nperseg.')
   1759     nstep = nperseg - noverlap
   1760 

ValueError: noverlap must be less than nperseg.

The problem is that, by default, welch is applied along the last axis of the input array. If that array has shape (240, 1), welch attempts to apply the calculation to each "row" of the 2-d array. But each row has length 1, which is too small for the given values of nperseg and noverlap, and that leads to the (somewhat cryptic) error.

You haven’t shown how you read the file and created data, but I suspect it is creating an array (or some other data structure, such as a Pandas DataFrame) that has shape (240, 1).

To fix this, you can "flatten" the data into a 1-d array (e.g. pass data.ravel() to welch), or pass the argument axis=0 to welch to tell it to act along the first dimension instead of the last. If you do the latter, be aware that the shape of pxx will be (26, 1), instead of the shape (26,) that you get when data has shape (240,).

Answered By: Warren Weckesser
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.