OverLordGoldDragon / ssqueezepy

Synchrosqueezing, wavelet transforms, and time-frequency analysis in Python
MIT License
618 stars 96 forks source link

No option to specify a maximum frequency for stft, ssq_stft etc. #40

Closed scottfleming closed 3 years ago

scottfleming commented 3 years ago

Currently the default for stft and ssq_stft is to return all scales up to the Nyquist frequency, but it would be helpful if there were a simple way to specify a maximum frequency or, better yet, a specific set of scales that should be queried. https://github.com/OverLordGoldDragon/ssqueezepy/blob/master/ssqueezepy/_ssq_stft.py#L241 Particularly in cases where you don't want to query everything up to the Nyquist frequency for efficiency purposes, it would be helpful to have this option.

OverLordGoldDragon commented 3 years ago

Hello,

ssqueezepy implements STFT with column-wise FFTs (as is standard), which necessarily spans dc to Nyquist. Unneeded frequencies can be discarded as a post-processing step. The reassignment frequencies in ssq_stft are specified via ssq_freqs, which can be sub-Nyquist, but rows up to Nyquist would still be computed and reassigned to the highest frequency in ssq_freqs; if this is undesired, one should emulate ssq_stft's logic with an intermediate step where stft's output is trimmed.

Row-wise implementation is possible but I do not intend to support it. However, one can emulate it with CWT (which is row-wise) with an appropriate wavelet (complex sinusoid weighted by a symmetric window) and linear scales. I might support hop_len for CWT in the future.

scottfleming commented 3 years ago

Thanks! That's helpful. Could you say more about why STFT with column-wise FFT necessarily spans dc to Nysquist? I guess my question was, if as you suggest one intends to "discard unneeded frequencies as a post-processing step", in theory would it not be more efficient to just not query the unneeded frequencies to begin with? Maybe I'm missing something obvious here. Or maybe that's really not the bottleneck with this implementation of STFT?

OverLordGoldDragon commented 3 years ago

"Column-wise" means we take FFT (Discrete Fourier Transform) along columns, where a column is a windowing of the input at a time-shift; the output is a linear sweep of frequencies dc to Nyquist at that time-shift. Any other algorithm would be significantly slower and more memory-intensive.

scottfleming commented 3 years ago

Right, that all makes sense. By "any other algorithm" here do you mean any algorithm other than FFT or any algorithm which would not do a linear sweep of frequencies dc to Nyquist at that time-shift? Because it seems to me that running FFT albeit with a linear sweep over a constrained subset of {dc to Nyquist frequencies} would be faster. But maybe I'm misunderstanding something?

OverLordGoldDragon commented 3 years ago

running FFT albeit with a linear sweep over a constrained subset

There's no such thing. There might be algorithms that perform better over a subset, but I'm not aware of them. The best approach to what you seek is a row-wise FFT implementation, which is already implemented here as CWT so one needs only to appropriately design the wavelet. It'd be nice to have the API handle this, but I don't plan on it.

OverLordGoldDragon commented 2 years ago

There's no such thing.

... at least there wasn't until recently - though needs a Python port. I might need this in the future - may either port it or implement row-wise STFT.

OverLordGoldDragon commented 2 years ago

60