Blame doc/filter.rst

Packit 67cb25
*****************
Packit 67cb25
Digital Filtering
Packit 67cb25
*****************
Packit 67cb25
Packit 67cb25
Introduction
Packit 67cb25
============
Packit 67cb25
Packit 67cb25
The filters discussed in this chapter are based on the following moving data
Packit 67cb25
window which is centered on :math:`i`-th sample:
Packit 67cb25
Packit 67cb25
.. only:: not texinfo
Packit 67cb25
Packit 67cb25
   .. math:: W_i^H = \left\{ x_{i-H}, \dots, x_i, \dots, x_{i+H} \right\}
Packit 67cb25
Packit 67cb25
.. only:: texinfo
Packit 67cb25
Packit 67cb25
   ::
Packit 67cb25
Packit 67cb25
      W_i^H = { x_{i-H}, ..., x_i, ..., x_{i+H} }
Packit 67cb25
Packit 67cb25
Here, :math:`H` is a non-negative integer called the *window half-length*, which
Packit 67cb25
represents the number of samples before and after sample :math:`i`.
Packit 67cb25
The total window length is :math:`K = 2 H + 1`.
Packit 67cb25
Packit 67cb25
Handling Endpoints
Packit 67cb25
==================
Packit 67cb25
Packit 67cb25
When processing samples near the ends of the input signal, there will not
Packit 67cb25
be enough samples to fill the window :math:`W_i^H` defined above.
Packit 67cb25
Therefore the user must specify how to construct the windows near the end points.
Packit 67cb25
This is done by passing an input argument of type :type:`gsl_filter_end_t`:
Packit 67cb25
Packit 67cb25
.. type:: gsl_filter_end_t
Packit 67cb25
Packit 67cb25
   This data type specifies how to construct windows near end points and can
Packit 67cb25
   be selected from the following choices:
Packit 67cb25
Packit 67cb25
   .. macro:: GSL_FILTER_END_PADZERO
Packit 67cb25
Packit 67cb25
      With this option, a full window of length :math:`K` will be constructed
Packit 67cb25
      by inserting zeros into the window near the signal end points. Effectively,
Packit 67cb25
      the input signal is modified to
Packit 67cb25
Packit 67cb25
      .. only:: not texinfo
Packit 67cb25
Packit 67cb25
         .. math:: \tilde{x} = \{ \underbrace{0, \dots, 0}_{H \textrm{ zeros}}, x_1, x_2, \dots, x_{n-1}, x_n, \underbrace{0, \dots, 0}_{H \textrm{ zeros} } \}
Packit 67cb25
Packit 67cb25
      .. only:: texinfo
Packit 67cb25
Packit 67cb25
         ::
Packit 67cb25
Packit 67cb25
            x~ = { 0, ..., 0, x_1, x_2, ..., x_{n-1}, x_n, 0, ..., 0 }
Packit 67cb25
Packit 67cb25
      to ensure a well-defined window for all :math:`x_i`.
Packit 67cb25
Packit 67cb25
   .. macro:: GSL_FILTER_END_PADVALUE
Packit 67cb25
Packit 67cb25
      With this option, a full window of length :math:`K` will be constructed
Packit 67cb25
      by padding the window with the first and last sample in the input signal.
Packit 67cb25
      Effectively, the input signal is modified to
Packit 67cb25
Packit 67cb25
      .. only:: not texinfo
Packit 67cb25
Packit 67cb25
         .. math:: \tilde{x} = \{ \underbrace{x_1, \dots, x_1}_{H}, x_1, x_2, \dots, x_{n-1}, x_n, \underbrace{x_n, \dots, x_n}_{H} \}
Packit 67cb25
Packit 67cb25
      .. only:: texinfo
Packit 67cb25
Packit 67cb25
         ::
Packit 67cb25
Packit 67cb25
            x~ = { x_1, ..., x_1, x_1, x_2, ..., x_{n-1}, x_n, x_n, ..., x_n }
Packit 67cb25
Packit 67cb25
   .. macro:: GSL_FILTER_END_TRUNCATE
Packit 67cb25
Packit 67cb25
      With this option, no padding is performed, and the windows are simply truncated
Packit 67cb25
      as the end points are approached.
Packit 67cb25
Packit 67cb25
Linear Digital Filters
Packit 67cb25
======================
Packit 67cb25
Packit 67cb25
Gaussian Filter
Packit 67cb25
---------------
Packit 67cb25
Packit 67cb25
The Gaussian filter convolves the input signal with a Gaussian kernel or window. This filter
Packit 67cb25
is often used as a smoothing or noise reduction filter. The Gaussian kernel is
Packit 67cb25
defined by
Packit 67cb25
Packit 67cb25
.. only:: not texinfo
Packit 67cb25
Packit 67cb25
   .. math:: G(k) = e^{-\frac{1}{2} \left( \alpha \frac{k}{(K-1)/2} \right)^2} = e^{-k^2/2\sigma^2}
Packit 67cb25
Packit 67cb25
.. only:: texinfo
Packit 67cb25
Packit 67cb25
   ::
Packit 67cb25
Packit 67cb25
      G(k) = e^{-1/2 ( \alpha k/((K-1)/2) )^2} = e^{-k^2/2\sigma^2}
Packit 67cb25
Packit 67cb25
for :math:`-(K-1)/2 \le k \le (K-1)/2`, and :math:`K` is the size of the kernel. The
Packit 67cb25
parameter :math:`\alpha` specifies the number of standard deviations :math:`\sigma` desired
Packit 67cb25
in the kernel. So for example setting :math:`\alpha = 3` would define a Gaussian window
Packit 67cb25
of length :math:`K` which spans :math:`\pm 3 \sigma`. It is often more convenient to specify
Packit 67cb25
the parameter :math:`\alpha` rather than the standard deviation :math:`\sigma` when constructing
Packit 67cb25
the kernel, since a fixed value of :math:`\alpha` would correspond to the same shape of
Packit 67cb25
Gaussian regardless of the size :math:`K`. The appropriate value of the standard deviation
Packit 67cb25
depends on :math:`K` and is related to :math:`\alpha` as
Packit 67cb25
Packit 67cb25
.. only:: not texinfo
Packit 67cb25
Packit 67cb25
   .. math:: \sigma = \frac{K - 1}{2\alpha}
Packit 67cb25
Packit 67cb25
.. only:: texinfo
Packit 67cb25
Packit 67cb25
   ::
Packit 67cb25
Packit 67cb25
      \sigma = (K - 1)/(2 \alpha)
Packit 67cb25
Packit 67cb25
The routines below accept :math:`\alpha` as an input argument instead of :math:`\sigma`.
Packit 67cb25
Packit 67cb25
The Gaussian filter offers a convenient way of differentiating and smoothing an input signal
Packit 67cb25
in a single pass. Using the derivative property of a convolution,
Packit 67cb25
Packit 67cb25
.. only:: not texinfo
Packit 67cb25
Packit 67cb25
   .. math:: \frac{d}{dt} \left( G * x \right) = \frac{dG}{dt} * x
Packit 67cb25
Packit 67cb25
.. only:: texinfo
Packit 67cb25
Packit 67cb25
   ::
Packit 67cb25
Packit 67cb25
      d/dt ( G * x ) = dG/dt * x
Packit 67cb25
Packit 67cb25
the input signal :math:`x(t)` can be smoothed and differentiated at the same time by
Packit 67cb25
convolution with a derivative Gaussian kernel, which can be readily computed from the
Packit 67cb25
analytic expression above. The same principle applies to higher order derivatives.
Packit 67cb25
Packit 67cb25
.. function:: gsl_filter_gaussian_workspace * gsl_filter_gaussian_alloc(const size_t K)
Packit 67cb25
Packit 67cb25
   This function initializes a workspace for Gaussian filtering using a kernel of
Packit 67cb25
   size :data:`K`. Here, :math:`H = K / 2`. If :math:`K` is even, it is rounded up to the next
Packit 67cb25
   odd integer to ensure a symmetric window. The size of the workspace is :math:`O(K)`.
Packit 67cb25
Packit 67cb25
.. function:: void gsl_filter_gaussian_free(gsl_filter_gaussian_workspace * w)
Packit 67cb25
Packit 67cb25
   This function frees the memory associated with :data:`w`.
Packit 67cb25
Packit 67cb25
.. function:: int gsl_filter_gaussian(const gsl_filter_end_t endtype, const double alpha, const size_t order, const gsl_vector * x, gsl_vector * y, gsl_filter_gaussian_workspace * w)
Packit 67cb25
Packit 67cb25
   This function applies a Gaussian filter parameterized by :data:`alpha` to the input vector :data:`x`,
Packit 67cb25
   storing the output in :data:`y`. The derivative order is specified by :data:`order`, with
Packit 67cb25
   :code:`0` corresponding to a Gaussian, :code:`1` corresponding to a first derivative
Packit 67cb25
   Gaussian, and so on. The parameter :data:`endtype` specifies how the signal end points are handled.
Packit 67cb25
   It is allowed for :data:`x` = :data:`y` for an in-place filter.
Packit 67cb25
Packit 67cb25
.. function:: int gsl_filter_gaussian_kernel(const double alpha, const size_t order, const int normalize, gsl_vector * kernel)
Packit 67cb25
Packit 67cb25
   This function constructs a Gaussian kernel parameterized by :data:`alpha` and
Packit 67cb25
   stores the output in :data:`kernel`. The parameter :data:`order` specifies the
Packit 67cb25
   derivative order, with :code:`0` corresponding to a Gaussian, :code:`1` corresponding
Packit 67cb25
   to a first derivative Gaussian, and so on. If :data:`normalize` is set to :code:`1`, then
Packit 67cb25
   the kernel will be normalized to sum to one on output. If :data:`normalize` is set to
Packit 67cb25
   :code:`0`, no normalization is performed.
Packit 67cb25
Packit 67cb25
Nonlinear Digital Filters
Packit 67cb25
=========================
Packit 67cb25
Packit 67cb25
The nonlinear digital filters described below are based on the window median, which is given
Packit 67cb25
by
Packit 67cb25
Packit 67cb25
.. only:: not texinfo
Packit 67cb25
Packit 67cb25
   .. math:: m_i = \textrm{median} \left\{ W_i^H \right\} = \textrm{median} \left\{ x_{i-H}, \dots, x_i, \dots, x_{i+H} \right\}
Packit 67cb25
Packit 67cb25
.. only:: texinfo
Packit 67cb25
Packit 67cb25
   ::
Packit 67cb25
Packit 67cb25
      m_i = median { W_i^H } = median { x_{i-H}, ..., x_i, ..., x_{i+H} }
Packit 67cb25
Packit 67cb25
The median is considered robust to local outliers, unlike the mean.
Packit 67cb25
Median filters can preserve sharp edges while at the same removing signal noise, and are used
Packit 67cb25
in a wide range of applications.
Packit 67cb25
Packit 67cb25
Standard Median Filter
Packit 67cb25
----------------------
Packit 67cb25
Packit 67cb25
The *standard median filter* (SMF) simply replaces the sample :math:`x_i` by the median
Packit 67cb25
:math:`m_i` of the window :math:`W_i^H`: This filter has one tuning parameter given
Packit 67cb25
by :math:`H`. The standard median filter is considered highly resistant to
Packit 67cb25
local outliers and local noise in the data sequence :math:`\{x_i\}`.
Packit 67cb25
Packit 67cb25
.. function:: gsl_filter_median_workspace * gsl_filter_median_alloc(const size_t K)
Packit 67cb25
Packit 67cb25
   This function initializes a workspace for standard median filtering using a symmetric centered moving window of
Packit 67cb25
   size :data:`K`. Here, :math:`H = K / 2`. If :math:`K` is even, it is rounded up to the next
Packit 67cb25
   odd integer to ensure a symmetric window. The size of the workspace is :math:`O(7K)`.
Packit 67cb25
Packit 67cb25
.. function:: void gsl_filter_median_free(gsl_filter_median_workspace * w)
Packit 67cb25
Packit 67cb25
   This function frees the memory associated with :data:`w`.
Packit 67cb25
Packit 67cb25
.. function:: int gsl_filter_median(const gsl_filter_end_t endtype, const gsl_vector * x, gsl_vector * y, gsl_filter_median_workspace * w)
Packit 67cb25
Packit 67cb25
   This function applies a standard median filter to the input :data:`x`, storing the output in :data:`y`.
Packit 67cb25
   The parameter :data:`endtype` specifies how the signal end points are handled. It
Packit 67cb25
   is allowed to have :data:`x` = :data:`y` for an in-place filter.
Packit 67cb25
Packit 67cb25
Recursive Median Filter
Packit 67cb25
-----------------------
Packit 67cb25
Packit 67cb25
The *recursive median filter* (RMF) is a modification of the SMF to include previous filter outputs
Packit 67cb25
in the window before computing the median. The filter's response is
Packit 67cb25
Packit 67cb25
.. only:: not texinfo
Packit 67cb25
Packit 67cb25
   .. math:: y_i = \textrm{median} \left( y_{i-H}, \dots, y_{i-1}, x_i, x_{i+1}, \dots, x_{i+H} \right)
Packit 67cb25
Packit 67cb25
.. only:: texinfo
Packit 67cb25
Packit 67cb25
   ::
Packit 67cb25
Packit 67cb25
      y_i = median ( y_{i-H}, ..., y_{i-1}, x_i, x_{i+1}, ..., x_{i+H} )
Packit 67cb25
Packit 67cb25
Sometimes, the SMF must be applied several times in a row to achieve adequate smoothing (i.e. a cascade filter).
Packit 67cb25
The RMF, on the other hand, converges to a *root sequence* in one pass,
Packit 67cb25
and can sometimes provide a smoother result than several passes of the SMF. A root sequence is an input which is
Packit 67cb25
left unchanged by the filter.  So there is no need to apply a recursive median filter twice to an input vector.
Packit 67cb25
Packit 67cb25
.. function:: gsl_filter_rmedian_workspace * gsl_filter_rmedian_alloc(const size_t K)
Packit 67cb25
Packit 67cb25
   This function initializes a workspace for recursive median filtering using a symmetric centered moving window of
Packit 67cb25
   size :data:`K`. Here, :math:`H = K / 2`. If :math:`K` is even, it is rounded up to the next
Packit 67cb25
   odd integer to ensure a symmetric window. The size of the workspace is :math:`O(K)`.
Packit 67cb25
Packit 67cb25
.. function:: void gsl_filter_rmedian_free(gsl_filter_rmedian_workspace * w)
Packit 67cb25
Packit 67cb25
   This function frees the memory associated with :data:`w`.
Packit 67cb25
Packit 67cb25
.. function:: int gsl_filter_rmedian(const gsl_filter_end_t endtype, const gsl_vector * x, gsl_vector * y, gsl_filter_rmedian_workspace * w)
Packit 67cb25
Packit 67cb25
   This function applies a recursive median filter to the input :data:`x`, storing the output in :data:`y`.
Packit 67cb25
   The parameter :data:`endtype` specifies how the signal end points are handled. It
Packit 67cb25
   is allowed to have :data:`x` = :data:`y` for an in-place filter.
Packit 67cb25
Packit 67cb25
Impulse Detection Filter
Packit 67cb25
------------------------
Packit 67cb25
Packit 67cb25
Impulsive noise is characterized by short sequences of data points distinct from those in the
Packit 67cb25
surrounding neighborhood. This section describes a powerful class of filters, also known as
Packit 67cb25
*impulse rejection filters* and *decision-based filters*, designed to detect and remove such outliers from data.
Packit 67cb25
The filter's response is given by
Packit 67cb25
Packit 67cb25
.. only:: not texinfo
Packit 67cb25
Packit 67cb25
   .. math:: y_i = \left\{
Packit 67cb25
                     \begin{array}{cc}
Packit 67cb25
                       x_i, & |x_i - m_i| \le t S_i \\
Packit 67cb25
                       m_i, & |x_i - m_i| > t S_i
Packit 67cb25
                     \end{array}
Packit 67cb25
                   \right.
Packit 67cb25
Packit 67cb25
.. only:: texinfo
Packit 67cb25
Packit 67cb25
   ::
Packit 67cb25
Packit 67cb25
      y_i = { x_i, |x_i - m_i| <= t * S_i
Packit 67cb25
            { m_i, |x_i - m_i| > t * S_i
Packit 67cb25
Packit 67cb25
where :math:`m_i` is the median value of the window :math:`W_i^H`, :math:`S_i` is a robust estimate
Packit 67cb25
of the scatter or dispersion for the window :math:`W_i^H`, and :math:`t` is a tuning parameter specifying
Packit 67cb25
the number of scale factors needed to determine that a point is an outlier. The main idea is that the median
Packit 67cb25
:math:`m_i` will be unaffected by a small number of outliers in the window, and so a given
Packit 67cb25
sample :math:`x_i` is tested to determine how far away it is from the median in terms of the local
Packit 67cb25
scale estimate :math:`S_i`. Samples which are more than :math:`t` scale estimates away from the median
Packit 67cb25
are labeled as outliers and replaced by the window median :math:`m_i`. Samples which are less than
Packit 67cb25
:math:`t` scale estimates from the median are left unchanged by the filter.
Packit 67cb25
Packit 67cb25
Note that when :math:`t = 0`, the impulse detection filter is equivalent to the standard median filter. When
Packit 67cb25
:math:`t \rightarrow \infty`, it becomes the identity filter. This means the impulse detection filter can
Packit 67cb25
be viewed as a "less aggressive" version of the standard median filter, becoming less aggressive as :math:`t` is
Packit 67cb25
increased. Note that this filter modifies only samples identified as outliers, while the standard median
Packit 67cb25
filter changes all samples to the local median, regardless of whether they are outliers. This fact, plus
Packit 67cb25
the additional flexibility offered by the additional tuning parameter :math:`t` can make the impulse detection filter
Packit 67cb25
a better choice for some applications.
Packit 67cb25
Packit 67cb25
It is important to have a robust and accurate scale estimate :math:`S_i` in order to
Packit 67cb25
detect impulse outliers even in the presence of noise. The window standard deviation is not
Packit 67cb25
typically a good choice, as it can be significantly perturbed by the presence of even one outlier.
Packit 67cb25
GSL offers the following choices (specified by a parameter of type :type:`gsl_filter_scale_t`) for
Packit 67cb25
computing the scale estimate :math:`S_i`, all of which are robust to the presence of impulse outliers.
Packit 67cb25
Packit 67cb25
.. type:: gsl_filter_scale_t
Packit 67cb25
Packit 67cb25
   This type specifies how the scale estimate :math:`S_i` of the window :math:`W_i^H` is calculated.
Packit 67cb25
Packit 67cb25
   .. macro:: GSL_FILTER_SCALE_MAD
Packit 67cb25
Packit 67cb25
      This option specifies the median absolute deviation (MAD) scale estimate, defined by
Packit 67cb25
Packit 67cb25
      .. only:: not texinfo
Packit 67cb25
Packit 67cb25
         .. math:: S_i = 1.4826 \times \textrm{median} \left\{ | W_i^H - m_i | \right\}
Packit 67cb25
Packit 67cb25
      .. only:: texinfo
Packit 67cb25
Packit 67cb25
         ::
Packit 67cb25
Packit 67cb25
            S_i = 1.4826 median { | W_i^H - m_i | }
Packit 67cb25
Packit 67cb25
      This choice of scale estimate is also known as the *Hampel filter* in the statistical literature.
Packit 67cb25
      See :ref:`here <sec_mad-statistic>` for more information.
Packit 67cb25
Packit 67cb25
   .. macro:: GSL_FILTER_SCALE_IQR
Packit 67cb25
Packit 67cb25
      This option specifies the interquartile range (IQR) scale estimate, defined as the difference between
Packit 67cb25
      the 75th and 25th percentiles of the window :math:`W_i^H`,
Packit 67cb25
Packit 67cb25
      .. only:: not texinfo
Packit 67cb25
Packit 67cb25
         .. math:: S_i = 0.7413 \left( Q_{0.75} - Q_{0.25} \right)
Packit 67cb25
Packit 67cb25
      .. only:: texinfo
Packit 67cb25
Packit 67cb25
         ::
Packit 67cb25
Packit 67cb25
            S_i = 0.7413 ( Q_{0.75} - Q_{0.25} )
Packit 67cb25
Packit 67cb25
      where :math:`Q_p` is the p-quantile of the window :math:`W_i^H`. The idea is to throw away the largest
Packit 67cb25
      and smallest 25% of the window samples (where the outliers would be), and estimate a scale from the middle 50%.
Packit 67cb25
      The factor :math:`0.7413` provides an unbiased estimate of the standard deviation for Gaussian data.
Packit 67cb25
Packit 67cb25
   .. macro:: GSL_FILTER_SCALE_SN
Packit 67cb25
Packit 67cb25
      This option specifies the so-called :math:`S_n` statistic proposed by Croux and Rousseeuw.
Packit 67cb25
      See :ref:`here <sec_Sn-statistic>` for more information.
Packit 67cb25
Packit 67cb25
   .. macro:: GSL_FILTER_SCALE_QN
Packit 67cb25
Packit 67cb25
      This option specifies the so-called :math:`Q_n` statistic proposed by Croux and Rousseeuw.
Packit 67cb25
      See :ref:`here <sec_Qn-statistic>` for more information.
Packit 67cb25
Packit 67cb25
.. warning::
Packit 67cb25
Packit 67cb25
   While the scale estimates defined above are much less sensitive to outliers than the standard deviation,
Packit 67cb25
   they can suffer from an effect called *implosion*. The standard deviation of a window :math:`W_i^H` will be zero
Packit 67cb25
   if and only if all samples in the window are equal. However, it is possible for the MAD of a window
Packit 67cb25
   to be zero even if all the samples in the window are not equal. For example, if :math:`K/2 + 1` or more
Packit 67cb25
   of the :math:`K` samples in the window are equal to some value :math:`x^{*}`, then the window median will
Packit 67cb25
   be equal to :math:`x^{*}`. Consequently, at least :math:`K/2 + 1` of the absolute deviations
Packit 67cb25
   :math:`|x_j - x^{*}|` will be zero, and so the MAD will be zero. In such a case, the Hampel
Packit 67cb25
   filter will act like the standard median filter regardless of the value of :math:`t`. Caution should also
Packit 67cb25
   be exercised if dividing by :math:`S_i`.
Packit 67cb25
Packit 67cb25
.. function:: gsl_filter_impulse_workspace * gsl_filter_impulse_alloc(const size_t K)
Packit 67cb25
Packit 67cb25
   This function initializes a workspace for impulse detection filtering using a symmetric moving window of
Packit 67cb25
   size :data:`K`. Here, :math:`H = K / 2`. If :math:`K` is even, it is rounded up to the next
Packit 67cb25
   odd integer to ensure a symmetric window. The size of the workspace is :math:`O(6K)`.
Packit 67cb25
Packit 67cb25
.. function:: void gsl_filter_impulse_free(gsl_filter_impulse_workspace * w)
Packit 67cb25
Packit 67cb25
   This function frees the memory associated with :data:`w`.
Packit 67cb25
Packit 67cb25
.. function:: int gsl_filter_impulse(const gsl_filter_end_t endtype, const gsl_filter_scale_t scale_type, const double t, const gsl_vector * x, gsl_vector * y, gsl_vector * xmedian, gsl_vector * xsigma, size_t * noutlier, gsl_vector_int * ioutlier, gsl_filter_impulse_workspace * w)
Packit 67cb25
Packit 67cb25
   These functions apply an impulse detection filter to the input vector :data:`x`, storing the filtered output
Packit 67cb25
   in :data:`y`. The tuning parameter :math:`t` is provided in :data:`t`.
Packit 67cb25
   The window medians :math:`m_i` are stored in :data:`xmedian` and the :math:`S_i` are stored in :data:`xsigma` on output.
Packit 67cb25
   The number of outliers detected is stored in :data:`noutlier` on output, while
Packit 67cb25
   the locations of flagged outliers are stored in the boolean array :data:`ioutlier`. The input
Packit 67cb25
   :data:`ioutlier` may be :code:`NULL` if not desired. It  is allowed to have :data:`x` = :data:`y` for an
Packit 67cb25
   in-place filter.
Packit 67cb25
Packit 67cb25
Examples
Packit 67cb25
========
Packit 67cb25
Packit 67cb25
Gaussian Example 1
Packit 67cb25
------------------
Packit 67cb25
Packit 67cb25
This example program illustrates the Gaussian filter applied to smoothing a time series of length
Packit 67cb25
:math:`N = 500` with a kernel size of :math:`K = 51`. Three filters are applied with
Packit 67cb25
parameters :math:`\alpha = 0.5, 3, 10`. The results are shown in :numref:`fig_filt-gaussian`.
Packit 67cb25
Packit 67cb25
.. _fig_filt-gaussian:
Packit 67cb25
Packit 67cb25
.. figure:: /images/gaussfilt.png
Packit 67cb25
   :scale: 60%
Packit 67cb25
Packit 67cb25
   Top panel: Gaussian kernels (unnormalized) for :math:`\alpha = 0.5, 3, 10`.
Packit 67cb25
   Bottom panel: Time series (gray) with Gaussian filter output for same :math:`\alpha`
Packit 67cb25
   values.
Packit 67cb25
Packit 67cb25
We see that the filter corresponding to :math:`\alpha = 0.5` applies the most smoothing,
Packit 67cb25
while :math:`\alpha = 10` corresponds to the least amount of smoothing.
Packit 67cb25
The program is given below.
Packit 67cb25
Packit 67cb25
.. include:: examples/gaussfilt.c
Packit 67cb25
   :code:
Packit 67cb25
Packit 67cb25
Gaussian Example 2
Packit 67cb25
------------------
Packit 67cb25
Packit 67cb25
A common application of the Gaussian filter is to detect edges, or sudden jumps, in a noisy
Packit 67cb25
input signal. It is used both for 1D edge detection in time series, as well as 2D edge
Packit 67cb25
detection in images. Here we will examine a noisy time series of length :math:`N = 1000`
Packit 67cb25
with a single edge. The input signal is defined as
Packit 67cb25
Packit 67cb25
.. only:: not texinfo
Packit 67cb25
Packit 67cb25
   .. math:: x(n) = e(n) +
Packit 67cb25
               \left\{
Packit 67cb25
                 \begin{array}{cc}
Packit 67cb25
                   0, & n \le N/2 \\
Packit 67cb25
                   0.5, & n > N/2
Packit 67cb25
                 \end{array}
Packit 67cb25
               \right.
Packit 67cb25
Packit 67cb25
.. only:: texinfo
Packit 67cb25
Packit 67cb25
   ::
Packit 67cb25
Packit 67cb25
      x(n) = e(n) + { 0,   n <= N/2
Packit 67cb25
                    { 0.5, n >  N/2
Packit 67cb25
Packit 67cb25
where :math:`e(n)` is Gaussian random noise. The program smooths the input signal
Packit 67cb25
with order :math:`0,1,` and :math:`2` Gaussian filters of length :math:`K = 61` with
Packit 67cb25
:math:`\alpha = 3`. For comparison, the program also computes finite differences
Packit 67cb25
of the input signal without smoothing. The results are shown in :numref:`fig_filt-gaussian2`.
Packit 67cb25
Packit 67cb25
.. _fig_filt-gaussian2:
Packit 67cb25
Packit 67cb25
.. figure:: /images/gaussfilt2.png
Packit 67cb25
   :scale: 60%
Packit 67cb25
Packit 67cb25
   Top row: original input signal :math:`x(n)` (black) with Gaussian smoothed signal in red.
Packit 67cb25
   Second row: First finite differences of input signal.
Packit 67cb25
   Third row: Input signal smoothed with a first order Gaussian filter.
Packit 67cb25
   Fourth row: Input signal smoothed with a second order Gaussian filter.
Packit 67cb25
Packit 67cb25
The finite difference approximation of the first derivative (second row) shows
Packit 67cb25
the common problem with differentiating a noisy signal. The noise is amplified
Packit 67cb25
and makes it extremely difficult to detect the sharp gradient at sample :math:`500`.
Packit 67cb25
The third row shows the first order Gaussian smoothed signal with a clear peak
Packit 67cb25
at the location of the edge. Alternatively, one could examine the second order
Packit 67cb25
Gaussian smoothed signal (fourth row) and look for zero crossings to determine
Packit 67cb25
the edge location.
Packit 67cb25
Packit 67cb25
The program is given below.
Packit 67cb25
Packit 67cb25
.. include:: examples/gaussfilt2.c
Packit 67cb25
   :code:
Packit 67cb25
Packit 67cb25
Square Wave Signal Example
Packit 67cb25
--------------------------
Packit 67cb25
Packit 67cb25
The following example program illustrates the median filters on a noisy
Packit 67cb25
square wave signal. Median filters are well known for preserving sharp
Packit 67cb25
edges in the input signal while reducing noise. The program constructs
Packit 67cb25
a 5 Hz square wave signal with Gaussian noise added. Then the signal is
Packit 67cb25
filtered with a standard median filter and recursive median filter using
Packit 67cb25
a symmetric window of length :math:`K = 7`. The results are shown in
Packit 67cb25
:numref:`fig_filt-edge`.
Packit 67cb25
Packit 67cb25
.. _fig_filt-edge:
Packit 67cb25
Packit 67cb25
.. figure:: /images/filt_edge.png
Packit 67cb25
   :scale: 60%
Packit 67cb25
Packit 67cb25
   Original time series is in gray. The standard median filter output is in
Packit 67cb25
   green and the recursive median filter output is in red.
Packit 67cb25
Packit 67cb25
Both filters preserve the sharp signal edges while reducing the noise. The
Packit 67cb25
recursive median filter achieves a smoother result than the standard median
Packit 67cb25
filter. The "blocky" nature of the output is characteristic of all median
Packit 67cb25
filters. The program is given below.
Packit 67cb25
Packit 67cb25
.. include:: examples/filt_edge.c
Packit 67cb25
   :code:
Packit 67cb25
Packit 67cb25
Impulse Detection Example
Packit 67cb25
-------------------------
Packit 67cb25
Packit 67cb25
The following example program illustrates the impulse detection filter. First,
Packit 67cb25
it constructs a sinusoid signal of length :math:`N = 1000` with Gaussian noise
Packit 67cb25
added. Then, about 1% of the data are perturbed to represent large outliers. An
Packit 67cb25
impulse detecting filter is applied with a window size :math:`K = 25` and
Packit 67cb25
tuning parameter :math:`t = 4`, using the :math:`Q_n` statistic as the robust
Packit 67cb25
measure of scale. The results are plotted in :numref:`fig_impulse`.
Packit 67cb25
Packit 67cb25
.. _fig_impulse:
Packit 67cb25
Packit 67cb25
.. figure:: /images/impulse.png
Packit 67cb25
   :scale: 60%
Packit 67cb25
Packit 67cb25
   Original time series is in blue, filter output is in green, upper and
Packit 67cb25
   lower intervals for detecting outliers are in red and yellow respectively.
Packit 67cb25
   Detected outliers are marked with squares.
Packit 67cb25
Packit 67cb25
The program is given below.
Packit 67cb25
Packit 67cb25
.. include:: examples/impulse.c
Packit 67cb25
   :code:
Packit 67cb25
Packit 67cb25
References and Further Reading
Packit 67cb25
==============================
Packit 67cb25
Packit 67cb25
The following publications are relevant to the algorithms described
Packit 67cb25
in this chapter,
Packit 67cb25
Packit 67cb25
* F. J. Harris, *On the use of windows for harmonic analysis with the discrete Fourier transform*,
Packit 67cb25
  Proceedings of the IEEE, 66 (1), 1978.
Packit 67cb25
Packit 67cb25
* S-J. Ko, Y-H. Lee, and A. T. Fam. *Efficient implementation of one-dimensional recursive median filters*,
Packit 67cb25
  IEEE transactions on circuits and systems 37.11 (1990): 1447-1450.
Packit 67cb25
Packit 67cb25
* R. K. Pearson and M. Gabbouj, *Nonlinear Digital Filtering with Python: An Introduction*.
Packit 67cb25
  CRC Press, 2015.