Repository: mne-tools/mne-python

Issue:
Add window argument to psd_welch?
I was wondering if a new `window` argument might be useful for the `mne.time_frequency.psd_welch` function, where the user can specify the window type (now the SciPy default is used, which corresponds to a Tukey 0.25 window). I usually use a Hamming or Hanning window, not because I know they work better but just out of habit. For reference, MATLAB uses a Hamming window by default for its [`pwelch` function](https://www.mathworks.com/help/signal/ref/pwelch.html).


Discussion:
Can you try playing with it locally first to see if it makes much
difference? I'd rather not add it if the practical implications are limited
for our data, and instead document that it's different from MATLAB.

Yes, it will make a difference, as will all other possible choices of window functions. Although it would be nice to have an argument to specify the window function (as different people will have different needs), a sane default might be sufficient for EEG/MEG application. At the very least, the used window should be documented in the `psd_welch` function, which is currently not the case. Now that I've looked over the code again, I'm not even sure that the Tukey window is used - I think the window is set to a Hann window [here](https://github.com/mne-tools/mne-python/blob/master/mne/time_frequency/psd.py#L17), which overrides the SciPy `spectrogram` default. Correct?

What do others think? Is there a need to specify [window functions](https://en.wikipedia.org/wiki/Window_function)? If Hann is really used, this might be a sensible choice for most use cases.
I would favor a good default choice for EEG/MEG/iEEG data. If there is no
such things then we need to motivate / document it.

Not sure if there any studies specific to electrophysiological PSD windowing functions. I think that this is likely a very minor point, so let's at least document which window is being used in `psd_welch`. Can you confirm that it is indeed a Hann window?
> Can you confirm that it is indeed a Hann window?

Yeah it looks like we use `hann`. If you want, we could switch it to `hamming` for consistency. I don't expect it will make much difference in the output. If you do want to change it, go ahead and do it and we can compare the CircleCI output for the sample dataset raw PSD to see if it's qualitatively different.

Documentation either way is appreciated

Resolving patch:
diff --git a/mne/time_frequency/psd.py b/mne/time_frequency/psd.py
--- a/mne/time_frequency/psd.py
+++ b/mne/time_frequency/psd.py
@@ -14,7 +14,7 @@
 def _psd_func(epoch, noverlap, n_per_seg, nfft, fs, freq_mask, func):
     """Aux function."""
     return func(epoch, fs=fs, nperseg=n_per_seg, noverlap=noverlap,
-                nfft=nfft, window='hann')[2][..., freq_mask, :]
+                nfft=nfft, window='hamming')[2][..., freq_mask, :]
 
 
 def _check_nfft(n, n_fft, n_per_seg, n_overlap):
@@ -84,9 +84,8 @@ def psd_array_welch(x, sfreq, fmin=0, fmax=np.inf, n_fft=256, n_overlap=0,
         The number of points of overlap between segments. Will be adjusted
         to be <= n_per_seg. The default value is 0.
     n_per_seg : int | None
-        Length of each Welch segment. The smaller it is with respect to the
-        signal length the smoother are the PSDs. Defaults to None, which sets
-        n_per_seg equal to n_fft.
+        Length of each Welch segment (windowed with a Hamming window). Defaults
+        to None, which sets n_per_seg equal to n_fft.
     n_jobs : int
         Number of CPUs to use in the computation.
     verbose : bool, str, int, or None
@@ -140,8 +139,8 @@ def psd_welch(inst, fmin=0, fmax=np.inf, tmin=None, tmax=None, n_fft=256,
               reject_by_annotation=True, verbose=None):
     """Compute the power spectral density (PSD) using Welch's method.
 
-    Calculates periodigrams for a sliding window over the
-    time dimension, then averages them together for each channel/epoch.
+    Calculates periodograms for a sliding window over the time dimension, then
+    averages them together for each channel/epoch.
 
     Parameters
     ----------
@@ -164,9 +163,8 @@ def psd_welch(inst, fmin=0, fmax=np.inf, tmin=None, tmax=None, n_fft=256,
         The number of points of overlap between segments. Will be adjusted
         to be <= n_per_seg. The default value is 0.
     n_per_seg : int | None
-        Length of each Welch segment. The smaller it is with respect to the
-        signal length the smoother are the PSDs. Defaults to None, which sets
-        n_per_seg equal to n_fft.
+        Length of each Welch segment (windowed with a Hamming window). Defaults
+        to None, which sets n_per_seg equal to n_fft.
     picks : array-like of int | None
         The selection of channels to include in the computation.
         If None, take all channels.


Test patch: