You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This is clearly a bug as using 1 second windows for Welch with 500 ms overlap is a very typical analysis. But it will fail if two bad segments are less than 500 ms spaced apart.
Importantly, this was no issue with my data in the past. The bug must have been introduced with some mne update (unfortunately, I don't know which one).
The bad segments should be set to np.nan and good data segment windows with less than n_fft sample points should be discarded. This works with n_overlap=None but it does not work with n_overlap > 0.
Actual results
---------------------------------------------------------------------------ValueErrorTraceback (mostrecentcalllast)
CellIn[11], line1---->1spectrum=raw.compute_psd(method="welch", **kwargs)
File<decorator-gen-336>:12, incompute_psd(self, method, fmin, fmax, tmin, tmax, picks, exclude, proj, remove_dc, reject_by_annotation, n_jobs, verbose, **method_kw)
File~/anaconda3/envs/local_sns013/lib/python3.12/site-packages/mne/io/base.py:2232, inBaseRaw.compute_psd(self, method, fmin, fmax, tmin, tmax, picks, exclude, proj, remove_dc, reject_by_annotation, n_jobs, verbose, **method_kw)
2229method=_validate_method(method, type(self).__name__)
2230self._set_legacy_nfft_default(tmin, tmax, method, method_kw)
->2232returnSpectrum(
2233self,
2234method=method,
2235fmin=fmin,
2236fmax=fmax,
2237tmin=tmin,
2238tmax=tmax,
2239picks=picks,
2240exclude=exclude,
2241proj=proj,
2242remove_dc=remove_dc,
2243reject_by_annotation=reject_by_annotation,
2244n_jobs=n_jobs,
2245verbose=verbose,
2246**method_kw,
2247 )
File~/anaconda3/envs/local_sns013/lib/python3.12/site-packages/mne/time_frequency/spectrum.py:1146, inSpectrum.__init__(self, inst, method, fmin, fmax, tmin, tmax, picks, exclude, proj, remove_dc, reject_by_annotation, n_jobs, verbose, **method_kw)
1144self._nave=getattr(inst, "nave", None)
1145# compute the spectra->1146self._compute_spectra(data, fmin, fmax, n_jobs, method_kw, verbose)
1147# check for correct shape and bad values1148self._check_values()
File~/anaconda3/envs/local_sns013/lib/python3.12/site-packages/mne/time_frequency/spectrum.py:445, inBaseSpectrum._compute_spectra(self, data, fmin, fmax, n_jobs, method_kw, verbose)
443def_compute_spectra(self, data, fmin, fmax, n_jobs, method_kw, verbose):
444# make the spectra-->445result=self._psd_func(
446data, self.sfreq, fmin=fmin, fmax=fmax, n_jobs=n_jobs, verbose=verbose447 )
448# assign ._data ._freqs, ._shape449psds, freqs=resultFile<decorator-gen-5>:12, inpsd_array_welch(x, sfreq, fmin, fmax, n_fft, n_overlap, n_per_seg, n_jobs, average, window, remove_dc, output, verbose)
File~/anaconda3/envs/local_sns013/lib/python3.12/site-packages/mne/time_frequency/psd.py:272, inpsd_array_welch(x, sfreq, fmin, fmax, n_fft, n_overlap, n_per_seg, n_jobs, average, window, remove_dc, output, verbose)
270agg_func=np.concatenate271func=_func-->272f_spect=parallel(
273my_spect_func(d, func=func, freq_sl=freq_sl, average=average, output=output)
274fordinx_splits275 )
276psds=agg_func(f_spect, axis=0)
277shape=dshape+ (len(freqs),)
File~/anaconda3/envs/local_sns013/lib/python3.12/site-packages/mne/time_frequency/psd.py:273, in<genexpr>(.0)
270agg_func=np.concatenate271func=_func272f_spect=parallel(
-->273my_spect_func(d, func=func, freq_sl=freq_sl, average=average, output=output)
274fordinx_splits275 )
276psds=agg_func(f_spect, axis=0)
277shape=dshape+ (len(freqs),)
File~/anaconda3/envs/local_sns013/lib/python3.12/site-packages/mne/time_frequency/psd.py:75, in_spect_func(epoch, func, freq_sl, average, output)
73spect=np.apply_along_axis(_decomp_aggregate_mask, -1, epoch, **kwargs)
74else:
--->75spect=_decomp_aggregate_mask(epoch, **kwargs)
76returnspectFile~/anaconda3/envs/local_sns013/lib/python3.12/site-packages/mne/time_frequency/psd.py:52, in_decomp_aggregate_mask(epoch, func, average, freq_sl)
51def_decomp_aggregate_mask(epoch, func, average, freq_sl):
--->52_, _, spect=func(epoch)
53spect=spect[..., freq_sl, :]
54# Do the averaging here (per epoch) to save memoryFile~/anaconda3/envs/local_sns013/lib/python3.12/site-packages/mne/time_frequency/psd.py:266, inpsd_array_welch.<locals>.func(*args, **kwargs)
259withwarnings.catch_warnings():
260warnings.filterwarnings(
261action="ignore",
262module="scipy",
263category=UserWarning,
264message=r"nperseg = \d+ is greater than input length",
265 )
-->266return_func(*args, **kwargs)
File~/anaconda3/envs/local_sns013/lib/python3.12/site-packages/scipy/signal/_spectral_py.py:783, inspectrogram(x, fs, window, nperseg, noverlap, nfft, detrend, return_onesided, scaling, axis, mode)
780noverlap=nperseg//8782ifmode=='psd':
-->783freqs, time, Sxx=_spectral_helper(x, x, fs, window, nperseg,
784noverlap, nfft, detrend,
785return_onesided, scaling, axis,
786mode='psd')
788else:
789freqs, time, Sxx=_spectral_helper(x, x, fs, window, nperseg,
790noverlap, nfft, detrend,
791return_onesided, scaling, axis,
792mode='stft')
File~/anaconda3/envs/local_sns013/lib/python3.12/site-packages/scipy/signal/_spectral_py.py:1851, in_spectral_helper(x, y, fs, window, nperseg, noverlap, nfft, detrend, return_onesided, scaling, axis, mode, boundary, padded)
1849noverlap=int(noverlap)
1850ifnoverlap>=nperseg:
->1851raiseValueError('noverlap must be less than nperseg.')
1852nstep=nperseg-noverlap1854# Padding occurs after boundary extension, so that the extended signal ends1855# in zeros, instead of introducing an impulse at the end.1856# I.e. if x = [..., 3, 2]1857# extend then pad -> [..., 3, 2, 2, 3, 0, 0, 0]1858# pad then extend -> [..., 3, 2, 0, 0, 0, 2, 3]ValueError: noverlapmustbelessthannperseg.
I could now trace back where this error came from. The bug is absent in mne=1.6 and it exists from 1.7 on.
@drammock, is it possible that it was introduced with bug fixes #12536 or #12538? I checked the files but could not directly understand how the introduced changes impact overlapping windows.
@drammock, is it possible that it was introduced with bug fixes #12536 or #12538? I checked the files but could not directly understand how the introduced changes impact overlapping windows.
Seems quite possible. I'll try to take a look next week
Description of the problem
Using
n_overlap
only works if there are no good data segments shorter thann_overlap
:This is clearly a bug as using 1 second windows for Welch with 500 ms overlap is a very typical analysis. But it will fail if two bad segments are less than 500 ms spaced apart.
Importantly, this was no issue with my data in the past. The bug must have been introduced with some mne update (unfortunately, I don't know which one).
Steps to reproduce
Link to data
Jupyter Notebook Example
Expected results
The bad segments should be set to
np.nan
and good data segment windows with less thann_fft
sample points should be discarded. This works withn_overlap=None
but it does not work withn_overlap > 0
.Actual results
Additional information
Platform macOS-15.1.1-arm64-arm-64bit
Python 3.12.5 | packaged by conda-forge | (main, Aug 8 2024, 18:32:50) [Clang 16.0.6 ]
Executable /Users/moritzgerster/anaconda3/envs/local_sns013/bin/python
CPU arm (10 cores)
Memory 16.0 GB
Core
├☒ mne 1.7.1 (outdated, release 1.9.0 is available!)
├☑ numpy 2.0.1 (OpenBLAS 0.3.27 with 10 threads)
├☑ scipy 1.14.0
└☑ matplotlib 3.9.1 (backend=module://matplotlib_inline.backend_inline)
Numerical (optional)
├☑ sklearn 1.5.1
├☑ numba 0.60.0
├☑ nibabel 5.2.1
├☑ nilearn 0.10.4
├☑ pandas 2.2.2
├☑ h5io 0.2.4
├☑ h5py 3.11.0
└☐ unavailable dipy, openmeeg, cupy
Visualization (optional)
└☐ unavailable pyvista, pyvistaqt, vtk, qtpy, ipympl, pyqtgraph, mne-qt-browser, ipywidgets, trame_client, trame_server, trame_vtk, trame_vuetify
Ecosystem (optional)
├☑ mne-bids 0.15.0
├☑ eeglabio 0.0.2-4
├☑ edfio 0.4.3
├☑ pybv 0.7.5
└☐ unavailable mne-nirs, mne-features, mne-connectivity, mne-icalabel, mne-bids-pipeline, neo, mffpy
The text was updated successfully, but these errors were encountered: