-
Notifications
You must be signed in to change notification settings - Fork 65
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[ENH] Zero padding + Welch's PSD #318
Conversation
This comment was marked as resolved.
This comment was marked as resolved.
The latest adds an import numpy as np
from neurodsp.spectral import compute_spectrum
from neurodsp.utils import normalize_sig
from timescales.sim import sim_branching
from timescales.conversions import convert_knee
# Settings
np.random.seed(0)
fs = 1000
tau = convert_knee(20)
nperseg = 99
npad = 1000
nwindows = 10
nsamples = ((2*npad) + nperseg) * nwindows # prime -> slow
# Simulate
sig = normalize_sig(sim_branching(nsamples/fs, fs, tau, 1000), 0, 1) With npad: %%timeit
f, p = compute_spectrum(sig, fs, nperseg=nperseg, noverlap=0, npad=npad, f_range=(1, 200))
%%timeit
f, p = compute_spectrum(sig, fs, nperseg=nperseg, noverlap=0, npad=npad, f_range=(1, 200), fast_len=True)
Without npad: %%timeit
compute_spectrum(sig, fs, nperseg=2099, noverlap=0, f_range=(1, 200))
%%timeit
compute_spectrum(sig, fs, nperseg=2099, noverlap=0, f_range=(1, 200), fast_len=True)
|
This looks awesome! I think this is a very useful I've done a quick scan of the code, and it all looks good, but before a deeper dive, I wanted to check / ask about how best to specify padding. As I currently understand, This would also make our API broadly consistent with how MNE specifies this (see Thoughts on tweaking the input values for this? I'm hoping it wouldn't be too much of an annoying change if we want to go for this. |
Yeah, in playing with this my thoughts were similar to what Tom says above. As a user I not only want to know how long my total zero-padded signal is (with or without the 2**x rounding), but I would also love to have the option to spit out the frequency resolution, as well as see a visualization of the window function overlaid with a segment of data where the zeros have been added. I wish we could hire Eric L. back for a bit, because my inclination would be to de-mean and de-trend the window, then zero-pad, then apply a windowing function, but I believe from a DSP perspective this isn't the right way to do it. I believe you're supposed to window then zero-pad. But the window-then-pad approach still kills a ton of the data at the edge of your window, whereas the preprocess-then-pad-then-window seems like it'd allow for more of your data window to contribute to your spectrum. |
@TomDonoghue I integrated your feedback and removed @voytek, the freq res is now equal to import matplotlib.pyplot as plt
from neurodsp.spectral.utils import trim_spectrum, window_pad
# PSD
nperseg = 25
nfft = 500
npad = nfft - nperseg
noverlap = 0
# Window
sig_pad, nperseg, noverlap = window_pad(sig, nperseg, noverlap, npad, fast_len=False)
sig_windowed = sig_pad.reshape(-1, nperseg)
# Plot first window
plt.plot(sig_windowed[0]) ![]() Demeaning windows before padding creates an odd psd. If windows are demeaned, then recombined back into a 1d signal, power at low freqs should be reduced since the slow structure is messed up from demeaning short windows. But I'm not sure why this is the case when computing the spectrogram of windows separately then averaging. Understanding how zero-padding works at the edges would be useful! ![]() |
I mean, this looks good to me but we need to do much more in-depth testing on padding! |
Okay - coming back to this:
|
I think this should be good to go unless you see anything that's odd |
I did some minor direct edits to merge to main and do a bit of linting - otherwise since this all seems good to go, I'm going to merge! |
Adds ability to zeropad windows used in Welch's psd via a
npad
kwarg. This can result in smoother spectra. Working on timescales led me to think autoregressive PSD was a smoother method, but it really was the process of zero padding prior to taking the fft that lead to a smooth spectra. Similarily, zero padding the signal prior to fft is similar to zero padding either AR or ACF coefficients prior to fft'ing.Here's an example using timescales (orange is a zeropadded welch's spectrum), but it also works for powerlaws.