SignalSystemAnalysis_pythonApplication
SignalSystemAnalysis_pythonApplication
This lab demonstrates how to calculate Fourier Series coefficients numerically using Python
instead of manual integration. We'll use SciPy's integration capabilities to evaluate the
integrals and visualize the spectrum.
2. Numerical Integration with SciPy
import numpy as np
def fcos(t):
return np.cos(np.pi*t)
return np.exp(-np.abs(t))
Calculate the k-th Fourier series coefficient for periodic function x(t)
"""
omega0 = 2*np.pi/T0
return ak/T0
N = 10
T0 = 2*np.pi
plt.figure(figsize=(10, 5))
plt.stem(k_values, np.abs(coefficients))
plt.xlabel('k')
plt.ylabel('|a_k|')
plt.grid(True)
plt.show()
import numpy as np
T0 = 2 * np.pi
result = np.zeros_like(t)
return result
ax.set_xlim(-np.pi, np.pi)
ax.set_ylim(-1.5, 1.5)
ax.set_xlabel("t")
ax.set_ylabel("Signal")
ax.legend()
def update(frame):
y_values = square_wave_fourier(t_values, N)
line.set_data(t_values, y_values)
return line,
# Create animation
# Display animation
HTML(ani.to_jshtml())
import numpy as np
T0 = 2 * np.pi
def fourier_coefficient(k):
if k == 0:
return 0 # No DC component
elif k % 2 == 1: # Only odd harmonics exist
return 4 / (np.pi * k)
else:
def plot_fourier_approximation(N_terms=5):
t = np.linspace(-2*np.pi, 2*np.pi, 1000)
approximation = np.zeros_like(t)
ak = fourier_coefficient(k)
plt.figure(figsize=(10, 5))
plt.plot(t, approximation, label='Fourier approximation')
plt.legend()
plt.grid(True)
plt.show()
interactive_plot = widgets.interactive(plot_fourier_approximation,
N_terms=widgets.IntSlider(min=1, max=20, value=5))
display(interactive_plot)
Design with Fourier Series – Distortion
import numpy as np
plt.figure(figsize=(12, 5))
# Input Spectrum
plt.subplot(1, 2, 1)
plt.title("Input Spectrum")
plt.xlabel("Frequency (rad/s)")
plt.ylabel("|a_k|")
plt.grid(True)
plt.subplot(1, 2, 2)
plt.xlabel("Frequency (rad/s)")
plt.ylabel("|b_k|")
plt.grid(True)
plt.tight_layout()
plt.show()
import numpy as np
omega0 = 2*np.pi/T0
signal += ak * np.exp(1j*k*omega0*t)
return np.real(signal)
# Define parameters
T0 = 2 * np.pi
plt.figure(figsize=(10, 5))
plt.show()
import numpy as np
%matplotlib inline
# Sampling parameters
# Compute FFT
fft_values = np.fft.fft(signal)
freqs = np.fft.fftfreq(N, 1/Fs)
# Only take positive frequencies
mask = freqs >= 0 # Fixed issue: previously filtering only greater than zero
plt.figure(figsize=(12, 5))
plt.subplot(1, 2, 1)
plt.plot(t, signal, label="Time-domain Signal", color="royalblue")
plt.xlabel("Time (s)")
plt.ylabel("Amplitude")
plt.title("Original Signal")
plt.legend()
plt.grid(True)
plt.xlabel("Frequency (Hz)")
plt.ylabel("Magnitude")
plt.grid(True)
plt.tight_layout()
plt.show()
interactive_fft = widgets.interactive(plot_fft,
display(interactive_fft)
1. Discrete-Time Convolution
import numpy as np
import matplotlib.pyplot as plt
N = len(x)
M = len(h)
y = np.zeros(N + M - 1)
for n in range(len(y)):
for k in range(max(0, n-M+1), min(n+1, N)):
return y
y = discrete_convolution(x, h)
plt.figure(figsize=(12, 4))
plt.subplot(1, 3, 1)
plt.stem(x, markerfmt="ro") # Removed use_line_collection=True
plt.title("Input Signal x[n]")
plt.subplot(1, 3, 2)
plt.subplot(1, 3, 3)
plt.stem(y, markerfmt="go") # Removed use_line_collection=True
plt.tight_layout()
plt.show()
2. Continuous-Time Convolution
x = np.exp(-0.25*t) * (t <= 6)
h = np.exp(-t) * ((t >= -1) & (t <= 5)) # Shifted to include negative time
# Perform convolution
plt.figure(figsize=(12, 4))
plt.subplot(1, 3, 1)
plt.plot(t, x)
plt.title('Input Signal x(t)')
plt.subplot(1, 3, 2)
plt.plot(t, h)
plt.subplot(1, 3, 3)
plt.plot(t, y)
plt.tight_layout()
plt.show()
ax1.plot(t, x, label='x(τ)')
ax2.plot(t, h, label='h(τ)')
ax2.legend()
ax3.set_xlim(t[0], t[-1])
def update(frame):
ax1.clear()
ax1.plot(t, x, label='x(τ)')
ax1.plot(t, shifted_h, 'g--', label=f'h({frame}-τ)')
ax1.set_title(f'Time t = {t[frame]:.2f}')
ax1.legend()
ax2.clear()
line.set_data(t[:frame], full_conv[:frame])
return line,
return HTML(ani.to_jshtml())
# Create signals
x = np.exp(-0.5*t) * (t <= 5)
h = np.exp(-2*t) * (t <= 3)
animate_convolution(x, h, t)
Other Applications
signal = np.zeros_like(t)
return t, signal
t, sig = multipath_signal()
plt.figure(figsize=(10, 4))
plt.plot(t, sig)
plt.xlabel('Time (s)')
plt.ylabel('Amplitude')
plt.grid(True)
plt.show()
2. Spectrogram Analysis
t = np.arange(0, 1, 1/fs)
x = np.cos(2*np.pi*f_inst*t)
# Compute spectrogram
plt.figure(figsize=(10, 5))
plt.ylabel('Frequency [Hz]')
plt.xlabel('Time [sec]')
plt.show()