
/*********************************************************************
 * E.S.O. - VLT project
 *
 * "@(#) $Id: kmclipm_functions.h,v 1.23 2013-10-08 14:55:01 erw Exp $"
 *
 * Functions that are implemented as recipes. They are also useedd in KMOS
 * data reduction pipeline.
 *
 * who       when        what
 * --------  ----------  ----------------------------------------------
 * agudo     2008-06-12  created
 */

#ifndef KMCLIPM_FUNCTIONS_H
#define KMCLIPM_FUNCTIONS_H

/**
    @defgroup kmclipm_functions Functions used in KMCLIPM & KMOS

    This module contains essential functions needed by the modules
    @ref kmclipm_rtd_image and the KMOS-pipeline

    @par Synopsis:
    @code
      #include <kmclipm_functions.h>
    @endcode

    @{
 */

/*------------------------------------------------------------------------------
 *              Includes
 *----------------------------------------------------------------------------*/

#include <cpl.h>

#include "kmclipm_vector.h"

extern int          kmclipm_band_samples,
                    kmclipm_omit_warning_one_slice;
extern double       kmclipm_band_start,
                    kmclipm_band_end;

/*------------------------------------------------------------------------------
 *              Types
 *----------------------------------------------------------------------------*/

/** @brief The reconstruction methods
    - NEAREST_NEIGHBOR
    - LINEAR_WEIGHTED_NEAREST_NEIGHBOR
    - SQUARE_WEIGHTED_NEAREST_NEIGHBOR
    - CUBIC_SPLINE
*/
enum reconstructMethod {
    NEAREST_NEIGHBOR=10,
    LINEAR_WEIGHTED_NEAREST_NEIGHBOR,
    SQUARE_WEIGHTED_NEAREST_NEIGHBOR,
    CUBIC_SPLINE,
    MODIFIED_SHEPARDS_METHOD,
    QUADRATIC_INTERPOLATION
};

/** @brief The type of neighborhood to account for:
    - N_CUBE <br>
      A cube around each spaxel
    - N_SPHERE <br>
      A sphere around each spaxel
*/
enum neighborhoodType {
    N_CUBE,
    N_SPHERE
};

/** @brief The type of extrapolation behavior:
    - NONE_NANS: <br>
      no extrapolation will be done, points outside the input images will be
      set to NAN
    - NONE_CLIPPING <br>
      no extrapolation will be done, points outside the input images will be
      removed, the output image will be smaller
    - BCS_NATURAL: <br>
      only valid for the "BCS" interpolation, which will be of type natural,
      i.e. at the image edge the first derivate is assumed to be zero
    - BCS_ESTIMATED <br>
      only valid for the "BCS" interpolation, the second derivate at the
      image egde will be estimated by interpolation using the last three
      points.
    - RESIZE_NANS <br>
    - RESIZE_BCS_NATURAL <br>
    - RESIZE_BCS_ESTIMATED <br>
*/
enum extrapolationType {
    NONE_NANS,
    NONE_CLIPPING,
    BCS_NATURAL,
    BCS_ESTIMATED,
    RESIZE_NANS,
    RESIZE_BCS_NATURAL,
    RESIZE_BCS_ESTIMATED
};

/*erwdoc*/
/** @brief ??? */
enum scaleType {
    PIXEL=2,
    UNIT
};

/** @brief Shows the return status of kmclipm_combine_vector():
    If the status is combine_rejected after returning, the pixel
    should be rejected
*/
enum combine_status {
    combine_ok,
    combine_rejected
};

typedef struct {
    int     dim;            /* number of grid points for this axis */
    float   start;          /* lowest value for this axis */
    float   delta;          /* distance between two grid points */
} gridAxis;

typedef struct {
    float   distance;
    enum    scaleType scale;
    enum    neighborhoodType type;
} neighborHoodStruct;

typedef struct {
    gridAxis            x;
    gridAxis            y;
    gridAxis            l;
    float               lamdaDistanceScale;  /* factor to scale the lamda */
                                             /* direction to reconstructMethod */
                                             /* method */
    enum                reconstructMethod method;
    neighborHoodStruct  neighborHood;
    float               rot_na_angle;          /* rotator angle relative to nasmyth */
    float               rot_off_angle;          /* rotator offset angle */
} gridDefinition;

/** @brief Contains all return values for any of the three
    kmclipm_rt_image-Functions.
    All pointers are arrays of length KMOS_NR_IFUS+1
    The first value is always -1.
    If no target has been identified or it hasn't been specified to be processed
    the value will be -1 as well.
*/
typedef struct {
    double          *xpos;
    double          *xpos_error;
    double          *ypos;
    double          *ypos_error;
    double          *intensity;
    double          *intensity_error;
    double          *fwhm;
    double          *fwhm_error;
    double          *background;
    double          *background_error;
    long int        *nr_saturated_pixels;
} kmclipm_fitpar;

/*------------------------------------------------------------------------------
 *              Declaration Block
 *----------------------------------------------------------------------------*/

#ifdef __cplusplus
extern "C" {
#endif

/*-----------------------------------------------------------------------------
 *              Prototypes
 *----------------------------------------------------------------------------*/

cpl_image*      kmclipm_load_image_with_extensions(
                            const char *path);

cpl_error_code  kmclipm_gaussfit_2d(
                            const cpl_image *img,
                            double *fitted_pars);

cpl_imagelist*  kmclipm_reconstruct(
                            const int ifu,
                            cpl_image *ifu_raw,
                            const cpl_image *ifu_noise,
                            cpl_image *ifu_xcal,
                            cpl_image *ifu_ycal,
                            cpl_image *ifu_lcal,
                            const gridDefinition gd,
                            const char *lut_path,
                            int lut_valid,
                            cpl_array *timestamp,
                            const cpl_vector *calAngles,
                            cpl_imagelist **noise_cube);

cpl_imagelist*  kmclipm_shift(
                            const cpl_imagelist *data_in,
                            double xshift_sub,
                            double yshift_sub,
                            const char *method,
                            const enum extrapolationType extrapolation);

cpl_imagelist*  kmclipm_rotate(
                            const cpl_imagelist *data_in,
                            double alpha,
                            const char *method,
                            const enum extrapolationType extrapolation);

cpl_error_code  kmclipm_reject_deviant(
                            kmclipm_vector *kv,
                            double cpos_rej,
                            double cneg_rej,
                            double *stddev,
                            double *mean);

cpl_error_code  kmclipm_make_image(
                            const cpl_imagelist *data_in,
                            const cpl_imagelist *noise_in,
                            cpl_image **data_out,
                            cpl_image **noise_out,
                            cpl_vector *identified_slices,
                            const char *method,
                            double pos_rej_thres,
                            double neg_rej_thres,
                            int nr_iter,
                            int nr_max,
                            int nr_min);

double          kmclipm_combine_vector(
                            const kmclipm_vector *data,
                            const kmclipm_vector *noise,
                            const char *cmethod,
                            double cpos_rej,
                            double cneg_rej,
                            int citer,
                            int cmax,
                            int cmin,
                            int *new_size,
                            double *stdev,
                            double *stderr,
                            double default_val,
                            enum combine_status *status);

cpl_error_code  kmclipm_combine_frames(
                            const cpl_imagelist *data,
                            const cpl_imagelist *noise,
                            cpl_vector *identified_slices,
                            const char *cmethod,
                            double cpos_rej,
                            double cneg_rej,
                            int citer,
                            int cmax,
                            int cmin,
                            cpl_image **avg_data,
                            cpl_image **avg_noise,
                            double default_val);

cpl_error_code  kmclipm_setup_grid(
                            gridDefinition *gd,
                            const char *method,
                            double neighborhoodRange,
                            double pixel_scale,
                            double rot_angle);

cpl_error_code kmclipm_setup_grid_band_lcal(
                            gridDefinition *gd,
                            const char *filter_id,
                            const cpl_table *tbl);
/*
cpl_error_code  kmclipm_setup_grid_band_auto(
                            gridDefinition *gd,
                            const cpl_propertylist *main_header,
                            int det_nr, const cpl_table *tbl);
*/
cpl_error_code  kmclipm_setup_grid_band(
                            gridDefinition *gd,
                            const char *filter_id,
                            const cpl_table *tbl);

cpl_error_code  kmclipm_update_property_int(
                            cpl_propertylist *pl,
                            const char *name,
                            int val,
                            const char* comment);

cpl_error_code  kmclipm_update_property_double(
                            cpl_propertylist *pl,
                            const char *name,
                            double val,
                            const char* comment);

cpl_error_code  kmclipm_update_property_string(
                            cpl_propertylist *pl,
                            const char *name,
                            const char* val,
                            const char* comment);

double          kmclipm_strip_angle(
                            double *angle);

double          kmclipm_diff_angle(
                            double angle1,
                            double angle2);

cpl_array*      kmclipm_reconstruct_nnlut_get_timestamp(
                            const char *filename,
                            const int ifu,
                            const gridDefinition gd);

int             kmclipm_compare_timestamps(
                            const cpl_array *ts1,
                            const cpl_array *ts2);

int*            kmclipm_extract_bounds(
                            const cpl_propertylist* pl);

cpl_propertylist* kmclipm_propertylist_load(
                            const char *filename,
                            int position);

cpl_image*      kmclipm_image_load(
                            const char *filename,
                            cpl_type im_type,
                            int pnum,
                            int xtnum);

cpl_image*      kmclipm_cal_image_load(
                            const char *filename,
                            cpl_type im_type,
                            int pnum,
                            int device,
                            int noise,
                            double angle,
                            double *angle_found,
                            double *secondClosestAngle);

double          kmclipm_cal_propertylist_find_angle(
                            const char *filename,
                            int device,
                            int noise,
                            double rotangle,
                            int *xtnum,
                            double *secondClosestAngle);

cpl_propertylist* kmclipm_cal_propertylist_load(
                            const char *filename,
                            int device,
                            int noise,
                            double rotangle,
                            double *angle_found);

cpl_image*      kmclipm_image_load_window(
                            const char *filename,
                            cpl_type im_type,
                            int pnum,
                            int xtnum,
                            int llx,
                            int lly,
                            int urx,
                            int ury);

cpl_imagelist*  kmclipm_imagelist_load(
                            const char *filename,
                            cpl_type im_type,
                            int xtnum);

cpl_table*      kmclipm_table_load(
                            const char *filename,
                            int xtnum,
                            int check_nulls);

cpl_table*      kmclipm_cal_table_load(
                            const char *filename,
                            int device,
                            double angle,
                            int check_nulls,
                            double *found_angle);

cpl_error_code  kmclipm_image_save(const cpl_image *img,
                            const char *filename,
                            cpl_type_bpp bpp,
                            const cpl_propertylist *pl,
                            unsigned mode,
                            double rej_val);

cpl_error_code  kmclipm_imagelist_save(const cpl_imagelist *cube,
                            const char *filename,
                            cpl_type_bpp bpp,
                            const cpl_propertylist *pl,
                            unsigned mode,
                            double rej_val);

cpl_error_code  kmclipm_set_cal_path(const char *path,
                            int test_mode);

cpl_error_code  kmclipm_reject_nan(cpl_image *img);

int             kmclipm_reconstruct_check_lut (const char *filename,
                            const int ifu,
                            const gridDefinition gd,
                            const cpl_array *cal_timestamp,
                            const cpl_vector *calAngles);

void            kmclipm_free_fitpar(kmclipm_fitpar *fitpar);

cpl_error_code kmclipm_reject_saturated_pixels (cpl_image *img, int mask_sat_pixels,  int *nr_sat);


/*----------------------------------------------------------------------------*/

#ifdef __cplusplus
}   /* extern "C" */
#endif

/** @} */

#endif
