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