/* $Id: sinfo_utilities.h,v 1.13 2011/12/09 07:47:42 amodigli Exp $
 *
 * This file is part of the SINFONI Pipeline
 * Copyright (C) 2002,2003 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

/*
 * $Author: amodigli $
 * $Date: 2011/12/09 07:47:42 $
 * $Revision: 1.13 $
 * $Name: sinfo-2_4_0 $
 */
#ifndef SINFO_UTILITIES_H
#define SINFO_UTILITIES_H

#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif
#include <sinfo_cpl_size.h>

/*
  This recipe implements error handling cleanly using a pair of macros called
  sinfo_skip_if() and sinfo_end_skip.

  sinfo_skip_if() takes one argument, which is a logical expression.
  If the logical expression is false sinfo_skip_if() takes no action and
  program execution continues.
  If the logical expression is true this indicates an error. In this case
  sinfo_skip_if() will set the location of the error to the point where it
  was invoked in the recipe code (unless the error location is already in the
  recipe code). If no error code had been set, then sinfo_skip_if() will set
  one. Finally, sinfo_skip_if() causes program execution to skip to the
  macro 'sinfo_end_skip'.
  The macro sinfo_end_skip is located towards the end of the function, after
  which all resource deallocation and the function return is located.

  The use of sinfo_skip_if() assumes the following coding practice:
  1) Pointers used for dynamically allocated memory that they "own" shall
     always
     point to either NULL or to allocated memory (including CPL-objects).
  2) Such pointers may not be reused to point to memory whose deallocation
     requires calls to different functions.
  3) Pointers of type FILE should be set NULL when not pointing to an open
     stream and their closing calls (fclose(), freopen(), etc.) following the
     'sinfo_end_skip' should be guarded against such NULL pointers.

  Error checking with sinfo_skip_if() is encouraged due to the following
  advantages:
  1) It ensures that a CPL-error code is set.
  2) It ensures that the location of the error in the _recipe_ code is noted.
  3) The error checking may be confined to a single concise line.
  4) It is not necessary to replicate memory deallocation for every error
     condition.
  5) If more extensive error reporting/handling is required it is not precluded
     by the use of sinfo_skip_if().
  6) It allows for a single point of function return.
  7) It allows for optional, uniformly formatted debugging/tracing information
     at each macro invocation.

  The implementation of sinfo_skip_if() uses a goto/label construction.
  According to Kerningham & Ritchie, The C Programming Language, 2nd edition,
  Section 3.8:
  "This organization is handy if the error-handling code is non-trivial,
  and if errors can occur in several places."

  The use of goto for any other purpose should be avoided.

*/

#define sinfo_skip_if(CONDITION) \
  do if (CONDITION) { \
    if (cpl_error_get_code()) { \
        cpl_msg_debug("", "Skip in %s line %d due to '%s' with error '%s' " \
                      "at %s", __FILE__, __LINE__, #CONDITION, \
                      cpl_error_get_message(), cpl_error_get_where());  \
        if (strstr(cpl_error_get_where(), "visir") == NULL) \
            cpl_error_set_where(""); \
    } else { \
        cpl_msg_debug("", "Skip in %s line %d due to '%s'", \
                        __FILE__, __LINE__, #CONDITION);  \
        cpl_error_set("", CPL_ERROR_UNSPECIFIED); \
    } \
    goto cleanup; \
  } else { \
    if (cpl_error_get_code()) \
        cpl_msg_debug("", "No skip in %s line %d due to '%s' with error '%s' " \
                      "at %s", __FILE__, __LINE__, #CONDITION, \
                      cpl_error_get_message(), cpl_error_get_where()); \
    else \
        cpl_msg_debug("", "No skip in %s line %d due to '%s'", \
                      __FILE__, __LINE__, #CONDITION);  \
  } while (0)


#define sinfo_end_skip \
    do { \
        cleanup: \
        if (cpl_error_get_code()) \
            cpl_msg_debug("", "Cleanup in %s line %d with error '%s' at %s", \
                           __FILE__, __LINE__, \
                          cpl_error_get_message(), cpl_error_get_where()); \
        else \
            cpl_msg_debug("", "Cleanup in %s line %d", \
                          __FILE__, __LINE__);  \
    } while (0)


#include <cpl.h>
#include <sinfo_image_ops.h>
#include "sinfo_globals.h"
CPL_BEGIN_DECLS


cpl_image*
sinfo_vector_to_image(const cpl_vector* vector,cpl_type type);

int
sinfo_table_column_dump(cpl_table* t, const char* name, cpl_type type);

cpl_table*
sinfo_table_shift_column_spline3(cpl_table* t,
                                 const char* col,
                                 const double s);

cpl_table*
sinfo_table_shift_column_poly(cpl_table* t,
                              const char* col,
                              const double s,
                              const int order);

cpl_table*
sinfo_table_shift_column_int(const cpl_table* t,
                             const char* col,
                             const double s,
                                   double* r);

cpl_error_code
sinfo_ima_line_cor(cpl_parameterlist * parlist, cpl_frameset* in);


void sinfo_new_array_set_value( float * array, float value, int i );
float sinfo_new_array_get_value( float * array, int i );
void sinfo_new_destroy_array(float ** array);
void sinfo_new_destroy_stringarray(char ** array, int size_x);
void sinfo_new_intarray_set_value( int * array, int value, int i );
void sinfo_new_array2D_set_value( float ** array, float value, int x, int y );
void sinfo_new_destroy_2Dintarray(int *** array, int size_x);
void sinfo_new_destroy_2Dfloatarray(float *** array, int size_x);
void sinfo_new_destroy_2Ddoublearray(double *** array, int size_x);
void sinfo_new_destroy_intarray(int ** array);
void sinfo_new_destroy_doublearray(double * array);
void sinfo_new_doublearray_set_value( double * array, double value, int i );
int sinfo_new_intarray_get_value( int * array, int i );
int * sinfo_new_intarray( int size);
int ** sinfo_new_2Dintarray( int size_x, int size_y);
double ** sinfo_new_2Ddoublearray( int size_x, int size_y);
char * sinfo_new_get_rootname(const char * filename);
char * sinfo_new_get_basename(const char *filename);
float sinfo_new_Stats_get_cleanstdev(Stats * stats);
float sinfo_new_Stats_get_cleanmean(Stats * stats);
float sinfo_new_array2D_get_value( float ** array, int x, int y );
float * sinfo_new_floatarray( int size);
float ** sinfo_new_2Dfloatarray( int size_x, int size_y);
double   sinfo_new_doublearray_get_value( double * array, int i );

double * sinfo_new_doublearray( int size);
/*
FitParams ** sinfo_new_fit_params( int n_params ) ;
*/
cpl_imagelist * sinfo_new_frameset_to_iset(cpl_frameset *) ;
cpl_imagelist *
sinfo_new_imagelist_load_frameset(const cpl_frameset * frameset,cpl_type type,
                                            int pnum,int extnum);

char ** sinfo_new_frameset_to_filenames(cpl_frameset *set, int *nfiles);
char ** new_frameset_to_tags(cpl_frameset *set, int *ntags);
double sinfo_spline_hermite(double xp,
                            const double *x,
                            const double *y,
                                  int n,
                                  int *istart );

cpl_error_code update_bad_pixel_map(cpl_image* im);
/* replacement of deprecated functions */
cpl_polynomial * sinfo_polynomial_fit_2d_create(cpl_bivector     *  xy_pos,
                                              cpl_vector       *  values,
                                              cpl_size                 degree,
                                              double           *  mse);
cpl_polynomial * sinfo_polynomial_fit_1d_create(
		const cpl_vector    *   x_pos,
        const cpl_vector    *   values,
        int                     degree,
        double              *   mse
        );
cpl_image * sinfo_image_filter_median(const cpl_image *, const cpl_matrix *);
cpl_image * sinfo_image_filter_linear(const cpl_image *, const cpl_matrix *);
cpl_image * sinfo_image_filter_linear2(const cpl_image *, const cpl_matrix *);
CPL_END_DECLS

#endif
