/*
 * This file is part of the KMOS 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
 */

#ifndef KMOS_DFS_H
#define KMOS_DFS_H

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

#include <cpl.h>

#include "kmclipm_vector.h"

#include "kmo_utils.h"

/*------------------------------------------------------------------------------
                       Defines
 -----------------------------------------------------------------------------*/
#define INSTRUMENT                  "INSTRUME"
#define TPL_ID                      "ESO TPL ID"
#define MAPPING8                    "KMOS_spec_obs_mapping8"
#define MAPPING24                   "KMOS_spec_obs_mapping24"

/* ----- EXTNAME keyword related defines ------------------------------------ */
// first part of EXTNAME string
#define EXTNAME_RAW                 "CHIP"

// strings to be pasted into EXTNAME keyword
#define EXT_DATA                    "DATA"
#define EXT_NOISE                   "NOISE"
#define EXT_BADPIX                  "BADPIX"
#define EXT_SPEC                    "SPEC"
#define EXT_LIST                    "LIST"

/* ----- DO categories ------------------------------------------------------ */
//
// calibration recipes
//
// kmo_dark
#define DARK                     "DARK"                 // RAW
#define MASTER_DARK              "MASTER_DARK"          // CALIB
#define BADPIXEL_DARK            "BADPIXEL_DARK"        // CALIB
//kmo_flat
#define FLAT_ON                  "FLAT_ON"              // RAW
#define FLAT_OFF                 "FLAT_OFF"             // RAW
#define BADPIXEL_FLAT            "BADPIXEL_FLAT"        // CALIB
#define MASTER_FLAT              "MASTER_FLAT"          // CALIB
#define XCAL                     "XCAL"                 // CALIB
#define YCAL                     "YCAL"                 // CALIB
#define FLAT_EDGE                "FLAT_EDGE"            // CALIB
// kmo_wave_cal
#define ARC_ON                   "ARC_ON"               // RAW
#define ARC_OFF                  "ARC_OFF"              // RAW
#define ARC_LIST                 "ARC_LIST"             // CALIB
#define REF_LINES                "REF_LINES"            // CALIB
#define LCAL                     "LCAL"                 // CALIB
#define DET_IMG_WAVE             "DET_IMG_WAVE"

/* kmos_gen_reflines */
#define KMOS_GEN_REFLINES_RAW   "REFLINES_TXT"

// kmo_illumination
#define FLAT_SKY                 "FLAT_SKY"             // RAW
#define ILLUM_CORR               "ILLUM_CORR"           // CALIB
#define SKYFLAT_EDGE             "SKYFLAT_EDGE"         // CALIB
// kmo_illumination_flat
#define FLAT_SKY_FLAT            "FLAT_SKY_FLAT"        // RAW
#define ILLUM_CORR_FLAT          "ILLUM_CORR"           // CALIB
// kmo_std_star
#define STD                      "STD"                  // RAW
#define TELLURIC                 "TELLURIC"             // CALIB
#define RESPONSE                 "RESPONSE"             // CALIB
#define TELLURIC_CORR            "TELLURIC_CORR"        // CALIB
#define ATMOS_MODEL              "ATMOS_MODEL"          // CALIB
#define SOLAR_SPEC               "SOLAR_SPEC"           // CALIB
#define SPEC_TYPE_LOOKUP         "SPEC_TYPE_LOOKUP"     // CALIB
#define STD_IMAGE                "STD_IMAGE"
#define STD_MASK                 "STD_MASK"
#define STD_CUBE                 "STD_CUBE"
#define STAR_SPEC                "STAR_SPEC"
#define NOISE_SPEC               "NOISE_SPEC"
// kmo_sci_red
#define SCIENCE                  "SCIENCE"              // RAW
#define COMBINED_RECONS          "COMBINE_SCI_RECONSTRUCTED"
#define COMBINED_CUBE            "SCI_COMBINED"
#define COMBINED_COLLAPSED       "SCI_COMBINED_COLL"
#define COMBINED_RECONS_COLLAPSED "COMBINE_SCI_RECONSTRUCTED_COLL"
#define RECONSTRUCTED_CUBE       "SCI_RECONSTRUCTED"
#define RECONSTRUCTED_COLLAPSED  "SCI_RECONSTRUCTED_COLL"
#define INTERIM_OBJECT_CUBE      "SCI_INTERIM_OBJECT"
#define INTERIM_OBJECT_SKY       "SCI_INTERIM_SKY"
// kmo_multi_reconstruct
#define CUBE_MULTI               "CUBE_MULTI"

//
// other recipes
//
// kmo_arithmetic
#define ARITH_OP1                "ARITH_OP1"
#define ARITH_OP2                "ARITH_OP2"
#define ARITHMETIC               "ARITHMETIC"
// kmos_combine
#define COMBINE                  "COMBINE"
#define EXP_MASK                 "EXP_MASK"
// kmo_copy
#define COPY                     "COPY"
// kmo_reconstruct
#define CUBE_DARK                "CUBE_DARK"
#define CUBE_FLAT                "CUBE_FLAT"
#define CUBE_ARC                 "CUBE_ARC"
#define CUBE_OBJECT              "CUBE_OBJECT"
#define CUBE_STD                 "CUBE_STD"
#define CUBE_SCIENCE             "CUBE_SCIENCE"
#define DET_IMG_REC              "DET_IMG_REC"
#define OBJECT                   "OBJECT"               // RAW
#define WAVE_BAND                "WAVE_BAND"
#define OH_SPEC                  "OH_SPEC"

// kmo_extract_spec
#define EXTRACT_SPEC             "EXTRACT_SPEC"
#define EXTRACT_SPEC_MASK        "EXTRACT_SPEC_MASK"
// kmo_fit_profile
#define FIT_PROFILE              "FIT_PROFILE"
// kmo_fits_stack
#define FITS_STACK               "FITS_STACK"
#define FS_DATA                  "STACK_DATA"
#define FS_NOISE                 "STACK_NOISE"
#define FS_BADPIX                "STACK_BADPIX"
// kmo_make_image
#define MAKE_IMAGE               "MAKE_IMAGE"
// kmo_noise_map
#define NOISE_MAP                "NOISE_MAP"
// kmo_rotate
#define ROTATE                   "ROTATE"
// kmo_shift
#define SHIFT                    "SHIFT"
// kmo_sky_mask
#define SKY_MASK                 "SKY_MASK"
// kmo_stats
#define STATS                    "STATS"
// kmo_strip
#define STRIP                    "STRIP"
// kmos_sky_tweak
#define CUBE_SKY                 "CUBE_SKY"
#define SKY_TWEAK                "SKY_TWEAK"

// needed for sof-workaround (if a file is provided instead of a sof-file)
#define COMMANDLINE              "COMMAND_LINE"

/* ----- additional keywords added by recipes ------------------------------- */
#define FILT_ID                  "ESO FILT ID"
// kmo_fit_profile
//#define FIT_METHOD               "FIT METHOD"
#define FIT_MAX_PIX              "ESO PRO FIT MAX PIX"
#define FIT_MAX_PIX_X            "ESO PRO FIT MAX PIX X"
#define FIT_MAX_PIX_Y            "ESO PRO FIT MAX PIX Y"
#define FIT_CENTROID             "ESO PRO FIT CENTROID"
#define FIT_CENTROID_X           "ESO PRO FIT CENTROID X"
#define FIT_CENTROID_Y           "ESO PRO FIT CENTROID Y"
#define FIT_RADIUS_X             "ESO PRO FIT RADIUS X"
#define FIT_RADIUS_Y             "ESO PRO FIT RADIUS Y"
#define FIT_OFFSET               "ESO PRO FIT OFFSET"
#define FIT_INTENSITY            "ESO PRO FIT INTENS"
#define FIT_SIGMA                "ESO PRO FIT SIGMA"
#define FIT_ALPHA                "ESO PRO FIT ALPHA"
#define FIT_BETA                 "ESO PRO FIT BETA"
#define FIT_SCALE                "ESO PRO FIT SCALE"
#define FIT_ROTATION             "ESO PRO FIT ROT"
#define FIT_ERR_CENTROID         "ESO PRO FIT ERR CENTROID"
#define FIT_ERR_CENTROID_X       "ESO PRO FIT ERR CENTROID X"
#define FIT_ERR_CENTROID_Y       "ESO PRO FIT ERR CENTROID Y"
#define FIT_ERR_RADIUS_X         "ESO PRO FIT ERR RADIUS X"
#define FIT_ERR_RADIUS_Y         "ESO PRO FIT ERR RADIUS Y"
#define FIT_ERR_OFFSET           "ESO PRO FIT ERR OFFSET"
#define FIT_ERR_ROTATION         "ESO PRO FIT ERR ROT"
#define FIT_ERR_INTENSITY        "ESO PRO FIT ERR INTENS"
#define FIT_ERR_SIGMA            "ESO PRO FIT ERR SIGMA"
#define FIT_ERR_ALPHA            "ESO PRO FIT ERR ALPHA"
#define FIT_ERR_BETA             "ESO PRO FIT ERR BETA"
#define FIT_ERR_SCALE            "ESO PRO FIT ERR SCALE"
#define FIT_RED_CHISQ            "ESO PRO FIT RED CHISQ"

/* ----- QC parameters ------------------------------------------------------ */
// kmo_dark
#define QC_DARK                  "ESO QC DARK"
#define QC_DARK_MEDIAN           "ESO QC DARK MEDIAN"
#define QC_READNOISE             "ESO QC RON"
#define QC_READNOISE_MEDIAN      "ESO QC RON MEDIAN"
#define QC_NR_BAD_PIX            "ESO QC BADPIX NCOUNTS"
#define QC_DARK_CURRENT          "ESO QC DARKCUR"

// kmo_flat
#define QC_FLAT_EFF              "ESO QC FLAT EFF"
#define QC_FLAT_SAT              "ESO QC FLAT SAT NCOUNTS"
#define QC_FLAT_SN               "ESO QC FLAT SN"
#define QC_GAP_MEAN              "ESO QC GAP MEAN"
#define QC_GAP_SDV               "ESO QC GAP SDV"
#define QC_GAP_MAXDEV            "ESO QC GAP MAXDEV"
#define QC_SLIT_MEAN             "ESO QC SLIT MEAN"
#define QC_SLIT_SDV              "ESO QC SLIT SDV"
#define QC_SLIT_MAXDEV           "ESO QC SLIT MAXDEV"

// kmo_wave_cal
#define QC_ARC_AR_EFF            "ESO QC ARC AR EFF"
#define QC_ARC_NE_EFF            "ESO QC ARC NE EFF"
#define QC_ARC_SAT               "ESO QC ARC SAT NCOUNTS"
#define QC_ARC_AR_POS_MEAN       "ESO QC ARC AR POS MEAN"
#define QC_ARC_AR_POS_MAXDIFF    "ESO QC ARC AR POS MAXDIFF"
#define QC_ARC_AR_POS_MAXDIFF_ID "ESO QC ARC AR POS MAXDIFF ID"
#define QC_ARC_AR_POS_STDEV      "ESO QC ARC AR POS STDEV"
#define QC_ARC_AR_POS_95ILE      "ESO QC ARC AR POS 95PILE"
#define QC_ARC_AR_FWHM_MEAN      "ESO QC ARC AR FWHM MEAN"
#define QC_ARC_AR_FWHM_STDEV     "ESO QC ARC AR FWHM STDEV"
#define QC_ARC_AR_FWHM_95ILE     "ESO QC ARC AR FWHM 95PILE"
#define QC_ARC_AR_VSCALE         "ESO QC ARC AR VSCALE"
#define QC_ARC_NE_POS_MEAN       "ESO QC ARC NE POS MEAN"
#define QC_ARC_NE_POS_MAXDIFF    "ESO QC ARC NE POS MAXDIFF"
#define QC_ARC_NE_POS_MAXDIFF_ID "ESO QC ARC NE POS MAXDIFF ID"
#define QC_ARC_NE_POS_STDEV      "ESO QC ARC NE POS STDEV"
#define QC_ARC_NE_POS_95ILE      "ESO QC ARC NE POS 95PILE"
#define QC_ARC_NE_FWHM_MEAN      "ESO QC ARC NE FWHM MEAN"
#define QC_ARC_NE_FWHM_STDEV     "ESO QC ARC NE FWHM STDEV"
#define QC_ARC_NE_FWHM_95ILE     "ESO QC ARC NE FWHM 95PILE"
#define QC_ARC_NE_VSCALE         "ESO QC ARC NE VSCALE"

// kmo_illumination
#define QC_SPAT_UNIF             "ESO QC SPAT UNIF"
#define QC_SPAT_MAX_DEV          "ESO QC SPAT MAX DEV"
#define QC_SPAT_MAX_DEV_ID       "ESO QC SPAT MAX DEV ID"
#define QC_SPAT_MAX_NONUNIF      "ESO QC SPAT MAX NONUNIF"
#define QC_SPAT_MAX_NONUNIF_ID   "ESO QC SPAT MAX NONUNIF ID"

// kmo_std_star
#define QC_ZEROPOINT             "ESO QC ZPOINT"
#define QC_SPAT_RES              "ESO QC SPAT RES"
#define QC_THROUGHPUT            "ESO QC THRUPUT"
#define QC_THROUGHPUT_MEAN       "ESO QC THRUPUT MEAN"
#define QC_THROUGHPUT_SDV        "ESO QC THRUPUT SDV"
#define QC_STD_TRACE             "ESO QC STD TRACE"
#define QC_NR_STD_STARS          "ESO QC NR STD STARS"
#define QC_SNR                   "ESO QC SNR"

/*------------------------------------------------------------------------------
                        Functions prototypes
 -----------------------------------------------------------------------------*/

extern int override_err_msg;
extern int print_cal_angle_msg_once;
extern int print_xcal_angle_msg_once;
extern int cal_load_had_xcal;
extern int cal_load_had_ycal;
extern double cal_load_first_angle;
extern double cal_load_second_angle;

//extern int sat_mode_msg;
//extern int sat_mode_last_device_nr;

const char*         strlower(char *s);

void                kmo_clean_string(char *str);

cpl_error_code      kmo_extname_extractor(const char *extname,
                                       enum kmo_frame_type *type,
                                       int *id,
                                       char *content);

char*               kmo_extname_creator(enum kmo_frame_type type,
                                       int device_nr,
                                       const char *content);

cpl_error_code     kmo_update_sub_keywords(cpl_propertylist *pl,
                                       int is_noise,
                                       int is_badpix,
                                       enum kmo_frame_type type,
                                       int device_nr);

int                kmo_get_index_from_ocs_name(const cpl_frame *frame,
                                       const char *ocs_name);

char*              kmo_get_name_from_ocs_ifu(const cpl_frame *frame,
                                       int ifu_nr);

/* ---------------------- load -------------------------------------------- */
cpl_propertylist*  kmo_dfs_load_primary_header(
                                       cpl_frameset *frameset,
                                       const char *category);

cpl_propertylist * kmos_dfs_load_sub_header(
        cpl_frame       *   frame,
        int                 device,
        int                 noise) ;

cpl_propertylist*  kmo_dfs_load_sub_header(
                                       cpl_frameset *frameset,
                                       const char *category,
                                       int device,
                                       int noise);
kmclipm_vector * kmos_dfs_load_vector(
        cpl_frame       *   frame,
        int                 device,
        int                 noise) ;

kmclipm_vector*    kmo_dfs_load_vector(cpl_frameset *frameset,
                                       const char *category,
                                       int device,
                                       int noise);

cpl_image*         kmo_dfs_load_image(cpl_frameset *frameset,
                                       const char *category,
                                       int device,
                                       int noise,
                                       int sat_mode,
                                       int *nr_sat);

cpl_image* kmo_dfs_load_cal_image(cpl_frameset *frameset,
                                  const char *category,
                                  int device,
                                  int noise,
                                  double angle,
                                  int sat_mode,
                                  int *nr_sat,
                                  double *angle_found,
                                  int ifu_nr,
                                  int low_bound,
                                  int high_bound);

cpl_image*         kmo_dfs_load_image_window(
                                       cpl_frameset *frameset,
                                       const char *category,
                                       int device,
                                       int noise,
                                       int llx,
                                       int lly,
                                       int urx,
                                       int ury,
                                       int sat_mode,
                                       int *nr_sat);

cpl_image*         kmo_dfs_load_image_frame(
                                       cpl_frame *frame,
                                       int device,
                                       int noise,
                                       int sat_mode,
                                       int *nr_sat);

cpl_image*         kmo_dfs_load_cal_image_frame(
                                       cpl_frame *frame,
                                       int device,
                                       int noise,
                                       double angle,
                                       int sat_mode,
                                       int *nr_sat,
                                       double *angle_found,
                                       int ifu_nr,
                                       int low_bound,
                                       int high_bound);

cpl_image*         kmo_dfs_load_image_frame_window(
                                       cpl_frame *frame,
                                       int device,
                                       int noise,
                                       int llx,
                                       int lly,
                                       int urx,
                                       int ury,
                                       int sat_mode,
                                       int *nr_sat);
cpl_imagelist * kmos_dfs_load_cube(
        cpl_frame   *   frame,
        int             device,
        int             noise) ;

cpl_imagelist*     kmo_dfs_load_cube(cpl_frameset *frameset,
                                       const char *category,
                                       int device,
                                       int noise);

cpl_table*         kmo_dfs_load_table(cpl_frameset *frameset,
                                       const char *category,
                                       int device,
                                       int noise);

/* ---------------------- save -------------------------------------------- */
char*              kmo_dfs_get_suffix(const cpl_frame *frame,
                                       int grating,
                                       int angle);

cpl_error_code     kmo_dfs_save_main_header(cpl_frameset *frameset,
                                       const char *category,
                                       const char *suffix,
                                       const cpl_frame *frame,
                                       const cpl_propertylist *header,
                                       const cpl_parameterlist *parlist,
                                       const char *recipename);

cpl_error_code     kmo_dfs_save_sub_header(const char *category,
                                       const char *suffix,
                                       const cpl_propertylist *pl);

cpl_error_code     kmo_dfs_save_vector(kmclipm_vector *vec,
                                       const char *category,
                                       const char *suffix,
                                       cpl_propertylist *header,
                                       double rej_val);

cpl_error_code     kmo_dfs_save_image(cpl_image *image,
                                       const char *category,
                                       const char *suffix,
                                       cpl_propertylist *header,
                                       double rej_val);

cpl_error_code     kmo_dfs_save_cube(cpl_imagelist *imagelist,
                                       const char *category,
                                       const char *suffix,
                                       cpl_propertylist *header,
                                       double rej_val);

cpl_error_code     kmo_dfs_save_table(cpl_table *table,
                                       const char *category,
                                       const char *suffix,
                                       cpl_propertylist *header);

/* ---------------------- get frame --------------------------------------- */
cpl_frame*         kmo_dfs_get_frame(cpl_frameset *frameset,
                                       const char *category);

/* ---------------------- get parameters ---------------------------------- */
int                kmo_dfs_get_parameter_bool(cpl_parameterlist *parlist,
                                       const char *name);
int                kmo_dfs_get_parameter_int(cpl_parameterlist *parlist,
                                       const char *name);
double             kmo_dfs_get_parameter_double(cpl_parameterlist *parlist,
                                       const char *name);
const char*        kmo_dfs_get_parameter_string(cpl_parameterlist *parlist,
                                       const char *name);

cpl_error_code     kmo_dfs_print_parameter_help(cpl_parameterlist *parlist,
                                       const char *name);

/* ---------------------- get properties ---------------------------------- */
int                kmo_dfs_get_property_bool(cpl_propertylist *header,
                                       const char *keyword);
int                kmo_dfs_get_property_int(cpl_propertylist *header,
                                       const char *keyword);
double             kmo_dfs_get_property_double(const cpl_propertylist *header,
                                       const char *keyword);
const char*        kmo_dfs_get_property_string(cpl_propertylist *header,
                                       const char *keyword);

/* ---------------------- little helpers ---------------------------------- */
int                 kmo_identify_index(const char *filename,
                                       int device,
                                       int noise);

int                 kmo_identify_index_desc(const main_fits_desc desc,
                                       int device,
                                       int noise);

int                 kmo_check_lamp(const cpl_propertylist *header,
                                       const char *bool_id);

int                 kmo_dfs_set_groups(cpl_frameset *frameset) ;

cpl_error_code      kmo_dfs_check_saturation(
                                       cpl_frame *frame,
                                       cpl_image *img,
                                       int sat_mode,
                                       int *nr_sat);

#endif
