/* $Id: sinfo_rec_utils.c,v 1.15 2013-09-17 08:10:58 amodigli Exp $
 *
 * This file is part of the SINFONI 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
 */
/*
 * $Author: amodigli $
 * $Date: 2013-09-17 08:10:58 $
 * $Revision: 1.15 $
 * $Name: not supported by cvs2svn $
 */

/****************************************************************
 *           Object Data reduction                              *
 ****************************************************************/

#ifdef HAVE_CONFIG_H
#include <config.h>          /* allows the program compilation */
#endif

/*-----------------------------------------------------------------------------
                                Includes
-----------------------------------------------------------------------------*/
//Used only for cpl_propertylist_has
#include "sinfo_dfs.h"

#include <stdio.h>
#include <sinfo_rec_utils.h>
#include <sinfo_functions.h>
#include <sinfo_new_cubes_build.h>
#include <sinfo_error.h>
#include <sinfo_globals.h>
#include <sinfo_utils_wrappers.h>
/*-----------------------------------------------------------------------------
                            Functions prototypes
 ----------------------------------------------------------------------------*/
/**@{*/
/*---------------------------------------------------------------------------*/
/**
 * @defgroup sinfo_rec_utils   Recipe utilities
 */
/*---------------------------------------------------------------------------*/
static const char* sinfo_new_set_stk_procatg(const char* tag);
/*
static int
sinfo_get_obj_sky_frm_pair(cpl_frameset** obj_set,
                           const int i,
                           cpl_frame** obj_frm,
                           cpl_frame** sky_frm);
 */

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

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

int
sinfo_new_stack_frames(cpl_parameterlist* cfg,
                       cpl_frameset* set,
                       const char* procatg,
                       const int id,
                       fake* fk,
                       const char* plugin_id)
{
    int ind=0;
    sinfo_msg("------------------------------") ;
    sinfo_msg("PREPARE STACKED SET %d",id) ;
    sinfo_msg("------------------------------") ;
    ck0( ( ind = sinfo_new_prepare_stacked_frames(plugin_id,cfg, set, NULL,procatg,
                    id,fk) )," no: %d", ind) ;
    sinfo_msg("------------------------------") ;
    sinfo_msg("PREPARED STACKED SET %d",id) ;
    sinfo_msg("------------------------------") ;
    return 0;

    cleanup:
    return -1;

}

cpl_frame*
sinfo_new_get_dummy_sky(cpl_frameset* obj_set)
{

    cpl_imagelist* obj_list=NULL;
    cpl_image* fake_sky=NULL;
    cpl_frame* frame=NULL;
    cpl_frame* sky_frame=NULL;

    cpl_propertylist* plist=NULL;
    char filename[FILE_NAME_SZ];

    check_nomsg(obj_list=cpl_imagelist_load_frameset(obj_set,CPL_TYPE_FLOAT,0,0));
    check_nomsg(fake_sky = cpl_imagelist_collapse_median_create(obj_list));

    check_nomsg(frame = cpl_frameset_get_frame(obj_set,0));
    strcpy(filename,cpl_frame_get_filename(frame));

    check(plist = cpl_propertylist_load(filename, 0),
          "getting header from reference ima frame %s",filename);

    if (cpl_propertylist_has(plist, KEY_NAME_DPR_TYPE)) {
        cpl_propertylist_set_string(plist, KEY_NAME_DPR_TYPE, "SKY");
    } else {
        cpl_propertylist_append_string(plist, KEY_NAME_DPR_TYPE,"SKY") ;
    }

    check(cpl_image_save(fake_sky, "out_fake_sky.fits", CPL_BPP_IEEE_FLOAT,
                    plist,CPL_IO_DEFAULT),
          "Cannot save the product %s","out_fake_sky.fits");

    sinfo_free_propertylist(&plist);

    check_nomsg(sky_frame = cpl_frame_new()) ;
    check_nomsg(cpl_frame_set_filename(sky_frame, "out_fake_sky.fits")) ;
    check_nomsg(cpl_frame_set_tag(sky_frame, PRO_SKY_DUMMY)) ;
    check_nomsg(cpl_frame_set_type(sky_frame, CPL_FRAME_TYPE_IMAGE));
    /*
  check_nomsg(cpl_frame_set_group(sky_frame, CPL_FRAME_GROUP_PRODUCT));
     */
    check_nomsg(cpl_frame_set_level(sky_frame, CPL_FRAME_LEVEL_FINAL));
    sinfo_free_image(&fake_sky);
    sinfo_free_imagelist(&obj_list);

    return sky_frame;

    cleanup:

    sinfo_free_propertylist(&plist) ;

    return NULL;

}



int
sinfo_new_get_dummy_obj_sky_stacked(cpl_frameset* obj_set,cpl_frameset** set,
                                    cpl_parameterlist* config,fake* fk, char* pro_ctg, const char* plugin_id)
{
    int nobj=0;
    int ncdb=0;
    int ntot=0;
    int nstk=0;
    //int nwrk=0;
    int i=0;
    int k=0;

    double mjd_obj=0;
    double mjd_sky_inf=0;
    double mjd_sky_sup=0;
    char sky_name[FILE_NAME_SZ];
    char out_name[FILE_NAME_SZ];

    char fake_sky_name[FILE_NAME_SZ];

    cpl_frame* obj_frm=NULL;
    cpl_frame* sky_frm=NULL;
    cpl_frame* cdb_frm=NULL;
    cpl_frame* wrk_frm=NULL;
    cpl_frame* tot_frm=NULL;
    cpl_frame* dup_frm=NULL;

    cpl_frame* sky_frm_inf=NULL;
    cpl_frame* sky_frm_sup=NULL;

    cpl_propertylist* plist=NULL;
    cpl_frameset* wrk_set=NULL;
    cpl_frameset* cdb_set=NULL;
    cpl_frameset* tot_set=NULL;
    cpl_frameset* stk_set=NULL;
    cpl_image* sky_ima=NULL;
    double obj_cumx=0;
    double obj_cumy=0;

    double sky_sup_cumx=0;
    double sky_sup_cumy=0;

    double sky_inf_cumx=0;
    double sky_inf_cumy=0;
    double cum_thres=0.5;

    check_nomsg(cdb_set=cpl_frameset_new());
    ck0(sinfo_extract_mst_frames(*set,cdb_set),"Error extracting CDB frames");
    nobj=cpl_frameset_get_size(obj_set);
    ncdb=cpl_frameset_get_size(cdb_set);


    check_nomsg(tot_set=cpl_frameset_new());

    for(i=0;i<nobj;i++) {




        check_nomsg(obj_frm=cpl_frameset_get_frame(obj_set,i));
        mjd_obj    = sinfo_get_mjd_obs(obj_frm);
        obj_cumx=sinfo_get_cumoffsetx(obj_frm);
        obj_cumy=sinfo_get_cumoffsety(obj_frm);

        if(i>0) {
            check_nomsg(sky_frm_inf=cpl_frameset_get_frame(obj_set,i-1));
            mjd_sky_inf = sinfo_get_mjd_obs(sky_frm_inf);
            sky_inf_cumx=sinfo_get_cumoffsetx(sky_frm_inf);
            sky_inf_cumy=sinfo_get_cumoffsety(sky_frm_inf);
        }

        if(i<nobj-1) {
            check_nomsg(sky_frm_sup=cpl_frameset_get_frame(obj_set,i+1));
            mjd_sky_sup = sinfo_get_mjd_obs(sky_frm_sup);
            sky_sup_cumx=sinfo_get_cumoffsetx(sky_frm_sup);
            sky_sup_cumy=sinfo_get_cumoffsety(sky_frm_sup);
        }



        if(i==0) {
            sky_frm = sky_frm_sup;
        }
        else if(i==(nobj-1)) {
            sky_frm = sky_frm_inf;
        } else {
            if( fabs( mjd_sky_inf - mjd_obj ) <
                            fabs( mjd_sky_sup - mjd_obj ) ) {
                if((fabs(sky_inf_cumx-obj_cumx) > cum_thres) ||
                                (fabs(sky_inf_cumy-obj_cumy) > cum_thres)) {
                    sky_frm = sky_frm_inf;
                } else {
                    sky_frm = sky_frm_sup;
                }
            } else {
                if((fabs(sky_sup_cumx-obj_cumx) > cum_thres) ||
                                (fabs(sky_sup_cumy-obj_cumy) > cum_thres)) {
                    sky_frm = sky_frm_sup;
                } else {
                    sky_frm = sky_frm_inf;
                }
            }
        }

        strcpy(sky_name,cpl_frame_get_filename(sky_frm));

        sinfo_msg("obj: %s",cpl_frame_get_filename(obj_frm));
        sinfo_msg("sky: %s",sky_name);

        if (strstr(sky_name, "." ) != NULL ) {
            /*snprintf(fake_sky_name,MAX_NAME_SIZE-1,"%s%s","fake_",
        basename(sky_name)); */
            snprintf(fake_sky_name,MAX_NAME_SIZE-1,"%s%d%s","out_fake_sky",i,".fits");
        } else {
            snprintf(fake_sky_name, MAX_NAME_SIZE-1,"%s", sky_name) ;
        }

        check_nomsg(sky_ima=cpl_image_load(sky_name,CPL_TYPE_FLOAT,0,0));

        cknull(plist = cpl_propertylist_load(sky_name, 0),
               "getting header from reference ima frame %s",sky_name);

        if (cpl_propertylist_has(plist, KEY_NAME_DPR_TYPE)) {
            cpl_propertylist_set_string(plist, KEY_NAME_DPR_TYPE, "SKY");
        } else {
            cpl_propertylist_append_string(plist, KEY_NAME_DPR_TYPE,"SKY") ;
        }

        check(cpl_image_save(sky_ima, fake_sky_name, CPL_BPP_IEEE_FLOAT,
                        plist,CPL_IO_DEFAULT),
              "Cannot save the product %s",fake_sky_name);

        sinfo_free_propertylist(&plist);
        sinfo_free_image(&sky_ima);

        check_nomsg(cpl_frame_set_filename(sky_frm, fake_sky_name)) ;
        /* The following makes program crash
       check_nomsg(cpl_frame_set_tag(sky_frm, PRO_SKY_DUMMY)) ;
         */
        check_nomsg(cpl_frame_set_type(sky_frm, CPL_FRAME_TYPE_IMAGE));
        /* check_nomsg(cpl_frame_set_group(sky_frm, CPL_FRAME_GROUP_PRODUCT)); */
        check_nomsg(cpl_frame_set_level(sky_frm, CPL_FRAME_LEVEL_FINAL));


        check_nomsg(wrk_set=cpl_frameset_new());

        check_nomsg(dup_frm=cpl_frame_duplicate(obj_frm));
        check_nomsg(cpl_frameset_insert(wrk_set,dup_frm));

        check_nomsg(dup_frm=cpl_frame_duplicate(sky_frm));
        check_nomsg(cpl_frameset_insert(wrk_set,dup_frm));


        for(k=0;k<ncdb;k++) {
            check_nomsg(cdb_frm=cpl_frameset_get_frame(cdb_set,k));
            check_nomsg(dup_frm=cpl_frame_duplicate(cdb_frm));
            check_nomsg(cpl_frameset_insert(wrk_set,dup_frm));
        }
        snprintf(out_name,MAX_NAME_SIZE-1,"%s%d%s","out_stack",i,".fits");
        //nwrk=cpl_frameset_get_size(wrk_set);


        ck0(sinfo_new_stack_frames(config,wrk_set,pro_ctg,i,fk,plugin_id),
            "Error stacking frames");

        check_nomsg(cpl_frame_set_filename(sky_frm, sky_name)) ;
        /* This commented as was screwing up the catalogue.
    check_nomsg(cpl_frame_set_tag(sky_frm, RAW_OBJECT_NODDING)) ;
         */
        check_nomsg(stk_set=cpl_frameset_new());
        sinfo_contains_frames_kind(wrk_set,stk_set,PRO_STACKED);
        nstk=cpl_frameset_get_size(stk_set);
        for(k=0;k<nstk;k++) {
            check_nomsg(wrk_frm=cpl_frameset_get_frame(stk_set,k));
            check_nomsg(dup_frm=cpl_frame_duplicate(wrk_frm));
            check_nomsg(cpl_frameset_insert(tot_set,dup_frm));
        }
        sinfo_free_frameset(&stk_set);
        sinfo_free_frameset(&wrk_set);

    }
    ntot=cpl_frameset_get_size(tot_set);
    for(k=0;k<ntot;k++) {
        check_nomsg(tot_frm=cpl_frameset_get_frame(tot_set,k));
        check_nomsg(dup_frm=cpl_frame_duplicate(tot_frm));
        check_nomsg(cpl_frameset_insert(*set,dup_frm));
    }

    sinfo_free_frameset(&cdb_set);
    sinfo_free_frameset(&tot_set);

    return 0;

    cleanup:
    sinfo_free_propertylist(&plist) ;
    sinfo_free_frameset(&cdb_set);
    sinfo_free_frameset(&tot_set);
    return -1;

}

int
sinfo_get_dummy_obj_sky_stacked_and_cubes(cpl_frameset* obj_set,
                                          cpl_frameset** set,
                                          cpl_parameterlist* config,
                                          fake* fk,
                                          char* pro_ctg,
                                          const char* plugin_id)
{
    int nobj=0;
    int ncdb=0;
    //int nwrk=0;
    int i=0;
    int k=0;
    int ind=0;

    double mjd_obj=0;
    double mjd_sky_inf=0;
    double mjd_sky_sup=0;
    char sky_name[FILE_NAME_SZ];
    char out_name[FILE_NAME_SZ];

    char fake_sky_name[FILE_NAME_SZ];

    cpl_frame* obj_frm=NULL;
    cpl_frame* sky_frm=NULL;
    cpl_frame* cdb_frm=NULL;
    cpl_frame* dup_frm=NULL;

    cpl_frame* sky_frm_inf=NULL;
    cpl_frame* sky_frm_sup=NULL;

    cpl_propertylist* plist=NULL;
    cpl_frameset* wrk_set=NULL;
    cpl_frameset* cdb_set=NULL;
    cpl_frameset* tot_set=NULL;
    cpl_frameset* pro_set=NULL;
    cpl_image* sky_ima=NULL;
    double obj_cumx=0;
    double obj_cumy=0;

    double sky_sup_cumx=0;
    double sky_sup_cumy=0;

    double sky_inf_cumx=0;
    double sky_inf_cumy=0;
    double cum_thres=0.5;

    check_nomsg(cdb_set=cpl_frameset_new());
    ck0(sinfo_extract_mst_frames(*set,cdb_set),"Error extracting CDB frames");
    nobj=cpl_frameset_get_size(obj_set);
    ncdb=cpl_frameset_get_size(cdb_set);


    check_nomsg(tot_set=cpl_frameset_new());

    for(i=0;i<nobj;i++) {

        check_nomsg(obj_frm=cpl_frameset_get_frame(obj_set,i));
        mjd_obj    = sinfo_get_mjd_obs(obj_frm);
        obj_cumx=sinfo_get_cumoffsetx(obj_frm);
        obj_cumy=sinfo_get_cumoffsety(obj_frm);

        if(i>0) {
            check_nomsg(sky_frm_inf=cpl_frameset_get_frame(obj_set,i-1));
            mjd_sky_inf = sinfo_get_mjd_obs(sky_frm_inf);
            sky_inf_cumx=sinfo_get_cumoffsetx(sky_frm_inf);
            sky_inf_cumy=sinfo_get_cumoffsety(sky_frm_inf);
        }

        if(i<nobj-1) {
            check_nomsg(sky_frm_sup=cpl_frameset_get_frame(obj_set,i+1));
            mjd_sky_sup = sinfo_get_mjd_obs(sky_frm_sup);
            sky_sup_cumx=sinfo_get_cumoffsetx(sky_frm_sup);
            sky_sup_cumy=sinfo_get_cumoffsety(sky_frm_sup);
        }



        if(i==0) {
            sky_frm = sky_frm_sup;
        }
        else if(i==(nobj-1)) {
            sky_frm = sky_frm_inf;
        } else {
            if( fabs( mjd_sky_inf - mjd_obj ) <
                            fabs( mjd_sky_sup - mjd_obj ) ) {
                if((fabs(sky_inf_cumx-obj_cumx) > cum_thres) ||
                                (fabs(sky_inf_cumy-obj_cumy) > cum_thres)) {
                    sky_frm = sky_frm_inf;
                } else {
                    sky_frm = sky_frm_sup;
                }
            } else {
                if((fabs(sky_sup_cumx-obj_cumx) > cum_thres) ||
                                (fabs(sky_sup_cumy-obj_cumy) > cum_thres)) {
                    sky_frm = sky_frm_sup;
                } else {
                    sky_frm = sky_frm_inf;
                }
            }
        }


        strcpy(sky_name,cpl_frame_get_filename(sky_frm));
        sinfo_msg("obj: %s",cpl_frame_get_filename(obj_frm));
        sinfo_msg("sky: %s",sky_name);
        if (strstr(sky_name, "." ) != NULL ) {
            /*snprintf(fake_sky_name,MAX_NAME_SIZE-1,"%s%s",
                 "fake_",basename(sky_name)); */
            snprintf(fake_sky_name,MAX_NAME_SIZE-1,"%s%d%s","out_fake_sky",i,".fits");
        } else {
            snprintf(fake_sky_name, MAX_NAME_SIZE-1, "%s", sky_name) ;
        }

        check_nomsg(sky_ima=cpl_image_load(sky_name,CPL_TYPE_FLOAT,0,0));

        cknull(plist = cpl_propertylist_load(sky_name, 0),
               "getting header from reference ima frame %s",sky_name);

        if (cpl_propertylist_has(plist, KEY_NAME_DPR_TYPE)) {
            cpl_propertylist_set_string(plist, KEY_NAME_DPR_TYPE, "SKY");
        } else {
            cpl_propertylist_append_string(plist, KEY_NAME_DPR_TYPE,"SKY") ;
        }
        check(cpl_image_save(sky_ima, fake_sky_name, CPL_BPP_IEEE_FLOAT,
                        plist,CPL_IO_DEFAULT),
              "Cannot save the product %s",fake_sky_name);

        sinfo_free_propertylist(&plist);
        sinfo_free_image(&sky_ima);

        check_nomsg(cpl_frame_set_filename(sky_frm, fake_sky_name)) ;
        /* The following makes program crash
       check_nomsg(cpl_frame_set_tag(sky_frm, PRO_SKY_DUMMY)) ;
         */
        check_nomsg(cpl_frame_set_type(sky_frm, CPL_FRAME_TYPE_IMAGE));
        /* check_nomsg(cpl_frame_set_group(sky_frm, CPL_FRAME_GROUP_PRODUCT)); */
        check_nomsg(cpl_frame_set_level(sky_frm, CPL_FRAME_LEVEL_FINAL));


        check_nomsg(wrk_set=cpl_frameset_new());

        check_nomsg(dup_frm=cpl_frame_duplicate(obj_frm));
        check_nomsg(cpl_frameset_insert(wrk_set,dup_frm));

        check_nomsg(dup_frm=cpl_frame_duplicate(sky_frm));
        check_nomsg(cpl_frameset_insert(wrk_set,dup_frm));

        for(k=0;k<ncdb;k++) {
            check_nomsg(cdb_frm=cpl_frameset_get_frame(cdb_set,k));
            check_nomsg(dup_frm=cpl_frame_duplicate(cdb_frm));
            check_nomsg(cpl_frameset_insert(wrk_set,dup_frm));
        }
        snprintf(out_name,MAX_NAME_SIZE-1,"%s%d%s","out_stack",i,".fits");
        //nwrk=cpl_frameset_get_size(wrk_set);


        ck0(sinfo_new_stack_frames(config,wrk_set,pro_ctg,i,fk,plugin_id),
            "Error stacking frames");


        check_nomsg(cpl_frame_set_filename(sky_frm, sky_name)) ;
        /* This commented as was screwing up the catalogue.
    check_nomsg(cpl_frame_set_tag(sky_frm, RAW_OBJECT_NODDING)) ;
         */
        sinfo_msg("--------------------------------------");
        sinfo_msg("BUILDING CUBE %d",i);
        sinfo_msg("--------------------------------------");

        /* cube generation */
        ck0( (ind = sinfo_new_cubes_build(plugin_id,config,wrk_set,pro_ctg,i) ) ,
            "GENERATING CUBE no. %d\n", ind) ;
        sinfo_msg("--------------------------------------");
        sinfo_msg("BUILT CUBE %d",i);
        sinfo_msg("--------------------------------------");


        check_nomsg(sinfo_extract_frames_group_type(wrk_set,&pro_set,
                        CPL_FRAME_GROUP_PRODUCT));
        check_nomsg(cpl_frameset_join(tot_set,pro_set));
        sinfo_free_frameset(&pro_set);
        sinfo_free_frameset(&wrk_set);

    } /* end loop over object frames */

    check_nomsg(sinfo_extract_frames_group_type(tot_set,&pro_set,
                    CPL_FRAME_GROUP_PRODUCT));
    check_nomsg(cpl_frameset_join(*set,pro_set));
    sinfo_free_frameset(&pro_set);
    sinfo_free_frameset(&tot_set);
    sinfo_free_frameset(&cdb_set);

    return 0;

    cleanup:
    sinfo_free_image(&sky_ima);
    sinfo_free_propertylist(&plist) ;
    sinfo_free_frameset(&wrk_set);
    sinfo_free_frameset(&pro_set);
    sinfo_free_frameset(&cdb_set);
    sinfo_free_frameset(&tot_set);
    return -1;

}

int sinfo_cub_stk_frames(cpl_parameterlist* config,
                         cpl_frameset** set,
                         const char* recipe_id,
                         const char** pro_ctg_cube)
{
    cpl_frame     * obj_frm=NULL;
    char tag[FILE_NAME_SZ];
    char pro_ctg_stack[FILE_NAME_SZ];
    char outname[FILE_NAME_SZ];
    char filename[FILE_NAME_SZ];


    cpl_frameset * obj_set=NULL;
    cpl_frameset * sky_set=NULL;
    cpl_frameset * cdb_set=NULL;
    cpl_frameset * wrk_set=NULL;
    cpl_frameset * tot_set=NULL;
    cpl_frameset * pro_set=NULL;
    cpl_frame    * sky_frm=NULL;
    cpl_frame    * cdb_frm=NULL;
    cpl_frame    * dup_frm=NULL;

    int nsky=0;
    int nobj=0;
    int ncdb=0;

    int i=0;
    int j=0;
    int k=0;
    int aj_meth=0;
    int ind=0;

    double mjd_obj=0;
    double mjd_sky=0;
    double mjd_sky_frm=0;
    cpl_parameter* p=NULL;
    fake* fk=sinfo_fake_new();

    obj_set=cpl_frameset_new();
    sky_set=cpl_frameset_new();
    cdb_set=cpl_frameset_new();

    sinfo_extract_obj_frames(*set,obj_set);
    sinfo_extract_sky_frames(*set,sky_set);
    sinfo_extract_mst_frames(*set,cdb_set);

    cknull(obj_frm = cpl_frameset_get_frame(obj_set,0),
           "No object frames in input set.");


    strcpy(tag,cpl_frame_get_tag(obj_frm));
    if(NULL!=sinfo_new_set_obj_procatg(tag)){
        *pro_ctg_cube=sinfo_new_set_obj_procatg(tag);
    } else {
        sinfo_msg_error("Frame tag %s not supported.",tag);
        goto cleanup;
    }


    if(NULL!=sinfo_new_set_stk_procatg(tag)){
        strcpy(pro_ctg_stack,sinfo_new_set_stk_procatg(tag));
    } else {
        sinfo_msg_error("Frame tag %s not supported.",tag);
        goto cleanup;
    }

    nobj=cpl_frameset_get_size(obj_set);
    nsky=cpl_frameset_get_size(sky_set);
    ncdb=cpl_frameset_get_size(cdb_set);

    if ((nobj==0) && (nsky==0)) {
        sinfo_msg_error("Empty input set");
        goto cleanup;
    }


    if ( (nobj != 0) && (nsky != 0) ) {
        /* We have either OBJ and SKY: we need to create OBJ-SKY pairs */
        sinfo_msg("------------------------------") ;
        sinfo_msg("Generates OBJ-SKY pairs");
        sinfo_msg("------------------------------") ;

        check_nomsg(tot_set=cpl_frameset_new());
        check_nomsg(p = cpl_parameterlist_find(config,
                        "sinfoni.objnod.autojitter_method"));
        check_nomsg(cpl_parameter_set_int(p,0));

        for (i=0;i<nobj;i++) {

            cknull_nomsg(wrk_set=cpl_frameset_new());
            check_nomsg(obj_frm=cpl_frameset_get_frame(obj_set,i));
            mjd_obj=sinfo_get_mjd_obs(obj_frm);
            check_nomsg(sky_frm=cpl_frameset_get_frame(sky_set,0));
            mjd_sky=sinfo_get_mjd_obs(sky_frm);
            strcpy(filename,cpl_frame_get_filename(obj_frm));


            for (j=1;j<nsky;j++) {
                mjd_sky_frm = sinfo_get_mjd_obs(cpl_frameset_get_frame(sky_set,j));
                if(1000.*(mjd_sky_frm-mjd_obj)*(mjd_sky_frm-mjd_obj) <
                                1000.*(mjd_sky-    mjd_obj)*(mjd_sky-    mjd_obj) ) {
                    mjd_sky=mjd_sky_frm;
                    check_nomsg(sky_frm=cpl_frameset_get_frame(sky_set,j));
                }
            }
            strcpy(filename,cpl_frame_get_filename(sky_frm));



            /* monitors whih obj-sky frames are inserted in each wrk_set */
            cknull_nomsg(dup_frm=cpl_frame_duplicate(obj_frm));
            check_nomsg(cpl_frameset_insert(wrk_set,dup_frm));
            cknull_nomsg(dup_frm=cpl_frame_duplicate(sky_frm));
            check_nomsg(cpl_frameset_insert(wrk_set,dup_frm));

            /* merged CDB frames to work set */
            for(k=0;k<ncdb;k++) {
                check_nomsg(cdb_frm=cpl_frameset_get_frame(cdb_set,k));
                check_nomsg(dup_frm=cpl_frame_duplicate(cdb_frm));
                check_nomsg(cpl_frameset_insert(wrk_set,dup_frm));
            }


            /* defines a new name for the output stacked frame */
            snprintf(outname,MAX_NAME_SIZE-1,"%s%d%s","out_stack",i,".fits");
            ck0(sinfo_new_stack_frames(config,wrk_set,pro_ctg_stack,i,fk,recipe_id),
                "Cannot stack frames");

            /* cube generation */
            ck0( ( ind=sinfo_new_cubes_build(recipe_id,config,wrk_set,
                            *pro_ctg_cube,i) ) ,
                "GENERATING CUBE no. %d\n", ind) ;

            check_nomsg(sinfo_extract_frames_group_type(wrk_set,
                            &pro_set,
                            CPL_FRAME_GROUP_PRODUCT));
            check_nomsg(cpl_frameset_join(tot_set,pro_set));
            sinfo_free_frameset(&pro_set);
            sinfo_free_frameset(&wrk_set);


        }

        check_nomsg(sinfo_extract_frames_group_type(tot_set,
                        &pro_set,
                        CPL_FRAME_GROUP_PRODUCT));
        check_nomsg(cpl_frameset_join(*set,pro_set));
        sinfo_free_frameset(&pro_set);
        sinfo_free_frameset(&tot_set);

    }


    if ( (nobj == 0) && (nsky != 0) ) {

        /* ===============================================================
        SKY FRAMES STACKING
        =============================================================== */

        {
            sinfo_msg("------------------------------") ;
            sinfo_msg("SKY ONLY FRAMES DATA REDUCTION NOT SUPPORTED") ;
            sinfo_msg("------------------------------") ;
            goto cleanup;
        }


    }



    if ( (nobj != 0) && (nsky == 0) ) {

        /* ===============================================================
        OBJ FRAMES STACKING
        =============================================================== */
        check_nomsg(p=cpl_parameterlist_find(config,
                        "sinfoni.objnod.autojitter_method"));
        check_nomsg(aj_meth =  cpl_parameter_get_int(p));
        if(strcmp(pro_ctg_stack,PRO_PUPIL_LAMP_STACKED) == 0) {

            aj_meth = 0;

        }

        if(aj_meth == 2) {

            sinfo_msg("Dummy sky case");
            sinfo_msg("Fake sky is coming from median of all objects");
            if( (sky_frm = sinfo_new_get_dummy_sky(obj_set)) == NULL) {

                sinfo_msg_error("Problem to get dummy frame");

                return -1;

            }
            sinfo_msg("------------------------------") ;
            sinfo_msg("Generates OBJ-SKY pairs");
            sinfo_msg("------------------------------") ;

            check_nomsg(tot_set=cpl_frameset_new());


            for (i=0;i<nobj;i++) {

                check_nomsg(wrk_set=cpl_frameset_new());
                check_nomsg(obj_frm=cpl_frameset_get_frame(obj_set,i));
                check_nomsg(dup_frm=cpl_frame_duplicate(obj_frm));
                check_nomsg(cpl_frameset_insert(wrk_set,dup_frm));
                check_nomsg(dup_frm=cpl_frame_duplicate(sky_frm));
                check_nomsg(cpl_frameset_insert(wrk_set,dup_frm));
                for(k=0;k<ncdb;k++) {
                    check_nomsg(cdb_frm=cpl_frameset_get_frame(cdb_set,k));
                    check_nomsg(dup_frm=cpl_frame_duplicate(cdb_frm));
                    check_nomsg(cpl_frameset_insert(wrk_set,dup_frm));
                }

                snprintf(outname,MAX_NAME_SIZE-1,"%s%d%s","out_stack",i,".fits");
                ck0(sinfo_new_stack_frames(config,wrk_set,pro_ctg_stack,
                                i,fk,recipe_id),"Error Stacking frame %d",i);


                /* cube generation */
                ck0( ( ind = sinfo_new_cubes_build(recipe_id,config,wrk_set,
                                *pro_ctg_cube,i) ),
                    "Error GENERATING CUBE no. %d\n", ind) ;




                check_nomsg(sinfo_extract_frames_group_type(wrk_set,
                                &pro_set,
                                CPL_FRAME_GROUP_PRODUCT));
                check_nomsg(cpl_frameset_join(tot_set,pro_set));
                sinfo_free_frameset(&pro_set);
                sinfo_free_frameset(&wrk_set);


            }
            check_nomsg(sinfo_extract_frames_group_type(tot_set,
                            &pro_set,
                            CPL_FRAME_GROUP_PRODUCT));
            check_nomsg(cpl_frameset_join(*set,pro_set));
            sinfo_free_frameset(&pro_set);
            sinfo_free_frameset(&tot_set);
            sinfo_free_frame(&sky_frm);
        } else if(aj_meth == 1 ) {


            sinfo_msg("Dummy obj-sky case");
            sinfo_msg("Fake sky is coming from each next object");

            if(nobj > 1) {
                fk->is_fake_sky=1;
                ck0(sinfo_get_dummy_obj_sky_stacked_and_cubes(obj_set,&(*set),config,
                                fk,pro_ctg_stack,recipe_id),
                    "Found error to get obj-sky-stacked frame");

            } else {
                sinfo_msg("Only one object frame, no sky");
                check_nomsg(p=cpl_parameterlist_find(config,
                                "sinfoni.sinfo_utl_skycor.rot_cor"));
                check_nomsg(cpl_parameter_set_bool(p,FALSE));

                ck0(sinfo_new_stack_frames(config,*set,pro_ctg_stack,0,fk,recipe_id),
                    "Error stacking frame");

                /* cube generation */
                sinfo_msg("------------------------------") ;
                sinfo_msg("BUILDING CUBE %d",i);
                sinfo_msg("------------------------------") ;
                ck0(sinfo_new_cubes_build(recipe_id,config,*set,*pro_ctg_cube,i),
                    "Error GENERATING CUBE %d", i) ;

                sinfo_msg("------------------------------") ;
                sinfo_msg("BUILT CUBE %d",i);
                sinfo_msg("------------------------------") ;

            }

        } else { /* aj_meth == 0 */

            sinfo_msg("------------------------------") ;
            sinfo_msg("staks each OBJECT ");
            sinfo_msg("------------------------------") ;
            check_nomsg(tot_set=cpl_frameset_new());

            for (i=0;i<nobj;i++) {

                check_nomsg(wrk_set=cpl_frameset_new());
                check_nomsg(obj_frm=cpl_frameset_get_frame(obj_set,i));
                check_nomsg(dup_frm=cpl_frame_duplicate(obj_frm));
                check_nomsg(cpl_frameset_insert(wrk_set,dup_frm));
                for(k=0;k<ncdb;k++) {
                    check_nomsg(cdb_frm=cpl_frameset_get_frame(cdb_set,k));
                    check_nomsg(dup_frm=cpl_frame_duplicate(cdb_frm));
                    check_nomsg(cpl_frameset_insert(wrk_set,dup_frm));
                }


                snprintf(outname,MAX_NAME_SIZE-1,"%s%d%s","out_stack",i,".fits");
                ck0(sinfo_new_stack_frames(config,wrk_set,pro_ctg_stack,
                                i,fk,recipe_id),"Error stacking frame %d",i);


                /* cube generation */
                sinfo_msg("------------------------------") ;
                sinfo_msg("BUILDING CUBE %d",i);
                sinfo_msg("------------------------------") ;
                ck0( ( ind=sinfo_new_cubes_build(recipe_id,config,wrk_set,
                                *pro_ctg_cube,i) ),
                    "Error GENERATING CUBE no. %d\n", ind) ;

                sinfo_msg("------------------------------") ;
                sinfo_msg("BUILT CUBE %d",i);
                sinfo_msg("------------------------------") ;
                check_nomsg(sinfo_extract_frames_group_type(wrk_set,
                                &pro_set,
                                CPL_FRAME_GROUP_PRODUCT));
                check_nomsg(cpl_frameset_join(tot_set,pro_set));
                sinfo_free_frameset(&pro_set);
                sinfo_free_frameset(&wrk_set);


            }


            check_nomsg(sinfo_extract_frames_group_type(tot_set,
                            &pro_set,
                            CPL_FRAME_GROUP_PRODUCT));
            check_nomsg(cpl_frameset_join(*set,pro_set));
            sinfo_free_frameset(&pro_set);
            sinfo_free_frameset(&tot_set);

        }
    }
    sinfo_free_frameset(&obj_set);
    sinfo_free_frameset(&sky_set);
    sinfo_free_frameset(&cdb_set);
    sinfo_fake_delete(&fk);

    return 0;

    cleanup:

    sinfo_free_frameset(&wrk_set);
    sinfo_free_frameset(&tot_set);
    sinfo_free_frameset(&obj_set);
    sinfo_free_frameset(&sky_set);
    sinfo_free_frameset(&cdb_set);
    sinfo_fake_delete(&fk);
    return -1;


}



static const char* sinfo_new_set_stk_procatg(const char* tag)
{

    const char* pro_ctg_stack=NULL;

    if(strstr(tag,"OBJ") != NULL) {
        pro_ctg_stack=PRO_OBJECT_NODDING_STACKED;
    } else if(strstr(tag,"PSF") != NULL) {
        pro_ctg_stack=PRO_PSF_CALIBRATOR_STACKED;
    } else if(strstr(tag,"STD") != NULL) {
        pro_ctg_stack=PRO_STD_NODDING_STACKED;
    } else if(strstr(tag,"PUPIL") != NULL) {
        pro_ctg_stack=PRO_PUPIL_LAMP_STACKED;
    } else {
        sinfo_msg_error("frame tag %s not supported",tag);
        return NULL;
    }

    return pro_ctg_stack;

}
const char* sinfo_new_set_obj_procatg(const char* tag)
{
    const char* pro_ctg_cube=NULL;

    if(strstr(tag,"OBJ") != NULL) {
        pro_ctg_cube=PRO_COADD_OBJ;
    } else if(strstr(tag,"PSF") != NULL) {
        pro_ctg_cube=PRO_COADD_PSF;
    } else if(strstr(tag,"STD") != NULL) {
        pro_ctg_cube=PRO_COADD_STD;
    } else if(strstr(tag,"PUPIL") != NULL) {
        pro_ctg_cube=PRO_COADD_PUPIL;
    } else {
        sinfo_msg_error("frame tag %s not supported",tag);
        return NULL;
    }

    return pro_ctg_cube;

}

/*
static int
sinfo_get_obj_sky_frm_pair(
cpl_frameset** obj_set,
const int i,
cpl_frame** obj_frm,
cpl_frame** sky_frm)
{
  double mjd_obj=0;
  double mjd_sky_inf=0;
  double mjd_sky_sup=0;


  double obj_cumx=0;
  double obj_cumy=0;

  double sky_sup_cumx=0;
  double sky_sup_cumy=0;

  double sky_inf_cumx=0;
  double sky_inf_cumy=0;
  double cum_thres=0.5;
  int nobj=0;
  cpl_frame* sky_frm_inf=NULL;
  cpl_frame* sky_frm_sup=NULL;

  check_nomsg(*obj_frm=cpl_frameset_get_frame(*obj_set,i));
  mjd_obj    = sinfo_get_mjd_obs(*obj_frm);
  obj_cumx=sinfo_get_cumoffsetx(*obj_frm);
  obj_cumy=sinfo_get_cumoffsety(*obj_frm);

  if(i>0) {
    check_nomsg(sky_frm_inf=cpl_frameset_get_frame(*obj_set,i-1));
    mjd_sky_inf = sinfo_get_mjd_obs(sky_frm_inf);
    sky_inf_cumx=sinfo_get_cumoffsetx(sky_frm_inf);
    sky_inf_cumy=sinfo_get_cumoffsety(sky_frm_inf);
  }

  if(i<nobj-1) {
    check_nomsg(sky_frm_sup=cpl_frameset_get_frame(*obj_set,i+1));
    mjd_sky_sup = sinfo_get_mjd_obs(sky_frm_sup);
    sky_sup_cumx=sinfo_get_cumoffsetx(sky_frm_sup);
    sky_sup_cumy=sinfo_get_cumoffsety(sky_frm_sup);
  }

  if(i==0) {
    *sky_frm = sky_frm_sup;
  } else if(i==(nobj-1)) {
    *sky_frm = sky_frm_inf;
  } else {
       if( fabs( mjd_sky_inf - mjd_obj ) <
           fabs( mjd_sky_sup - mjd_obj ) ) {
         if((fabs(sky_inf_cumx-obj_cumx) > cum_thres) ||
            (fabs(sky_inf_cumy-obj_cumy) > cum_thres)) {
            *sky_frm = sky_frm_inf;
         } else {
            *sky_frm = sky_frm_sup;
         }
       } else {
         if((fabs(sky_sup_cumx-obj_cumx) > cum_thres) ||
            (fabs(sky_sup_cumy-obj_cumy) > cum_thres)) {
            *sky_frm = sky_frm_sup;
         } else {
            *sky_frm = sky_frm_inf;
         }
       }
  }
  return 0;

 cleanup:
  return -1;

}
 */
/**@}*/
