from scipy.signal import get_window
import dascore as dc
from dascore.units import second, percent
patch = dc.get_example_patch("chirp", channel_count=2)
# Simple stft with 10 second window and 4 seconds overlap
pa1 = patch.stft(time=10*second, overlap=4*second)
# Same as above, but using a boxcar window and 10% overlap.
pa2 = patch.stft(time=10*second, taper_window="boxcar", overlap=10*percent)
# Using a custom window array and specifying window/overlap in samples.
window = get_window(("tukey", 0.1), 1000)
pa2 = patch.stft(time=1000, taper_window=window, overlap=100, samples=True)
# Zero pad each 1000 sample window to a 4096 point FFT.
pa3 = patch.stft(time=1000, samples=True, nfft=4096)
# Local f-k spectra: windows of 32 channels by 64 samples.
fk = dc.get_example_patch().stft(distance=32, time=64, samples=True)stft
stft(
patch: Patch ,
taper_window: str | numpy.ndarray | tuple[str, ndarray, tuple[str | Any[str, Any], …]] = hann,
overlap: pint.registry.Quantity | int | None[Quantity, int, None] = 50 %,
samples: bool = False,
detrend: bool = False,
nfft: int | pint.registry.Quantity | numpy.timedelta64 | collections.abc.Mapping[int, Quantity, timedelta64, collections.abc.Mapping[str, Any], None] = None,
**kwargs ,
)
Perform a short-time fourier transform.
Parameters
| Parameter | Description |
|---|---|
| patch | The patch to transform. |
| taper_window |
The taper each window is multiplied by before its transform: a name, an array, or a (name, parameter) tuple get_window knows, forevery windowed dimension, or a list with one per dimension. |
| overlap |
The overlap between windows. Can be a number (assumed to be in units of the transformed dimension if samples==False), a percent, or None for0 overlap. |
| samples |
If True, the window length (provided in kwargs) and overlap parameters are in samples (or explicit units). |
| detrend |
If True, detrend each time window before performing fourier transform. This can lead to nicer looking spectrograms, but means the istft is no longer possible. |
| nfft |
The length of the FFT taken of each window, in samples, or as a quantity or timedelta in the transformed dimension’s units; a mapping gives each dimension its own. None, the default, is the window length. A longer FFT zero pads each window, which samples the same spectrum at more, closer frequencies; it adds no resolution, since the window holds no more data. Must be at least the window length. |
| **kwargs |
The dimensions to window and the window along each, in coordinate units or, with samples, in samples. More than one dimension giveseach window’s spectrum over all of them: distance=32, time=64is a local frequency-wavenumber spectrum. |
Examples
Note
- The output is scaled the same as Patch.dft. For a given sliding window, Parseval’s theorem doesn’t hold exactly (unless a boxcar window is used) because the taper window changes the time series signal before the transformation.
- An array passed for taper_window must have as many samples as the window; one of another length is refused. To zero pad each window’s FFT, give
nfft. - Real data is transformed one-sided along the last windowed dimension and centred along the others, as Patch.dft with
real=Trueis; complex data is centred along every one. - The output is a stack of windows as Patch.tile_apply makes one, transformed along the window: the transformed dimension becomes the window centres,
{dim}_startand{dim}_stopgive physical cell edges in the dimension’s units, the frequencies sit where the dimension was and the centres come last. Private_tile_index_{dim}coordinates retain sample indices, and the coordinates the stack carries for Patch.reassemble are what Patch.istft blends the windows back with. Non-dimensional coordinates along the transformed dimension travel with the stack and come back on the inverse.