ubuntu2404
\documentclass[11pt,a4paper]{article}12% Signal Processing and Fourier Analysis Template3% SEO Keywords: signal processing latex template, fourier analysis latex, digital signal processing latex45\usepackage[utf8]{inputenc}6\usepackage[T1]{fontenc}7\usepackage{amsmath,amsfonts,amssymb}8\usepackage{mathtools}9\usepackage{siunitx}10\usepackage{graphicx}11\usepackage{float}12\usepackage{hyperref}13\usepackage{cleveref}14\usepackage{booktabs}15\usepackage{pythontex}1617\usepackage[style=numeric,backend=biber]{biblatex}18\addbibresource{references.bib}1920\title{Signal Processing and Fourier Analysis:\\21Digital Methods and Spectral Techniques}22\author{CoCalc Scientific Templates}23\date{\today}2425\begin{document}2627\maketitle2829\begin{abstract}30This comprehensive signal processing template demonstrates Fourier analysis, digital filter design, spectral estimation, and time-frequency analysis. Features include FFT algorithms, window functions, filter implementations, and wavelet transforms with applications to real-world signal analysis problems and professional visualizations.3132\textbf{Keywords:} signal processing, Fourier analysis, digital filters, spectral estimation, FFT, wavelets, time-frequency analysis33\end{abstract}3435\tableofcontents36\newpage3738\section{Fourier Transform and Spectral Analysis}39\label{sec:fourier-analysis}4041\begin{pycode}42import numpy as np43import matplotlib.pyplot as plt44import matplotlib45matplotlib.use('Agg')46from scipy import signal47from scipy.signal import windows48from scipy.fft import fft, fftfreq, fftshift4950# Set random seed for reproducibility51np.random.seed(42)5253def generate_test_signal():54"""Generate complex test signal for analysis"""5556# Time parameters57fs = 1000 # Sampling frequency (Hz)58T = 2.0 # Duration (seconds)59t = np.arange(0, T, 1/fs)60N = len(t)6162# Signal components63f1, f2, f3 = 50, 120, 300 # Frequencies (Hz)6465# Construct signal: sinusoids + chirp + noise66signal_clean = (np.sin(2*np.pi*f1*t) +670.5*np.sin(2*np.pi*f2*t + np.pi/4) +680.3*np.sin(2*np.pi*f3*t))6970# Add frequency-modulated chirp71chirp = signal.chirp(t, f0=10, f1=200, t1=T, method='linear')7273# Add noise74noise = 0.2 * np.random.randn(N)7576test_signal = signal_clean + 0.3*chirp + noise7778print(f"Signal Processing: Test Signal Generation")79print(f" Sampling frequency: {fs} Hz")80print(f" Duration: {T} s")81print(f" Samples: {N}")82print(f" Component frequencies: {f1}, {f2}, {f3} Hz")8384return t, test_signal, signal_clean, fs8586def fourier_analysis(t, x, fs):87"""Perform comprehensive Fourier analysis"""8889N = len(x)9091# Compute FFT92X = fft(x)93freqs = fftfreq(N, 1/fs)9495# Magnitude and phase spectra96magnitude = np.abs(X)97phase = np.angle(X)9899# Power spectral density100psd = magnitude**2 / (fs * N)101102# Only positive frequencies for display103positive_freqs = freqs[:N//2]104magnitude_positive = magnitude[:N//2]105psd_positive = psd[:N//2]106107print(f"\nFourier Analysis Results:")108print(f" Frequency resolution: {freqs[1]:.2f} Hz")109print(f" Maximum frequency: {positive_freqs[-1]:.1f} Hz")110111# Find spectral peaks112peaks, properties = signal.find_peaks(magnitude_positive,113height=np.max(magnitude_positive)*0.1,114distance=10)115116peak_freqs = positive_freqs[peaks]117peak_magnitudes = magnitude_positive[peaks]118119print(f" Detected peaks at frequencies:")120for freq, mag in zip(peak_freqs, peak_magnitudes):121print(f" {freq:.1f} Hz (magnitude: {mag:.0f})")122123return freqs, X, magnitude, phase, psd, positive_freqs, magnitude_positive, psd_positive124125# Generate and analyze test signal126t, test_sig, clean_sig, fs = generate_test_signal()127freqs, X, mag, phase, psd, pos_freqs, mag_pos, psd_pos = fourier_analysis(t, test_sig, fs)128\end{pycode}129130\section{Digital Filter Design}131\label{sec:digital-filters}132133\begin{pycode}134# Digital filter design and implementation135def design_filters(fs):136"""Design various digital filters"""137138nyquist = fs / 2139140# Low-pass Butterworth filter141cutoff_lp = 100 # Hz142order_lp = 4143b_lp, a_lp = signal.butter(order_lp, cutoff_lp/nyquist, btype='low')144145# High-pass Butterworth filter146cutoff_hp = 200 # Hz147order_hp = 4148b_hp, a_hp = signal.butter(order_hp, cutoff_hp/nyquist, btype='high')149150# Band-pass Chebyshev filter151low_band, high_band = 80, 150 # Hz152order_bp = 6153b_bp, a_bp = signal.cheby1(order_bp, 1, [low_band/nyquist, high_band/nyquist], btype='band')154155# FIR filter using window method156numtaps = 101157cutoff_fir = 150 # Hz158b_fir = signal.firwin(numtaps, cutoff_fir/nyquist, window='hamming')159a_fir = [1.0] # FIR filters have a_k = [1, 0, 0, ...]160161filters = {162'Low-pass': (b_lp, a_lp),163'High-pass': (b_hp, a_hp),164'Band-pass': (b_bp, a_bp),165'FIR': (b_fir, a_fir)166}167168print(f"\nDigital Filter Design:")169print(f" Low-pass: Order {order_lp}, cutoff {cutoff_lp} Hz")170print(f" High-pass: Order {order_hp}, cutoff {cutoff_hp} Hz")171print(f" Band-pass: Order {order_bp}, band {low_band}-{high_band} Hz")172print(f" FIR: {numtaps} taps, cutoff {cutoff_fir} Hz")173174return filters175176def apply_filters(signal_data, filters, fs):177"""Apply filters to signal and analyze results"""178179filtered_signals = {}180181for name, (b, a) in filters.items():182# Apply filter183filtered = signal.filtfilt(b, a, signal_data)184filtered_signals[name] = filtered185186# Compute filter response187w, h = signal.freqz(b, a, fs=fs)188189# Store frequency response190filters[name] = (b, a, w, h)191192return filtered_signals193194# Design filters and apply to test signal195filters = design_filters(fs)196filtered_sigs = apply_filters(test_sig, filters, fs)197\end{pycode}198199\section{Window Functions and Spectral Estimation}200\label{sec:windows-spectral}201202\begin{pycode}203# Window functions and spectral estimation204def compare_window_functions(N=256):205"""Compare different window functions"""206207window_funcs = {208'Rectangular': np.ones(N),209'Hamming': windows.hamming(N),210'Hann': windows.hann(N),211'Blackman': windows.blackman(N),212'Kaiser': windows.kaiser(N, beta=8.6)213}214215# Compute frequency responses216window_spectra = {}217freqs_win = np.linspace(-0.5, 0.5, 1024)218219for name, window in window_funcs.items():220# Zero-pad for better frequency resolution221padded = np.zeros(1024)222padded[:N] = window223224# Compute FFT and shift225spectrum = fftshift(fft(padded))226window_spectra[name] = spectrum227228# Calculate metrics229main_lobe_width = np.sum(np.abs(spectrum) > 0.5 * np.max(np.abs(spectrum))) / 1024230side_lobe_level = 20 * np.log10(np.max(np.abs(spectrum[np.abs(spectrum) < 0.9*np.max(np.abs(spectrum))])) / np.max(np.abs(spectrum)))231232print(f" {name}: Main lobe width ~= {main_lobe_width:.3f}, Side lobe level ~= {side_lobe_level:.1f} dB")233234print(f"\nWindow Function Analysis (N = {N}):")235236return window_funcs, window_spectra, freqs_win237238def welch_spectral_estimation(signal_data, fs, nperseg=256, overlap_factor=0.5):239"""Welch's method for spectral estimation"""240241# Different window types242window_types = ['hamming', 'hann', 'blackman']243244spectral_estimates = {}245246for window in window_types:247freqs, psd = signal.welch(signal_data, fs, window=window,248nperseg=nperseg,249noverlap=int(nperseg * overlap_factor),250return_onesided=True)251spectral_estimates[window] = (freqs, psd)252253print(f"\nWelch Spectral Estimation:")254print(f" Segment length: {nperseg}")255print(f" Overlap: {overlap_factor*100:.0f}%")256print(f" Windows tested: {window_types}")257258return spectral_estimates259260# Analyze window functions and spectral estimation261window_funcs, win_spectra, freqs_win = compare_window_functions()262welch_estimates = welch_spectral_estimation(test_sig, fs)263\end{pycode}264265\section{Time-Frequency Analysis}266\label{sec:time-frequency}267268\begin{pycode}269# Time-frequency analysis using spectrograms and wavelets270def compute_spectrogram(signal_data, fs, nperseg=256, noverlap=None):271"""Compute and analyze spectrogram"""272273if noverlap is None:274noverlap = nperseg // 2275276f, t_spec, Sxx = signal.spectrogram(signal_data, fs,277nperseg=nperseg,278noverlap=noverlap)279280print(f"\nSpectrogram Analysis:")281print(f" Time resolution: {t_spec[1] - t_spec[0]:.4f} s")282print(f" Frequency resolution: {f[1] - f[0]:.2f} Hz")283print(f" Time bins: {len(t_spec)}")284print(f" Frequency bins: {len(f)}")285286return f, t_spec, Sxx287288def continuous_wavelet_transform(signal_data, fs, wavelet='morl'):289"""Simplified continuous wavelet transform demonstration"""290291# Define scales for CWT292scales = np.arange(1, 128)293294# Create a simple Morlet-like wavelet manually295def morlet_wavelet(M, w=5.0, s=1.0, complete=True):296"""297Simple Morlet wavelet implementation298"""299x = np.arange(0, M) - (M - 1.0) / 2300x = x / s301output = np.exp(1j * w * x) * np.exp(-0.5 * x**2) * np.pi**(-0.25)302if not complete:303output -= np.exp(-0.5 * w**2) * np.exp(-0.5 * x**2) * np.pi**(-0.25)304return output305306# Compute CWT manually using convolution307cwt_matrix = np.zeros((len(scales), len(signal_data)), dtype=complex)308309for i, scale in enumerate(scales):310# Create wavelet at this scale311wavelet_length = min(int(10 * scale), len(signal_data))312if wavelet_length % 2 == 0:313wavelet_length += 1314315psi = morlet_wavelet(wavelet_length, s=scale)316317# Normalize318psi = psi / np.sqrt(scale)319320# Convolve signal with wavelet321cwt_row = np.convolve(signal_data, np.conj(psi[::-1]), mode='same')322cwt_matrix[i, :] = cwt_row323324# Convert scales to frequencies (approximate)325frequencies = fs / (2 * scales)326327print(f"\nContinuous Wavelet Transform:")328print(f" Wavelet: {wavelet}")329print(f" Scales: {len(scales)}")330print(f" Frequency range: {frequencies[-1]:.1f} - {frequencies[0]:.1f} Hz")331332return frequencies, cwt_matrix333334# Perform time-frequency analysis335f_spec, t_spec, Sxx = compute_spectrogram(test_sig, fs)336freq_cwt, cwt_coeffs = continuous_wavelet_transform(test_sig, fs)337\end{pycode}338339\begin{pycode}340# Create comprehensive signal processing visualization341import os342os.makedirs('assets', exist_ok=True)343344fig = plt.figure(figsize=(20, 15))345gs = fig.add_gridspec(4, 4, hspace=0.3, wspace=0.3)346347# Time domain signal348ax1 = fig.add_subplot(gs[0, :2])349ax1.plot(t[:500], test_sig[:500], 'b-', linewidth=1.5, label='Test signal')350ax1.plot(t[:500], clean_sig[:500], 'r--', linewidth=1.5, alpha=0.7, label='Clean components')351ax1.set_xlabel('Time (s)')352ax1.set_ylabel('Amplitude')353ax1.set_title('Time Domain Signal')354ax1.legend()355ax1.grid(True, alpha=0.3)356357# Frequency domain (FFT)358ax2 = fig.add_subplot(gs[0, 2:])359ax2.loglog(pos_freqs[1:], psd_pos[1:], 'b-', linewidth=2)360ax2.set_xlabel('Frequency (Hz)')361ax2.set_ylabel('Power Spectral Density')362ax2.set_title('Power Spectrum (FFT)')363ax2.grid(True, alpha=0.3)364365# Filter frequency responses366ax3 = fig.add_subplot(gs[1, :2])367for name, (b, a, w, h) in filters.items():368if len(w) > 0: # Check if frequency response was computed369ax3.plot(w, 20*np.log10(np.abs(h)), linewidth=2, label=name)370ax3.set_xlabel('Frequency (Hz)')371ax3.set_ylabel('Magnitude (dB)')372ax3.set_title('Filter Frequency Responses')373ax3.legend()374ax3.grid(True, alpha=0.3)375376# Filtered signals (time domain)377ax4 = fig.add_subplot(gs[1, 2:])378time_slice = slice(0, 1000) # Show first second379ax4.plot(t[time_slice], test_sig[time_slice], 'k-', alpha=0.5, label='Original')380colors = ['red', 'blue', 'green', 'orange']381for i, (name, filt_sig) in enumerate(filtered_sigs.items()):382if i < len(colors):383ax4.plot(t[time_slice], filt_sig[time_slice],384color=colors[i], linewidth=1.5, label=name)385ax4.set_xlabel('Time (s)')386ax4.set_ylabel('Amplitude')387ax4.set_title('Filtered Signals')388ax4.legend()389ax4.grid(True, alpha=0.3)390391# Window functions392ax5 = fig.add_subplot(gs[2, :2])393for name, window in window_funcs.items():394ax5.plot(window, linewidth=2, label=name)395ax5.set_xlabel('Sample')396ax5.set_ylabel('Amplitude')397ax5.set_title('Window Functions')398ax5.legend()399ax5.grid(True, alpha=0.3)400401# Window frequency responses402ax6 = fig.add_subplot(gs[2, 2:])403for name, spectrum in win_spectra.items():404ax6.plot(freqs_win, 20*np.log10(np.abs(spectrum)/np.max(np.abs(spectrum))),405linewidth=2, label=name)406ax6.set_xlabel('Normalized Frequency')407ax6.set_ylabel('Magnitude (dB)')408ax6.set_title('Window Frequency Responses')409ax6.set_ylim([-80, 5])410ax6.legend()411ax6.grid(True, alpha=0.3)412413# Spectrogram414ax7 = fig.add_subplot(gs[3, :2])415pcm = ax7.pcolormesh(t_spec, f_spec, 10*np.log10(Sxx), shading='gouraud', cmap='hot')416ax7.set_xlabel('Time (s)')417ax7.set_ylabel('Frequency (Hz)')418ax7.set_title('Spectrogram')419plt.colorbar(pcm, ax=ax7, label='Power (dB)')420421# Wavelet transform422ax8 = fig.add_subplot(gs[3, 2:])423cwt_magnitude = np.abs(cwt_coeffs)424pcm2 = ax8.pcolormesh(t, freq_cwt, cwt_magnitude, shading='gouraud', cmap='viridis')425ax8.set_xlabel('Time (s)')426ax8.set_ylabel('Frequency (Hz)')427ax8.set_title('Continuous Wavelet Transform')428ax8.set_ylim([0, 400]) # Limit frequency range for visibility429plt.colorbar(pcm2, ax=ax8, label='|CWT|')430431plt.suptitle('Signal Processing and Fourier Analysis', fontsize=16, fontweight='bold')432plt.savefig('assets/signal-processing-analysis.pdf', dpi=300, bbox_inches='tight')433plt.close()434435print("Signal processing analysis saved to assets/signal-processing-analysis.pdf")436\end{pycode}437438\begin{figure}[H]439\centering440\includegraphics[width=0.95\textwidth]{assets/signal-processing-analysis.pdf}441\caption{Comprehensive signal processing and Fourier analysis including (top row) time domain signal with clean components and power spectrum via FFT, (second row) digital filter frequency responses and filtered signal comparisons, (third row) window function shapes and their frequency responses, and (bottom row) spectrogram and continuous wavelet transform providing time-frequency representations of the test signal.}442\label{fig:signal-processing-analysis}443\end{figure}444445\section{Conclusion}446\label{sec:conclusion}447448This signal processing template demonstrates comprehensive spectral analysis techniques including:449450\begin{itemize}451\item Fourier transform theory and FFT implementation452\item Digital filter design (IIR and FIR)453\item Window functions and their spectral properties454\item Time-frequency analysis via spectrograms and wavelets455\item Professional visualization of signal characteristics456\end{itemize}457458The computational methods provide a foundation for advanced signal processing applications in communications, audio processing, and scientific instrumentation.459460\printbibliography461462\end{document}463464