KMOS Pipeline Reference Manual  1.3.15
kmos_combine.c
00001 /* 
00002  * This file is part of the KMOS Pipeline
00003  * Copyright (C) 2002,2003 European Southern Observatory
00004  *
00005  * This program is free software; you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License as published by
00007  * the Free Software Foundation; either version 2 of the License, or
00008  * (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program; if not, write to the Free Software
00017  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018  */
00019 
00020 #ifdef HAVE_CONFIG_H
00021 #include <config.h>
00022 #endif
00023 
00024 /*-----------------------------------------------------------------------------
00025  *                              Includes
00026  *----------------------------------------------------------------------------*/
00027 
00028 #include <string.h>
00029 #include <math.h>
00030 
00031 #include <cpl.h>
00032 #include <cpl_wcs.h>
00033 
00034 #include "kmo_debug.h"
00035 #include "kmo_utils.h"
00036 #include "kmo_dfs.h"
00037 #include "kmo_error.h"
00038 #include "kmo_priv_functions.h"
00039 #include "kmo_cpl_extensions.h"
00040 #include "kmo_constants.h"
00041 #include "kmo_priv_combine.h"
00042 
00043 /*-----------------------------------------------------------------------------
00044  *                          Functions prototypes
00045  *----------------------------------------------------------------------------*/
00046 
00047 static char * kmos_combine_create_used_ifus_string(const int *,const int *,int);
00048 static cpl_bivector * kmos_combine_parse_skipped(const char *) ;
00049 static int kmos_combine_is_skipped(const cpl_bivector *, int, int) ;
00050 
00051 static int kmos_combine_create(cpl_plugin *);
00052 static int kmos_combine_exec(cpl_plugin *);
00053 static int kmos_combine_destroy(cpl_plugin *);
00054 static int kmos_combine(cpl_parameterlist *, cpl_frameset *);
00055 
00056 /*-----------------------------------------------------------------------------
00057  *                          Static variables
00058  *----------------------------------------------------------------------------*/
00059 
00060 static char kmos_combine_description[] =
00061 "This recipe shifts several exposures of an object and combines them. Diffe-\n"
00062 "rent methods to match the exposures are described here (--method parameter).\n"
00063 "The output cube is larger than the input cubes, according to the shifts to\n"
00064 "be applied. Additionally a border of NaN values is added. The WCS is the\n"
00065 "same as for the first exposure.\n"
00066 "For each spatial/spectral pixel a new value is calculated (according the\n"
00067 "--cmethod parameter) and written into the output cube.\n"
00068 "Only exposures with the same WCS orientation can be combined (except\n"
00069 "-–method=”none”), north must point to the same direction. It is recommended\n"
00070 "to apply any rotation possibly after combining.\n"
00071 "\n"
00072 "The behavior of the selection of IFUs to combine differs for some templates\n"
00073 "and can be controlled with the parameters --name and --ifus.\n"
00074 "If the input data cubes stem from templates KMOS_spec_obs_mapping8 or\n"
00075 "KMOS_spec_obs_mapping24 all extensions from all input frames are combined\n"
00076 "into a single map by default (like in recipe kmo_sci_red). If just the area\n"
00077 "of a specific IFU should be combined, the parameter --ifus can be specified,\n"
00078 "or more easily --name.\n"
00079 "If the input data cubes stem from other templates like e.g.\n"
00080 "KMOS_spec_obs_freedither all extensions of all input frames are combined\n"
00081 "into several output frames by default. The input IFUs are grouped according\n"
00082 "to their targeted object name stored in the keywords ESO OCS ARMx NAME. If \n"
00083 "just a specific object should be combined, its name can be specified with \n"
00084 "--name. If arbitrary IFUs shoukd be comined, one can specify these with the\n"
00085 "parameter --ifus.\n"
00086 "\n"
00087 "The default mapping mode is done via the --name parameter, where the name of\n"
00088 "the object has to be provided. The recipe searches in input data cubes IFUs\n"
00089 "pointing to that object.\n"
00090 "\n"
00091 "---------------------------------------------------------------------------\n"
00092 "  Input files:\n"
00093 "\n"
00094 "   DO                  KMOS                                                \n"
00095 "   category            Type   Explanation                  Required #Frames\n"
00096 "   --------            -----  -----------                  -------- -------\n"
00097 "   <none or any>       F3I    data frame                       Y      2-n  \n"
00098 "\n"
00099 "  Output files:\n"
00100 "\n"
00101 "   DO                      KMOS\n"
00102 "   category                Type    Explanation\n"
00103 "   --------                -----   -----------\n"
00104 "   COMBINE_<ESO PRO CATG>  F3I     Combined data cube\n"
00105 "   EXP_MASK_<ESO PRO CATG> F3I     Exposure time mask\n"
00106 "   SCI_COMBINED_COLL               (optional) Collapsed combined cube\n"
00107 "                                   (set --collapse_combined)\n"
00108 "---------------------------------------------------------------------------\n"
00109 "\n";
00110 
00111 /*-----------------------------------------------------------------------------
00112  *                              Functions code
00113  *----------------------------------------------------------------------------*/
00114 
00115 /*----------------------------------------------------------------------------*/
00119 /*----------------------------------------------------------------------------*/
00120 
00123 /*----------------------------------------------------------------------------*/
00132 /*----------------------------------------------------------------------------*/
00133 int cpl_plugin_get_info(cpl_pluginlist *list)
00134 {
00135     cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe);
00136     cpl_plugin *plugin = &recipe->interface;
00137 
00138     cpl_plugin_init(plugin,
00139             CPL_PLUGIN_API,
00140             KMOS_BINARY_VERSION,
00141             CPL_PLUGIN_TYPE_RECIPE,
00142             "kmos_combine",
00143             "Combine reconstructed cubes",
00144             kmos_combine_description,
00145             "Alex Agudo Berbel, Y. Jung",
00146             "usd-help@eso.org",
00147             kmos_get_license(),
00148             kmos_combine_create,
00149             kmos_combine_exec,
00150             kmos_combine_destroy);
00151     cpl_pluginlist_append(list, plugin);
00152 
00153     return 0;
00154 }
00155 
00156 /*----------------------------------------------------------------------------*/
00164 /*----------------------------------------------------------------------------*/
00165 static int kmos_combine_create(cpl_plugin *plugin)
00166 {
00167     cpl_recipe *recipe;
00168     cpl_parameter *p;
00169 
00170     /* Check that the plugin is part of a valid recipe */
00171     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00172         recipe = (cpl_recipe *)plugin;
00173     else
00174         return -1;
00175 
00176     /* Create the parameters list in the cpl_recipe object */
00177     recipe->parameters = cpl_parameterlist_new();
00178 
00179     /* Fill the parameters list */
00180     /* --name */
00181     p = cpl_parameter_new_value("kmos.kmos_combine.name", CPL_TYPE_STRING,
00182             "Name of the object to combine.", "kmos.kmos_combine", "");
00183     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "name");
00184     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00185     cpl_parameterlist_append(recipe->parameters, p);
00186 
00187     /* --ifus */
00188     p = cpl_parameter_new_value("kmos.kmos_combine.ifus", CPL_TYPE_STRING,
00189             "The indices of the IFUs to combine. " "\"ifu1;ifu2;...\"", 
00190             "kmos.kmos_combine", "");
00191     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "ifus");
00192     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00193     cpl_parameterlist_append(recipe->parameters, p);
00194 
00195     /* --method */
00196     p = cpl_parameter_new_value("kmos.kmos_combine.method", CPL_TYPE_STRING,
00197             "The shifting method:   "
00198             "'none': no shifting, combined directly, "
00199             "'header': shift according to WCS (default), "
00200             "'center': centering algorithm, "
00201             "'user': read shifts from file",
00202             "kmos.kmos_combine", "none");
00203     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "method");
00204     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00205     cpl_parameterlist_append(recipe->parameters, p);
00206 
00207     /* --fmethod */
00208     p = cpl_parameter_new_value("kmos.kmos_combine.fmethod", CPL_TYPE_STRING,
00209             "The fitting method (applies only when method='center'):   "
00210             "'gauss': fit a gauss function to collapsed image (default), "
00211             "'moffat': fit a moffat function to collapsed image",
00212             "kmos.kmos_combine", "gauss");
00213     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "fmethod");
00214     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00215     cpl_parameterlist_append(recipe->parameters, p);
00216 
00217     /* --filename */
00218     p = cpl_parameter_new_value("kmos.kmos_combine.filename", CPL_TYPE_STRING,
00219             "The path to the file with the shift vectors (method='user')",
00220             "kmos.kmos_combine", "");
00221     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "filename");
00222     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00223     cpl_parameterlist_append(recipe->parameters, p);
00224 
00225     /* --flux */
00226     p = cpl_parameter_new_value("kmos.kmos_combine.flux", CPL_TYPE_BOOL,
00227             "Apply flux conservation: (TRUE (apply) or FALSE (don't apply)",
00228             "kmos.kmos_combine", FALSE);
00229     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "flux");
00230     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00231     cpl_parameterlist_append(recipe->parameters, p);
00232 
00233     /* --edge_nan */
00234     p = cpl_parameter_new_value("kmos.kmos_combine.edge_nan", CPL_TYPE_BOOL,
00235             "Set borders of cubes to NaN before combining them."
00236             "(TRUE (apply) or FALSE (don't apply)", "kmos.kmos_combine", FALSE);
00237     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "edge_nan");
00238     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00239     cpl_parameterlist_append(recipe->parameters, p);
00240 
00241     /* --skipped_frames */
00242     p = cpl_parameter_new_value("kmos.kmos_combine.skipped_frames", 
00243             CPL_TYPE_STRING,
00244             "Comma separated List of IFUs to skip for the combination. An IFU is specified with R:I."
00245             "R is the index (starting at 1) of the reconstructed frame, I the IFU number", 
00246             "kmos.kmos_combine", "");
00247     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "skipped_frames");
00248     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00249     cpl_parameterlist_append(recipe->parameters, p);
00250 
00251     /* --suppress_extension */
00252     p = cpl_parameter_new_value("kmos.kmos_combine.suppress_extension",
00253             CPL_TYPE_BOOL, "Suppress arbitrary filename extension.",
00254             "kmos.kmos_combine", FALSE);
00255     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "suppress_extension");
00256     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00257     cpl_parameterlist_append(recipe->parameters, p);
00258 
00259     /* --collapse_combined */
00260     p = cpl_parameter_new_value("kmos.kmos_combine.collapse_combined",
00261             CPL_TYPE_BOOL, "Flag to collapse the combined images",
00262             "kmos.kmos_combine", FALSE);
00263     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "collapse_combined");
00264     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00265     cpl_parameterlist_append(recipe->parameters, p);
00266 
00267     return kmos_combine_pars_create(recipe->parameters, "kmos.kmos_combine",
00268             DEF_REJ_METHOD, FALSE);
00269 }
00270 
00271 /*----------------------------------------------------------------------------*/
00277 /*----------------------------------------------------------------------------*/
00278 static int kmos_combine_exec(cpl_plugin *plugin)
00279 {
00280     cpl_recipe  *recipe;
00281 
00282     /* Get the recipe out of the plugin */
00283     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00284         recipe = (cpl_recipe *)plugin;
00285     else return -1 ;
00286 
00287     return kmos_combine(recipe->parameters, recipe->frames);
00288 }
00289 
00290 /*----------------------------------------------------------------------------*/
00296 /*----------------------------------------------------------------------------*/
00297 static int kmos_combine_destroy(cpl_plugin *plugin)
00298 {
00299     cpl_recipe *recipe;
00300 
00301     /* Get the recipe out of the plugin */
00302     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00303         recipe = (cpl_recipe *)plugin;
00304     else return -1 ;
00305 
00306     cpl_parameterlist_delete(recipe->parameters);
00307     return 0 ;
00308 }
00309 
00310 /*----------------------------------------------------------------------------*/
00323 /*----------------------------------------------------------------------------*/
00324 static int kmos_combine(cpl_parameterlist *parlist, cpl_frameset *frameset)
00325 {
00326     const cpl_parameter *   par ;
00327     const char      * filename,* fmethod,* method,* ifus_txt,* cmethod,
00328                     * skipped_frames;
00329     double          cpos_rej, cneg_rej ;
00330     cpl_vector      *   ifus ;
00331     int                 citer, cmin, cmax, nr_frames, index,
00332                         data_cube_counter, noise_cube_counter, flux,
00333                         edge_nan, name_vec_size, found, suppress_extension,
00334                         suppress_index, ifu_nr, nv, collapse_combined ;
00335     char            * tmp_str, * fn_combine, * fn_mask, * mapping_mode,
00336                     * name, ** name_vec ;
00337     const char      * frame_filename, * tmp_strc ;
00338     cpl_image       * exp_mask ;
00339     cpl_imagelist   ** data_cube_list, ** noise_cube_list, * cube_combined_data,
00340                     * cube_combined_noise ;
00341     cpl_propertylist    * main_header, **data_header_list, **noise_header_list,
00342                         * tmp_header, * pro_plist ;
00343     cpl_bivector    *   skipped_bivector ;
00344     cpl_frame       *   frame ;
00345     cpl_size            ci ;
00346     main_fits_desc      desc;
00347     int             *   used_frame_idx ;
00348     int             *   used_ifus ;
00349     char            *   used_ifus_str ;
00350     enum extrapolationType  extrapol_enum = NONE_CLIPPING;
00351     int             i, j ;
00352 
00353     /* Check entries */
00354     if (parlist == NULL || frameset == NULL) {
00355         cpl_msg_error(__func__, "Null Inputs") ;
00356         cpl_error_set(__func__, CPL_ERROR_NULL_INPUT) ;
00357         return -1 ;
00358     }
00359 
00360     /* Get parameters */
00361     par = cpl_parameterlist_find_const(parlist, "kmos.kmos_combine.method");
00362     method = cpl_parameter_get_string(par) ;
00363     par = cpl_parameterlist_find_const(parlist, "kmos.kmos_combine.fmethod");
00364     fmethod = cpl_parameter_get_string(par) ;
00365     par = cpl_parameterlist_find_const(parlist, "kmos.kmos_combine.filename");
00366     filename = cpl_parameter_get_string(par) ;
00367     par = cpl_parameterlist_find_const(parlist, "kmos.kmos_combine.ifus");
00368     ifus_txt = cpl_parameter_get_string(par) ;
00369     par = cpl_parameterlist_find_const(parlist, "kmos.kmos_combine.name");
00370     name = (char*)cpl_parameter_get_string(par) ;
00371     par = cpl_parameterlist_find_const(parlist, "kmos.kmos_combine.flux");
00372     flux = cpl_parameter_get_bool(par) ;
00373     par = cpl_parameterlist_find_const(parlist, 
00374             "kmos.kmos_combine.skipped_frames");
00375     skipped_frames = cpl_parameter_get_string(par) ;
00376     par = cpl_parameterlist_find_const(parlist, "kmos.kmos_combine.edge_nan");
00377     edge_nan = cpl_parameter_get_bool(par) ;
00378     par = cpl_parameterlist_find_const(parlist,
00379             "kmos.kmos_combine.suppress_extension");
00380     suppress_extension = cpl_parameter_get_bool(par) ;
00381     kmos_combine_pars_load(parlist, "kmos.kmos_combine", &cmethod, &cpos_rej, 
00382             &cneg_rej, &citer, &cmin, &cmax, FALSE);
00383     par = cpl_parameterlist_find_const(parlist,
00384             "kmos.kmos_combine.collapse_combined");
00385     collapse_combined = cpl_parameter_get_bool(par);
00386 
00387     /* Check Parameters */
00388     if (strcmp(method, "none") && strcmp(method, "header") &&
00389             strcmp(method, "center") && strcmp(method, "user")) {
00390         cpl_msg_error(__func__,
00391             "shift methods must be 'none', 'header', 'center' or 'user'") ;
00392         cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
00393         return -1 ;
00394     }
00395     if (strcmp(ifus_txt, "") && strcmp(name, "")) {
00396         cpl_msg_error(__func__,
00397                 "name and IFU indices cannot be both provided") ;
00398         cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
00399         return -1 ;
00400     }
00401     if (!strcmp(method, "user") && !strcmp(filename, "")) {
00402         cpl_msg_error(__func__,
00403                 "path of file with shift information must be provided") ;
00404         cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
00405         return -1 ;
00406     }
00407 
00408     /* Identify the RAW and CALIB frames in the input frameset */
00409     if (kmo_dfs_set_groups(frameset, "kmos_combine") != 1) {
00410         cpl_msg_error(__func__, "Cannot identify RAW and CALIB frames") ;
00411         cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
00412         return -1 ;
00413     }
00414 
00415     /* Parse the skipped frames option */
00416     skipped_bivector = NULL ;
00417     if (strcmp(skipped_frames, "")) {
00418         skipped_bivector = kmos_combine_parse_skipped(skipped_frames) ;
00419         if (skipped_bivector != NULL) 
00420             cpl_msg_info(__func__, "Skip the following frames: %s", 
00421                     skipped_frames);
00422     } 
00423 
00424 
00425     /* Check Nb of frames */
00426     nr_frames = cpl_frameset_get_size(frameset);
00427     if (nr_frames < 2) {
00428         if (skipped_bivector!=NULL) cpl_bivector_delete(skipped_bivector) ;
00429         cpl_msg_error(__func__, "At least two frames must be provided") ;
00430         cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
00431         return -1 ;
00432     }
00433 
00434     /* Load IFUS if specified */
00435     if (strcmp(ifus_txt, "")) {
00436         ifus = kmo_identify_values(ifus_txt);
00437         if (ifus == NULL || cpl_vector_get_size(ifus) != nr_frames) {
00438             if (ifus != NULL) cpl_vector_delete(ifus);
00439             if (skipped_bivector!=NULL) cpl_bivector_delete(skipped_bivector) ;
00440             cpl_msg_error(__func__, "ifus size must match the science frames") ;
00441             cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
00442             return -1 ;
00443         }
00444     } else {
00445         ifus = NULL ;
00446     }
00447 
00448     /* Check for mapping mode */
00449     mapping_mode = NULL ;
00450     cpl_size fs_size = cpl_frameset_get_size(frameset);
00451     for (ci = 0; ci < fs_size; ci++) {
00452         frame = cpl_frameset_get_position(frameset, ci);
00453         tmp_header = kmclipm_propertylist_load(cpl_frame_get_filename(frame),0);
00454         if (cpl_propertylist_has(tmp_header, TPL_ID)) {
00455             tmp_strc = cpl_propertylist_get_string(tmp_header, TPL_ID);
00456             if (mapping_mode == NULL) {
00457                 if (!strcmp(tmp_strc, MAPPING8)) 
00458                     mapping_mode = cpl_sprintf("%s", tmp_strc);
00459                 if (!strcmp(tmp_strc, MAPPING24)) 
00460                     mapping_mode = cpl_sprintf("%s", tmp_strc);
00461             } else {
00462                 if (strcmp(tmp_strc, mapping_mode)) {
00463                     cpl_msg_warning(__func__,
00464                             "There are different TPL IDs in input: %s and %s",
00465                             tmp_strc, mapping_mode);
00466                 }
00467             }
00468         }
00469         cpl_propertylist_delete(tmp_header);
00470     }
00471 
00472     if (mapping_mode != NULL) {
00473         if (!strcmp(ifus_txt, "") && !strcmp(name, "")) {
00474             cpl_msg_info(__func__,"*****************************************");
00475             cpl_msg_info(__func__,"* A map with all IFUs will be generated *");
00476             cpl_msg_info(__func__,"*****************************************");
00477             extrapol_enum = BCS_NATURAL;
00478         } else {
00479             cpl_msg_info(__func__, "No Map as name / ifu is specified");
00480             cpl_free(mapping_mode);
00481             mapping_mode = NULL ;
00482         }
00483     }
00484 
00485     /* Create name/ifu map... */
00486     name_vec = cpl_calloc(nr_frames*KMOS_NR_IFUS, sizeof(char*));
00487 
00488     /* No name / IFU specified - Non mapping mode */
00489     if (!strcmp(ifus_txt, "") && !strcmp(name, "") && mapping_mode==NULL) {
00490         /* All available names should be combined in one go */
00491         name_vec_size = 0;
00492         for (i = 0; i < nr_frames; i++) {
00493             tmp_str = cpl_sprintf("%d", i);
00494             frame = kmo_dfs_get_frame(frameset, tmp_str);
00495             cpl_free(tmp_str);
00496             for (ifu_nr = 1; ifu_nr <= KMOS_NR_IFUS; ifu_nr++) {
00497                 found = 0;
00498                 tmp_str = kmo_get_name_from_ocs_ifu(frame, ifu_nr);
00499                 if (tmp_str != NULL) {
00500                     for (j = 0; j < name_vec_size; j++) {
00501                         if (!strcmp(name_vec[j], tmp_str)) {
00502                             found = TRUE;
00503                             break;
00504                         }
00505                     }
00506                     if (!found)     name_vec[name_vec_size++] = tmp_str;
00507                     else            cpl_free(tmp_str);
00508                 }
00509             }
00510         }
00511     } else {
00512         /* Standard behavior: either ifu_nr- or name- or mapping-case */
00513         name_vec_size = 1;
00514         if (mapping_mode != NULL) {
00515             name_vec[0] = cpl_sprintf("mapping");
00516         } else {
00517             if (ifus != NULL) {
00518                 char *tmptmp = NULL;
00519 
00520                 // replace all ; with _
00521                 char *found_char = NULL;
00522                 found_char = strstr(ifus_txt, ";");
00523                 while (found_char != NULL) {
00524                     strncpy(found_char, "_", 1);
00525                     found_char = strstr(ifus_txt, ";");
00526                 }
00527 
00528                 if (strlen(ifus_txt) > 10) {
00529                     tmptmp = kmo_shorten_ifu_string(ifus_txt);
00530                     cpl_msg_info(__func__, "Truncate to ..ifu%s..", tmptmp);
00531                 } else {
00532                     tmptmp = cpl_sprintf("%s", ifus_txt);
00533                 }
00534                 name_vec[0] = cpl_sprintf("IFU%s", tmptmp);
00535                 ifus_txt = "";
00536                 cpl_free(tmptmp); 
00537             } else {
00538                 name_vec[0] = cpl_sprintf("%s", name);
00539             }
00540         }
00541     }
00542    
00543     /* Load data and noise */
00544     data_cube_list = cpl_calloc(nr_frames*KMOS_NR_IFUS, 
00545             sizeof(cpl_imagelist*));
00546     data_header_list = cpl_calloc(nr_frames*KMOS_NR_IFUS, 
00547             sizeof(cpl_propertylist*));
00548     noise_cube_list = cpl_calloc(nr_frames*KMOS_NR_IFUS,
00549             sizeof(cpl_imagelist*));
00550     noise_header_list = cpl_calloc(nr_frames*KMOS_NR_IFUS,
00551             sizeof(cpl_propertylist*));
00552  
00553     /*
00554     if (ifus != NULL) cpl_vector_delete(ifus);
00555     cpl_free(data_cube_list);
00556     cpl_free(noise_cube_list);
00557     cpl_free(data_header_list);
00558     cpl_free(noise_header_list);
00559     for (i = 0; i < name_vec_size ; i++) cpl_free(name_vec[i]);
00560     cpl_free(name_vec);
00561     if (mapping_mode != NULL) cpl_free(mapping_mode) ;
00562     return 0 ;
00563     */
00564 
00565     /* Load all data (and noise if existent) cubes and store them */
00566     for (nv = 0; nv < name_vec_size; nv++) {
00567         name = name_vec[nv];
00568 
00569         used_frame_idx = cpl_calloc(nr_frames*KMOS_NR_IFUS, sizeof(int)) ;
00570         used_ifus = cpl_calloc(nr_frames*KMOS_NR_IFUS, sizeof(int)) ;
00571         
00572         data_cube_counter = 0;
00573         noise_cube_counter = 0;
00574         for (i = 0; i < nr_frames; i++) {
00575             tmp_str = cpl_sprintf("%d", i);
00576             frame = kmo_dfs_get_frame(frameset, tmp_str);
00577             frame_filename = cpl_frame_get_filename(frame);
00578             kmo_init_fits_desc(&desc);
00579             desc = kmo_identify_fits_header(frame_filename);
00580 
00581             if (mapping_mode != NULL) {
00582                 /* Mapping mode */
00583                 for (j = 1; j <= KMOS_NR_IFUS; j++) {
00584                     /* Loop over all IFUs */
00585                     if (desc.sub_desc[j-1].valid_data == TRUE &&
00586                             !kmos_combine_is_skipped(skipped_bivector,i+1,j)) {
00587                         /* Load data frames */
00588                         override_err_msg = TRUE;
00589                         data_cube_list[data_cube_counter] =
00590                             kmo_dfs_load_cube(frameset, tmp_str, j,FALSE);
00591                         override_err_msg = FALSE;
00592                         if (data_cube_list[data_cube_counter] == NULL) {
00593                             cpl_error_reset();
00594                         } else {
00595                             if (edge_nan) kmo_edge_nan(
00596                                     data_cube_list[data_cube_counter], j);
00597                             data_header_list[data_cube_counter] =
00598                                 kmo_dfs_load_sub_header(frameset, 
00599                                         tmp_str, j, FALSE);
00600                             cpl_propertylist_update_string(
00601                                     data_header_list[data_cube_counter],
00602                                     "ESO PRO FRNAME", frame_filename);
00603                             cpl_propertylist_update_int(
00604                                     data_header_list[data_cube_counter],
00605                                     "ESO PRO IFUNR", j);
00606                             used_frame_idx[data_cube_counter] = i+1 ;
00607                             used_ifus[data_cube_counter] = j ;
00608                             data_cube_counter++;
00609                         }
00610 
00611                         /* Load noise frames */
00612                         override_err_msg = TRUE;
00613                         noise_cube_list[noise_cube_counter] =
00614                             kmo_dfs_load_cube(frameset, tmp_str, j, TRUE);
00615 
00616                         override_err_msg = FALSE;
00617                         if (noise_cube_list[noise_cube_counter] == NULL) {
00618                             // no noise found for this IFU
00619                             cpl_error_reset();
00620                         } else {
00621                             if (edge_nan) kmo_edge_nan(
00622                                     noise_cube_list[noise_cube_counter], j);
00623                             noise_header_list[noise_cube_counter] =
00624                                 kmo_dfs_load_sub_header(frameset, tmp_str,
00625                                         j, TRUE);
00626                             noise_cube_counter++;
00627                         }
00628 
00629                         /* Check if number of data and noise frames match */
00630                         if (noise_cube_counter > 0) {
00631                             if (data_cube_counter != noise_cube_counter) {
00632                                 cpl_msg_error(__func__, "Noise missing") ;
00633                                 cpl_error_set(__func__,CPL_ERROR_ILLEGAL_INPUT);
00634                                 /* TODO - deallocate */
00635                                 return -1 ;
00636                             }
00637                         }
00638                     } 
00639                 }
00640             } else {
00641                 /* name/ifu mode (single) */
00642                 if (ifus != NULL)   ifu_nr = cpl_vector_get(ifus, i);
00643                 else        ifu_nr = kmo_get_index_from_ocs_name(frame, name);
00644                 if (ifu_nr > 0) {
00645                     index = kmo_identify_index(frame_filename, ifu_nr , FALSE);
00646                     if (desc.sub_desc[index-1].valid_data == TRUE &&
00647                             !kmos_combine_is_skipped(skipped_bivector,i+1,
00648                                 ifu_nr)) {
00649                         /* Load data frames */
00650                         override_err_msg = TRUE;
00651                         data_cube_list[data_cube_counter] =
00652                             kmo_dfs_load_cube(frameset, tmp_str, ifu_nr, 
00653                                     FALSE);
00654                         override_err_msg = FALSE;
00655                         if (data_cube_list[data_cube_counter] == NULL) {
00656                             /* No data found for this IFU */
00657                             cpl_error_reset();
00658                             if (ifus != NULL)   cpl_msg_warning(cpl_func, 
00659                                     "IFU %d miѕsing in frame %s",
00660                                     ifu_nr, frame_filename);
00661                             else                cpl_msg_warning(cpl_func, 
00662                                     "Object %s missing in Frame %d (%s)",
00663                                     name,  i+1, frame_filename) ;
00664                         } else {
00665                             if (edge_nan) kmo_edge_nan(
00666                                     data_cube_list[data_cube_counter], ifu_nr);
00667                             data_header_list[data_cube_counter] =
00668                                 kmo_dfs_load_sub_header(frameset, tmp_str,
00669                                         ifu_nr, FALSE);
00670                             cpl_propertylist_update_string(
00671                                     data_header_list[data_cube_counter],
00672                                     "ESO PRO FRNAME", frame_filename);
00673                             cpl_propertylist_update_int(
00674                                     data_header_list[data_cube_counter],
00675                                     "ESO PRO IFUNR", ifu_nr);
00676                             used_frame_idx[data_cube_counter] = i+1 ;
00677                             used_ifus[data_cube_counter] = ifu_nr ;
00678                             data_cube_counter++;
00679                         }
00680 
00681                         /* Load noise frames */
00682                         override_err_msg = TRUE;
00683                         noise_cube_list[noise_cube_counter] =
00684                             kmo_dfs_load_cube(frameset, tmp_str, ifu_nr, 
00685                                     TRUE);
00686                         override_err_msg = FALSE;
00687                         if (noise_cube_list[noise_cube_counter] == NULL) {
00688                             /* No noise found for this IFU */
00689                             cpl_error_reset();
00690                         } else {
00691                             if (edge_nan) kmo_edge_nan(
00692                                     noise_cube_list[noise_cube_counter],ifu_nr);
00693                             noise_header_list[noise_cube_counter] =
00694                                     kmo_dfs_load_sub_header(frameset, 
00695                                             tmp_str, ifu_nr, TRUE);
00696                             noise_cube_counter++;
00697                         }
00698 
00699                         /* Check if number of data and noise frames match */
00700                         if (noise_cube_counter > 0) {
00701                             if (data_cube_counter != noise_cube_counter) {
00702                                 /* TODO - deallocate */
00703                                 cpl_msg_error(__func__, "Noise missing") ;
00704                                 cpl_error_set(__func__,CPL_ERROR_ILLEGAL_INPUT);
00705                                 return -1 ;
00706                             }
00707                         }
00708                     } 
00709                 } 
00710             }
00711             kmo_free_fits_desc(&desc);
00712             cpl_free(tmp_str);
00713         } 
00714  
00715         /* Create String for the output header - IFUs usage */
00716         used_ifus_str = kmos_combine_create_used_ifus_string(used_frame_idx, 
00717                 used_ifus, data_cube_counter);
00718         cpl_free(used_frame_idx) ;
00719         cpl_free(used_ifus) ;
00720 
00721         /* Combine data */
00722         exp_mask = NULL ;
00723         cube_combined_noise = NULL ;
00724         cube_combined_data = NULL ;
00725         if (kmo_priv_combine(data_cube_list, noise_cube_list, data_header_list,
00726                     noise_header_list, data_cube_counter, noise_cube_counter, 
00727                     name, ifus_txt, method, "BCS", fmethod, filename, cmethod, 
00728                     cpos_rej, cneg_rej, citer, cmin, cmax, extrapol_enum, flux,
00729                     &cube_combined_data, &cube_combined_noise, 
00730                     &exp_mask) != CPL_ERROR_NONE) {
00731             for (i = 0; i < data_cube_counter ; i++) 
00732                 cpl_imagelist_delete(data_cube_list[i]);
00733             for (i = 0; i < noise_cube_counter ; i++) 
00734                 cpl_imagelist_delete(noise_cube_list[i]);
00735             for (i = 0; i < data_cube_counter ; i++) 
00736                 cpl_propertylist_delete(data_header_list[i]);
00737             for (i = 0; i < noise_cube_counter ; i++) 
00738                 cpl_propertylist_delete(noise_header_list[i]);
00739             if (ifus != NULL) cpl_vector_delete(ifus);
00740             cpl_free(data_cube_list);
00741             cpl_free(noise_cube_list);
00742             cpl_free(data_header_list);
00743             cpl_free(noise_header_list);
00744             for (i = 0; i < name_vec_size ; i++) cpl_free(name_vec[i]);
00745             cpl_free(name_vec);
00746             cpl_free(used_ifus_str) ;
00747             if (mapping_mode != NULL) cpl_free(mapping_mode) ;
00748             cpl_msg_error(__func__, "Failed Combination") ;
00749             cpl_error_set(__func__,CPL_ERROR_ILLEGAL_INPUT);
00750             return -1 ;
00751         }
00752         for (i = 0; i < data_cube_counter ; i++) 
00753             cpl_imagelist_delete(data_cube_list[i]);
00754         for (i = 0; i < noise_cube_counter ; i++) 
00755             cpl_imagelist_delete(noise_cube_list[i]);
00756         
00757         /*
00758         for (i = 0; i < data_cube_counter ; i++) 
00759             cpl_propertylist_delete(data_header_list[i]);
00760         for (i = 0; i < noise_cube_counter ; i++) 
00761             cpl_propertylist_delete(noise_header_list[i]);
00762         if (ifus != NULL) cpl_vector_delete(ifus);
00763         cpl_free(data_cube_list);
00764         cpl_free(noise_cube_list);
00765         cpl_free(data_header_list);
00766         cpl_free(noise_header_list);
00767         for (i = 0; i < name_vec_size ; i++) cpl_free(name_vec[i]);
00768         cpl_free(name_vec);
00769         if (mapping_mode != NULL) cpl_free(mapping_mode) ;
00770         cpl_image_delete(exp_mask);
00771         cpl_imagelist_delete(cube_combined_noise);
00772         cpl_imagelist_delete(cube_combined_data);
00773         if (noise_header_list!=NULL && noise_cube_counter==0) 
00774             cpl_propertylist_delete(noise_header_list[0]) ;
00775         */
00776         /* Save data */
00777         if (!suppress_extension) {
00778             /* Setup output category COMBINE + ESO PRO CATG */
00779             main_header = kmo_dfs_load_primary_header(frameset, "0");
00780             fn_combine = cpl_sprintf("%s_%s_%s", COMBINE,
00781                     cpl_propertylist_get_string(main_header, CPL_DFS_PRO_CATG),
00782                     name_vec[nv]);
00783             fn_mask = cpl_sprintf("%s_%s_%s", EXP_MASK,
00784                     cpl_propertylist_get_string(main_header, CPL_DFS_PRO_CATG),
00785                     name_vec[nv]);
00786             cpl_propertylist_delete(main_header);
00787         } else {
00788             fn_combine = cpl_sprintf("%s_%d", COMBINE, suppress_index);
00789             fn_mask = cpl_sprintf("%s_%d", EXP_MASK, suppress_index++);
00790         }
00791 
00792         /* Create PRO keys plist */
00793         pro_plist = cpl_propertylist_new() ;
00794         cpl_propertylist_update_string(pro_plist, "ESO PRO USEDIFUS", 
00795                 used_ifus_str) ;
00796 
00797         /* Save Headers first */
00798         frame = cpl_frameset_find(frameset, NULL);
00799         kmo_dfs_save_main_header(frameset, fn_combine, "", frame, pro_plist, 
00800                 parlist, cpl_func);
00801         kmo_dfs_save_main_header(frameset, fn_mask, "", frame, pro_plist, 
00802                 parlist, cpl_func);
00803         cpl_propertylist_delete(pro_plist) ;
00804         cpl_free(used_ifus_str) ;
00805 
00806         /* Clean */
00807         if (data_header_list[0] != NULL) {
00808             if (cpl_propertylist_has(data_header_list[0], "ESO PRO FRNAME")) {
00809                 cpl_propertylist_erase(data_header_list[0], "ESO PRO FRNAME");
00810             }
00811             if (cpl_propertylist_has(data_header_list[0], "ESO PRO IFUNR")) {
00812                 cpl_propertylist_erase(data_header_list[0], "ESO PRO IFUNR");
00813             }
00814         }
00815         if (noise_header_list[0] != NULL) {
00816             if (cpl_propertylist_has(noise_header_list[0], "ESO PRO FRNAME")) {
00817                 cpl_propertylist_erase(noise_header_list[0], "ESO PRO FRNAME");
00818             }
00819             if (cpl_propertylist_has(noise_header_list[0], "ESO PRO IFUNR")) {
00820                 cpl_propertylist_erase(noise_header_list[0], "ESO PRO IFUNR");
00821             }
00822         }
00823         kmo_dfs_save_cube(cube_combined_data, fn_combine, "", 
00824                 data_header_list[0], 0./0.);
00825         cpl_imagelist_delete(cube_combined_data);
00826         kmo_dfs_save_cube(cube_combined_noise, fn_combine, "", 
00827                 noise_header_list[0], 0./0.);
00828         cpl_imagelist_delete(cube_combined_noise);
00829         cpl_free(fn_combine);
00830         
00831         cpl_propertylist_erase(data_header_list[0], CRPIX3);
00832         cpl_propertylist_erase(data_header_list[0], CRPIX3);
00833         cpl_propertylist_erase(data_header_list[0], CRVAL3);
00834         cpl_propertylist_erase(data_header_list[0], CDELT3);
00835         cpl_propertylist_erase(data_header_list[0], CD1_3);
00836         cpl_propertylist_erase(data_header_list[0], CD2_3);
00837         cpl_propertylist_erase(data_header_list[0], CD3_1);
00838         cpl_propertylist_erase(data_header_list[0], CD3_2);
00839         cpl_propertylist_erase(data_header_list[0], CD3_3);
00840         cpl_propertylist_erase(data_header_list[0], CTYPE3);
00841         kmo_dfs_save_image(exp_mask, fn_mask, "", data_header_list[0], 0./0.);
00842         cpl_free(fn_mask);
00843         cpl_image_delete(exp_mask);
00844 
00845         for (i = 0; i < data_cube_counter ; i++) 
00846             cpl_propertylist_delete(data_header_list[i]);
00847         for (i = 0; i < noise_cube_counter ; i++) 
00848             cpl_propertylist_delete(noise_header_list[i]);
00849         if (noise_header_list!=NULL && noise_cube_counter==0) 
00850             cpl_propertylist_delete(noise_header_list[0]) ;
00851     } 
00852     if (skipped_bivector!=NULL) cpl_bivector_delete(skipped_bivector) ;
00853     if (ifus != NULL) cpl_vector_delete(ifus);
00854     cpl_free(data_cube_list);
00855     cpl_free(noise_cube_list);
00856     cpl_free(data_header_list);
00857     cpl_free(noise_header_list);
00858     for (i = 0; i < name_vec_size ; i++) cpl_free(name_vec[i]);
00859     cpl_free(name_vec);
00860     cpl_free(mapping_mode) ;
00861 
00862     /* Collapse the combined cubes if requested */
00863     if (collapse_combined) {
00864         kmos_collapse_cubes(COMBINED_RECONS, frameset, parlist, 0.1, "",
00865                 DEF_REJ_METHOD, DEF_POS_REJ_THRES, DEF_NEG_REJ_THRES,
00866                 DEF_ITERATIONS, DEF_NR_MIN_REJ, DEF_NR_MAX_REJ) ;
00867     }
00868     return 0;
00869 }
00870 
00873 /*----------------------------------------------------------------------------*/
00879 /*----------------------------------------------------------------------------*/
00880 static char * kmos_combine_create_used_ifus_string(
00881         const int   *   used_frame_idx,
00882         const int   *   used_ifus,
00883         int             nb)
00884 {
00885     char        out[500] ;
00886     char        tmp[7] ;
00887     int         i ;
00888     if (nb > 99) return NULL ;
00889     for (i=0 ; i<nb ; i++) {
00890         /* Build the current string */
00891         if (used_frame_idx[i] < 10 && used_ifus[i] < 10) 
00892             if (i==0) sprintf(tmp, "%1d:%1d", used_frame_idx[i], used_ifus[i]);
00893             else sprintf(tmp, ",%1d:%1d", used_frame_idx[i], used_ifus[i]);
00894         else if (used_frame_idx[i] < 10 && used_ifus[i] >= 10) 
00895             if (i==0) sprintf(tmp, "%1d:%2d", used_frame_idx[i], used_ifus[i]);
00896             else sprintf(tmp, ",%1d:%2d", used_frame_idx[i], used_ifus[i]);
00897         else if (used_frame_idx[i] >= 10 && used_ifus[i] < 10) 
00898             if (i==0) sprintf(tmp, "%2d:%1d", used_frame_idx[i], used_ifus[i]);
00899             else sprintf(tmp, ",%2d:%1d", used_frame_idx[i], used_ifus[i]);
00900         else if (used_frame_idx[i] >= 10 && used_ifus[i] >= 10) 
00901             if (i==0) sprintf(tmp, "%2d:%2d", used_frame_idx[i], used_ifus[i]);
00902             else sprintf(tmp, ",%2d:%2d", used_frame_idx[i], used_ifus[i]);
00903         else return NULL ;
00904 
00905         if (i==0)   strcpy(out, tmp) ;
00906         else        strcat(out, tmp);
00907     }
00908     return cpl_strdup(out) ;
00909 }
00910 
00911 /*----------------------------------------------------------------------------*/
00917 /*----------------------------------------------------------------------------*/
00918 static cpl_bivector * kmos_combine_parse_skipped(const char * str)
00919 {
00920     cpl_bivector    *   out ;
00921     cpl_vector      *   out_x ;
00922     cpl_vector      *   out_y ;
00923     char            *   my_str ;
00924     int                 nb_values ;
00925     char            *   s1 ;
00926     char            *   s2 ;
00927     int                 val1, val2, ret ;
00928     
00929     /* Check Entries */
00930     if (str == NULL) return NULL ;
00931 
00932     /* Initialise */
00933     nb_values = 0 ;
00934     my_str = cpl_strdup(str) ;
00935     
00936     /* Count the values */
00937     for (s2 = my_str; s2; ) {
00938         while (*s2 == ' ' || *s2 == '\t') s2++;
00939         s1 = strsep(&s2, ",") ;
00940         if (*s1) {
00941             if (sscanf(s1," %i:%i", &val1, &val2) == 2) {
00942                 nb_values ++ ;
00943             }
00944         }
00945     }
00946     cpl_free(my_str) ;
00947     if (nb_values == 0) return NULL ;
00948 
00949     /* Create the vector */
00950     out = cpl_bivector_new(nb_values) ;
00951     out_x = cpl_bivector_get_x(out) ;
00952     out_y = cpl_bivector_get_y(out) ;
00953     
00954     /* Fill the vector */
00955     nb_values = 0 ;
00956     my_str = cpl_strdup(str) ;
00957     for (s2 = my_str; s2; ) {
00958         while (*s2 == ' ' || *s2 == '\t') s2++;
00959         s1 = strsep(&s2, ",") ;
00960         if (*s1) {
00961             if (sscanf(s1," %i:%i", &val1, &val2) == 2) {
00962                 cpl_vector_set(out_x, nb_values, val1) ;
00963                 cpl_vector_set(out_y, nb_values, val2) ;
00964                 nb_values ++ ;
00965             }
00966         }
00967     }
00968     cpl_free(my_str) ;
00969     return out;
00970 }
00971 
00972 /*----------------------------------------------------------------------------*/
00980 /*----------------------------------------------------------------------------*/
00981 static int kmos_combine_is_skipped(
00982         const cpl_bivector  *   skipped, 
00983         int                     frame_idx,
00984         int                     ifu_nr) 
00985 {
00986     const cpl_vector    *   vec_x ;
00987     const cpl_vector    *   vec_y ;
00988     double                  val1, val2 ;
00989     int                     i ;
00990 
00991     /* Check entries */
00992     if (skipped == NULL) return 0;
00993 
00994     /* Initialise */
00995     vec_x = cpl_bivector_get_x_const(skipped) ;
00996     vec_y = cpl_bivector_get_y_const(skipped) ;
00997 
00998     /* Loop */
00999     for (i=0 ; i<cpl_bivector_get_size(skipped) ; i++) {
01000         val1 = cpl_vector_get(vec_x, i) ;
01001         val2 = cpl_vector_get(vec_y, i) ;
01002         if (fabs(val1-frame_idx)<1e-3 && fabs(val2-ifu_nr)<1e-3) return 1 ; 
01003     }
01004     return 0 ;
01005 }
01006