Convolution in Python
In [1]:
import numpy as np
import matplotlib.pyplot as plt
Initializing the arrays¶
In [2]:
x = np.arange(0,6,1)
h = np.zeros(5)
h[2:4] = 1
plt.stem(x)
plt.xlabel("n")
plt.ylabel("amplitude = x[n]")
plt.title("A Signal")
plt.show()
plt.stem(h)
plt.xlabel("n")
plt.ylabel("amplitude = x[n]")
plt.title("A Pulse")
plt.show()
Initialize the output array¶
In [3]:
y = np.zeros((len(x)+len(h)-1))
plt.stem(y)
plt.xlabel("n")
plt.ylabel("amplitude = y[n]")
plt.title("Output Array")
plt.show()
Analyze the Equation¶
$$ y[n] = (x * h)[n] = \sum_{k=-\infty}^{\infty} x[k]\; h[n - k] $$
We have two variables here, n
which tells you the index of the output
and a shift variable k
which is used to calculate the summation
Writing this as an equation in python, is simple:
y[n] += x[k] * h[n - k]
But the algorithm gets tricky when we try to implement the actual loops for the summation
In [4]:
import numpy as np
import matplotlib.pyplot as plt
In [5]:
def printFunc(check,x,h,n,k):
zeroBase1 = np.zeros((len(x)+len(h)-1))
zeroBase2 = np.zeros((len(x)+len(h)-1))
if(check ==0):
h_rev = h[::-1]
print("Aligned Sig:", x[k:k+len(h)])
zeroBase1[k:k+len(h_rev[(len(h) - (n-k)-1):len(h)])] = h_rev[(len(h) - (n-k)-1):len(h)]
print("Aligned Imp:", h_rev[(len(h) - (n-k)-1):len(h)])
zeroBase1[k:k+len(h_rev[(len(h) - (n-k)-1):len(h)])] = h_rev[(len(h) - (n-k)-1):len(h)]
print("Aligned Sig:", x[k:k+len(h)])
zeroBase2[0:len(x)] = x[:]
plt.stem(zeroBase1, linefmt='g-', markerfmt='ro',)
plt.stem(zeroBase2)
plt.xlabel("n")
plt.ylabel("amplitude")
plt.title("convolution")
check = 1
return check
In [6]:
#Let's implement the first pass
n = 0
check=0
for k in range(len(x)):
# Ensure we do not go out of bounds with our impulse
if 0 <= n - k < len(h):
# Ignore, this helps with Visualization
check = printFunc(check,x,h,n,k)
# Accumulation
y[n] += x[k] * h[n - k]
print("sum =",y[n])
Aligned Sig: [0 1 2 3 4] Aligned Imp: [0.] Aligned Sig: [0 1 2 3 4] sum = 0.0
In [7]:
#Let's implement the first pass
n = 1
check = 0
for k in range(len(x)):
# Ensure we do not go out of bounds with our impulse
if 0 <= n - k < len(h):
# Ignore, this helps with Visualization
check = printFunc(check,x,h,n,k)
# Accumulation
y[n] += x[k] * h[n - k]
print("sum =",y[n])
Aligned Sig: [0 1 2 3 4] Aligned Imp: [0. 0.] Aligned Sig: [0 1 2 3 4] sum = 0.0
In [8]:
#Let's implement the first pass
n = 2
check = 0
for k in range(len(x)):
# Ensure we do not go out of bounds with our impulse
if 0 <= n - k < len(h):
# Ignore, this helps with Visualization
check = printFunc(check,x,h,n,k)
# Accumulation
y[n] += x[k] * h[n - k]
print("sum =",y[n])
Aligned Sig: [0 1 2 3 4] Aligned Imp: [1. 0. 0.] Aligned Sig: [0 1 2 3 4] sum = 0.0
In [9]:
#Let's implement the first pass
n = 3
check = 0
for k in range(len(x)):
# Ensure we do not go out of bounds with our impulse
if 0 <= n - k < len(h):
# Ignore, this helps with Visualization
check = printFunc(check,x,h,n,k)
# Accumulation
y[n] += x[k] * h[n - k]
print("sum =",y[n])
Aligned Sig: [0 1 2 3 4] Aligned Imp: [1. 1. 0. 0.] Aligned Sig: [0 1 2 3 4] sum = 1.0
In [10]:
#Let's implement the first pass
n = 4
check = 0
for k in range(len(x)):
# Ensure we do not go out of bounds with our impulse
if 0 <= n - k < len(h):
# Ignore, this helps with Visualization
check = printFunc(check,x,h,n,k)
# Accumulation
y[n] += x[k] * h[n - k]
print("sum =",y[n])
Aligned Sig: [0 1 2 3 4] Aligned Imp: [0. 1. 1. 0. 0.] Aligned Sig: [0 1 2 3 4] sum = 3.0
In [11]:
#Let's implement the first pass
n = 5
check = 0
for k in range(len(x)):
# Ensure we do not go out of bounds with our impulse
if 0 <= n - k < len(h):
# Ignore, this helps with Visualization
check = printFunc(check,x,h,n,k)
# Accumulation
y[n] += x[k] * h[n - k]
print("sum =",y[n])
Aligned Sig: [1 2 3 4 5] Aligned Imp: [0. 1. 1. 0. 0.] Aligned Sig: [1 2 3 4 5] sum = 5.0
In [12]:
#Let's implement the first pass
n = 6
check = 0
for k in range(len(x)):
# Ensure we do not go out of bounds with our impulse
if 0 <= n - k < len(h):
# Ignore, this helps with Visualization
check = printFunc(check,x,h,n,k)
# Accumulation
y[n] += x[k] * h[n - k]
print("sum =",y[n])
Aligned Sig: [2 3 4 5] Aligned Imp: [0. 1. 1. 0. 0.] Aligned Sig: [2 3 4 5] sum = 7.0
In [13]:
#Let's implement the first pass
n = 7
check = 0
for k in range(len(x)):
# Ensure we do not go out of bounds with our impulse
if 0 <= n - k < len(h):
# Ignore, this helps with Visualization
check = printFunc(check,x,h,n,k)
# Accumulation
y[n] += x[k] * h[n - k]
print("sum =",y[n])
Aligned Sig: [3 4 5] Aligned Imp: [0. 1. 1. 0. 0.] Aligned Sig: [3 4 5] sum = 9.0
In [14]:
#Let's implement the first pass
n = 8
check = 0
for k in range(len(x)):
# Ensure we do not go out of bounds with our impulse
if 0 <= n - k < len(h):
# Ignore, this helps with Visualization
check = printFunc(check,x,h,n,k)
# Accumulation
y[n] += x[k] * h[n - k]
print("sum =",y[n])
Aligned Sig: [4 5] Aligned Imp: [0. 1. 1. 0. 0.] Aligned Sig: [4 5] sum = 5.0
In [15]:
#Let's implement the first pass
n = 9
check = 0
for k in range(len(x)):
# Ensure we do not go out of bounds with our impulse
if 0 <= n - k < len(h):
# Ignore, this helps with Visualization
check = printFunc(check,x,h,n,k)
# Accumulation
y[n] += x[k] * h[n - k]
print("sum =",y[n])
Aligned Sig: [5] Aligned Imp: [0. 1. 1. 0. 0.] Aligned Sig: [5] sum = 0.0
In [16]:
plt.stem(y)
plt.xlabel("n")
plt.ylabel("amplitude = y[n]")
plt.title("Output Array")
plt.show()
In [17]:
y = np.convolve(x,h)
plt.stem(y)
plt.xlabel("n")
plt.ylabel("amplitude = y[n]")
plt.title("Output Array")
plt.show()