scipy.signal.ShortTimeFFT.

from_win_equals_dual#

метод класса ShortTimeFFT.from_win_equals_dual(desired_win, hop, fs, *, fft_mode='onesided', mfft=None, scale_to=None, phase_shift=0)[источник]#

Создать экземпляр, где окно и его двойник равны с точностью до масштабного коэффициента.

Создан экземпляр, где окно и двойное окно равны, а также являются наиболее близкими к параметру desired_win в смысле наименьших квадратов, т.е., минимизируя abs(win-desired_win)**2. Следовательно, win имеет ту же длину, что и desired_win. Затем применяется масштабный коэффициент в соответствии с scale_to параметр.

Все остальные параметры имеют тот же смысл, что и в инициализаторе.

Чтобы иметь возможность рассчитать корректное окно, desired_win должен иметь допустимое двойное STFT-окно для заданного hop интервал. Если это не так, то ValueError вызывается исключение.

Параметры:
desired_winnp.ndarray

Вещественный или комплексный одномерный массив, содержащий выборку желаемого окна.

hopint

Приращение в выборках, на которое окно сдвигается на каждом шаге.

fsfloat

Частота дискретизации входного сигнала и окна. Её связь с интервалом дискретизации T является T = 1 / fs.

fft_mode'twosided', 'centered', 'onesided', 'onesided2X'

Режим БПФ для использования (по умолчанию 'onesided'). См. свойство fft_mode подробности.

mfft: int | None

Длина БПФ, используемого, если требуется дополненный нулями БПФ. Если None (по умолчанию), длина окна win используется.

scale_to‘magnitude’ | ‘psd’ | ‘unitary’ | None

Если не None (по умолчанию) оконная функция масштабируется, так что каждый столбец STFT представляет либо спектр 'амплитуды', либо спектральную плотность мощности ('psd'). В качестве альтернативы, STFT можно масштабировать до `унитарного` отображения, т.е., разделив окно на np.sqrt(mfft) и умножение двойного окна на ту же величину.

phase_shiftint | None

Если установлено, добавить линейную фазу phase_shift / mfft * f для каждой частоты f. Значение по умолчанию 0 гарантирует отсутствие фазового сдвига на нулевом срезе (где t=0 центрировано). См. свойство phase_shift для получения дополнительной информации.

Смотрите также

closest_STFT_dual_window

Вычислить двойное окно STFT для заданного окна, наиболее близкое к желаемому двойному окну.

ShortTimeFFT.spectrogram

Вычислить квадраты STFT

ShortTimeFFT

Класс, к которому принадлежит это свойство.

Примечания

Множество всех возможных окон с одинаковым дуальным определяется множеством линейных ограничений уравнения. (24) в Кратковременное преобразование Фурье раздел Руководство пользователя SciPy. Там также выводится, что ShortTimeFFT.dual_win == ShortTimeFFT.m_pts * ShortTimeFFT.win должно выполняться для того, чтобы STFT было унитарным отображением.

Унитарное отображение сохраняет значение скалярного произведения, т.е.,

\[\langle x, y\rangle = \sum_k x[k]\, \overline{y[k]} \stackrel{\stackrel{\text{unitary}}{\downarrow}}{=} \sum_{q,p} S_x[q,p]\, \overline{S_y[q,p]} = \langle S_x[q,p], S_y[q,p]\rangle\ ,\]

с \(S_{x,y}\) является STFT для \(x,y\). Следовательно, энергия \(E_x=T\sum_k |x[k]|^2\) сигнала также сохраняется. Это также проиллюстрировано в примере ниже.

Причина различения между отсутствием масштабирования (т.е., параметром scale_to является None) и унитарное масштабирование (т.е., scale_to = 'unitary') обусловлено тем, что используемая функция БПФ не является унитарной (т.е., использует значение по умолчанию 'backward' для fft параметр norm).

Примеры

Следующий пример показывает, что STFT действительно может быть унитарным:

>>> import matplotlib.pyplot as plt
>>> import numpy as np
>>> from scipy.signal import ShortTimeFFT, windows
...
>>> m, hop, std = 36, 8, 5
>>> desired_win = windows.gaussian(m, std, sym=True)
>>> SFT = ShortTimeFFT.from_win_equals_dual(desired_win, hop, fs=1/m,
...                                         fft_mode='twosided',
...                                         scale_to='unitary')
>>> np.allclose(SFT.dual_win, SFT.win * SFT.m_num)  # check if STFT is unitary
True
>>> x1, x2 = np.tile([-1, -1, 1, 1], 5), np.tile([1, -1, -1, 1], 5)
>>> np.sum(x1*x2) # scalar product is zero -> orthogonal signals
0
>>> np.sum(x1**2)  # scalar product of x1 with itself
20
>>> Sx11, Sx12 = SFT.spectrogram(x1), SFT.spectrogram(x1, x2)
>>> np.sum(Sx12)  # STFT scalar product is also zero
-4.163336342344337e-16+0j  # may vary
>>> np.sum(Sx11)  # == np.sum(x1**2)
19.999999999999996  # may vary
...
... # Do the plotting:
>>> fg1, (ax11, ax12) = plt.subplots(1, 2, tight_layout=True, figsize=(8, 4))
>>> s_fac = np.sqrt(SFT.mfft)
>>> _ = fg1.suptitle(f"Scaled Unitary Window of {m} Sample Gaussian with " +
...                  rf"{hop=}, $\sigma={std}$, Scale factor: {s_fac}")
>>> ax11.set(ylabel="Amplitude", xlabel="Samples", xlim=(0, m))
>>> ax12.set(xlabel="Frequency Bins", ylabel="Magnitude Spectrum",
...          xlim=(0, 15), ylim=(1e-5, 1.5))
>>> u_win_str = rf"Unitary $\times{s_fac:g}$"
>>> for x_, n_ in zip((desired_win, SFT.win*s_fac), ('Desired', u_win_str)):
...     ax11.plot(x_, '.-', alpha=0.5, label=n_)
...     X_ = np.fft.rfft(x_) / np.sum(abs(x_))
...     ax12.semilogy(abs(X_), '.-', alpha=0.5, label=n_)
>>> for ax_ in (ax11, ax12):
...     ax_.grid(True)
...     ax_.legend()
>>> plt.show()
../../_images/scipy-signal-ShortTimeFFT-from_win_equals_dual-1_00_00.png

Обратите внимание, что fftmode='twosided' используется, поскольку нам нужна сумма по всей временной частотной плоскости. Из-за передачи scale_to='unitary' окно SFT.win масштабируется на 1/np.sqrt(SFT.mfft). Следовательно, SFT.win нужно масштабировать на s_fac на графике выше.