In [1]:
 

$$\require{color} \require{cancel} \def\tf#1{{\mathrm{FT}\left\{ #1 \right\}}} \def\flecheTF{\rightleftharpoons } \def\TFI#1#2#3{{\displaystyle{\int_{-\infty}^{+\infty} #1 ~e^{j2\pi #2 #3} ~\dr{#2}}}} \def\TF#1#2#3{{\displaystyle{\int_{-\infty}^{+\infty} #1 ~e^{-j2\pi #3 #2} ~\dr{#2}}}} \def\sha{ш} \def\dr#1{\mathrm{d}#1} \def\egalpardef{\mathop{=}\limits^\triangle} \def\sinc#1{{\mathrm{sinc}\left( #1 \right)}} \def\rect{\mathrm{rect}} \definecolor{lightred}{rgb}{1,0.1,0} \def\myblueeqbox#1{{\fcolorbox{blue}{lightblue}{$ extcolor{blue}{ #1}$}}} \def\myeqbox#1#2{{\fcolorbox{#1}{light#1}{$ extcolor{#1}{ #2}$}}} \def\eqbox#1#2#3#4{{\fcolorbox{#1}{#2}{$\textcolor{#3}{ #4}$}}} % border|background|text \def\eqboxa#1{{\boxed{#1}}} \def\eqboxb#1{{\eqbox{green}{white}{green}{#1}}} \def\eqboxc#1{{\eqbox{blue}{white}{blue}{#1}}} \def\eqboxd#1{{\eqbox{blue}{lightblue}{blue}{#1}}} \def\E#1{\mathbb{E}\left[#1\right]} \def\ta#1{\left<#1\right>} \def\egalparerg{{\mathop{=}\limits_\mathrm{erg}}} \def\expo#1{\exp\left(#1\right)} \def\d#1{\mathrm{d}#1} \def\wb{\mathbf{w}} \def\sb{\mathbf{s}} \def\xb{\mathbf{x}} \def\Rb{\mathbf{R}} \def\rb{\mathbf{r}} \def\mystar{{*}} \def\ub{\mathbf{u}} \def\wbopt{\mathop{\mathbf{w}}\limits^\triangle} \def\deriv#1#2{\frac{\mathrm{d}#1}{\mathrm{d}#2}} \def\Ub{\mathbf{U}} \def\db{\mathbf{d}} \def\eb{\mathbf{e}} \def\vb{\mathbf{v}} \def\Ib{\mathbf{I}} \def\Vb{\mathbf{V}} \def\Lambdab{\mathbf{\Lambda}} \def\Ab{\mathbf{A}} \def\Bb{\mathbf{B}} \def\Cb{\mathbf{C}} \def\Db{\mathbf{D}} \def\Kb{\mathbf{K}} \def\sinc#1{\mathrm{sinc\left(#1\right)}} $$


A basic introduction to filtering

Through examples, we define several operations on signals and show how they transform them. Then we define what is a filter and the notion of impulse response.

Transformations of signals - Examples of difference equations

We begin by defining a test signal.

In [2]:
# rectangular pulse
N=20; L=5; M=10
r=np.zeros(N)

r[L:M]=1
#
plt.stem(r)
_=plt.ylim([0, 1.2])
In [3]:
def op1(signal):
    transformed_signal=np.zeros(np.size(signal))
    for t in np.arange(np.size(signal)):
        transformed_signal[t]=signal[t]-signal[t-1]
    return transformed_signal    

def op2(signal):
    transformed_signal=np.zeros(np.size(signal))
    for t in np.arange(np.size(signal)):
        transformed_signal[t]=0.5*signal[t]+0.5*signal[t-1]
    return transformed_signal
In [4]:
plt.figure()
plt.stem(op1(r))
_=plt.ylim([-1.2, 1.2])
plt.title("Filtering of rectangular signal with op1")
plt.figure()
plt.stem(op2(r),'r')
_=plt.ylim([-0.2, 1.2])
plt.title("Filtering of rectangular signal with op2")
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-4-e2dbae2047ad> in <module>()
      4 plt.title("Filtering of rectangular signal with op1")
      5 plt.figure()
----> 6 plt.stem(op2(r),'r')
      7 _=plt.ylim([-0.2, 1.2])
      8 plt.title("Filtering of rectangular signal with op2")

/usr/local/lib/python3.5/site-packages/matplotlib/pyplot.py in stem(linefmt, markerfmt, basefmt, bottom, label, data, *args)
   2924         *args, linefmt=linefmt, markerfmt=markerfmt, basefmt=basefmt,
   2925         bottom=bottom, label=label, **({"data": data} if data is not
-> 2926         None else {}))
   2927 
   2928 

/usr/local/lib/python3.5/site-packages/matplotlib/__init__.py in inner(ax, data, *args, **kwargs)
   1808                         "the Matplotlib list!)" % (label_namer, func.__name__),
   1809                         RuntimeWarning, stacklevel=2)
-> 1810             return func(ax, *args, **kwargs)
   1811 
   1812         inner.__doc__ = _add_data_doc(inner.__doc__,

/usr/local/lib/python3.5/site-packages/matplotlib/axes/_axes.py in stem(self, linefmt, markerfmt, basefmt, bottom, label, *args)
   2625         else:
   2626             x = y
-> 2627             y = np.asarray(args[0], dtype=float)
   2628             args = args[1:]
   2629 

/usr/local/lib/python3.5/site-packages/numpy/core/numeric.py in asarray(a, dtype, order)
    499 
    500     """
--> 501     return array(a, dtype, copy=False, order=order)
    502 
    503 

ValueError: could not convert string to float: 'r'

We define a sine wave and check that the operation implemented by "op1" seems to be a derivative...

In [5]:
t=np.linspace(0,100,500)
sig=np.sin(2*pi*0.05*t)
plt.plot(t,sig, label="Initial signal")
plt.plot(t,5/(2*pi*0.05)*op1(sig), label="Filtered signal")
plt.legend()
Out[5]:
<matplotlib.legend.Legend at 0x7fdb1b34a0b8>

Composition of operations:

In [6]:
plt.stem(op1(op2(r)),'r')
_=plt.ylim([-1.2, 1.2])
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-6-96c17cc23118> in <module>()
----> 1 plt.stem(op1(op2(r)),'r')
      2 _=plt.ylim([-1.2, 1.2])

/usr/local/lib/python3.5/site-packages/matplotlib/pyplot.py in stem(linefmt, markerfmt, basefmt, bottom, label, data, *args)
   2924         *args, linefmt=linefmt, markerfmt=markerfmt, basefmt=basefmt,
   2925         bottom=bottom, label=label, **({"data": data} if data is not
-> 2926         None else {}))
   2927 
   2928 

/usr/local/lib/python3.5/site-packages/matplotlib/__init__.py in inner(ax, data, *args, **kwargs)
   1808                         "the Matplotlib list!)" % (label_namer, func.__name__),
   1809                         RuntimeWarning, stacklevel=2)
-> 1810             return func(ax, *args, **kwargs)
   1811 
   1812         inner.__doc__ = _add_data_doc(inner.__doc__,

/usr/local/lib/python3.5/site-packages/matplotlib/axes/_axes.py in stem(self, linefmt, markerfmt, basefmt, bottom, label, *args)
   2625         else:
   2626             x = y
-> 2627             y = np.asarray(args[0], dtype=float)
   2628             args = args[1:]
   2629 

/usr/local/lib/python3.5/site-packages/numpy/core/numeric.py in asarray(a, dtype, order)
    499 
    500     """
--> 501     return array(a, dtype, copy=False, order=order)
    502 
    503 

ValueError: could not convert string to float: 'r'
In [7]:
def op3(signal):
    transformed_signal=np.zeros(np.size(signal))
    for t in np.arange(np.size(signal)):
        transformed_signal[t]= 0.7*transformed_signal[t-1]+signal[t]
    return transformed_signal

plt.stem(op3(r),'r')
plt.title("Filtering of rectangular signal with op3")
_=plt.ylim([-0.2, 3.2])
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-7-3cf0c745df68> in <module>()
      5     return transformed_signal
      6 
----> 7 plt.stem(op3(r),'r')
      8 plt.title("Filtering of rectangular signal with op3")
      9 _=plt.ylim([-0.2, 3.2])

/usr/local/lib/python3.5/site-packages/matplotlib/pyplot.py in stem(linefmt, markerfmt, basefmt, bottom, label, data, *args)
   2924         *args, linefmt=linefmt, markerfmt=markerfmt, basefmt=basefmt,
   2925         bottom=bottom, label=label, **({"data": data} if data is not
-> 2926         None else {}))
   2927 
   2928 

/usr/local/lib/python3.5/site-packages/matplotlib/__init__.py in inner(ax, data, *args, **kwargs)
   1808                         "the Matplotlib list!)" % (label_namer, func.__name__),
   1809                         RuntimeWarning, stacklevel=2)
-> 1810             return func(ax, *args, **kwargs)
   1811 
   1812         inner.__doc__ = _add_data_doc(inner.__doc__,

/usr/local/lib/python3.5/site-packages/matplotlib/axes/_axes.py in stem(self, linefmt, markerfmt, basefmt, bottom, label, *args)
   2625         else:
   2626             x = y
-> 2627             y = np.asarray(args[0], dtype=float)
   2628             args = args[1:]
   2629 

/usr/local/lib/python3.5/site-packages/numpy/core/numeric.py in asarray(a, dtype, order)
    499 
    500     """
--> 501     return array(a, dtype, copy=False, order=order)
    502 
    503 

ValueError: could not convert string to float: 'r'

A curiosity

In [8]:
def op4(signal):
    transformed_signal=np.zeros(np.size(signal))
    for t in np.arange(np.size(signal)):
        transformed_signal[t]= 1*transformed_signal[t-1]+signal[t]
    return transformed_signal

plt.stem(op4(r),'r')
plt.title("Filtering of rectangular signal with op4")
_=plt.ylim([-0.2, 5.6])
# And then..
plt.figure()
plt.stem(op1(op4(r)),'r')
plt.title("Filtering of rectangular signal with op1(op4)")
_=plt.ylim([-0.2, 1.2])
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-8-46cc0d896a24> in <module>()
      5     return transformed_signal
      6 
----> 7 plt.stem(op4(r),'r')
      8 plt.title("Filtering of rectangular signal with op4")
      9 _=plt.ylim([-0.2, 5.6])

/usr/local/lib/python3.5/site-packages/matplotlib/pyplot.py in stem(linefmt, markerfmt, basefmt, bottom, label, data, *args)
   2924         *args, linefmt=linefmt, markerfmt=markerfmt, basefmt=basefmt,
   2925         bottom=bottom, label=label, **({"data": data} if data is not
-> 2926         None else {}))
   2927 
   2928 

/usr/local/lib/python3.5/site-packages/matplotlib/__init__.py in inner(ax, data, *args, **kwargs)
   1808                         "the Matplotlib list!)" % (label_namer, func.__name__),
   1809                         RuntimeWarning, stacklevel=2)
-> 1810             return func(ax, *args, **kwargs)
   1811 
   1812         inner.__doc__ = _add_data_doc(inner.__doc__,

/usr/local/lib/python3.5/site-packages/matplotlib/axes/_axes.py in stem(self, linefmt, markerfmt, basefmt, bottom, label, *args)
   2625         else:
   2626             x = y
-> 2627             y = np.asarray(args[0], dtype=float)
   2628             args = args[1:]
   2629 

/usr/local/lib/python3.5/site-packages/numpy/core/numeric.py in asarray(a, dtype, order)
    499 
    500     """
--> 501     return array(a, dtype, copy=False, order=order)
    502 
    503 

ValueError: could not convert string to float: 'r'

Filters

Definition A filter is a time-invariant linear system.

  • Time invariance means that if $y(n)$ is the response associated with an input $x(n)$, then $y(n-n_0)$ is the response associated with the input $x(n-n_0)$.
  • Linearity means that if $y_1(n)$ and $y_2(n)$ are the outputs associated with $x_1(n)$ and $x_2(n)$, then the output associated with $a_1x_1(n)+a_2x_2(n)$ is $a_1y_1(n)+a_2y_2(n)$ (superposition principle)
\begin{exercise} Check whether the following systems are filters or not. - $x(n) \rightarrow 2x(n)$ - $x(n) \rightarrow 2x(n) + 1$ - $x(n) \rightarrow 2x(n)+x(n-1)$ - $x(n) \rightarrow x(n)^2$ \end{exercise}

Notion of impulse response

\begin{definition}\label{def:def0} A Dirac impulse (or impulse for short) is defined by $$ \delta(n) = \begin{cases} 1 &\text{ if } n=0 \\ 0 &\text{ elsewhere} \end{cases} $$ \end{definition}\begin{definition}\label{def:def1} The impulse response of a system is nothing but the output of the system excited by a Dirac impulse. It is often denoted $h(h)$. $$ \delta(n) \rightarrow \text{System} \rightarrow h(n) $$ \end{definition}
In [9]:
def dirac(n):
# dirac function
    return 1 if n==0 else 0
def dirac_vector(N):
    out = np.zeros(N)
    out[0]=1
    return out
In [10]:
d=dirac_vector(20)
fig,ax=plt.subplots(2,2,sharex=True)

ax[0][0].stem(op1(d),  label="Filter 1")
ax[0][0].legend()
ax[0][1].stem(op2(d),  label="Filter 2")
ax[0][1].legend()
ax[1][0].stem(op3(d), label="Filter 3")
ax[1][0].legend()
ax[1][1].stem(op4(d), label="Filter 4")
ax[1][1].legend()
plt.suptitle("Impulse responses")
Out[10]:
Text(0.5, 0.98, 'Impulse responses')

Curiosity (continued)

The impulse response of op4(op1) is given by

In [11]:
h=op4(op1(dirac_vector(20)))
plt.stem(h, label="Filter 4(1)")
_=plt.axis([-5, 20, 0, 1.2])

This is nothing but a Dirac impulse! We already observed that op4(op1(signal))=signal; that is the filter is an identity transformation. In other words, op4 acts as the "inverse" of op1. Finally, we note that the impulse response of the indentity filter is a Dirac impulse.