Blame filter/test_impulse.c

Packit 67cb25
/* filter/test_impulse.c
Packit 67cb25
 * 
Packit 67cb25
 * Copyright (C) 2018 Patrick Alken
Packit 67cb25
 * 
Packit 67cb25
 * This program is free software; you can redistribute it and/or modify
Packit 67cb25
 * it under the terms of the GNU General Public License as published by
Packit 67cb25
 * the Free Software Foundation; either version 3 of the License, or (at
Packit 67cb25
 * your option) any later version.
Packit 67cb25
 * 
Packit 67cb25
 * This program is distributed in the hope that it will be useful, but
Packit 67cb25
 * WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 67cb25
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 67cb25
 * General Public License for more details.
Packit 67cb25
 * 
Packit 67cb25
 * You should have received a copy of the GNU General Public License
Packit 67cb25
 * along with this program; if not, write to the Free Software
Packit 67cb25
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Packit 67cb25
 */
Packit 67cb25
Packit 67cb25
#include <gsl/gsl_math.h>
Packit 67cb25
#include <gsl/gsl_vector.h>
Packit 67cb25
#include <gsl/gsl_filter.h>
Packit 67cb25
#include <gsl/gsl_movstat.h>
Packit 67cb25
#include <gsl/gsl_test.h>
Packit 67cb25
#include <gsl/gsl_rng.h>
Packit 67cb25
#include <gsl/gsl_randist.h>
Packit 67cb25
Packit 67cb25
static int
Packit 67cb25
vector_sum(const gsl_vector_int * v)
Packit 67cb25
{
Packit 67cb25
  size_t i;
Packit 67cb25
  int sum = 0;
Packit 67cb25
Packit 67cb25
  for (i = 0; i < v->size; ++i)
Packit 67cb25
    {
Packit 67cb25
      int vi = gsl_vector_int_get(v, i);
Packit 67cb25
      sum += vi;
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  return sum;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
static void
Packit 67cb25
test_impulse_proc(const double tol, const size_t n, const size_t K, const double nsigma,
Packit 67cb25
                  const gsl_filter_end_t etype, const gsl_filter_scale_t stype,
Packit 67cb25
                  const double outlier_percentage, gsl_rng * r)
Packit 67cb25
{
Packit 67cb25
  gsl_vector * x = gsl_vector_alloc(n);
Packit 67cb25
  gsl_vector * y = gsl_vector_alloc(n);
Packit 67cb25
  gsl_vector * z = gsl_vector_alloc(n);
Packit 67cb25
  gsl_vector * y_med = gsl_vector_alloc(n);
Packit 67cb25
  gsl_vector * xmedian = gsl_vector_alloc(n);
Packit 67cb25
  gsl_vector * xsigma = gsl_vector_alloc(n);
Packit 67cb25
  size_t noutlier;
Packit 67cb25
  gsl_vector_int * ioutlier = gsl_vector_int_alloc(n);
Packit 67cb25
  gsl_vector_int * ioutlier_exact = gsl_vector_int_alloc(n);
Packit 67cb25
  size_t i;
Packit 67cb25
  gsl_filter_impulse_workspace *impulse_p = gsl_filter_impulse_alloc(K);
Packit 67cb25
  gsl_filter_median_workspace *median_p = gsl_filter_median_alloc(K);
Packit 67cb25
  size_t noutlier_exact = 0;
Packit 67cb25
  char buf[1024];
Packit 67cb25
Packit 67cb25
  gsl_vector_int_set_zero(ioutlier_exact);
Packit 67cb25
Packit 67cb25
  for (i = 0; i < n; ++i)
Packit 67cb25
    {
Packit 67cb25
      double xi = gsl_ran_gaussian(r, 1.0);
Packit 67cb25
      double vi = gsl_rng_uniform(r);
Packit 67cb25
Packit 67cb25
      if (vi <= outlier_percentage)
Packit 67cb25
        {
Packit 67cb25
          xi += 15.0 * GSL_SIGN(xi);
Packit 67cb25
          ++noutlier_exact;
Packit 67cb25
          gsl_vector_int_set(ioutlier_exact, i, 1);
Packit 67cb25
        }
Packit 67cb25
Packit 67cb25
      gsl_vector_set(x, i, xi);
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  /* first test that median filter is equal to impulse filter with nsigma = 0 */
Packit 67cb25
Packit 67cb25
  gsl_filter_median(etype, x, y_med, median_p);
Packit 67cb25
  gsl_filter_impulse(etype, stype, 0.0, x, y, xmedian, xsigma, &noutlier, ioutlier, impulse_p);
Packit 67cb25
Packit 67cb25
  sprintf(buf, "impulse nsigma=0 smf comparison, etype=%u stype=%u", etype, stype);
Packit 67cb25
  compare_vectors(tol, y, y_med, buf);
Packit 67cb25
Packit 67cb25
  /* second test: filter y = impulse(x) with given nsigma */
Packit 67cb25
Packit 67cb25
  gsl_filter_impulse(etype, stype, nsigma, x, y, xmedian, xsigma, &noutlier, ioutlier, impulse_p);
Packit 67cb25
Packit 67cb25
  /* test correct number of outliers detected */
Packit 67cb25
  gsl_test(noutlier != noutlier_exact, "impulse [n=%zu,K=%zu,nsigma=%g,outlier_percentage=%g] noutlier=%zu exact=%zu",
Packit 67cb25
           n, K, nsigma, outlier_percentage, noutlier, noutlier_exact);
Packit 67cb25
Packit 67cb25
#if 0
Packit 67cb25
  {
Packit 67cb25
    for (i = 0; i < n; ++i)
Packit 67cb25
      {
Packit 67cb25
        printf("%.12e %.12e %d %.12e %.12e\n",
Packit 67cb25
               gsl_vector_get(x, i),
Packit 67cb25
               gsl_vector_get(y, i),
Packit 67cb25
               gsl_vector_int_get(ioutlier, i),
Packit 67cb25
               gsl_vector_get(xmedian, i) + nsigma * gsl_vector_get(xsigma, i),
Packit 67cb25
               gsl_vector_get(xmedian, i) - nsigma * gsl_vector_get(xsigma, i));
Packit 67cb25
      }
Packit 67cb25
  }
Packit 67cb25
#endif
Packit 67cb25
Packit 67cb25
  /* test outliers found in correct locations */
Packit 67cb25
  for (i = 0; i < n; ++i)
Packit 67cb25
    {
Packit 67cb25
      int val = gsl_vector_int_get(ioutlier, i);
Packit 67cb25
      int val_exact = gsl_vector_int_get(ioutlier_exact, i);
Packit 67cb25
Packit 67cb25
      gsl_test(val != val_exact, "test_impulse: outlier mismatch [i=%zu,K=%zu,nsigma=%g,outlier_percentage=%g] ioutlier=%d ioutlier_exact=%d",
Packit 67cb25
               i, K, nsigma, outlier_percentage, val, val_exact);
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  /* test noutlier = sum(ioutlier) */
Packit 67cb25
  {
Packit 67cb25
    size_t iout_sum = vector_sum(ioutlier);
Packit 67cb25
    gsl_test(noutlier != iout_sum, "impulse [K=%zu,nsigma=%g,outlier_percentage=%g] noutlier=%zu sum(ioutlier)=%zu",
Packit 67cb25
             K, nsigma, outlier_percentage, noutlier, iout_sum);
Packit 67cb25
  }
Packit 67cb25
Packit 67cb25
  /* third test: test in-place filter z = impulse(z) */
Packit 67cb25
Packit 67cb25
  gsl_vector_memcpy(z, x);
Packit 67cb25
  gsl_filter_impulse(etype, stype, nsigma, z, z, xmedian, xsigma, &noutlier, ioutlier, impulse_p);
Packit 67cb25
Packit 67cb25
  sprintf(buf, "impulse in-place nsigma=%g,n=%zu,K=%zu,etype=%u stype=%u", nsigma, n, K, etype, stype);
Packit 67cb25
  compare_vectors(GSL_DBL_EPSILON, z, y, buf);
Packit 67cb25
Packit 67cb25
  gsl_vector_free(x);
Packit 67cb25
  gsl_vector_free(y);
Packit 67cb25
  gsl_vector_free(z);
Packit 67cb25
  gsl_vector_free(y_med);
Packit 67cb25
  gsl_vector_free(xmedian);
Packit 67cb25
  gsl_vector_free(xsigma);
Packit 67cb25
  gsl_vector_int_free(ioutlier);
Packit 67cb25
  gsl_vector_int_free(ioutlier_exact);
Packit 67cb25
  gsl_filter_impulse_free(impulse_p);
Packit 67cb25
  gsl_filter_median_free(median_p);
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
static void
Packit 67cb25
test_impulse(gsl_rng * r)
Packit 67cb25
{
Packit 67cb25
  const double tol = 1.0e-10;
Packit 67cb25
Packit 67cb25
  test_impulse_proc(tol, 1000, 21, 6.0, GSL_FILTER_END_TRUNCATE, GSL_FILTER_SCALE_QN, 0.05, r);
Packit 67cb25
  test_impulse_proc(tol, 1000, 21, 6.0, GSL_FILTER_END_TRUNCATE, GSL_FILTER_SCALE_SN, 0.05, r);
Packit 67cb25
  test_impulse_proc(tol, 1000, 21, 6.0, GSL_FILTER_END_TRUNCATE, GSL_FILTER_SCALE_MAD, 0.05, r);
Packit 67cb25
  test_impulse_proc(tol, 1000, 21, 6.0, GSL_FILTER_END_TRUNCATE, GSL_FILTER_SCALE_IQR, 0.05, r);
Packit 67cb25
}