/* 
 * 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
 */

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

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

#include <string.h>

#include <cpl.h>

#include "kmo_debug.h"
#include "kmo_utils.h"
#include "kmo_dfs.h"
#include "kmo_error.h"
#include "kmo_priv_make_image.h"
#include "kmo_priv_functions.h"
#include "kmo_functions.h"

/*----------------------------------------------------------------------------*/
/**
  @defgroup kmos_priv_make_image  Helper functions for recipe kmo_make_image.
 */
/*----------------------------------------------------------------------------*/

/**@{*/

/*----------------------------------------------------------------------------*/
/**
  @brief Identifies spectral slices of a cube to collapse.
  @param spec_data_in   The data of the OH-spectrum 
  @param spec_lambda_in The wavelength values of the OH-spectrum 
  @param ranges         The wavelength ranges or NULL
  @param threshold      The maximum threshold (if < 0 it will be ignored).
  @param ifu_crpix      Reference pixel position (CRPIX3 from FITS-header).
  @param ifu_crval      Value of reference pixel (CRVAL3 from FITS-header).
  @param ifu_cdelt      Delta between pixels (CDELT3 from FITS-header).
  @param size_ifu       The number of spectral slices of the IFU.
  @return A vector in case of success, NULL otherwise. The vector is of the
          same size as @c spec_data_in and contains 1 for valid slices and
          0 for invalid slices.
    
  This function identifies spectral slices of a cube to collapse. 
  For that it uses the provided OH spectrum with a threshold AND an optional  
  number of wavelength ranges. 
  
  The wavelength values of the IFU are created and compared to the OH ones.
  A passed maximum threshold is used to select or not the slice. The OH
  intensity is compared to the threshold.
  The oh-spectrum is interpolated to match the spectrum of the IFU.
  The returned vector has to be deallocated with cpl_vector_delete().
  Possible cpl_error_code set in this function:
  @li CPL_ERROR_NULL_INPUT    if any input pointer is NULL
  @li CPL_ERROR_ILLEGAL_INPUT if @c spec_data_in and @c spec_lambda_in don't
                              have the same size
*/
/*----------------------------------------------------------------------------*/
cpl_vector * kmo_identify_slices_with_oh(
        cpl_vector  *   spec_data_in,
        cpl_vector  *   spec_lambda_in,
        cpl_vector  *   ranges,
        double          threshold,
        double          ifu_crpix,
        double          ifu_crval,
        double          ifu_cdelt,
        int             size_ifu)
{
    cpl_vector      *slices           = NULL,
                    *spec_data_out    = NULL,
                    *ifu_lambda_in    = NULL;

    cpl_bivector    *bivec_ref        = NULL,
                    *bivec_out        = NULL;

    double          min_lambda        = -1.0,
                    max_lambda        = -1.0,
                    *data             = NULL;

    int             start_index       = 0,
                    stop_index        = 0,
                    i                 = 0,
                    size_spec         = 0,
                    ind               = 0;

    KMO_TRY
    {
        /* Check inputs */
        KMO_TRY_ASSURE((spec_data_in != NULL) && (spec_lambda_in != NULL),
                CPL_ERROR_NULL_INPUT, "Not all input data is provided!");

        size_spec = cpl_vector_get_size(spec_lambda_in);
        KMO_TRY_ASSURE(cpl_vector_get_size(spec_data_in) == size_spec,
                CPL_ERROR_ILLEGAL_INPUT,
                "Lambda- and data-vector of OH-line have different sizes!");

        /* create lambda-vector for IFU */
        KMO_TRY_EXIT_IF_NULL(ifu_lambda_in = kmo_create_lambda_vec(size_ifu, 
                    ifu_crpix, ifu_crval, ifu_cdelt));
        
        /* Keep only the part of ifu_lambda_in that is on the OH spec range */
        start_index = 0;
        stop_index = size_ifu - 1;
        min_lambda = cpl_vector_get(spec_lambda_in, 0);
        max_lambda = cpl_vector_get(spec_lambda_in, size_spec - 1);
        if ((cpl_vector_get(ifu_lambda_in, 0) <= min_lambda) ||
            (cpl_vector_get(ifu_lambda_in, size_ifu - 1) >= max_lambda)) {
            data = cpl_vector_get_data(ifu_lambda_in);
            for (i = 0; i < size_ifu; i++) {
                if (min_lambda <= data[i]) {
                    start_index = i;
                    break;
                }
            }
            for (i = size_ifu - 1; i >= 0; i--) {
                if (max_lambda >= data[i]) {
                    stop_index = i;
                    break;
                }
            }
            slices=cpl_vector_extract(ifu_lambda_in, start_index, stop_index,1);
            cpl_vector_delete(ifu_lambda_in);
            ifu_lambda_in = slices; slices = NULL;
        }

        /* interpolate oh-line to match lambdas of IFU -> spec_data_out */
        KMO_TRY_EXIT_IF_NULL(
            spec_data_out = cpl_vector_new(stop_index - start_index + 1));
        KMO_TRY_EXIT_IF_NULL(
            bivec_ref = cpl_bivector_wrap_vectors(spec_lambda_in,spec_data_in));
        KMO_TRY_EXIT_IF_NULL(
            bivec_out = cpl_bivector_wrap_vectors(ifu_lambda_in,spec_data_out));
        KMO_TRY_EXIT_IF_ERROR(
            cpl_bivector_interpolate_linear(bivec_out, bivec_ref));
        cpl_bivector_unwrap_vectors(bivec_ref);
        cpl_bivector_unwrap_vectors(bivec_out);

        /* allocate output vector with 0s */
        KMO_TRY_EXIT_IF_NULL(slices = cpl_vector_new(size_ifu));
        KMO_TRY_EXIT_IF_ERROR(cpl_vector_fill(slices, 0.0));

        /* Identify wished Slices and set them to 1 */
        KMO_TRY_EXIT_IF_NULL(data = cpl_vector_get_data(slices));
        ind = 0;
        for (i = start_index; i <= stop_index; i++) {
            if ((ranges == NULL) || kmo_is_in_range(ranges,ifu_lambda_in,ind)) {
                if (threshold < 0.0) {
                    data[i] = 1;
                } else if (threshold > cpl_vector_get(spec_data_out, ind)) {
                    data[i] = 1;
                }
            }
            ind++;
        }
    }
    KMO_CATCH
    {
        KMO_CATCH_MSG();
        cpl_vector_delete(slices); slices = NULL;
    }
    cpl_vector_delete(spec_data_out); spec_data_out = NULL;
    cpl_vector_delete(ifu_lambda_in); ifu_lambda_in = NULL;
    return slices;
}

/** @} */
