/*
 * 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 <math.h>

#include <cpl.h>

#include "kmclipm_functions.h"
#include "kmclipm_constants.h"

#include "kmo_utils.h"
#include "kmos_pfits.h"
#include "kmo_dfs.h"

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

static int kmos_gen_telluric_get_avg_zpoint(
        const cpl_frame     *   zp_frame, 
        double              *   zp1_avg,
        double              *   zp2_avg,
        double              *   zp3_avg) ;
static int kmos_gen_telluric_create_file_multiply(
        const cpl_frame         *   data1_frame,
        const cpl_frame         *   data2_frame,
        const cpl_frame         *   zp_frame,
        const char              *   filename,
        cpl_frameset            *   allframes,
        const cpl_parameterlist *   parlist) ;
static int kmos_gen_telluric_create_file_simple(
        const cpl_frame         *   data_frame,
        const cpl_frame         *   zp_frame,
        const char              *   filename,
        cpl_frameset            *   allframes,
        const cpl_parameterlist *   parlist) ;

static int kmos_gen_telluric_check_inputs(cpl_frameset *, int);

static int kmos_gen_telluric_create(cpl_plugin *);
static int kmos_gen_telluric_exec(cpl_plugin *);
static int kmos_gen_telluric_destroy(cpl_plugin *);
static int kmos_gen_telluric(cpl_parameterlist *, cpl_frameset *);

/*-----------------------------------------------------------------------------
 *                          Static variables
 *----------------------------------------------------------------------------*/

static char kmos_gen_telluric_description[] =
"This recipe creates the TELLURIC frame needed by kmos_sci_red by merging\n"
"the TELLURIC (produced by kmos_std_star), the static RESPONЅE frame and \n"
"the TELLURIC_CORR (produced with molecfit).\n"
"The way the frames are combined is controlled by the --method parameter:\n" 
"   - 0 (default) : use TELLURIC and get zpoint from TELLURIC\n"
"           If TELLURIC missing, use RESPONSE and get zpoint from RESPONSE\n"
"   - 1 : use TELLURIC_CORR and get zpoint from TELLURIC_CORR\n"
"   - 2 : use RESPONSE and get zpoint from TELLURIC\n"
"           If TELLURIC missing, get zpoint from RESPONSE\n"
"           For missing ZPOINTs, use the average of other IFUs for the \n"
"           same detector. \n"
"   - 3 : use RESPONSE x TELLURIC_CORR and get zpoint from TELLURIC_CORR\n"
"\n"
"----------------------------------------------------------------------------\n"
"Input files:\n"
"\n"
"   DO category         Explanation                    Required \n"
"   -----------         -----------                    -------- \n"
"   TELLURIC            Produced  by kmos_std_star          N\n"
"   TELLURIC_CORR       Produced  bym molecfit              N\n"
"   RESPONSE            static calibration                  N\n"
"\n"
"Output files:\n"
"\n"
"   DO category         Explanation\n"
"   -----------         -----------\n"
"   TELLURIC            Used by kmos_sci_red\n"
"----------------------------------------------------------------------------\n"
"\n";

/*-----------------------------------------------------------------------------
 *                              Functions code
 *----------------------------------------------------------------------------*/

/**
 * @defgroup kmos_gen_telluric  Generate a TELLURIC frame
 */

/**@{*/

/*----------------------------------------------------------------------------*/
/**
  @brief    Build the list of available plugins, for this module. 
  @param    list    the plugin list
  @return   0 if everything is ok, -1 otherwise

  Create the recipe instance and make it available to the application using the 
  interface. This function is exported.
 */
/*----------------------------------------------------------------------------*/
int cpl_plugin_get_info(cpl_pluginlist *list)
{
    cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe);
    cpl_plugin *plugin = &recipe->interface;

    cpl_plugin_init(plugin,
            CPL_PLUGIN_API,
            KMOS_BINARY_VERSION,
            CPL_PLUGIN_TYPE_RECIPE,
            "kmos_gen_telluric",
            "Generate a TELLURIC frame",
            kmos_gen_telluric_description,
            "Yves Jung",
            "usd-help@eso.org",
            kmos_get_license(),
            kmos_gen_telluric_create,
            kmos_gen_telluric_exec,
            kmos_gen_telluric_destroy);
    cpl_pluginlist_append(list, plugin);

    return 0;
}

/*----------------------------------------------------------------------------*/
/**
  @brief    Setup the recipe options    
  @param    plugin  the plugin
  @return   0 if everything is ok

  Defining the command-line/configuration parameters for the recipe.
 */
/*----------------------------------------------------------------------------*/
static int kmos_gen_telluric_create(cpl_plugin *plugin)
{
    cpl_recipe *recipe;
    cpl_parameter *p;

    // Check that the plugin is part of a valid recipe
    if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
        recipe = (cpl_recipe *)plugin;
    else
        return -1;

    // Create the parameters list in the cpl_recipe object
    recipe->parameters = cpl_parameterlist_new();

    // Fill the parameters list
    /* --method */
    p = cpl_parameter_new_value("kmos.kmos_gen_telluric.method",
            CPL_TYPE_INT, "How the TELLURIC is generated",
            "kmos.kmos_gen_telluric", 0);
    cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "method");
    cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
    cpl_parameterlist_append(recipe->parameters, p);

    return 0;
}

/*----------------------------------------------------------------------------*/
/**
  @brief    Execute the plugin instance given by the interface
  @param    plugin  the plugin
  @return   0 if everything is ok
 */
/*----------------------------------------------------------------------------*/
static int kmos_gen_telluric_exec(cpl_plugin *plugin)
{
    cpl_recipe  *recipe;

    // Get the recipe out of the plugin
    if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
        recipe = (cpl_recipe *)plugin;
    else return -1;

    return kmos_gen_telluric(recipe->parameters, recipe->frames);
}

/*----------------------------------------------------------------------------*/
/**
  @brief    Destroy what has been created by the 'create' function
  @param    plugin  the plugin
  @return   0 if everything is ok
 */
/*----------------------------------------------------------------------------*/
static int kmos_gen_telluric_destroy(cpl_plugin *plugin)
{
    cpl_recipe *recipe;

    // Get the recipe out of the plugin
    if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
        recipe = (cpl_recipe *)plugin;
    else return -1 ;

    cpl_parameterlist_delete(recipe->parameters);
    return 0 ;
}

/*----------------------------------------------------------------------------*/
/**
  @brief    Interpret the command line options and execute the data processing
  @param    parlist     the parameters list
  @param    frameset   the frames list
  @return   0 if everything is ok
 */
/*----------------------------------------------------------------------------*/
static int kmos_gen_telluric(cpl_parameterlist *parlist, cpl_frameset *frameset)
{
    const cpl_parameter     *   par ;
    int                         method ;
    cpl_frame               *   tell_frame ;
    cpl_frame               *   tell_corr_frame ;
    cpl_frame               *   resp_frame ;
    const char              *   fn ;

    int                         i, j, ifu_nr, ext_nb ;
    
    /* Check entries */
    if (parlist == NULL || frameset == NULL) {
        cpl_msg_error(__func__, "Null Inputs") ;
        cpl_error_set(__func__, CPL_ERROR_NULL_INPUT) ;
        return -1 ;
    }

    /* Initialise */
    fn = "kmos_gen_telluric.fits" ;
    
    /* Get Parameters */
    par = cpl_parameterlist_find_const(parlist,"kmos.kmos_gen_telluric.method");
    method = cpl_parameter_get_int(par);

    /* Identify the RAW and CALIB frames in the input frameset */
    if (kmo_dfs_set_groups(frameset) != 1) {
        cpl_msg_error(__func__, "Cannot identify RAW and CALIB frames") ;
        cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
        return -1 ;
    }

    /* Check the inputs consistency */
    if (kmos_gen_telluric_check_inputs(frameset, method) != 1) {
        cpl_msg_error(__func__, "Input frameset / parameter is unconsistent") ;
        cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
        return -1 ;
    }

    /* Get frames */
    tell_frame = cpl_frameset_find(frameset, TELLURIC) ;
    resp_frame = cpl_frameset_find(frameset, RESPONSE) ;
    tell_corr_frame = cpl_frameset_find(frameset, TELLURIC_CORR) ;

    /* Switch on the methods */
    if (method == 0) {
        if (tell_frame != NULL) {
            cpl_msg_info(__func__, "Use %s for Data and Zpoint", 
                    cpl_frame_get_filename(tell_frame)) ;
            kmos_gen_telluric_create_file_simple(tell_frame, NULL, fn,
                    frameset, parlist) ;
        } else {
            cpl_msg_info(__func__, "Use %s for Data and Zpoint", 
                    cpl_frame_get_filename(resp_frame)) ;
            kmos_gen_telluric_create_file_simple(resp_frame, NULL, fn,
                    frameset, parlist) ;
        }
    } else if (method == 1) {
        cpl_msg_info(__func__, "Use %s for Data and Zpoint", 
                cpl_frame_get_filename(tell_corr_frame)) ;
            kmos_gen_telluric_create_file_simple(tell_corr_frame, NULL, fn,
                    frameset, parlist) ;
    } else if (method == 2) {
        if (tell_frame != NULL) {
            cpl_msg_info(__func__, "Use %s for Data and %s for Zpoint",
                    cpl_frame_get_filename(resp_frame),
                    cpl_frame_get_filename(tell_frame)) ;
            kmos_gen_telluric_create_file_simple(resp_frame, tell_frame, fn,
                    frameset, parlist) ;
        } else {
            cpl_msg_info(__func__, "Use %s for Data and Zpoint", 
                    cpl_frame_get_filename(resp_frame)) ;
            kmos_gen_telluric_create_file_simple(resp_frame, NULL, fn,
                    frameset, parlist) ;
        }
    } else if (method == 3) {
        cpl_msg_info(__func__, "Use %s X %s for Data and %s for Zpoint", 
                cpl_frame_get_filename(resp_frame),
                cpl_frame_get_filename(tell_corr_frame),
                cpl_frame_get_filename(tell_corr_frame)) ;
        kmos_gen_telluric_create_file_multiply(resp_frame, tell_corr_frame, 
                tell_corr_frame, fn, frameset, parlist) ;
    } else {
        cpl_msg_error(__func__, "Unsupported - Should never come here") ;
        cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
        return -1 ;
    }
    return 0;
}

/**@}*/

static int kmos_gen_telluric_create_file_multiply(
        const cpl_frame         *   data1_frame,
        const cpl_frame         *   data2_frame,
        const cpl_frame         *   zp_frame,
        const char              *   filename,
        cpl_frameset            *   allframes,
        const cpl_parameterlist *   parlist)
{
    cpl_propertylist        *   mh ;
    cpl_propertylist        *   applist ;
    cpl_propertylist        *   eh ;
    cpl_propertylist        *   zph ;
    cpl_vector              *   vec1 ;
    cpl_vector              *   vec2 ;
    double                      zpoint ;
    enum kmo_frame_type         ft ;
    char                        content[256] ;
    const char              *   extname ;
    char                	*   keyword ;
    int                         i, ext_nb, id, ifu_nr ;
    
    /* Initialise */
    id = -1 ;
    ft = illegal_frame ; 

    /* Load main header */
    mh=kmclipm_propertylist_load(cpl_frame_get_filename(data1_frame), 0);

    /* Get Extensions number */
    ext_nb = cpl_fits_count_extensions(cpl_frame_get_filename(data1_frame)) ;

    /* Create applist with PRO CATG  */
    applist = cpl_propertylist_new() ;
    cpl_propertylist_update_string(applist, CPL_DFS_PRO_CATG, "TELLURIC") ;

    /* Create PRO_STD keywords */
    for (i = 0; i < ext_nb ; i++) {
        /* Load extension header */
        eh = kmclipm_propertylist_load(cpl_frame_get_filename(data2_frame),i+1);
        /* Read EXTNAME */
        extname = cpl_propertylist_get_string(eh, "EXTNAME") ;
        kmo_extname_extractor(extname, &ft, &ifu_nr, content) ;
        cpl_propertylist_delete(eh); 
        /* Load the data */
        vec1 = cpl_vector_load(cpl_frame_get_filename(data2_frame), i+1) ;
        if (vec1 != NULL) {
            cpl_vector_delete(vec1) ;

            /* The Telluric is presenet in this IFU - write the keyword */
            keyword = cpl_sprintf("%s%d", PRO_STD, ifu_nr);
            cpl_propertylist_update_int(applist, keyword, 1);
            cpl_free(keyword);
        } else {
            cpl_error_reset() ;
        }
    }

    /* Save product */
    cpl_dfs_save_propertylist(allframes, mh, parlist, allframes, NULL,
            "kmos_gen_telluric", applist, NULL, PACKAGE "/" PACKAGE_VERSION, 
            filename) ;

    cpl_propertylist_delete(mh); 
    cpl_propertylist_delete(applist); 

    /* Loop on the extensions */
    for (i = 0; i < ext_nb ; i++) {

        /* Load extension header */
        eh = kmclipm_propertylist_load(cpl_frame_get_filename(data1_frame),i+1);

        /* Read EXTNAME */
        extname = cpl_propertylist_get_string(eh, "EXTNAME") ;
        kmo_extname_extractor(extname, &ft, &id, content) ;

        /* Load the data */
        vec1 = cpl_vector_load(cpl_frame_get_filename(data1_frame), i+1) ;
        vec2 = cpl_vector_load(cpl_frame_get_filename(data2_frame), i+1) ;
        if (vec1 == NULL || vec2 == NULL) cpl_error_reset() ;

        /* Need to update ZPOINT ? */
        if (vec1 != NULL && vec2 != NULL && zp_frame != NULL) {
            zph=kmclipm_propertylist_load(cpl_frame_get_filename(zp_frame),i+1);
            zpoint = cpl_propertylist_get_double(zph, "ESO QC ZPOINT");
            cpl_propertylist_delete(zph); 
            if (cpl_error_get_code() != CPL_ERROR_NONE) {
                cpl_msg_warning(__func__, "No QC ZPOINT found in %s",
                        cpl_frame_get_filename(zp_frame)) ;
                cpl_error_reset() ;
            } else {
                cpl_propertylist_update_double(eh, "ESO QC ZPOINT", zpoint) ;
            }
        }

        /* Multiply the 2 vectors if Data */
        if (!strcmp(content, "DATA")) cpl_vector_multiply(vec1, vec2) ;
        cpl_vector_delete(vec2) ;

        /* Save the Extension */
        if (cpl_error_get_code() == CPL_ERROR_NONE) {
            /* Save the data */
            cpl_vector_save(vec1, filename, CPL_TYPE_DOUBLE, eh,CPL_IO_EXTEND) ;
        } else {
            /* Only the header */
            cpl_error_reset() ;
            cpl_propertylist_save(eh, filename, CPL_IO_EXTEND) ;
        }
        cpl_vector_delete(vec1) ;
        cpl_propertylist_delete(eh); 
    }
    return 0 ;
}

static int kmos_gen_telluric_create_file_simple(
        const cpl_frame         *   data_frame,
        const cpl_frame         *   zp_frame,
        const char              *   filename,
        cpl_frameset            *   allframes,
        const cpl_parameterlist *   parlist)
{
    cpl_propertylist        *   mh ;
    cpl_propertylist        *   applist ;
    cpl_propertylist        *   eh ;
    cpl_propertylist        *   zph ;
    cpl_vector              *   vec ;
    double                      zpoint, zp1_avg, zp2_avg, zp3_avg ;
    int                         i, ext_nb, id, det_nr, ifu_nr ;
    enum kmo_frame_type         ft ;
    char                        content[256] ;
    char                	*   keyword ;
    const char              *   extname ;
    
    /* Initialise */
    zp1_avg = zp2_avg = zp3_avg = -1.0 ;
    id = -1 ;
    ft = illegal_frame ; 

    /* Get Extensions number */
    ext_nb = cpl_fits_count_extensions(cpl_frame_get_filename(data_frame)) ;

    /* Load main header */
    mh=kmclipm_propertylist_load(cpl_frame_get_filename(data_frame), 0);

    /* Create applist with PRO CATG  */
    applist = cpl_propertylist_new() ;
    cpl_propertylist_update_string(applist, CPL_DFS_PRO_CATG, "TELLURIC") ;

    /* Create PRO_STD keywords */
    for (i = 0; i < ext_nb ; i++) {
        /* Load extension header */
        eh = kmclipm_propertylist_load(cpl_frame_get_filename(data_frame), i+1);
        /* Read EXTNAME */
        extname = cpl_propertylist_get_string(eh, "EXTNAME") ;
        kmo_extname_extractor(extname, &ft, &ifu_nr, content) ;
        cpl_propertylist_delete(eh); 
        /* Load the data */
        vec = cpl_vector_load(cpl_frame_get_filename(data_frame), i+1) ;
        if (vec != NULL) {
            cpl_vector_delete(vec) ;

            /* The Telluric is presenet in this IFU - write the keyword */
            keyword = cpl_sprintf("%s%d", PRO_STD, ifu_nr);
            cpl_propertylist_update_int(applist, keyword, 1);
            cpl_free(keyword);
        } else {
            cpl_error_reset() ;
        }
    }

    /* Save product */
    cpl_dfs_save_propertylist(allframes, mh, parlist, allframes, NULL,
            "kmos_gen_telluric", applist, NULL, PACKAGE "/" PACKAGE_VERSION, 
            filename) ;

    cpl_propertylist_delete(mh); 
    cpl_propertylist_delete(applist); 

    /* Get ZPOINT averages per detector from the Zp_frame */
    if (zp_frame != NULL) {
         kmos_gen_telluric_get_avg_zpoint(zp_frame,&zp1_avg,&zp2_avg,&zp3_avg) ;
    }

    /* Loop on the extensions */
    for (i = 0; i < ext_nb ; i++) {

        /* Load extension header */
        eh = kmclipm_propertylist_load(cpl_frame_get_filename(data_frame), i+1);

        /* Read EXTNAME */
        extname = cpl_propertylist_get_string(eh, "EXTNAME") ;
        kmo_extname_extractor(extname, &ft, &id, content) ;

        if (id >= 1 && id <= 8)         det_nr = 1 ;
        else if (id >= 9 && id <= 16)   det_nr = 2 ;
        else if (id >= 17 && id <= 24)  det_nr = 3 ;
        else {
            cpl_msg_error(__func__, "Cannot Identify the detector") ;
            cpl_propertylist_delete(eh); 
            return -1 ;
        }

        /* Load the data */
        vec = cpl_vector_load(cpl_frame_get_filename(data_frame), i+1) ;
        if (vec == NULL) cpl_error_reset() ;

        /* Need to update ZPOINT ? */
        if (vec != NULL && zp_frame != NULL) {
            zph=kmclipm_propertylist_load(cpl_frame_get_filename(zp_frame),i+1);
            zpoint = cpl_propertylist_get_double(zph, "ESO QC ZPOINT");
            cpl_propertylist_delete(zph); 
            if (cpl_error_get_code() != CPL_ERROR_NONE) {
                cpl_error_reset() ;
                if (det_nr == 1)        zpoint = zp1_avg ;
                else if (det_nr == 2)   zpoint = zp2_avg ;
                else                    zpoint = zp3_avg ;
                cpl_msg_warning(__func__, 
                        "No QC ZPOINT in %s[%d] - Use average for Det %d: %g",
                        cpl_frame_get_filename(zp_frame), i+1, det_nr, zpoint) ;
            }
            cpl_propertylist_update_double(eh, "ESO QC ZPOINT", zpoint) ;
        }

        /* Save the Extension */
        if (vec != NULL) {
            /* Save the data */
            cpl_vector_save(vec, filename, CPL_TYPE_DOUBLE, eh, CPL_IO_EXTEND) ;
            cpl_vector_delete(vec) ;
        } else {
            /* Only the header */
            cpl_propertylist_save(eh, filename, CPL_IO_EXTEND) ;
        }
        cpl_propertylist_delete(eh); 
    }
    return 0 ;
}

/*----------------------------------------------------------------------------*/
/**
  @brief    Compute Average ZPOINTs per detector
  @param    zp_frame    Input frame
  @param    zp1_avg     Avg ZPOINTS on Det 1
  @param    zp2_avg     Avg ZPOINTS on Det 2
  @param    zp3_avg     Avg ZPOINTS on Det 3
  @return   0 if ok, -1 in error case
 */
/*----------------------------------------------------------------------------*/
static int kmos_gen_telluric_get_avg_zpoint(
        const cpl_frame     *   zp_frame, 
        double              *   zp1_avg,
        double              *   zp2_avg,
        double              *   zp3_avg)
{
    double                  zp1_avg_loc, zp2_avg_loc, zp3_avg_loc, zpoint ; ;
    int                     zp1_nb, zp2_nb, zp3_nb, ext_nb, id, det_nr, i;
    cpl_propertylist    *   eh ;
    const char          *   extname ;
    enum kmo_frame_type     ft ;
    char                    content[256] ;

    /* Check entries */
    if (zp_frame==NULL || zp1_avg==NULL || zp2_avg==NULL || zp3_avg==NULL)
        return -1 ;

    /* Initialise */
    *zp1_avg = *zp2_avg = *zp3_avg = -1.0 ;
    zp1_nb = zp2_nb = zp3_nb = 0 ;
    zp1_avg_loc = zp2_avg_loc = zp3_avg_loc = 0.0 ;
    id = -1 ;
    ft = illegal_frame ; 

    /* Get Extensions number */
    ext_nb = cpl_fits_count_extensions(cpl_frame_get_filename(zp_frame)) ;

    /* Loop on the extensions */
    for (i = 0; i < ext_nb ; i++) {
        /* Load extension header */
        eh = kmclipm_propertylist_load(cpl_frame_get_filename(zp_frame), i+1);

        /* Read EXTNAME */
        extname = cpl_propertylist_get_string(eh, "EXTNAME") ;
        kmo_extname_extractor(extname, &ft, &id, content) ;

        /* Is Data ? */
        if (!strcmp(content, "DATA")) {
            /* Read ZPOINT */
            zpoint = cpl_propertylist_get_double(eh, "ESO QC ZPOINT");

            /* ZPOINT is there ? */
            if (cpl_error_get_code() == CPL_ERROR_NONE) {
                /* Get the detector Nr */
                if (id >= 1 && id <= 8)         det_nr = 1 ;
                else if (id >= 9 && id <= 16)   det_nr = 2 ;
                else if (id >= 17 && id <= 24)  det_nr = 3 ;
                else {
                    cpl_msg_error(__func__, "Cannot Identify the detector") ;
                    cpl_propertylist_delete(eh); 
                    return -1 ;
                }

                if (det_nr == 1) {
                    zp1_avg_loc += zpoint ;
                    zp1_nb ++ ;
                } else if (det_nr == 2) {
                    zp2_avg_loc += zpoint ;
                    zp2_nb ++ ;
                } else if (det_nr == 3) {
                    zp3_avg_loc += zpoint ;
                    zp3_nb ++ ;
                } else {
                    cpl_msg_error(__func__, "Cannot Identify the detector") ;
                    cpl_propertylist_delete(eh); 
                    return -1 ;
                }
            } else {
                cpl_error_reset() ;
            }
        }
        cpl_propertylist_delete(eh); 
    }

    /* Divide by the number */
    if (zp1_nb > 0) *zp1_avg = zp1_avg_loc / zp1_nb ;
    if (zp2_nb > 0) *zp2_avg = zp2_avg_loc / zp2_nb ;
    if (zp3_nb > 0) *zp3_avg = zp3_avg_loc / zp3_nb ;
    return 0 ;
} 
    
/*----------------------------------------------------------------------------*/
/**
  @brief    Make consistency checks
  @param    frameset        Set of frames 
  @param    method          Input parameter
  @return   1 if consistent, 0 if not, -1 in error case
 */
/*----------------------------------------------------------------------------*/
static int kmos_gen_telluric_check_inputs(
        cpl_frameset            *   frameset, 
        int                         method)
{
    cpl_frame       *   tell_frame ;
    cpl_frame       *   tell_corr_frame ;
    cpl_frame       *   resp_frame ;

    /* Check Entries */
    if (frameset == NULL) return -1;
    if (method < 0 || method > 3) return -1 ;

    tell_frame = cpl_frameset_find(frameset, TELLURIC) ;
    resp_frame = cpl_frameset_find(frameset, RESPONSE) ;
    tell_corr_frame = cpl_frameset_find(frameset, TELLURIC_CORR) ;

    if (method == 0 && tell_frame == NULL && resp_frame == NULL) 
        return 0 ;
    if (method == 1 && tell_corr_frame == NULL) 
        return 0 ;
    if (method == 2 && resp_frame == NULL) 
        return 0 ;
    if (method == 3 && (resp_frame == NULL || tell_corr_frame == NULL)) 
        return 0 ;
    return 1 ;
}

 
