0% found this document useful (0 votes)
45 views15 pages

SignalSystemAnalysis Pythonapplication

This document provides a comprehensive guide on using Python for signal processing, focusing on Fourier Series coefficients, numerical integration, and visualization techniques. It includes code examples for calculating Fourier coefficients, filtering signals, and performing convolution, along with interactive visualizations for better understanding. Additionally, it covers applications such as multipath channel analysis and spectrogram analysis.

Uploaded by

umusyucel3
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
45 views15 pages

SignalSystemAnalysis Pythonapplication

This document provides a comprehensive guide on using Python for signal processing, focusing on Fourier Series coefficients, numerical integration, and visualization techniques. It includes code examples for calculating Fourier coefficients, filtering signals, and performing convolution, along with interactive visualizations for better understanding. Additionally, it covers applications such as multipath channel analysis and spectrogram analysis.

Uploaded by

umusyucel3
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Python Signal Processing Lab: Applications

1. Introduction & Objective

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

from [Link] import quad

import [Link] as plt

# Define a simple function to integrate

def fcos(t):
return [Link]([Link]*t)

# Perform numerical integration

result, error = quad(fcos, 0, 5)

print(f"Integration result: {result:.6f}, Error estimate: {error:.2e}")

# More complex example with absolute value


def exp_abs(t):

return [Link](-[Link](t))

result, error = quad(exp_abs, -2, 2)

print(f"Integration of e^(-|t|) from -2 to 2: {result:.6f}")

3. Fourier Series Coefficient Calculation

def fourier_coefficient(x, k, T0, num_points=1000):


"""

Calculate the k-th Fourier series coefficient for periodic function x(t)
"""
omega0 = 2*[Link]/T0

integrand = lambda t: x(t) * [Link](-1j*k*omega0*t)

ak, _ = quad(integrand, -T0/2, T0/2)

return ak/T0

# Define a square wave function

def square_wave(t, T0=2*[Link]):


t_mod = t % T0

return 1 if t_mod < T0/2 else -1

# Calculate coefficients for k=-10 to 10

N = 10

T0 = 2*[Link]

coefficients = [fourier_coefficient(square_wave, k, T0) for k in range(-N, N+1)]

k_values = [Link](-N, N+1)

# Plot the magnitude spectrum

[Link](figsize=(10, 5))

[Link](k_values, [Link](coefficients))

[Link]('Fourier Series Coefficients for Square Wave')

[Link]('k')

[Link]('|a_k|')
[Link](True)

[Link]()

3.1. Interactive Square Wave Approximation

import numpy as np

import [Link] as plt


import [Link] as animation
from [Link] import HTML

# Fourier Series Square Wave Approximation

def square_wave_fourier(t, N):

T0 = 2 * [Link]

result = np.zeros_like(t)

for k in range(1, N+1, 2): # Only odd harmonics

result += (4 / ([Link] * k)) * [Link](k * (2 * [Link] / T0) * t)

return result

# Setting up the figure for animation

fig, ax = [Link](figsize=(8, 5))

ax.set_xlim(-[Link], [Link])

ax.set_ylim(-1.5, 1.5)
ax.set_xlabel("t")

ax.set_ylabel("Signal")

ax.set_title("Fourier Series Approximation of Square Wave")

t_values = [Link](-[Link], [Link], 500)

line, = [Link]([], [], lw=2, label="Fourier Approximation")

[Link]()

# Update function for animation

def update(frame):

N = frame * 2 + 1 # Increase number of terms incrementally

y_values = square_wave_fourier(t_values, N)

line.set_data(t_values, y_values)
return line,
# Create animation

ani = [Link](fig, update, frames=100, interval=300, repeat=True)

# Display animation

HTML(ani.to_jshtml())

4. Interactive Fourier Series Visualization

import numpy as np

import [Link] as plt

import ipywidgets as widgets

from [Link] import display

T0 = 2 * [Link]

def square_wave(t, T0=2*[Link]):

return [Link]((t % T0) < T0/2, 1, -1) # Vectorized for efficiency

def fourier_coefficient(k):

""" Analytical Fourier coefficients for a square wave """

if k == 0:

return 0 # No DC component
elif k % 2 == 1: # Only odd harmonics exist

return 4 / ([Link] * k)

else:

return 0 # Even harmonics are zero

def plot_fourier_approximation(N_terms=5):
t = [Link](-2*[Link], 2*[Link], 1000)
approximation = np.zeros_like(t)

for k in range(1, 2*N_terms, 2): # Only odd harmonics

ak = fourier_coefficient(k)

approximation += ak * [Link](k * (2 * [Link] / T0) * t)

[Link](figsize=(10, 5))
[Link](t, approximation, label='Fourier approximation')

[Link](t, square_wave(t), '--', label='Original signal')

[Link](f'Fourier Series Approximation with {2*N_terms-1} terms')

[Link]()

[Link](True)

[Link]()

interactive_plot = [Link](plot_fourier_approximation,
N_terms=[Link](min=1, max=20, value=5))

display(interactive_plot)
Design with Fourier Series – Distortion

1. Filtering Periodic Signals

import numpy as np

import [Link] as plt

# Define the frequency response of the filter


def H(jw):

return (1j * jw) / ((4 - jw**2) + 1j * jw / 3)

# Define Fourier series parameters


T0 = 2 * [Link]
omega0 = 2 * [Link] / T0

k_values = [Link](-10, 11) # Range of Fourier coefficients

# Generate Fourier coefficients (example function)

coefficients = [4 / ([Link] * k) if k % 2 == 1 else 0 for k in k_values] # Square wave Fourier


series

# Calculate output coefficients by filtering input coefficients

output_coeffs = [coeff * H(1j * k * omega0) for k, coeff in zip(k_values, coefficients)]

# Plot input and output spectra

[Link](figsize=(12, 5))

# Input Spectrum

[Link](1, 2, 1)

[Link](k_values * omega0, [Link](coefficients), markerfmt="ro", basefmt=" ")

[Link]("Input Spectrum")
[Link]("Frequency (rad/s)")

[Link]("|a_k|")

[Link](True)

# Output Spectrum After Filtering

[Link](1, 2, 2)

[Link](k_values * omega0, [Link](output_coeffs), markerfmt="bo", basefmt=" ")


[Link]("Output Spectrum After Filtering")

[Link]("Frequency (rad/s)")

[Link]("|b_k|")

[Link](True)
plt.tight_layout()

[Link]()

2. Time Domain Reconstruction

import numpy as np

import [Link] as plt

def reconstruct_signal(coeffs, t, T0, N):

omega0 = 2*[Link]/T0

signal = np.zeros_like(t, dtype=complex) # Ensure it's initialized properly

for k, ak in zip(range(-N, N+1), coeffs): # Pass N explicitly

signal += ak * [Link](1j*k*omega0*t)

return [Link](signal)

# Define parameters
T0 = 2 * [Link]

N = len(coefficients) // 2 # Ensure correct range for coefficients

t = [Link](-T0, 2*T0, 1000)

# Reconstruct input and output signals

input_signal = reconstruct_signal(coefficients, t, T0, N)

output_signal = reconstruct_signal(output_coeffs, t, T0, N)

# Plot reconstructed signals

[Link](figsize=(10, 5))

[Link](t, input_signal, label='Input Square Wave', color='blue')

[Link](t, output_signal, label='Filtered Output', color='red')

[Link]('Time Domain Signals Before and After Filtering')


[Link]()
[Link](True)

[Link]()

2. Fast Forier Transform (FFT) Visuilization

import numpy as np

import [Link] as plt

import ipywidgets as widgets


from [Link] import display

# Ensure correct backend for plotting

%matplotlib inline

# Sampling parameters

Fs = 1000 # Sampling frequency (Hz)

T = 1.0 # Duration (seconds)


t = [Link](0, T, int(Fs*T), endpoint=False) # Time array

def generate_signal(freq1=50, freq2=150, freq3=300):

""" Generate a signal composed of multiple sine waves """

return [Link](2*[Link]*freq1*t) + [Link](2*[Link]*freq2*t) + [Link](2*[Link]*freq3*t)

def plot_fft(freq1=50, freq2=150, freq3=300):


""" Compute and plot FFT of the generated signal """

signal = generate_signal(freq1, freq2, freq3)

N = len(signal) # Number of samples

# Compute FFT

fft_values = [Link](signal)
freqs = [Link](N, 1/Fs)
# Only take positive frequencies

mask = freqs >= 0 # Fixed issue: previously filtering only greater than zero

# Plot time-domain signal

[Link](figsize=(12, 5))

[Link](1, 2, 1)
[Link](t, signal, label="Time-domain Signal", color="royalblue")

[Link]("Time (s)")

[Link]("Amplitude")

[Link]("Original Signal")

[Link]()

[Link](True)

# Plot FFT magnitude spectrum with enhanced visuals


[Link](1, 2, 2)

[Link](freqs[mask], [Link](fft_values[mask]), markerfmt="ro")

[Link]("Frequency (Hz)")

[Link]("Magnitude")

[Link]("Frequency-domain (FFT) Spectrum")

[Link](True)

plt.tight_layout()

[Link]()

# Use interactive sliders with improved functionality for Colab

interactive_fft = [Link](plot_fft,

freq1=[Link](min=10, max=500, value=50, step=10),


freq2=[Link](min=10, max=500, value=150, step=10),
freq3=[Link](min=10, max=500, value=300, step=10))

display(interactive_fft)

Convolution Visualization in Python

1. Discrete-Time Convolution

import numpy as np
import [Link] as plt

def discrete_convolution(x, h):

N = len(x)

M = len(h)

y = [Link](N + M - 1)

for n in range(len(y)):
for k in range(max(0, n-M+1), min(n+1, N)):

y[n] += x[k] * h[n-k]

return y

# Create a pulse signal

x = [Link]([[Link](5), [Link](10), [Link](5)])

# Create a moving average filter


h = [Link](5)/5

y = discrete_convolution(x, h)

[Link](figsize=(12, 4))

[Link](1, 3, 1)
[Link](x, markerfmt="ro") # Removed use_line_collection=True
[Link]("Input Signal x[n]")

[Link](1, 3, 2)

[Link](h, markerfmt="bo") # Removed use_line_collection=True

[Link]("Impulse Response h[n]")

[Link](1, 3, 3)
[Link](y, markerfmt="go") # Removed use_line_collection=True

[Link]("Output y[n] = x[n] * h[n]")

plt.tight_layout()

[Link]()

2. Continuous-Time Convolution

from [Link] import convolve

# Define time axis

t = [Link](0, 10, 1000)

# Create exponential signals

x = [Link](-0.25*t) * (t <= 6)

h = [Link](-t) * ((t >= -1) & (t <= 5)) # Shifted to include negative time

# Perform convolution

y = convolve(x, h, mode='same') * (t[1]-t[0]) # Multiply by dt for proper scaling

[Link](figsize=(12, 4))

[Link](1, 3, 1)
[Link](t, x)
[Link]('Input Signal x(t)')

[Link](1, 3, 2)

[Link](t, h)

[Link]('Impulse Response h(t)')

[Link](1, 3, 3)
[Link](t, y)

[Link]('Output y(t) = x(t)*h(t)')

plt.tight_layout()

[Link]()

3. Interactive Convolution Visualization

from [Link] import FuncAnimation

from [Link] import HTML

def animate_convolution(x, h, t):

fig, (ax1, ax2, ax3) = [Link](3, 1, figsize=(10, 8))

# Plot original signals

[Link](t, x, label='x(τ)')

ax1.set_title('Input Signal x(τ)')


[Link]()

[Link](t, h, label='h(τ)')

ax2.set_title('Impulse Response h(τ)')

[Link]()

# Initialize output plot


line, = [Link]([], [], 'r-')

ax3.set_xlim(t[0], t[-1])

ax3.set_ylim(0, 1.1*[Link](convolve(x, h, mode='same')))

ax3.set_title('Convolution Result y(t) = x(t)*h(t)')

# Calculate full convolution result

full_conv = convolve(x, h, mode='same') * (t[1]-t[0])

def update(frame):

# Flip and shift h

shifted_h = [Link](h[::-1], frame)

# Clear and redraw

[Link]()

[Link](t, x, label='x(τ)')
[Link](t, shifted_h, 'g--', label=f'h({frame}-τ)')

ax1.set_title(f'Time t = {t[frame]:.2f}')

[Link]()

[Link]()

[Link](t, shifted_h, 'g--', label=f'h({frame}-τ)')

ax2.set_title('Flipped and Shifted Impulse Response')


[Link]()

# Update convolution result up to current frame

line.set_data(t[:frame], full_conv[:frame])

return line,

ani = FuncAnimation(fig, update, frames=len(t), interval=50, blit=True)


[Link]()

return HTML(ani.to_jshtml())

# Create signals

t = [Link](0, 10, 100)

x = [Link](-0.5*t) * (t <= 5)

h = [Link](-2*t) * (t <= 3)

animate_convolution(x, h, t)

Other Applications

1. Multipath Channel Analysis

def multipath_signal(f0=1000, delays=[0, 0.001, 0.002], amps=[1, 0.7, 0.3], dur=0.01,


fs=44100):

t = [Link](0, dur, 1/fs)

signal = np.zeros_like(t)

for delay, amp in zip(delays, amps):

signal += amp * [Link](2*[Link]*f0*(t - delay))

return t, signal

t, sig = multipath_signal()
[Link](figsize=(10, 4))

[Link](t, sig)

[Link]('Multipath Signal Composition')

[Link]('Time (s)')
[Link]('Amplitude')
[Link](True)

[Link]()

2. Spectrogram Analysis

from [Link] import spectrogram

# Create a signal with time-varying frequency


fs = 10000

t = [Link](0, 1, 1/fs)

f_inst = 100 + 800*t # Frequency sweeps from 100Hz to 900Hz

x = [Link](2*[Link]*f_inst*t)

# Compute spectrogram

f, t_spec, Sxx = spectrogram(x, fs, nperseg=1024)

[Link](figsize=(10, 5))

[Link](t_spec, f, 10*np.log10(Sxx), shading='gouraud')

[Link](label='Power Spectral Density (dB)')

[Link]('Frequency [Hz]')

[Link]('Time [sec]')

[Link]('Spectrogram of Frequency-Swept Signal')

[Link]()

You might also like