or
$$ (h \ast x)(t) = \int_{-\infty}^{\infty} h(\tau)x(t - \tau) \, d\tau $$Illustration: [1]
from IPython.display import HTML
HTML('<iframe src=http://mathworld.wolfram.com/images/gifs/convrect.gif width=300 height=260></iframe>')
from IPython.display import HTML
HTML('<iframe src=http://mathworld.wolfram.com/images/gifs/convgaus.gif width=300 height=260></iframe>')
def step(t, t_0):
return 1 * ((t - t_0) >= 0)
%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
t = np.arange(-4.0, 4.0, 0.01)
x = step(t,0)
h = step(t,0)
fig = plt.figure(figsize=(12,4))
plt.subplot(1, 2, 1)
plt.plot(t,x,'g-',linewidth=6);
plt.title('Input signal, $x(t)$')
plt.xlabel('t')
plt.subplot(1, 2, 2)
plt.plot(t,h,'r-',linewidth=6);
plt.title('Impulse response, $h(t)$')
plt.xlabel('t');
t = np.arange(-4.0, 4.0, 0.01)
h = step(-t, 0)
fig = plt.figure(figsize=(12,4))
plt.plot(t,h,'r-',linewidth=6);
plt.title('Impulse response, $h(-\u03c4)$ at t = 0')
plt.xlabel('T');
t = np.arange(-4.0, 4.0, 0.01)
h = step(-t, -0.5)
x = step(t, 0)
fig = plt.figure(figsize=(12,4))
ax1 = fig.add_axes([0, 0, 1, 1]) # [left, bottom, width, height]
plt.plot(t,h,'r-',linewidth=6);
plt.plot(t,x,'g-',linewidth=6);
plt.title('Impulse response, $h(-\u03c4)$ at t = 0.5 with the input signal, $u(t)$')
plt.xlabel('T');
ax1.fill_between(t,0,h,where=x==h,color='black');
ax1.annotate('$t$', xy=(0.5, 0), xytext=(0.6, 0.1),
arrowprops=dict(facecolor='yellow', shrink=0.05),
)
<matplotlib.text.Annotation at 0xb00f372c>
Notice that the time reversed Impulse response, $u(-\tau)$, starts intersecting the signal, which is also a unit step, $u(\tau)$, at $\tau = 0$ until $\tau = t$.
Thus,
$$ (x \ast h)(t) = \int_{0}^{t} x(\tau)h(t - \tau) \, d\tau$$$$ (x \ast h)(t) = \int_{0}^{t} u(\tau)u(t - \tau) \, d\tau$$$$ (x \ast h)(t) = \int_{0}^{t} (1)(1) \, d\tau$$$$ (x \ast h)(t) = \left. \tau \right |_0^t $$$$ (x \ast h)(t) = t \, u(t) $$t = np.arange(-4.0, 4.0, 0.01)
# input
x = step(t,0)
# impulse response
h = step(t,0)
# result
result = np.zeros(len(t))
result = t * (step(t,0))
fig = plt.figure(figsize=(16,4))
plt.plot(t,x,'go-',linewidth=5, label='Input signal, $x(t)$');
plt.plot(t,h,'rd-',linewidth=1, label='Impulse response, $h(t)$');
plt.plot(t,result,'b-',linewidth=3, label='Output signal, $y(t)$');
plt.xlabel('t')
plt.grid()
legend = plt.legend(loc='upper left');
t = np.arange(-4.0, 4.0, 0.01)
x = step(t,1) - step(t,3)
h = (t + 2)*(step(t,-2) - step(t,-1))
fig = plt.figure(figsize=(12,4))
plt.subplot(1, 2, 1)
plt.plot(t,x,'g-',linewidth=5);
plt.title('Input signal, $x(t)$')
plt.xlabel('t')
plt.subplot(1, 2, 2)
plt.plot(t,h,'r-',linewidth=3);
plt.title('Impulse response, $h(t)$')
plt.xlabel('t');
t = np.arange(-4.0, 4.0, 0.01)
h = (-t + 2)*(step(t,1) - step(t,2))
fig = plt.figure(figsize=(12,4))
plt.plot(t,h,'r-',linewidth=3);
plt.title('Impulse response, $h(-\u03c4)$ at t = 0')
plt.xlabel('T');
Note: This is the $h(t - \tau)$ at $t = 0$ and the signal starts at $\tau = t + 1$ and ends at $\tau = t + 2$.
t = np.arange(-4.0, 4.0, 0.01)
h_4 = (-t - 2)*(step(t,-3) - step(t,-2))
h_3 = (-t - 1)*(step(t,-2) - step(t,-1))
h_2 = (-t - 0)*(step(t,-1) - step(t,-0))
h_1 = (-t + 1)*(step(t,0) - step(t,1))
fig = plt.figure(figsize=(16,4))
plt.plot(t,h_4,'r-',linewidth=3, label="$t=-4$");
plt.plot(t,h_3,'c-',linewidth=3, label="$t=-3$");
plt.plot(t,h_2,'m-',linewidth=3, label="$t=-2$");
plt.plot(t,h_1,'y-',linewidth=3, label="$t=-1$");
plt.title('Impulse response, $h(-(\u03c4 - t))$ at t = -4,-3,-2,-1, with the input signal, $x(t)$')
plt.plot(t,x,'g-',linewidth=5, label="$x(t)$");
plt.xlabel('T');
legend = plt.legend()
t = np.arange(-4.0, 4.0, 0.01)
h_half = (-t + 1.5)*(step(t,0.5) - step(t,1.5))
fig = plt.figure(figsize=(12,2.5))
ax1 = fig.add_axes([0, 0, 1, 1]) # [left, bottom, width, height]
plt.plot(t,h_half,'r-',linewidth=3, label="$t=0.5$");
plt.title('Impulse response, $h(-(\u03c4 - t))$ at t = -0.5, with the input signal, $x(t)$')
plt.plot(t,x,'g-',linewidth=5, label="$x(t)$");
plt.xlabel('T');
ax1.fill_between(t,0,h_half,where=x>=h_half,color='black')
ax1.annotate('$t + 2$', xy=(1.5, 0), xytext=(1.6, 0.1),
arrowprops=dict(facecolor='yellow', shrink=0.05),
)
ax1.annotate('same \n length \n as \n base', xy=(1, 0.2), xytext=(0.55, 0.2),
arrowprops=dict(facecolor='yellow'),
)
ax1.annotate('t+2-1', xy=(1.25, 0), xytext=(1.1, -0.15),
arrowprops=dict(facecolor='yellow', shrink=0.05),
)
legend = plt.legend()
The overlap starts at $\tau = 1$ and ends at $\tau = t + 2$. Recall that the impulse response ends at $t+2$. Thus,
In the above interval, $x(\tau) = 1$ and $h(t - \tau) = - \tau + t + 2 $.
or $$ y(t) = \dfrac{1}{2} (t + 1)^2$$
Alternatively, this can be evaluated by the triangle area:
t = np.arange(-4.0, 4.0, 0.01)
h_half = (-t + 2.5)*(step(t,1.5) - step(t,2.5))
fig = plt.figure(figsize=(12,2.5))
ax1 = fig.add_axes([0, 0, 1, 1]) # [left, bottom, width, height]
plt.plot(t,h_half,'r-',linewidth=3, label="$h$ at $t=0.5$");
plt.title('Impulse response, $h(-(\u03c4 - t))$ at t = -0.5, with the input signal, $x(t)$')
plt.plot(t,x,'g-',linewidth=5, label="$x(t)$");
plt.xlabel('T');
ax1.fill_between(t,0,h_half,where=x>=h_half,color='black')
legend = plt.legend(loc='center')
ax1.annotate('$t + 2$', xy=(2.5, 0), xytext=(2.6, 0.1),
arrowprops=dict(facecolor='yellow', shrink=0.05),
)
ax1.annotate('$t + 1$', xy=(1.5, 0), xytext=(1.2, 0.1),
arrowprops=dict(facecolor='yellow', shrink=0.05),
);
The overlap starts at $\tau = t + 1$ and ends at $\tau = t + 2$.
In the above interval, $x(\tau) = 1$ and $h(t - \tau) = - \tau + t + 2 $. Thus,
Alternatively, this can be evaluated by the triangle area:
t = np.arange(-4.0, 4.0, 0.01)
h_half = (-t + 3.5)*(step(t,2.5) - step(t,3.5))
fig = plt.figure(figsize=(12,2.5))
ax1 = fig.add_axes([0, 0, 1, 1]) # [left, bottom, width, height]
plt.plot(t,h_half,'r-',linewidth=3, label="$h$ at $t=0.5$");
plt.title('Impulse response, $h(-(\u03c4 - t))$ at t = -0.5, with the input signal, $x(t)$')
plt.plot(t,x,'g-',linewidth=5, label="$x(t)$");
plt.xlabel('T');
ax1.fill_between(t,0,h_half,where=x>=h_half,color='black')
legend = plt.legend(loc='center')
ax1.annotate('$t + 1$', xy=(2.5, 0), xytext=(2.2, 0.1),
arrowprops=dict(facecolor='yellow', shrink=0.05),
);
The overlap starts at $\tau = t + 1$ and ends at $\tau = 3$.
In the above interval, $x(\tau) = 1$ and $h(t - \tau) = - \tau + t + 2 $. Thus,
$$ y(t) = \int_{t+1}^{3} (1) (- \tau + t + 2) \, d\tau $$$$ y(t) = \left. (t + 2) \tau - \dfrac{\tau^2}{2} \right |_{t+1}^{3} $$$$ y(t) = \left((t + 2)(3) - \dfrac{(3)^2}{2}\right) - \left((t + 2)(t + 1) - \dfrac{(t+1)^2}{2}\right) $$or
$$ y(t) = t (1 - \dfrac{t}{2}) $$Alternatively, this can be evaluated by subtracting the smaller triangle area, $A_t$, from the bigger triangle, $A_T$:
t = np.arange(-4.0, 4.0, 0.01)
h_half = (-t + 4)*(step(t,3) - step(t,4))
fig = plt.figure(figsize=(12,2.5))
ax1 = fig.add_axes([0, 0, 1, 1]) # [left, bottom, width, height]
plt.plot(t,h_half,'r-',linewidth=3, label="$h$ at $t=2$");
plt.title('Impulse response, $h(-(\u03c4 - t))$ at t = -0.5, with the input signal, $x(t)$')
plt.plot(t,x,'g-',linewidth=5, label="$x(t)$");
plt.xlabel('T');
ax1.fill_between(t,0,h_half,where=x>=h_half,color='black')
legend = plt.legend(loc='center')
ax1.annotate('No Overlap', xy=(3, 0.4), xytext=(2.2, 0.4),
arrowprops=dict(facecolor='yellow', shrink=0.05),
);
Therefore, the convolution result is:
$$ y(t) = \begin{cases} 0 & \mbox{if } -\infty < t < -1 \\ \frac{1}{2}(t+1)^2 & \mbox{if } -1 < t < 0 \\ \frac{1}{2} & \mbox{if } \, 0 < t < 1 \\ t - \frac{t^2}{2} & \mbox{if } \, 1 < t < 2 \\ 0 & \mbox{if } \, 2 < t < \infty \\ \end{cases} $$t = np.arange(-4.0, 4.0, 0.01)
# input
x = step(t,1) - step(t,3)
# impulse response
h = (t + 2)*(step(t,-2) - step(t,-1))
# result
result = np.zeros(len(t))
result = 0.5*(t+1)**2 * (step(t,-1)-step(t,0)) + 0.5* (step(t,0)-step(t,1)) + t * (1 - 0.5*t) * (step(t,1)-step(t,2))
fig = plt.figure(figsize=(14,4))
plt.plot(t,x,'g-',linewidth=5, label='Input signal, $x(t)$');
plt.plot(t,h,'r-',linewidth=3, label='Impulse response, $h(t)$');
plt.plot(t,result,'b-',linewidth=3, label='Output signal, $y(t)$');
plt.xlabel('t')
plt.grid()
legend = plt.legend(loc='upper left');
t = np.arange(-2.0, 2.0, 0.01)
x = step(t,0) - step(t,1)
h = (-t + 1)*(step(t,0) - step(t,1))
fig = plt.figure(figsize=(15,3))
plt.subplot(1, 2, 1)
plt.plot(t,x,'g-',linewidth=5);
plt.title('Input signal, $x(t)$')
plt.xlabel('t')
plt.subplot(1, 2, 2)
plt.plot(t,h,'r-',linewidth=3);
plt.title('Impulse response, $h(t)$')
plt.xlabel('t');
Note: In this exercise, the signal is time-reversed.
t = np.arange(-2.0, 2.0, 0.01)
x = step(t,-1) - step(t,0)
fig = plt.figure(figsize=(12,3))
ax1 = fig.add_axes([0, 0, 1, 1]) # [left, bottom, width, height]
plt.plot(t,x,'g-',linewidth=5);
plt.title('Time-reversed input signal, $x(t-\u03c4)$')
plt.xlabel('T');
ax1.annotate('$t$', xy=(0, 0), xytext=(0.1, 0.1),
arrowprops=dict(facecolor='yellow', shrink=0.05),
);
ax1.annotate('$t-1$', xy=(-1, 0), xytext=(-1.2, 0.1),
arrowprops=dict(facecolor='yellow', shrink=0.05),
);
Note: This rectangular pulse begins at $\tau = t-1$ and ends at $\tau = t$.
t = np.arange(-2.0, 2.0, 0.01)
x_0 = step(t,-1) - step(t,0)
x__5 = step(t,-1.5) - step(t,-0.5)
x_1 = step(t,-2) - step(t,-1)
h = (-t + 1)*(step(t,0) - step(t,1))
fig = plt.figure(figsize=(12,3))
ax1 = fig.add_axes([1, 0, 1, 1]) # [left, bottom, width, height]
plt.plot(t,x_1,'cd-.',linewidth=5, label="x at $t=-1$");
plt.plot(t,x__5,'m--',linewidth=5, label="x at $t=-0.5$");
plt.plot(t,x_0,'g-',linewidth=3, label="x at $t=0$");
plt.title('Time-reversed input signal, $x(t-\tau)$ with the Impulse response, $h(t)$')
plt.plot(t,h,'r-',linewidth=3, label="h(t)");
plt.xlabel('T');
legend = plt.legend(loc='upper right');
t = np.arange(-2.0, 2.0, 0.01)
x = step(t,-0.5) - step(t,0.5)
h = (-t + 1)*(step(t,0) - step(t,1))
fig = plt.figure(figsize=(12,3))
ax1 = fig.add_axes([1, 0, 1, 1]) # [left, bottom, width, height]
plt.plot(t,x,'g-',linewidth=5, label="x at $t=0.5$");
plt.title('Time-reversed input signal, $x(t-T)$ with the Impulse response, $h(t)$')
plt.plot(t,h,'r-',linewidth=3, label="h");
plt.xlabel('T');
ax1.annotate('$t$', xy=(0.5, 0), xytext=(0.6, 0.15),
arrowprops=dict(facecolor='yellow', shrink=0.05),
);
ax1.fill_between(t,0,h,where=x>=h,color='black')
legend = plt.legend(loc='upper right');
The overlap starts at $\tau = 0$ and ends at $\tau = t$. Thus,
In the above interval, $x(t -\tau) = 1$ and $h(\tau) = -\tau + 1 $.
or $$ y(t) = t ( 1 - \dfrac{t}{2}) $$
t = np.arange(-2.0, 2.0, 0.01)
x = step(t,0) - step(t,1)
h = (-t + 1)*(step(t,0) - step(t,1))
fig = plt.figure(figsize=(12,3))
ax1 = fig.add_axes([1, 0, 1, 1]) # [left, bottom, width, height]
plt.plot(t,x,'g-',linewidth=5, label="x at $t=0.5$");
plt.title('Time-reversed input signal, $x(t-T)$ with the Impulse response, $h(t)$')
plt.plot(t,h,'r-',linewidth=3, label="h");
plt.xlabel('T');
ax1.annotate('$t$', xy=(1, 0), xytext=(1.1, 0.15),
arrowprops=dict(facecolor='yellow', shrink=0.05),
);
ax1.annotate('$t-1$', xy=(0, 0), xytext=(-0.2, 0.15),
arrowprops=dict(facecolor='yellow', shrink=0.05),
);
ax1.fill_between(t,0,h,where=x>=h,color='black')
legend = plt.legend(loc='upper right');
at $t = 1$, $$ y(t) = (h \ast x)(t) = \int_{0}^{1} h(\tau)x(t - \tau) \, d\tau = \dfrac{3}{2} - 1 = \dfrac{1}{2}$$
t = np.arange(-2.0, 2.0, 0.01)
x = step(t,0.5) - step(t,1.5)
h = (-t + 1)*(step(t,0) - step(t,1))
fig = plt.figure(figsize=(12,3))
ax1 = fig.add_axes([1, 0, 1, 1]) # [left, bottom, width, height]
plt.plot(t,x,'g-',linewidth=5, label="x at $t=1.5$");
plt.title('Time-reversed input signal, $x(t-T)$ with the Impulse response, $h(t)$')
plt.plot(t,h,'r-',linewidth=3, label="h");
plt.xlabel('T');
ax1.annotate('$t-1$', xy=(0.5, 0), xytext=(0.3, 0.15),
arrowprops=dict(facecolor='yellow', shrink=0.05),
);
ax1.fill_between(t,0,h,where=x>=h,color='black')
legend = plt.legend(loc='upper right');
t = np.arange(-2.0, 2.0, 0.01)
x = step(t,1) - step(t,2)
h = (-t + 1)*(step(t,0) - step(t,1))
fig = plt.figure(figsize=(12,3))
ax1 = fig.add_axes([1, 0, 1, 1]) # [left, bottom, width, height]
plt.plot(t,x,'g-',linewidth=3, label="x at $t=2$");
plt.title('Time-reversed input signal, $x(t-T)$ with the Impulse response, $h(t)$')
plt.plot(t,h,'r-',linewidth=3, label="h");
plt.xlabel('T');
legend = plt.legend(loc='upper right');
Therefore, the convolution result is:
$$ y(t) = \begin{cases} 0 & \mbox{if } -\infty < t < 0 \\ t ( 1 - \frac{t}{2}) & \mbox{if } 0 < t < 1 \\ \frac{1}{2} & \mbox{if } \, t = 1 \\ \frac{t^2}{2} - 2t + 2 & \mbox{if } \, 1 < t < 2 \\ 0 & \mbox{if } \, 2 < t < \infty \\ \end{cases} $$t = np.arange(-4.0, 4.0, 0.01)
# input
x = step(t,0) - step(t,1)
# impulse response
h = (-t + 1)*(step(t,0) - step(t,1))
# result
result = np.zeros(len(t))
result = t * (1 - 0.5*t) * (step(t,0) - step(t,1)) + (0.5*t*t - 2*t + 2)*(step(t,1) - step(t,2))
fig = plt.figure(figsize=(16,4))
plt.plot(t,x,'g-',linewidth=5, label='Input signal, $x(t)$');
plt.plot(t,h,'r-',linewidth=3, label='Impulse response, $h(t)$');
plt.plot(t,result,'b-',linewidth=3, label='Output signal, $y(t)$');
plt.xlabel('t')
plt.grid()
legend = plt.legend(loc='upper left');
By: Melvin Cabatuan melvincabatuan@gmail.com
This ipython notebook is licensed under the CC-BY-NC-SA license: http://creativecommons.org/licenses/by-nc-sa/4.0/
References:
[1] Weisstein, Eric W. "Convolution." From MathWorld--A Wolfram Web Resource. http://mathworld.wolfram.com/Convolution.html
[2] Notes from Prof. Alan Oppenheim. http://ocw.mit.edu/resources/res-6-007-signals-and-systems-spring-2011/