| name | numpy-numerical-analysis-4-fft-and-frequency-analysis |
| description | Sub-skill of numpy-numerical-analysis: 4. FFT and Frequency Analysis. |
| version | 1.0.0 |
| category | data |
| type | reference |
| scripts_exempt | true |
4. FFT and Frequency Analysis
4. FFT and Frequency Analysis
FFT for Spectral Analysis:
def compute_fft_spectrum(
time_series: np.ndarray,
dt: float,
window: str = 'hann'
) -> tuple[np.ndarray, np.ndarray]:
"""
Compute FFT spectrum of time series.
Args:
time_series: Time series data
dt: Time step
window: Window function ('hann', 'hamming', 'blackman')
Returns:
(frequencies, amplitude_spectrum)
"""
n = len(time_series)
if window == 'hann':
windowed = time_series * np.hanning(n)
elif window == 'hamming':
windowed = time_series * np.hamming(n)
elif window == 'blackman':
windowed = time_series * np.blackman(n)
else:
windowed = time_series
fft_result = np.fft.fft(windowed)
frequencies = np.fft.fftfreq(n, d=dt)
amplitude = np.abs(fft_result)[:n//2] * 2 / n
frequencies_positive = frequencies[:n//2]
return frequencies_positive, amplitude
import numpy as np
t = np.linspace(0, 100, 10000)
dt = t[1] - t[0]
wave = (
2.0 * np.sin(2*np.pi*t / 6) +
1.5 * np.sin(2*np.pi*t / 8) +
1.0 * np.sin(2*np.pi*t / 10)
)
wave += 0.2 * np.random.randn(len(t))
freq, amplitude = compute_fft_spectrum(wave, dt, window='hann')
peak_indices = np.argsort(amplitude)[-3:]
peak_frequencies = freq[peak_indices]
peak_periods = 1 / peak_frequencies
print("Detected wave periods:")
for period in sorted(peak_periods, reverse=True):
print(f" T = {period:.2f} s")
Power Spectral Density:
def compute_power_spectral_density(
time_series: np.ndarray,
dt: float,
nfft: int = None
) -> tuple[np.ndarray, np.ndarray]:
"""
Compute power spectral density using Welch's method.
Args:
time_series: Time series data
dt: Time step
nfft: FFT length (None = length of time series)
Returns:
(frequencies, PSD)
"""
from scipy import signal
frequencies, psd = signal.welch(
time_series,
fs=1/dt,
nperseg=nfft or len(time_series)//8,
window='hann'
)
return frequencies, psd
t = np.linspace(0, 3600, 36000)
dt = t[1] - t[0]
wave_elevation = np.random.randn(len(t)) * 2.0
freq, psd = compute_power_spectral_density(wave_elevation, dt)
m0 = np.trapz(psd, freq)
Hs = 4 * np.sqrt(m0)
print(f"Significant wave height: {Hs:.2f} m")