0% found this document useful (0 votes)
16 views19 pages

DSP Lab Manual

The document consists of multiple labs focusing on signal processing techniques using Python, including generating various waveforms, analyzing Nyquist sampling, checking linearity and time invariance of systems, performing convolution, and calculating discrete Fourier transforms (DFT) and Z-transforms. Each lab contains code snippets for generating and plotting signals, along with theoretical explanations and visualizations of the results. The labs cover practical applications of signal processing concepts using libraries such as NumPy and Matplotlib.

Uploaded by

Jazib Hasan
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)
16 views19 pages

DSP Lab Manual

The document consists of multiple labs focusing on signal processing techniques using Python, including generating various waveforms, analyzing Nyquist sampling, checking linearity and time invariance of systems, performing convolution, and calculating discrete Fourier transforms (DFT) and Z-transforms. Each lab contains code snippets for generating and plotting signals, along with theoretical explanations and visualizations of the results. The labs cover practical applications of signal processing concepts using libraries such as NumPy and Matplotlib.

Uploaded by

Jazib Hasan
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
You are on page 1/ 19

LAB 1

# LAB 1
import numpy as np
import matplotlib.pyplot as plt

def generate_exponential_damped_sinusoid(alpha, freq, length,


sample_rate=1000):
t = np.linspace(0, length, int(sample_rate * length),
endpoint=False)
signal = np.exp(-alpha * t) * np.sin(2 * np.pi * freq * t)
return t, signal

def generate_sawtooth(freq, length, sample_rate=1000, width=1.0):


t = np.linspace(0, length, int(sample_rate * length),
endpoint=False)
signal = 2 * (t * freq - np.floor(t * freq + 0.5)) # Normalized
between -1 and 1
return t, signal

def generate_triangular_pulse(freq, length, sample_rate=1000,


width=0.5):
t = np.linspace(0, length, int(sample_rate * length),
endpoint=False)
signal = 2 * np.abs(2 * (t * freq - np.floor(t * freq + 0.5))) - 1
return t, signal

# Parameters for the signals


duration = 1.0 # 1 second duration
sample_rate = 1000 # 1000 samples per second

# Generate signals
t_exp, exp_signal = generate_exponential_damped_sinusoid(alpha=2,
freq=5, length=duration, sample_rate=sample_rate)
t_saw, saw_signal = generate_sawtooth(freq=2, length=duration,
sample_rate=sample_rate)
t_tri, tri_signal = generate_triangular_pulse(freq=1, length=duration,
sample_rate=sample_rate)

# Plot the signals


plt.figure(figsize=(15, 5))

# Exponentially damped sinusoid


plt.subplot(1, 3, 1)
plt.plot(t_exp, exp_signal)
plt.title('Exponentially Damped Sinusoid')
plt.xlabel('Time (s)')
plt.ylabel('Amplitude')
plt.grid(True)

# Sawtooth waveform
plt.subplot(1, 3, 2)
plt.plot(t_saw, saw_signal)
plt.title('Sawtooth Waveform')
plt.xlabel('Time (s)')
plt.ylabel('Amplitude')
plt.grid(True)

# Triangular pulse
plt.subplot(1, 3, 3)
plt.plot(t_tri, tri_signal)
plt.title('Triangular Pulse')
plt.xlabel('Time (s)')
plt.ylabel('Amplitude')
plt.grid(True)

plt.tight_layout()
plt.show()

LAB 2
# LAB 2
import numpy as np
import matplotlib.pyplot as plt

def analyze_nyquist(F, Fs, duration=1.0):


t = np.linspace(0, duration, int(Fs * duration), endpoint=False)
analog_signal = np.sin(2 * np.pi * F * t)
sampled_t = np.arange(0, duration, 1/Fs)
sampled_signal = np.sin(2 * np.pi * F * sampled_t)

plt.figure(figsize=(12, 8))
plt.subplot(2, 1, 1)
plt.plot(t, analog_signal, label='Analog Signal')
plt.stem(sampled_t, sampled_signal, linefmt='r-', markerfmt='ro',
basefmt=' ', label='Sampled Points')
plt.title(f'F = {F} Hz, Fs = {Fs} Hz')
plt.xlabel('Time (s)')
plt.ylabel('Amplitude')
plt.legend()
plt.grid(True)

plt.subplot(2, 1, 2)
fft_freq = np.fft.fftfreq(len(analog_signal), 1/Fs)
fft_values = np.abs(np.fft.fft(analog_signal))
plt.plot(fft_freq, fft_values)
plt.title('Frequency Spectrum')
plt.xlabel('Frequency (Hz)')
plt.ylabel('Magnitude')
plt.grid(True)
plt.xlim(0, 3*F)

plt.tight_layout()
plt.show()

F = float(input("Enter the signal frequency (F): "))


Fs = float(input("Enter the sampling frequency (Fs): "))

analyze_nyquist(F, Fs)

Enter the signal frequency (F): 50


Enter the sampling frequency (Fs): 20
LAB 3
# Lab 3 Part 1 #
import numpy as np
import matplotlib.pyplot as plt

t = np.linspace(-10, 10, 25)


x1 = lambda t: np.sin(t)
x2 = lambda t: np.cos(t)

def checkLinearity(Tr):
x1plusx2 = lambda t: x1(t)+x2(t)
plt.plot(t, Tr(x1)(t)+Tr(x2)(t),'b', label='T(x1)+T(x2)')
plt.plot(t, Tr(x1plusx2)(t),'r.', label='T(x1+x2)')
plt.legend()
plt.title('Linearity Check')
plt.grid()
plt.show()

def Tr(x):
return lambda t: x(t-2) # y(t) = x(t-2)

checkLinearity(Tr)
def Tr(x):
return lambda t: x(t)**2 # y(t) = x(t)²

checkLinearity(Tr)

# LAB 3 Part 2
t = np.linspace(-2, 4, 5)
x = lambda t: np.sin(t)

def showTimeInvariance(Tr):
plt.figure(figsize=(10,4))
plt.subplot(1,2,1)
plt.plot(t, x(t),'r', label='x(t)')
plt.plot(t, x(t-0.5),'b', label='x(t-0.5)')
plt.plot(t, x(t-1),'k', label='x(t-1)')
plt.title('Input Signals')
plt.legend()
plt.grid()

plt.subplot(1,2,2)
y1 = Tr(x)
y2 = Tr(lambda t: x(t-0.5))
y3 = Tr(lambda t: x(t-1))
plt.plot(t, y1(t), 'r', label='T(x(t))')
plt.plot(t, y2(t), 'b', label='T(x(t-0.5))')
plt.plot(t, [y1(ti-0.5) for ti in t], 'b--', label='y(t-0.5)')
plt.plot(t, y3(t), 'k', label='T(x(t-1))')
plt.plot(t, [y1(ti-1) for ti in t], 'k--', label='y(t-1)')
plt.title('Output Responses')
plt.legend()
plt.grid()
plt.show()

def Tr(x):
return lambda t: t*x(t) # y(t) = t·x(t)

showTimeInvariance(Tr)
def Tr(x):
return lambda t: x(t)**2 # y(t) = x(t)²

showTimeInvariance(Tr)

LAB 4
# Lab 4
import numpy as np
import matplotlib.pyplot as plt

# Set smaller default figure size


plt.rcParams['figure.figsize'] = (10, 3)

def plot_signals(x, h, y, title):


plt.figure()

plt.subplot(1, 3, 1)
plt.stem(x, markerfmt='bo')
plt.title('x(n)')
plt.grid(True, alpha=0.3)

plt.subplot(1, 3, 2)
plt.stem(h, markerfmt='ro')
plt.title('h(n)')
plt.grid(True, alpha=0.3)

plt.subplot(1, 3, 3)
plt.stem(y, markerfmt='go')
plt.title('y(n) = x(n)*h(n)')
plt.grid(True, alpha=0.3)
plt.suptitle(title, y=1.05) # Adjust title position
plt.tight_layout()
plt.show()

# Case 1
x1 = np.array([-3, -2, -1, 0, 1, 2, 3])
h1 = np.array([1, 1, 1, 1, 1])
y1 = np.convolve(x1, h1, mode='full')
plot_signals(x1, h1, y1, "Case 1: x(n) = { -3,-2,-1,0,1,2,3 }, h(n) =
{1,1,1,1,1}")

# Case 2
x2 = np.array([1, 2, 3, 4, 5])
h2 = np.array([1])
y2 = np.convolve(x2, h2, mode='full')
plot_signals(x2, h2, y2, "Case 2: x(n) = {1,2,3,4,5}, h(n) = {1}")

# Case 3
x3 = np.array([-1, -2, 0, 2, 1])
h3 = x3.copy()
y3 = np.convolve(x3, h3, mode='full')
plot_signals(x3, h3, y3, "Case 3: x(n) = { -1,-2,0,2,1}, h(n) = x(n)")
LAB 5
# Lab 5
import numpy as np
import matplotlib.pyplot as plt

# Set smaller figure sizes


plt.rcParams['figure.figsize'] = (8, 3)

# Task 1: DFT of f[n] = {1, 1, -1, -1}


f = np.array([1, 1, -1, -1])
F = np.fft.fft(f)

# Plot for Task 1


plt.figure()
plt.subplot(1, 2, 1)
plt.stem(np.abs(F))
plt.title('Magnitude (Task 1)')
plt.xlabel('k')
plt.grid(True)

plt.subplot(1, 2, 2)
plt.stem(np.angle(F))
plt.title('Phase (Task 1)')
plt.xlabel('k')
plt.grid(True)
plt.tight_layout()
plt.show()

# Task 2: IDFT of given signals


# Case a
Fa = np.array([0, 2-2j, 0, 2+2j])
fa = np.fft.ifft(Fa)

# Case b
Fb = np.array([30, 1-1j, 1, 1+1j])
fb = np.fft.ifft(Fb)

# Plot for Task 2a


plt.figure()
plt.subplot(1, 2, 1)
plt.stem(np.abs(Fa))
plt.title('Magnitude (Task 2a)')
plt.xlabel('k')
plt.grid(True)

plt.subplot(1, 2, 2)
plt.stem(np.angle(Fa))
plt.title('Phase (Task 2a)')
plt.xlabel('k')
plt.grid(True)
plt.tight_layout()
plt.show()

# Plot for Task 2b


plt.figure()
plt.subplot(1, 2, 1)
plt.stem(np.abs(Fb))
plt.title('Magnitude (Task 2b)')
plt.xlabel('k')
plt.grid(True)

plt.subplot(1, 2, 2)
plt.stem(np.angle(Fb))
plt.title('Phase (Task 2b)')
plt.xlabel('k')
plt.grid(True)
plt.tight_layout()
plt.show()

# Print results compactly


print("Task 1 - DFT:\n", F)
print("\nTask 2a - IDFT:\n", fa)
print("\nTask 2b - IDFT:\n", fb)
Task 1 - DFT:
[0.+0.j 2.-2.j 0.+0.j 2.+2.j]

Task 2a - IDFT:
[ 1.+0.j 1.+0.j -1.+0.j -1.+0.j]
Task 2b - IDFT:
[8.25+0.j 7.75+0.j 7.25+0.j 6.75+0.j]

LAB 6
# LAB 6
import numpy as np
import matplotlib.pyplot as plt
import sympy as sp
from sympy import symbols, summation, oo, exp, lambdify

# Define the symbolic variables


n, z = symbols('n z')

# Function 1: f(n) = 3^n


def z_transform_1():
f = 3**n
Z = summation(f * z**(-n), (n, 0, oo))
return Z.simplify()

# Function 2: f(n) = (-0.5)^n


def z_transform_2():
f = (-0.5)**n
Z = summation(f * z**(-n), (n, 0, oo))
return Z.simplify()

# Function 3: f(n) = n^2


def z_transform_3():
f = n**2
Z = summation(f * z**(-n), (n, 0, oo))
return Z.simplify()

# Calculate and print the Z-transforms


print("Z-transform of f(n) = 3^n:")
print(z_transform_1())

print("\nZ-transform of f(n) = (-0.5)^n:")


print(z_transform_2())

print("\nZ-transform of f(n) = n^2:")


print(z_transform_3())

# Visualization of the functions and their poles/zeros


def plot_z_transform(expr, title):
# Convert symbolic expression to numerical function
num_func = lambdify(n, expr, 'numpy')

# Plot the discrete-time function


n_vals = np.arange(0, 10)
f_vals = num_func(n_vals)

plt.figure(figsize=(10, 4))
plt.subplot(1, 2, 1)
plt.stem(n_vals, f_vals)
plt.title(f'Discrete Function: {title}')
plt.xlabel('n')
plt.ylabel('f(n)')
plt.grid(True, alpha=0.3)

# For pole-zero plot (simplified visualization)


plt.subplot(1, 2, 2)
if title == "3^n":
plt.plot(3, 0, 'rx', markersize=10) # Pole at z=3
elif title == "(-0.5)^n":
plt.plot(-0.5, 0, 'rx', markersize=10) # Pole at z=-0.5
elif title == "n^2":
plt.plot(1, 0, 'rx', markersize=10) # Pole at z=1 (double
pole)
plt.title('Pole Location (simplified)')
plt.xlabel('Real')
plt.ylabel('Imaginary')
plt.grid(True)
plt.axis('equal')
plt.xlim(-4, 4)
plt.ylim(-2, 2)
plt.tight_layout()
plt.show()

# Plot each function


plot_z_transform(3**n, "3^n")
plot_z_transform((-0.5)**n, "(-0.5)^n")
plot_z_transform(n**2, "n^2")

Z-transform of f(n) = 3^n:


Piecewise((z/(z - 3), (z > 3) | (z < -3)), (Sum(3**n/z**n, (n, 0,
oo)), True))

Z-transform of f(n) = (-0.5)^n:


Sum((-0.5)**n/z**n, (n, 0, oo))

Z-transform of f(n) = n^2:

WARNING:matplotlib.axes._base:Ignoring fixed x limits to fulfill fixed


data aspect with adjustable data limits.
WARNING:matplotlib.axes._base:Ignoring fixed y limits to fulfill fixed
data aspect with adjustable data limits.
Piecewise((z*(z + 1)/(z - 1)**3, (z > 1) | (z < -1)), (Sum(n**2/z**n,
(n, 0, oo)), True))

WARNING:matplotlib.axes._base:Ignoring fixed x limits to fulfill fixed


data aspect with adjustable data limits.
WARNING:matplotlib.axes._base:Ignoring fixed y limits to fulfill fixed
data aspect with adjustable data limits.

WARNING:matplotlib.axes._base:Ignoring fixed x limits to fulfill fixed


data aspect with adjustable data limits.
WARNING:matplotlib.axes._base:Ignoring fixed y limits to fulfill fixed
data aspect with adjustable data limits.
LAB 7
import numpy as np
import matplotlib.pyplot as plt
from scipy import signal

# Set up ultra-compact plotting style


plt.style.use('default')
plt.rcParams['figure.figsize'] = (10, 8) # Single figure with
subplots
plt.rcParams['axes.grid'] = True
plt.rcParams['grid.alpha'] = 0.2
plt.rcParams['axes.titlepad'] = 4
plt.rcParams['axes.labelpad'] = 2

# Parameters for filters


fs = 1000
center_freq = 100
bandwidth = 40

# Design filters
bp_b, bp_a = signal.butter(5, [center_freq-bandwidth/2,
center_freq+bandwidth/2],
btype='bandpass', fs=fs)
bs_b, bs_a = signal.butter(5, [center_freq-bandwidth/2,
center_freq+bandwidth/2],
btype='bandstop', fs=fs)

# Create test signal


t = np.linspace(0, 1, fs, False)
input_signal = np.sin(2*np.pi*30*t) + np.sin(2*np.pi*100*t) +
np.sin(2*np.pi*200*t)
# Process signals
bp_filtered = signal.lfilter(bp_b, bp_a, input_signal)
bs_filtered = signal.lfilter(bs_b, bs_a, input_signal)

# Create a single figure with all plots


fig, axs = plt.subplots(3, 2, constrained_layout=True)

# Frequency Responses
w, h_bp = signal.freqz(bp_b, bp_a, fs=fs)
axs[0,0].plot(w, 20*np.log10(abs(h_bp)), linewidth=1)
axs[0,0].set_title('Band Pass Frequency Response', fontsize=9)
axs[0,0].set_ylim(-60, 5)

w, h_bs = signal.freqz(bs_b, bs_a, fs=fs)


axs[0,1].plot(w, 20*np.log10(abs(h_bs)), linewidth=1)
axs[0,1].set_title('Band Stop Frequency Response', fontsize=9)
axs[0,1].set_ylim(-60, 5)

# Time Domain Signals


axs[1,0].plot(t[:100], input_signal[:100], 'b-', linewidth=1,
label='Original')
axs[1,0].plot(t[:100], bp_filtered[:100], 'r-', linewidth=1,
label='Filtered')
axs[1,0].set_title('Band Pass: Time Domain', fontsize=9)
axs[1,0].legend(fontsize=7)

axs[1,1].plot(t[:100], input_signal[:100], 'b-', linewidth=1,


label='Original')
axs[1,1].plot(t[:100], bs_filtered[:100], 'r-', linewidth=1,
label='Filtered')
axs[1,1].set_title('Band Stop: Time Domain', fontsize=9)
axs[1,1].legend(fontsize=7)

# Pole-Zero Plots
def plot_pz(ax, b, a, title):
z, p, k = signal.tf2zpk(b, a)
ax.scatter(np.real(z), np.imag(z), marker='o', facecolors='none',
edgecolors='b', s=40)
ax.scatter(np.real(p), np.imag(p), marker='x', color='r', s=40)
ax.axhline(0, color='black', linewidth=0.5)
ax.axvline(0, color='black', linewidth=0.5)
ax.set_title(title, fontsize=9)
ax.set_xlim(-1.5, 1.5)
ax.set_ylim(-1.5, 1.5)

plot_pz(axs[2,0], bp_b, bp_a, 'Band Pass: Pole-Zero')


plot_pz(axs[2,1], bs_b, bs_a, 'Band Stop: Pole-Zero')

# Common formatting
for ax in axs.flat:
ax.tick_params(axis='both', which='major', labelsize=7)
ax.grid(True, alpha=0.2)

plt.suptitle('Filter Analysis: Band Pass vs Band Stop', y=1.02,


fontsize=10)
plt.show()

LAB 8
import numpy as np
import matplotlib.pyplot as plt
from scipy import signal

# Set up compact plotting style


plt.rcParams['figure.figsize'] = (8, 4)
plt.rcParams['axes.grid'] = True

def plot_filters():
# Common parameters
cutoff = 50 # Cutoff frequency (rad/s)
order = 4

# Create frequency range


w = np.logspace(-1, 2, 1000)

# 1. Butterworth Filter
b_butter, a_butter = signal.butter(order, cutoff, 'low',
analog=True)
w_butter, h_butter = signal.freqs(b_butter, a_butter, worN=w)

# 2. Chebyshev Type I with different rp values


rp_values = [1, 3, 5] # Passband ripple in dB
cheby1_results = []
for rp in rp_values:
b, a = signal.cheby1(order, rp, cutoff, 'low', analog=True)
w_cheby1, h_cheby1 = signal.freqs(b, a, worN=w)
cheby1_results.append((rp, w_cheby1, h_cheby1))

# 3. Chebyshev Type II with different rs values


rs_values = [20, 40, 60] # Stopband attenuation in dB
cheby2_results = []
for rs in rs_values:
b, a = signal.cheby2(order, rs, cutoff, 'low', analog=True)
w_cheby2, h_cheby2 = signal.freqs(b, a, worN=w)
cheby2_results.append((rs, w_cheby2, h_cheby2))

# Plot results
fig, (ax1, ax2, ax3) = plt.subplots(1, 3, sharey=True)

# Butterworth plot
ax1.semilogx(w_butter, 20*np.log10(abs(h_butter)))
ax1.set_title('Butterworth (N=4)')
ax1.set_xlabel('Frequency [rad/s]')
ax1.set_ylabel('Amplitude [dB]')
ax1.axvline(cutoff, color='green', linestyle='--')
ax1.set_ylim(-60, 5)

# Chebyshev Type I plot


for rp, w_cheby1, h_cheby1 in cheby1_results:
ax2.semilogx(w_cheby1, 20*np.log10(abs(h_cheby1)),
label=f'rp={rp}dB')
ax2.set_title('Chebyshev Type I (N=4)')
ax2.set_xlabel('Frequency [rad/s]')
ax2.axvline(cutoff, color='green', linestyle='--')
ax2.legend()

# Chebyshev Type II plot


for rs, w_cheby2, h_cheby2 in cheby2_results:
ax3.semilogx(w_cheby2, 20*np.log10(abs(h_cheby2)),
label=f'rs={rs}dB')
ax3.set_title('Chebyshev Type II (N=4)')
ax3.set_xlabel('Frequency [rad/s]')
ax3.axvline(cutoff, color='green', linestyle='--')
ax3.legend()

plt.tight_layout()
plt.show()

plot_filters()

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy