https://github.com/NikVard/memstim-hh
Tip revision: 13f58bbfa77333a6a4e4f10b979338f54687ff7f authored by NikVard on 26 June 2022, 15:40:57 UTC
[FIX] working version w/ proper colors
[FIX] working version w/ proper colors
Tip revision: 13f58bb
freq_analysis.py
from scipy import signal
# Functions examples from https://www.programcreek.com/python/example/100546/scipy.signal.spectrogram
def power_spectrum(signal: np.ndarray,
fs: int,
window_width: int,
window_overlap: int) -> (np.ndarray, np.ndarray, np.ndarray):
"""
Computes the power spectrum of the specified signal.
A periodic Hann window with the specified width and overlap is used.
Parameters
----------
signal: numpy.ndarray
The input signal
fs: int
Sampling frequency of the input signal
window_width: int
Width of the Hann windows in samples
window_overlap: int
Overlap between Hann windows in samples
Returns
-------
f: numpy.ndarray
Array of frequency values for the first axis of the returned spectrogram
t: numpy.ndarray
Array of time values for the second axis of the returned spectrogram
sxx: numpy.ndarray
Power spectrogram of the input signal with axes [frequency, time]
"""
f, t, sxx = spectrogram(x=signal,
fs=fs,
window=hann(window_width, sym=False),
noverlap=window_overlap,
mode="magnitude")
return f, t, (1.0 / window_width) * (sxx ** 2)
def power_to_db(spectrum: np.ndarray,
clip_below: float = None,
clip_above: float = None) -> np.ndarray:
"""
Convert a spectrogram to the Decibel scale.
Optionally, frequencies with amplitudes below or above a certain threshold can be clipped.
Parameters
----------
spectrum: numpy.ndarray
The spectrogram to convert
clip_below: float, optional
Clip frequencies below the specified amplitude in dB
clip_above: float, optional
Clip frequencies above the specified amplitude in dB
Returns
-------
numpy.ndarray
The spectrogram on the Decibel scale
"""
# there might be zeros, fix them to the lowest non-zero power in the spectrogram
epsilon = np.min(spectrum[np.where(spectrum > 0)])
sxx = np.where(spectrum > epsilon, spectrum, epsilon)
sxx = 10 * np.log10(sxx / np.max(sxx))
if clip_below is not None:
sxx = np.maximum(sxx, clip_below)
if clip_above is not None:
sxx = np.minimum(sxx, clip_above)
return sxx
