/*
 * This file is part of the GIRAFFE Pipeline
 * Copyright (C) 2002-2019 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 St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#ifndef GIWLCALIBRATION_H
#define GIWLCALIBRATION_H

#include <cxtypes.h>

#include <cpl_macros.h>
#include <cpl_parameterlist.h>

#include <gitable.h>
#include <girange.h>
#include <gilinedata.h>
#include <gilocalization.h>
#include <giextraction.h>
#include <giwlsolution.h>


#ifdef __cplusplus
extern "C" {
#endif


/**
 * @brief
 *   Wavelength calibration configuration data structure.
 *
 * TBD
 */


struct GiWCalConfig {

    /**
     * Number of search windows
     */

    cxint line_nwidths;

    /**
     * List of search window widths used for line selection and fit.
     */

    cxint *line_widths;

    /**
     * Factor used to compute the minimal distance between adjacent lines
     * from the search window width. During the line fit only lines with
     * a larger separation are taken into account.
     */

    cxdouble line_separation;

    /**
     * Only lines with neighbours having a relative intensity
     * less than 1./line_fluxratio are accepted
     */

    cxdouble line_fluxratio;

    /**
     * Sets the lower limit of the line brightness. Only lines which
     * are brighter than this limit are selected from the line catalog.
     */

    cxdouble line_brightness;

    /**
     * The number of lines with the highest nominal brightness are selected
     * from the line list.
     */

    cxint line_count;

    /**
     * Wavelength range used for line selection [nm]
     */

    GiRange *line_wlrange;


    /**
     * Line model used during the line detection fit:
     *  - psfexp,
     *  - psfexp2, or
     *  - gaussian
     */

    cxchar *line_model;

    /**
     * Controls whether optical model residuals are used for the initial
     * computation of the line positions. If this is enabled the residuals
     * must be provided through a previous wavelength solution.
     */

    cxchar *line_residuals;

    /**
     * Line detection threshold during the line fitting
     * (multiple of BIAS sigma)
     */

    cxdouble line_threshold;

    /**
     * Accepted difference : position of (raw maximum - fit)
     */

    cxdouble line_offset;

    /**
     * Maximum number of iterations of the Sigma Clipping algorithm used
     * during the line detection fit
     */

    cxint line_niter;

    /**
     * Maximum number of tests performed by the Sigma Clipping algorithm used
     * during the line detection fit
     */

    cxint line_ntest;

    /**
     * Chi Square difference used by the Sigma Clipping algorithm used
     * during the line detection fit
     */

    cxdouble line_dchisq;

    /**
     * Maximum line_width/resolution_width ratio used during the line
     * detection fit
     */

    cxdouble line_rwidthratio;

    /**
     * Exponential line profile exponent used during the line
     * detection fit
     */

    cxdouble line_widthexponent;

    /**
     * Line saturation level.
     */

    cxdouble line_saturation;

    /**
     * Slit offset configuration
     */

    cxint16 slit_position;

    /**
     * Slit offset along dispersion direction
     */

    cxdouble slit_dx;

    /**
     * Slit offset along cross-dispersion direction
     */

    cxdouble slit_dy;

    /**
     * Slit rotation
     */

    cxdouble slit_phi;

    /**
     * Optical Model to use for the x direction fit during the physical
     * optical model fit:
     *  - xoptmod or
     *  - xoptmod2
     */

    cxchar *opt_model;

    /**
     * Optical dispersion direction: 1 or -1
     */

    cxint opt_direction;

    /**
     * Find optimal physical optical model using a fit of them
     * (TRUE/FALSE)
     */

    cxbool opt_solution;

    /**
     * If it is set to @c TRUE the subslit geometry is used for fitting the
     * optical model. Otherwise the whole slit is used.
     */

    cxbool opt_subslits;

    /**
     * Flags defining the optical model free parameters
     */

    cxint16 opt_flags;

    /**
     * Maximum number of iterations of the Sigma Clipping algorithm used
     * during the optical model fit
     */

    cxint opt_niter;

    /**
     * Maximum number of tests performed by the Sigma Clipping algorithm used
     * during the optical model fit
     */

    cxint opt_ntest;

    /**
     * Chi Square difference used by the Sigma Clipping algorithm used
     * during the optical model fit
     */

    cxdouble opt_dchisq;

    /**
     * Maximum number of sigma levels used by the Sigma Clipping algorithm
     * used during the PSF width fit
     */

    cxdouble pxw_cliplevel;

    /**
     * Maximum number of iterations of the Sigma Clipping algorithm used
     * during the PSF width fit
     */

    cxint pxw_clipniter;

    /**
     * Minimum fraction of rejected data points used by the Sigma Clipping
     * algorithm used during the PSF width fit [0.0..1.0]
     */

    cxdouble pxw_clipmfrac;

    /**
     * X polynomial order used during the PSF width fit (spectral)
     */

    cxint pxw_xorder;

    /**
     * Y polynomial order used during the PSF width fit (spatial)
     */

    cxint pxw_yorder;

    /**
     * Maximum number of sigma levels used by the Sigma Clipping algorithm
     * used during the wavelength solution fit
     */

    cxdouble xws_cliplevel;

    /**
     * Maximum number of iterations of the Sigma Clipping algorithm used
     * during the wavelength solution fit
     */

    cxint xws_clipniter;

    /**
     * Minimum fraction of rejected data points used by the Sigma
     * Clipping algorithm used during the optical model fit [0.0..1.0]
     */

    cxdouble xws_clipmfrac;

    /**
     * X polynomial order used during the X residuals fit
     */

    cxint xws_xorder;

    /**
     * Y polynomial order used during the X residuals fit
     */

    cxint xws_yorder;

};

typedef struct GiWCalConfig GiWCalConfig;


struct GiWCalData {
    GiTable *coeffs;
    GiTable *lines;
    GiLineData *linedata;
};

typedef struct GiWCalData GiWCalData;


GiWCalData *giraffe_wcaldata_new(void);
void giraffe_wcaldata_delete(GiWCalData *self);


cxint giraffe_calibrate_wavelength(GiWCalData *result,
                                   GiExtraction *extraction,
                                   GiLocalization *localization,
                                   GiTable *fibers, GiTable *slitgeometry,
                                   GiTable *grating, GiTable *lines,
                                   GiTable *initial, GiWCalConfig *config);

GiWCalConfig *giraffe_wlcalibration_config_create(cpl_parameterlist *);
void giraffe_wlcalibration_config_destroy(GiWCalConfig *);
void giraffe_wlcalibration_config_add(cpl_parameterlist *);


#ifdef __cplusplus
}
#endif

#endif /* GIWLCALIBRATION_H */
