/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set sw=2 sts=2 et cin: */
/*
 * This file is part of the MUSE Instrument Pipeline
 * Copyright (C) 2007-2014 European Southern Observatory
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

#include <muse.h>

/* symbolic property names we compare to */
enum {                       TMEAN = 0, TSTD, TMIN, TMAX, TFLUX };
/* comparison values for minimum and maximum values of above properties */
const double kComparisonMin[] = { 123., 444., -10., 3515., 5068950. },
             kComparisonMax[] = { 132., 470.,  -9., 3648., 5098805. };

void
image_resampling_test_image_stats(cpl_image *aImage, const char *aName)
{
  /* same tests as on central plane */
  cpl_stats *stats = cpl_stats_new_from_image(aImage, CPL_STATS_ALL);
  cpl_msg_debug(__func__, "%s: average: %f+/-%f, min/max: %f/%f, flux: %f",
                aName,
                cpl_stats_get_mean(stats), cpl_stats_get_stdev(stats),
                cpl_stats_get_min(stats), cpl_stats_get_max(stats),
                cpl_stats_get_flux(stats));
  cpl_test(cpl_stats_get_mean(stats) > kComparisonMin[TMEAN] &&
           cpl_stats_get_mean(stats) < kComparisonMax[TMEAN]);
  cpl_test(cpl_stats_get_stdev(stats) > kComparisonMin[TSTD] &&
           cpl_stats_get_stdev(stats) < kComparisonMax[TSTD]);
  cpl_test(cpl_stats_get_min(stats) > kComparisonMin[TMIN] &&
           cpl_stats_get_min(stats) < kComparisonMax[TMIN]);
  cpl_test(cpl_stats_get_max(stats) > kComparisonMin[TMAX] &&
           cpl_stats_get_max(stats) < kComparisonMax[TMAX]);
  cpl_test(cpl_stats_get_flux(stats) > kComparisonMin[TFLUX] &&
           cpl_stats_get_flux(stats) < kComparisonMax[TFLUX]);
  cpl_stats_delete(stats);
} /* image_resampling_test_image_stats() */

/*----------------------------------------------------------------------------*/
/**
  @brief   Test program to check that muse_resampling_image() works
           when called with the necessary data for resampling.

  This program explicitely tests only muse_resampling_image().
 */
/*----------------------------------------------------------------------------*/
int main(int argc, char **argv)
{
  cpl_test_init(PACKAGE_BUGREPORT, CPL_MSG_DEBUG);

  muse_pixtable *pt = NULL, *ptgeo = NULL;
  if (argc > 1) {
    /* assume that the parameter is the filename of a pixel table */
    pt = muse_pixtable_load(argv[1]);
  } else {
    pt = muse_pixtable_load(BASEFILENAME"_pt.fits");
    ptgeo = muse_pixtable_load(BASEFILENAME"_ptgeo.fits");
#if 0 /* to ease preparation of a new pixel table for this test */
    /* restrict to wavelength range and to slices 1 to 3 */
    muse_pixtable *p = pt;
    muse_pixtable_restrict_wavelength(p, 5745, 6000);
    cpl_table_unselect_all(p->table);
    int i;
    for (i = 0; i < cpl_table_get_nrow(p->table); i++) {
      if (muse_pixtable_origin_get_slice(cpl_table_get_int(p->table, "origin", i, NULL)) > 3) {
        cpl_table_select_row(p->table, i);
      }
    }
    cpl_table_erase_selected(p->table);
    muse_pixtable_save(p, BASEFILENAME"_p_new.fits");
    exit(111);
#endif
  }
  if (!pt) {
    return cpl_test_end(1);
  }
  cpl_msg_info(__func__, "using pixel table with %"CPL_SIZE_FORMAT" rows",
               muse_pixtable_get_nrow(pt));
  muse_pixtable *pts[] = { pt, ptgeo, NULL };

  /* only nearest and renka are supported for resampling to image */
  muse_resampling_type t;
  for (t = MUSE_RESAMPLE_NEAREST; t <= MUSE_RESAMPLE_WEIGHTED_RENKA; t++) {
    muse_pixtable *p;
    int i;
    for (i = 0, p = pts[i]; p; p = pts[++i]) {
      int issimple = muse_pixtable_get_type(p) == MUSE_PIXTABLE_TYPE_SIMPLE;
      cpl_msg_info(__func__, "Resampling to image, method %d, with %s "
                   "geometry info", t, issimple ? "simple" : "full");
      double cputime1 = cpl_test_get_cputime(),
             time1 = cpl_test_get_walltime();
      muse_image *image = muse_resampling_image(p, t, 1., 1.5);
      double cputime2 = cpl_test_get_cputime(),
             time2 = cpl_test_get_walltime();
      cpl_msg_debug(__func__, "...done took %gs (CPU) %gs (wall-clock)",
                    cputime2 - cputime1, time2 - time1);
      cpl_test(image != NULL);
      cpl_test(image->data != NULL);
      cpl_test(image->header != NULL);
      char *name = cpl_sprintf("method %d geo %s", t,
                               issimple ? "simple" : "full");
      image_resampling_test_image_stats(image->data, name);
      cpl_free(name);

      char *fn = cpl_sprintf("image_resampled_%d_geo%s.fits", t,
                             issimple ? "simple" : "full");
      cpl_image_save(image->data, fn, CPL_TYPE_FLOAT, image->header,
                     CPL_IO_CREATE);
      cpl_free(fn);
      muse_image_delete(image);
    } /* for p (all pixel tables) */
  } /* for t (the two allowed resampling methods) */

  /* test failure cases */
  muse_image *image = muse_resampling_image(NULL, MUSE_RESAMPLE_NEAREST, 1., 1.5);
  cpl_test_null(image);
  cpl_error_reset();
  image = muse_resampling_image(pt, MUSE_RESAMPLE_NONE, 1., 1.5);
  cpl_test_null(image);
  cpl_error_reset();

  muse_pixtable_delete(pt);
  muse_pixtable_delete(ptgeo);
  return cpl_test_end(0);
}
