/* $Id: hawki_save.c,v 1.12 2013/03/25 11:35:10 cgarcia Exp $
 *
 * This file is part of the HAWKI 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

/*
 * $Author: cgarcia $
 * $Date: 2013/03/25 11:35:10 $
 * $Revision: 1.12 $
 * $Name:  $
 */

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

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

#include <string.h>
#include <cpl.h>

#include "hawki_distortion.h"
#include "hawki_save.h"
#include "hawki_load.h"
#include "hawki_pfits.h"
#include "hawki_utils.h"
#include "hawki_dfs.h"

/*----------------------------------------------------------------------------*/
/**
 * @defgroup hawki_save    Saving related functions
 *
 */
/*----------------------------------------------------------------------------*/

/**@{*/

/*----------------------------------------------------------------------------*/
/**
  @brief    Save a HAWKI_NB_DETECTORS extensions HAWKI image
  @param    allframes  The list of input frames for the recipe
  @param    parlist    The list of input parameters
  @param    usedframes The list of raw/calibration frames used for this product
  @param    images     The image list to be saved
  @param    recipe     The recipe name
  @param    procat     The product category tag
  @param    protype    The product type tag
  @param    applist    Optional propertylist to append to primary header or NULL
  @param    applists   Optional propertylists to append to ext headers or NULL
  @param    pipe_id    PACKAGE "/" PACKAGE_VERSION
  @param    filename   Filename
  @return   0 if ok, -1 in error case
 */
/*----------------------------------------------------------------------------*/
int hawki_imagelist_save(
        cpl_frameset                *   allframes,
        const cpl_parameterlist     *   parlist,
        const cpl_frameset          *   usedframes,
        const cpl_imagelist         *   images,
        const char                  *   recipe,
        const char                  *   procat,
        const char                  *   protype,
        const cpl_propertylist      *   applist,
        const cpl_propertylist      **  applists,
        const char                  *   filename)
{
    const char          *   fname;
    cpl_propertylist    *   pro_list;
    cpl_type_bpp            pixeltype;
    char                    sval[16];
    int                     chip_nb;
    int                     iext;

    /* Test entries */
    if (allframes == NULL) return -1 ;

    /* Get a suitable reference frame */
    if((fname = hawki_get_extref_file(allframes)) == NULL)
    {
        cpl_msg_error(__func__, "Could not find a suitable reference frame");
        return -1;
    }

    /* Add the PRO keys */
    if (applist != NULL) pro_list = cpl_propertylist_duplicate(applist) ;
    else pro_list = cpl_propertylist_new() ;
    if (protype != NULL)
        cpl_propertylist_append_string(pro_list, CPL_DFS_PRO_TYPE, protype) ;
    if (procat != NULL)
        cpl_propertylist_append_string(pro_list, CPL_DFS_PRO_CATG, procat) ;

    /* File with extensions */
    if (cpl_dfs_save_image(allframes, NULL, parlist, usedframes, NULL, NULL,
                CPL_BPP_IEEE_FLOAT, recipe, pro_list, NULL, 
                PACKAGE "/" PACKAGE_VERSION,
                filename) != CPL_ERROR_NONE) {
        cpl_msg_error(__func__, "Cannot save the empty primary HDU of file %s",
                filename);
        cpl_propertylist_delete(pro_list);
        return -1 ;
    }

    /* Delete PRO LIST */
    cpl_propertylist_delete(pro_list);

    /* Get the file type */
    if (cpl_image_get_type(cpl_imagelist_get_const(images, 0)) == CPL_TYPE_INT)
        pixeltype = CPL_BPP_32_SIGNED ;
    else
        pixeltype = CPL_BPP_IEEE_FLOAT ;

    /* Save the extensions */
    for (iext=0 ; iext<HAWKI_NB_DETECTORS ; iext++) {
        cpl_propertylist    *   qc_ext_list;

        /* Get the chip number to store in this extension */
        if ((chip_nb = hawki_get_detector_from_ext(fname, iext+1)) == -1) {
            cpl_msg_error(__func__, "Cannot get the chip for extension %d when "
                    "writing file %s", iext+1, filename);
            return -1 ;
        }
        if ((applists != NULL) && (applists[chip_nb-1] != NULL))
            qc_ext_list = cpl_propertylist_duplicate(applists[chip_nb-1]) ;
        else
            qc_ext_list = cpl_propertylist_new() ;

        snprintf(sval, 16, "CHIP%d.INT1", chip_nb) ;
        cpl_propertylist_prepend_string(qc_ext_list, "EXTNAME", sval) ;
        if(cpl_image_save(cpl_imagelist_get_const(images, chip_nb-1), filename,
                       pixeltype, qc_ext_list, CPL_IO_EXTEND) != CPL_ERROR_NONE)
        {
            cpl_msg_error(__func__, "Cannot save extension %d of file %s",
                    iext+1, filename);
            cpl_propertylist_delete(qc_ext_list) ;
            return -1;
        }
        cpl_propertylist_delete(qc_ext_list) ;
    }

    return 0 ;
}

/*----------------------------------------------------------------------------*/
/**
  @brief    Save a main header and prepare it to store additional data
            units later on
  @param    allframes  The list of input frames for the recipe
  @param    parlist    The list of input parameters
  @param    usedframes The list of raw/calibration frames used for this product
  @param    images     The image list to be saved
  @param    recipe     The recipe name
  @param    procat     The product category tag
  @param    protype    The product type tag
  @param    applist    Optional propertylist to append to primary header or NULL
  @param    pipe_id    PACKAGE "/" PACKAGE_VERSION
  @param    filename   Filename
  @return   0 if ok, -1 in error case
 */
/*----------------------------------------------------------------------------*/
int hawki_main_header_save
(cpl_frameset                *   allframes,
 const cpl_parameterlist     *   parlist,
 const cpl_frameset          *   usedframes,
 const char                  *   recipe,
 const char                  *   procat,
 const char                  *   protype,
 const cpl_propertylist      *   applist,
 const char                  *   filename)
{
    cpl_propertylist    *   pro_list;

    /* Test entries */
    if (allframes == NULL) return -1 ;

    /* Add the PRO keys */
    if (applist != NULL) pro_list = cpl_propertylist_duplicate(applist) ;
    else pro_list = cpl_propertylist_new() ;
    if (protype != NULL)
        cpl_propertylist_append_string(pro_list, CPL_DFS_PRO_TYPE, protype) ;
    if (procat != NULL)
        cpl_propertylist_append_string(pro_list, CPL_DFS_PRO_CATG, procat) ;

    /* File with extensions */
    if (cpl_dfs_save_image(allframes, NULL, parlist, usedframes, NULL, NULL,
                CPL_BPP_IEEE_FLOAT, recipe, pro_list, NULL, 
                PACKAGE "/" PACKAGE_VERSION,
                filename) != CPL_ERROR_NONE) {
        cpl_msg_error(__func__, "Cannot save the empty primary HDU of file %s",
                filename);
        cpl_propertylist_delete(pro_list);
        return -1 ;
    }

    /* Delete PRO LIST */
    cpl_propertylist_delete(pro_list);

    return 0 ;
}

/*----------------------------------------------------------------------------*/
/**
  @brief    Save an image into a given extension 
  @return   1 if ok. -1 otherwise

  Extension iext means the main extension.
  For HAWK-I, iext should run from 1 to HAWKI_NB_DETECTORS 
 */
/*----------------------------------------------------------------------------*/
int hawki_image_ext_save
(const cpl_frameset      *   allframes,
 const cpl_image         *   image,
 int                         iext,
 const cpl_propertylist  *   ext_prop_list,
 const char              *   filename)
{
    const char          *   fname;
    cpl_type_bpp            pixeltype;
    cpl_propertylist    *   ext_prop;
    char                    sval[16];
    int                     idet;

    /* Test entries */
    if (allframes == NULL) return -1 ;

    /* Get a suitable reference frame */
    if((fname = hawki_get_extref_file(allframes)) == NULL)
    {
        cpl_msg_error(__func__, "Could not find a suitable reference frame");
        return -1;
    }

    /* Get the file type */
    if (cpl_image_get_type(image) == CPL_TYPE_INT)
        pixeltype = CPL_BPP_32_SIGNED ;
    else
        pixeltype = CPL_BPP_IEEE_FLOAT ;

    /* Save the extension */
    /* Get the chip number to store in this extension */
    if ((idet = hawki_get_detector_from_ext(fname, iext)) == -1) {
        cpl_msg_error(__func__, "Cannot get the chip id for extension %d "
                "when saving %s", iext, filename);
                return -1;
    }
    if (ext_prop_list != NULL)
        ext_prop = cpl_propertylist_duplicate(ext_prop_list) ;
    else
        ext_prop = cpl_propertylist_new() ;

    snprintf(sval, 16, "CHIP%d.INT1", idet) ;
    cpl_propertylist_prepend_string(ext_prop, "EXTNAME", sval) ;
    if(cpl_image_save(image, filename,
                      pixeltype, ext_prop, CPL_IO_EXTEND) != CPL_ERROR_NONE)
    {
        cpl_msg_error(__func__,"Could not save extension %d of file %s",
                iext, filename);
        cpl_propertylist_delete(ext_prop);
        return -1;
    }
    cpl_propertylist_delete(ext_prop) ;

    return 0 ;
}

/*----------------------------------------------------------------------------*/
/**
  @brief    Save a HAWKI_NB_DETECTORS extensions HAWKI image
  @param    allframes  The list of input frames for the recipe
  @param    parlist    The list of input parameters
  @param    usedframes The list of raw/calibration frames used for this product
  @param    images     The images to be saved
  @param    recipe     The recipe name
  @param    procat     The product category tag
  @param    protype    The product type tag
  @param    applist    Optional propertylist to append to primary header or NULL
  @param    applists   Optional propertylists to append to ext headers or NULL
  @param    pipe_id    PACKAGE "/" PACKAGE_VERSION
  @param    filename   Filename
  @return   0 if ok, -1 in error case

    This function allows to store images of different sizes in the
    extensions
 */
/*----------------------------------------------------------------------------*/
int hawki_images_save(
        cpl_frameset                *   allframes,
        const cpl_parameterlist     *   parlist,
        const cpl_frameset          *   usedframes,
        const cpl_image             **  images,
        const char                  *   recipe,
        const char                  *   procat,
        const char                  *   protype,
        const cpl_propertylist      *   applist,
        const cpl_propertylist      **  applists,
        const char                  *   filename)
{
    const char          *   fname ;
    cpl_propertylist    *   pro_list ;
    cpl_type_bpp            pixeltype ;
    cpl_propertylist    *   qc_ext_list ;
    char                    sval[16] ;
    int                     chip_nb ;
    int                     iext;

    /* Test entries */
    if (allframes == NULL) return -1 ;

    /* Get a suitable reference frame */
    if((fname = hawki_get_extref_file(allframes)) == NULL)
    {
        cpl_msg_error(__func__, "Could not find a suitable reference frame");
        return -1;
    }

    /* Add the PRO keys */
    if (applist != NULL) pro_list = cpl_propertylist_duplicate(applist) ;
    else pro_list = cpl_propertylist_new() ;
    if (protype != NULL)
        cpl_propertylist_append_string(pro_list, CPL_DFS_PRO_TYPE, protype) ;
    if (procat != NULL)
        cpl_propertylist_append_string(pro_list, CPL_DFS_PRO_CATG, procat) ;

    /* File with extensions */
    if (cpl_dfs_save_image(allframes, NULL, parlist, usedframes, NULL, NULL,
                CPL_BPP_IEEE_FLOAT, recipe, pro_list, NULL, 
                PACKAGE "/" PACKAGE_VERSION,
                filename) != CPL_ERROR_NONE) {
        cpl_msg_error(__func__, "Cannot save the empty primary HDU of file %s",
                filename);
        cpl_propertylist_delete(pro_list) ;
        return -1 ;
    }

    /* Delete PRO LIST */
    cpl_propertylist_delete(pro_list) ;

    /* Get the file type */
    if (cpl_image_get_type(images[0]) == CPL_TYPE_INT)
        pixeltype = CPL_BPP_32_SIGNED ;
    else
        pixeltype = CPL_BPP_IEEE_FLOAT ;

    /* Save the extensions */
    for (iext=0 ; iext<HAWKI_NB_DETECTORS ; iext++) {
        /* Get the chip number to store in this extension */
        if ((chip_nb = hawki_get_detector_from_ext(fname, iext+1)) == -1) {
            cpl_msg_error(__func__, "Cannot get the chip for extension %d "
                    "when saving file %s", iext+1, filename);
            return -1 ;
        }
        /* Get the QC list */
        if ((applists != NULL) && (applists[chip_nb-1] != NULL))
            qc_ext_list = cpl_propertylist_duplicate(applists[chip_nb-1]) ;
        else
            qc_ext_list = cpl_propertylist_new() ;

        snprintf(sval, 16, "CHIP%d.INT1", chip_nb) ;
        cpl_propertylist_prepend_string(qc_ext_list, "EXTNAME", sval) ;
        if(cpl_image_save(images[chip_nb-1], filename,
                pixeltype, qc_ext_list, CPL_IO_EXTEND) != CPL_ERROR_NONE)
        {
            cpl_msg_error(__func__,"Cannot save extension %d of file %s",
                    iext+1, filename);
            cpl_propertylist_delete(qc_ext_list);
            return -1;
        }
        cpl_propertylist_delete(qc_ext_list) ;
    }
    return 0 ;
}

/*----------------------------------------------------------------------------*/
/**
  @brief    Save a HAWKI_NB_DETECTORS extensions HAWKI table
  @param    allframes  The list of input frames for the recipe
  @param    parlist    The list of input parameters
  @param    usedframes The list of raw/calibration frames used for this product
  @param    tables     The table list to be saved
  @param    recipe     The recipe name
  @param    procat     The product category tag
  @param    protype    The product type tag
  @param    applist    Optional propertylist to append to primary header or NULL
  @param    applists   Optional propertylists to append to ext headers or NULL
  @param    pipe_id    PACKAGE "/" PACKAGE_VERSION
  @param    filename   Filename
  @return   0 if ok, -1 in error case
 */
/*----------------------------------------------------------------------------*/
int hawki_tables_save(
        cpl_frameset                *   allframes,
        const cpl_parameterlist     *   parlist,
        const cpl_frameset          *   usedframes,
        const cpl_table             **  tables,
        const char                  *   recipe,
        const char                  *   procat,
        const char                  *   protype,
        const cpl_propertylist      *   applist,
        const cpl_propertylist      **  applists,
        const char                  *   filename)
{
    cpl_propertylist    *   qc_ext_list ;
    cpl_propertylist    *   pro_list ;
    const char          *   fname ;
    char                    sval[16] ;
    int                     chip_nb ;
    int                     iext;

    /* Test entries */
    if (allframes == NULL) return -1 ;

    /* Get a suitable reference frame */
    if((fname = hawki_get_extref_file(allframes)) == NULL)
    {
        cpl_msg_error(__func__, "Could not find a suitable reference frame");
        return -1;
    }

    /* Add the PRO keys */
    if (applist != NULL) pro_list = cpl_propertylist_duplicate(applist) ;
    else pro_list = cpl_propertylist_new() ;
    if (protype != NULL)
        cpl_propertylist_append_string(pro_list, CPL_DFS_PRO_TYPE, protype) ;
    if (procat != NULL)
        cpl_propertylist_append_string(pro_list, CPL_DFS_PRO_CATG, procat) ;

    /* File with extensions */
    if ((applists != NULL) && (applists[0] != NULL))
        qc_ext_list = cpl_propertylist_duplicate(applists[0]) ;
    else
        qc_ext_list = cpl_propertylist_new() ;
    cpl_propertylist_prepend_string(qc_ext_list, "EXTNAME", "CHIP1.INT1") ;
    if (cpl_dfs_save_table(allframes, NULL, parlist, usedframes, NULL, tables[0],
                qc_ext_list, recipe, pro_list, NULL, 
                PACKAGE "/" PACKAGE_VERSION,
                filename) != CPL_ERROR_NONE) {
        cpl_msg_error(__func__,
                "Cannot save the first extension table of file %s", filename);
        cpl_propertylist_delete(qc_ext_list) ;
        cpl_propertylist_delete(pro_list) ;
        return -1 ;
    }
    cpl_propertylist_delete(qc_ext_list) ;
    cpl_propertylist_delete(pro_list) ;

    /* Save the extensions */
    for (iext=1 ; iext<HAWKI_NB_DETECTORS; iext++) {
        /* Get the chip number to store in this extension */
        if ((chip_nb = hawki_get_detector_from_ext(fname, iext+1)) == -1) {
            cpl_msg_error(__func__, "Cannot get the chip for extension %d "
                    "when writing file %s", iext+1, filename);
            return -1 ;
        }
        if ((applists != NULL) && (applists[chip_nb-1] != NULL))
            qc_ext_list = cpl_propertylist_duplicate(applists[chip_nb-1]) ;
        else
            qc_ext_list = cpl_propertylist_new() ;

        snprintf(sval, 16, "CHIP%d.INT1", chip_nb) ;
        cpl_propertylist_prepend_string(qc_ext_list, "EXTNAME", sval) ;
        if(cpl_table_save(tables[chip_nb-1], NULL, qc_ext_list, filename,
                CPL_IO_EXTEND) != CPL_ERROR_NONE)
        {
            cpl_msg_error(__func__, "Cannot save extension %d of table %s",
                    iext+1, filename);
            cpl_propertylist_delete(qc_ext_list) ;
            return -1;
        }

        cpl_propertylist_delete(qc_ext_list) ;
    }

    return 0 ;
}

/*----------------------------------------------------------------------------*/
/**
  @brief    Save a HAWKI_NB_DETECTORS extensions HAWKI distortion images
  @param    allframes  The list of input frames for the recipe
  @param    parlist    The list of input parameters
  @param    usedframes The list of raw/calibration frames used for this product
  @param    distortion The distortion to save
  @param    recipe     The recipe name
  @param    procat     The product category tag
  @param    protype    The product type tag
  @param    applist    Optional propertylist to append to primary header or NULL
  @param    applists   Optional propertylists to append to ext headers or NULL
  @param    pipe_id    PACKAGE "/" PACKAGE_VERSION
  @param    filename_x Filename for distortion image in X
  @param    filename_y Filename for distortion image in Y
  @return   0 if ok, -1 in error case

    This function allows to store images of different sizes in the
    extensions
 */
/*----------------------------------------------------------------------------*/
int hawki_distortion_save
(cpl_frameset                *   allframes,
 const cpl_parameterlist     *   parlist,
 const cpl_frameset          *   usedframes,
 const hawki_distortion      **  distortion,
 const char                  *   recipe,
 const cpl_propertylist      *   applist,
 const cpl_propertylist      **  applists,
 const char                  *   filename_x,
 const char                  *   filename_y)
{
    const char          *   fname ;
    cpl_propertylist    *   pro_list_x;
    cpl_propertylist    *   pro_list_y;
    cpl_type_bpp            pixeltype ;
    cpl_propertylist    *   qc_ext_list ;
    char                    sval[16] ;
    int                     chip_nb ;
    int                     iext;
    cpl_errorstate      error_prevstate = cpl_errorstate_get();

    /* Test entries */
    if (allframes == NULL) return -1 ;

    /* Get a suitable reference frame */
    if((fname = hawki_get_extref_file(allframes)) == NULL)
    {
        cpl_msg_error(__func__, "Could not find a suitable reference frame");
        return -1;
    }

    /* Add the PRO keys */
    if(applist != NULL)
        pro_list_x = cpl_propertylist_duplicate(applist);
    else
        pro_list_x = cpl_propertylist_new();
    if(applist != NULL) 
        pro_list_y = cpl_propertylist_duplicate(applist);
    else
        pro_list_y = cpl_propertylist_new();
    
    cpl_propertylist_append_string(pro_list_x, CPL_DFS_PRO_TYPE, 
                                   HAWKI_PROTYPE_DISTORTION_X);
    cpl_propertylist_append_string(pro_list_y, CPL_DFS_PRO_TYPE, 
                                   HAWKI_PROTYPE_DISTORTION_Y);
    cpl_propertylist_append_string(pro_list_x, CPL_DFS_PRO_CATG, 
                                   HAWKI_CALPRO_DISTORTION_X);
    cpl_propertylist_append_string(pro_list_y, CPL_DFS_PRO_CATG, 
                                   HAWKI_CALPRO_DISTORTION_Y);

    /* File with extensions */
    if (cpl_dfs_save_image(allframes, NULL, parlist, usedframes, NULL, NULL,
                CPL_BPP_IEEE_FLOAT, recipe, pro_list_x, NULL, 
                PACKAGE "/" PACKAGE_VERSION,
                filename_x) != CPL_ERROR_NONE) {
        cpl_msg_error(__func__, "Cannot save the empty primary HDU of file %s",
                filename_x);
        cpl_propertylist_delete(pro_list_x);
        cpl_propertylist_delete(pro_list_y);
        return -1 ;
    }
    if (cpl_dfs_save_image(allframes, NULL, parlist, usedframes, NULL, NULL,
                CPL_BPP_IEEE_FLOAT, recipe, pro_list_y, NULL, 
                PACKAGE "/" PACKAGE_VERSION,
                filename_y) != CPL_ERROR_NONE) {
        cpl_msg_error(__func__, "Cannot save the empty primary HDU of file %s",
                filename_y);
        cpl_propertylist_delete(pro_list_x);
        cpl_propertylist_delete(pro_list_y);
        return -1 ;
    }

    /* Delete PRO LIST */
    cpl_propertylist_delete(pro_list_x);
    cpl_propertylist_delete(pro_list_y);

    /* Get the file type */
    if (cpl_image_get_type(distortion[0]->dist_x) == CPL_TYPE_INT)
        pixeltype = CPL_BPP_32_SIGNED ;
    else
        pixeltype = CPL_BPP_IEEE_FLOAT ;

    /* Save the extensions */
    for (iext=0 ; iext<HAWKI_NB_DETECTORS ; iext++) {
        /* Get the chip number to store in this extension */
        if ((chip_nb = hawki_get_detector_from_ext(fname, iext+1)) == -1) {
            cpl_msg_error(__func__, "Cannot get the chip for extension %d "
                    "when saving %s and %s", iext+1, filename_x, filename_y);
            return -1 ;
        }
        /* Get the QC list */
        if ((applists != NULL) && (applists[chip_nb-1] != NULL))
            qc_ext_list = cpl_propertylist_duplicate(applists[chip_nb-1]) ;
        else
            qc_ext_list = cpl_propertylist_new() ;

        /* Add the CR* keywords */
        cpl_propertylist_prepend_double(qc_ext_list, "CRPIX2", 1);
        cpl_propertylist_prepend_double(qc_ext_list, "CDELT2",
                                        distortion[chip_nb-1]->y_cdelt);
        cpl_propertylist_prepend_double(qc_ext_list, "CRVAL2",
                                        distortion[chip_nb-1]->y_crval);
        cpl_propertylist_prepend_double(qc_ext_list, "CRPIX1", 1);
        cpl_propertylist_prepend_double(qc_ext_list, "CDELT1",
                                        distortion[chip_nb-1]->x_cdelt);
        cpl_propertylist_prepend_double(qc_ext_list, "CRVAL1",
                                        distortion[chip_nb-1]->x_crval);
        
        snprintf(sval, 16, "CHIP%d.INT1", chip_nb) ;
        cpl_propertylist_prepend_string(qc_ext_list, "EXTNAME", sval) ;
        if(cpl_image_save(distortion[chip_nb-1]->dist_x, filename_x,
                pixeltype, qc_ext_list, CPL_IO_EXTEND) != CPL_ERROR_NONE)
        {
            cpl_msg_error(__func__,"Cannot save extension %d of file %s",
                    iext+1, filename_x);
            cpl_propertylist_delete(qc_ext_list);
            return -1;
        }
        if(cpl_image_save(distortion[chip_nb-1]->dist_y, filename_y,
                pixeltype, qc_ext_list, CPL_IO_EXTEND) != CPL_ERROR_NONE)
        {
            cpl_msg_error(__func__,"Cannot save extension %d of file %s",
                    iext+1, filename_y);
            cpl_propertylist_delete(qc_ext_list);
            return -1;
        }
        cpl_propertylist_delete(qc_ext_list) ;
    }
        
    if(!cpl_errorstate_is_equal(error_prevstate ))
    {
        cpl_msg_error(__func__, "Cannot save distortion solution") ;
        return -1 ;
    }

    return 0 ;
}

/*----------------------------------------------------------------------------*/
/**
  @brief    Locate a filename where the extension <--> chip id relation
            can be derived
  @param    frameset A frameset where a suitable frame can be extracted.
  @return   The filename if ok. NULL otherwise

  This function will get the first frame with four extensions that is part
  of the RAW group.
 */
/*----------------------------------------------------------------------------*/

const char * hawki_get_extref_file(const cpl_frameset * frameset)
{
    int iframe;
    const char     * fname = NULL;

    for(iframe = 0 ; iframe < cpl_frameset_get_size(frameset); ++iframe)
    {
        const cpl_frame  * frame;

        frame = cpl_frameset_get_position_const(frameset, iframe);
        /* Check that it belongs to the raw frames
         * and then check if there are 4 extensions
         */
        if(cpl_frame_get_group(frame) == CPL_FRAME_GROUP_RAW &&
           cpl_frame_get_nextensions(frame) == HAWKI_NB_DETECTORS)
        {
            fname = cpl_frame_get_filename(frame);
            return fname;
        }
    }
    //Now look into the products, in case that there is no actual raw
    //reference frame. This is kind of a hack for hawki_util_gendist,
    //which allows to save the distortion images using the distortion
    //table as a reference
    for(iframe = 0 ; iframe < cpl_frameset_get_size(frameset); ++iframe)
    {
        const cpl_frame  * frame;

        frame = cpl_frameset_get_position_const(frameset, iframe);
        /* Check that it belongs to the raw frames
         * and then check if there are 4 extensions
         */
        if(cpl_frame_get_group(frame) == CPL_FRAME_GROUP_PRODUCT &&
           cpl_frame_get_nextensions(frame) == HAWKI_NB_DETECTORS)
        {
            fname = cpl_frame_get_filename(frame);
            return fname;
        }
    }
    //And if it didn't suceed, use the first frame:
    fname = cpl_frame_get_filename(cpl_frameset_get_position_const(frameset,0));

    return fname;
}


/**@}*/
