KMOS Pipeline Reference Manual  1.1.3
kmo_combine.c
00001 /* $Id: kmo_combine.c,v 1.27 2013/05/08 09:22:01 aagudo Exp $
00002  *
00003  * This file is part of the KMOS Pipeline
00004  * Copyright (C) 2002,2003 European Southern Observatory
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  */
00020 
00021 /*
00022  * $Author: aagudo $
00023  * $Date: 2013/05/08 09:22:01 $
00024  * $Revision: 1.27 $
00025  * $Name: HEAD $
00026  */
00027 
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031 
00032 #include <string.h>
00033 #include <math.h>
00034 
00035 #include <cpl.h>
00036 #include <cpl_wcs.h>
00037 
00038 #include "kmo_debug.h"
00039 #include "kmo_utils.h"
00040 #include "kmo_dfs.h"
00041 #include "kmo_error.h"
00042 #include "kmo_priv_functions.h"
00043 #include "kmo_cpl_extensions.h"
00044 #include "kmo_constants.h"
00045 #include "kmo_priv_combine.h"
00046 
00047 static int kmo_combine_create(cpl_plugin *);
00048 static int kmo_combine_exec(cpl_plugin *);
00049 static int kmo_combine_destroy(cpl_plugin *);
00050 static int kmo_combine(cpl_parameterlist *, cpl_frameset *);
00051 
00052 static char kmo_combine_description[] =
00053 "This recipe shifts several exposures of an object and combines them. The diffe-\n"
00054 "rent methods to match the exposures are described below (--method parameter).\n"
00055 "The output cube is larger than the input cubes, according to the shifts to be\n"
00056 "applied. Additionally a border of NaN values is added. The WCS is the same as\n"
00057 "for the first exposure.\n"
00058 "For each spatial/spectral pixel a new value will be calculated (according the\n"
00059 "--cmethod parameter) and written into the output cube.\n"
00060 "Only exposures with equal orientation regarding the WCS can be combined (except\n"
00061 "-–method=”none”), north must point to the same direction. It is recommended to\n"
00062 "apply any rotation possibly after combining.\n"
00063 "The default mapping mode is done via the --name parameter, where the name of\n"
00064 "the object has to be provided. The recipe searches in all input data cubes IFUs\n"
00065 "pointing to that object.\n"
00066 "\n"
00067 "BASIC PARAMETERS:\n"
00068 "-----------------\n"
00069 "--name\n"
00070 "--ifus\n"
00071 "Since an object can be present only once per exposure and since it can be\n"
00072 "located in different IFUs for the existing exposures, there are two modes to\n"
00073 "identify the objects:\n"
00074 "   * Combine by object names (default)\n"
00075 "   In this case the object name must be provided via the --name parameter. The\n"
00076 "   object name will be searched for in all primary headers of all provided frames\n"
00077 "   in the keyword ESO OCS ARMx NAME.\n"
00078 "\n"
00079 "   * Combine by index (advanced)\n"
00080 "   In this case the --ifus parameter must be provided. The parameter must have\n"
00081 "   the same number of entries as frames are provided, e.g. \"3;1;24\" for 3 expo-\n"
00082 "   sures. The index doesn't reference the extension in the frame but the real\n"
00083 "   index of the IFU as defined in the EXTNAME keyword (e.g. 'IFU.3.DATA').\n"
00084 "\n"
00085 "--method\n"
00086 "There are following sources to get the shift parameters from:\n"
00087 "   * 'none' (default)\n"
00088 "   The cubes are directly recombined, not shifting at all. The ouput frame will\n"
00089 "   have the same dimensions as the input cubes.\n"
00090 "   If the size differs a warning will be emitted and the cubes will be aligned\n"
00091 "   to the lower left corner. If the orientation differs a warning will be emit-\n"
00092 "   ted, but the cubes are combined anyway.\n"
00093 "\n"
00094 "   * 'header'\n"
00095 "   The shifts are calculated according to the WCS information stored in the\n"
00096 "   header of every IFU. The output frame will get larger, except the object is\n"
00097 "   at the exact same position for all exposures. The size of the exposures can\n"
00098 "   differ, but the orientation must be the same for all exposures.\n"
00099 "\n"
00100 "   * 'center'\n"
00101 "   The shifts are calculated using a centering algorithm. The cube will be col-\n"
00102 "   lapsed and a 2D profile will be fitted to it to identify the centre. With \n"
00103 "   the parameter --fmethod the function to fit can be provided. The size of the\n"
00104 "   exposures can differ, but the orientation must be the same for all exposures.\n"
00105 "\n"
00106 "   * 'user'\n"
00107 "   Read the shifts from a user specified file. The path of the file must be pro-\n"
00108 "   vided using the --filename parameter. For every exposure (except the first one)\n"
00109 "   two shift values are expected per line, they have to be separated with simple\n"
00110 "   spaces. The values indicate pixel shifts and are referenced to the first\n"
00111 "   frame. The 1st value is the shift in x-direction to the left, the 2nd the\n"
00112 "   shift in y-direction upwards. The size of the exposures can differ, but the\n"
00113 "   orientation must be the same for all exposures.\n"
00114 "\n"
00115 "ADVANCED PARAMETERS\n"
00116 "-------------------\n"
00117 "--edge_nan\n"
00118 "Set borders of two sides of the cubes to NaN before combining them. This minimises\n"
00119 "unwanted border effects when dithering.\n"
00120 "\n"
00121 "--fmethod\n"
00122 "see --method='center'\n"
00123 "The type of function that should be fitted spatially to the collapsed image.\n"
00124 "This fit is used to create a mask to extract the spectrum of the object. Valid\n"
00125 "values are “gauss” and “moffat”.\n"
00126 "\n"
00127 "--filename\n"
00128 "see --method='user'\n"
00129 "\n"
00130 "--cpos_rej\n"
00131 "--cneg_rej\n"
00132 "--citer\n"
00133 "see --cmethod='ksigma'\n"
00134 "\n"
00135 "--cmax\n"
00136 "--cmin\n"
00137 "see --cmethod='min_max'\n"
00138 "\n"
00139 "--flux\n"
00140 "Specify if flux conservation should be applied.\n"
00141 "\n"
00142 "-------------------------------------------------------------------------------\n"
00143 "  Input files:\n"
00144 "\n"
00145 "   DO                      KMOS                                                \n"
00146 "   category                Type   Explanation                  Required #Frames\n"
00147 "   --------                -----  -----------                  -------- -------\n"
00148 "   <none or any>           F3I    data frame                       Y      2-n  \n"
00149 "\n"
00150 "  Output files:\n"
00151 "\n"
00152 "   DO                      KMOS\n"
00153 "   category                Type   Explanation\n"
00154 "   --------                -----  -----------\n"
00155 "   COMBINE_<ESO PRO CATG>  F3I    Combined data cube\n"
00156 "-------------------------------------------------------------------------------\n"
00157 "\n";
00158 
00175 int cpl_plugin_get_info(cpl_pluginlist *list)
00176 {
00177     cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe);
00178     cpl_plugin *plugin = &recipe->interface;
00179 
00180     cpl_plugin_init(plugin,
00181                         CPL_PLUGIN_API,
00182                         KMOS_BINARY_VERSION,
00183                         CPL_PLUGIN_TYPE_RECIPE,
00184                         "kmo_combine",
00185                         "Combine reconstructed cubes",
00186                         kmo_combine_description,
00187                         "Alex Agudo Berbel",
00188                         "agudo@mpe.mpg.de",
00189                         kmos_get_license(),
00190                         kmo_combine_create,
00191                         kmo_combine_exec,
00192                         kmo_combine_destroy);
00193 
00194     cpl_pluginlist_append(list, plugin);
00195 
00196     return 0;
00197 }
00198 
00206 static int kmo_combine_create(cpl_plugin *plugin)
00207 {
00208     cpl_recipe *recipe;
00209     cpl_parameter *p;
00210 
00211     /* Check that the plugin is part of a valid recipe */
00212     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00213         recipe = (cpl_recipe *)plugin;
00214     else
00215         return -1;
00216 
00217     /* Create the parameters list in the cpl_recipe object */
00218     recipe->parameters = cpl_parameterlist_new();
00219 
00220     /* Fill the parameters list */
00221     /* --name */
00222     p = cpl_parameter_new_value("kmos.kmo_combine.name",
00223                                 CPL_TYPE_STRING,
00224                                 "Name of the object to combine.",
00225                                 "kmos.kmo_combine",
00226                                 "");
00227     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "name");
00228     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00229     cpl_parameterlist_append(recipe->parameters, p);
00230 
00231     /* --ifus */
00232     p = cpl_parameter_new_value("kmos.kmo_combine.ifus",
00233                                 CPL_TYPE_STRING,
00234                                 "The indices of the IFUs to combine. "
00235                                 "\"ifu1;ifu2;...\"",
00236                                 "kmos.kmo_combine",
00237                                 "");
00238     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "ifus");
00239     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00240     cpl_parameterlist_append(recipe->parameters, p);
00241 
00242     /* --method */
00243     p = cpl_parameter_new_value("kmos.kmo_combine.method",
00244                                 CPL_TYPE_STRING,
00245                                 "The shifting method:   "
00246                                 "'none': no shifting, combined directly "
00247                                                                   "(default), "
00248                                 "'header': shift according to WCS, "
00249                                 "'center': centering algorithm, "
00250                                 "'user': read shifts from file",
00251                                 "kmos.kmo_combine",
00252                                 "none");
00253     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "method");
00254     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00255     cpl_parameterlist_append(recipe->parameters, p);
00256 
00257     /* --fmethod */
00258     p = cpl_parameter_new_value("kmos.kmo_combine.fmethod",
00259                                 CPL_TYPE_STRING,
00260                                 "The fitting method (applies only when "
00261                                 "method='center'):   "
00262                                 "'gauss': fit a gauss function to collapsed "
00263                                 "image (default), "
00264                                 "'moffat': fit a moffat function to collapsed"
00265                                 " image",
00266                                 "kmos.kmo_combine",
00267                                 "gauss");
00268     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "fmethod");
00269     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00270     cpl_parameterlist_append(recipe->parameters, p);
00271 
00272     /* --filename */
00273     p = cpl_parameter_new_value("kmos.kmo_combine.filename",
00274                                 CPL_TYPE_STRING,
00275                                 "The path to the file with the shift vectors."
00276                                 "(Applies only to method='user')",
00277                                 "kmos.kmo_combine",
00278                                 "");
00279     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "filename");
00280     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00281     cpl_parameterlist_append(recipe->parameters, p);
00282 
00283     /* --flux */
00284     p = cpl_parameter_new_value("kmos.kmo_combine.flux",
00285                                 CPL_TYPE_BOOL,
00286                                 "Apply flux conservation: "
00287                                 "(TRUE (apply) or "
00288                                 "FALSE (don't apply)",
00289                                 "kmos.kmo_combine",
00290                                 FALSE);
00291     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "flux");
00292     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00293     cpl_parameterlist_append(recipe->parameters, p);
00294 
00295     /* --edge_nan */
00296     p = cpl_parameter_new_value("kmos.kmo_combine.edge_nan",
00297                                 CPL_TYPE_BOOL,
00298                                 "Set borders of cubes to NaN before combining them."
00299                                 "(TRUE (apply) or "
00300                                 "FALSE (don't apply)",
00301                                 "kmos.kmo_combine",
00302                                 FALSE);
00303     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "edge_nan");
00304     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00305     cpl_parameterlist_append(recipe->parameters, p);
00306 
00307     return kmo_combine_pars_create(recipe->parameters,
00308                                    "kmos.kmo_combine",
00309                                    DEF_REJ_METHOD,
00310                                    FALSE);
00311 }
00312 
00318 static int kmo_combine_exec(cpl_plugin *plugin)
00319 {
00320     cpl_recipe  *recipe;
00321 
00322     /* Get the recipe out of the plugin */
00323     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00324         recipe = (cpl_recipe *)plugin;
00325     else return -1 ;
00326 
00327     return kmo_combine(recipe->parameters, recipe->frames);
00328 }
00329 
00335 static int kmo_combine_destroy(cpl_plugin *plugin)
00336 {
00337     cpl_recipe *recipe;
00338 
00339     /* Get the recipe out of the plugin */
00340     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00341         recipe = (cpl_recipe *)plugin;
00342     else return -1 ;
00343 
00344     cpl_parameterlist_delete(recipe->parameters);
00345     return 0 ;
00346 }
00347 
00348 //int kmo_tolerance_round(double x, double tol)
00349 //{
00350 //    int ret = 0;
00351 
00352 //    KMO_TRY
00353 //    {
00354 //        if (fabs(x - floor(x)) < tol) {
00355 //            // value is slightly greater than the real int value
00356 //            ret = floor(x);
00357 //        } else {
00358 //            if (fabs(x - floor(x+tol)) < tol) {
00359 //                // value is slightly greater than the real int value
00360 //                ret = floor(x+tol);
00361 //            } else {
00362 //                // error: sub pixel shift
00363 //                KMO_TRY_ASSURE(1 == 0,
00364 //                               CPL_ERROR_ILLEGAL_INPUT,
00365 //                               "Please apply only whole pixel shifts here "
00366 //                               "and no subpixel shifts!");
00367 //            }
00368 //        }
00369 //    }
00370 //    KMO_CATCH
00371 //    {
00372 //        KMO_CATCH_MSG();
00373 
00374 //        ret = 0;
00375 //    }
00376 
00377 //    return ret;
00378 //}
00379 
00394 static int kmo_combine(cpl_parameterlist *parlist, cpl_frameset *frameset)
00395 {
00396     const char       *method             = NULL,
00397                      *cmethod            = NULL,
00398                      *fmethod            = NULL,
00399                      *filename           = NULL,
00400                      *frame_filename     = NULL,
00401                      *ifus_txt           = NULL,
00402                      *tmp_strc           = NULL;
00403 
00404     char             *tmp_str            = NULL,
00405                      *mapping_mode       = NULL,
00406                      *name               = NULL,
00407                      **name_vec          = NULL;
00408 
00409     cpl_imagelist    **data_cube_list    = NULL,
00410                      **noise_cube_list   = NULL,
00411                      *cube_combined_data = NULL,
00412                      *cube_combined_noise= NULL;
00413 
00414     cpl_vector       *ifus               = NULL;
00415 
00416     int              ret_val             = 0,
00417                      nr_frames           = 0,
00418                      index               = 0,
00419                      data_cube_counter   = 0,
00420                      noise_cube_counter  = 0,
00421                      ifu_nr              = 0,
00422                      citer               = 0,
00423                      cmin                = 0,
00424                      cmax                = 0,
00425                      flux                = FALSE,
00426                      edge_nan            = FALSE,
00427                      name_vec_size       = 0,
00428                      found               = 0;
00429 
00430     double           cpos_rej            = 0.0,
00431                      cneg_rej            = 0.0;
00432 
00433     cpl_propertylist *main_header        = NULL,
00434                      **data_header_list  = NULL,
00435                      **noise_header_list = NULL,
00436                      *tmp_header         = NULL;
00437 
00438     cpl_frame        *frame              = NULL;
00439 
00440     main_fits_desc   desc;
00441 
00442     enum extrapolationType extrapol_enum = NONE_CLIPPING;
00443 
00444     KMO_TRY
00445     {
00446         /* --- check input --- */
00447         KMO_TRY_ASSURE((parlist != NULL) &&
00448                        (frameset != NULL),
00449                        CPL_ERROR_NULL_INPUT,
00450                        "Not all input data is provided!");
00451 
00452         nr_frames = cpl_frameset_get_size(frameset);
00453 
00454         KMO_TRY_ASSURE(nr_frames >= 2,
00455                        CPL_ERROR_NULL_INPUT,
00456                        "At least two frames must be provided to combine!");
00457 
00458         KMO_TRY_ASSURE(kmo_dfs_set_groups(frameset, "kmo_combine") == 1,
00459                        CPL_ERROR_ILLEGAL_INPUT,
00460                        "Cannot identify RAW and CALIB frames!");
00461 
00462         cpl_msg_info("", "--- Parameter setup for kmo_combine -------");
00463 
00464         KMO_TRY_EXIT_IF_NULL(
00465             method = kmo_dfs_get_parameter_string(parlist,
00466                                            "kmos.kmo_combine.method"));
00467 
00468         KMO_TRY_EXIT_IF_NULL(
00469             fmethod = kmo_dfs_get_parameter_string(parlist,
00470                                            "kmos.kmo_combine.fmethod"));
00471 
00472         KMO_TRY_ASSURE((strcmp(method, "none") == 0) ||
00473                        (strcmp(method, "header") == 0) ||
00474                        (strcmp(method, "center") == 0) ||
00475                        (strcmp(method, "user") == 0),
00476                        CPL_ERROR_ILLEGAL_INPUT,
00477                        "Following shift methods are available : 'none', "
00478                        "'header', 'center' or 'user'");
00479 
00480         if (strcmp(method, "user") == 0) {
00481             filename = kmo_dfs_get_parameter_string(parlist,
00482                                                    "kmos.kmo_combine.filename");
00483             KMO_TRY_CHECK_ERROR_STATE();
00484 
00485             KMO_TRY_ASSURE(strcmp(filename, "") != 0,
00486                            CPL_ERROR_ILLEGAL_INPUT,
00487                            "path of file with shift information must be "
00488                            "provided!");
00489 
00490             KMO_TRY_EXIT_IF_ERROR(
00491                 kmo_dfs_print_parameter_help(parlist,
00492                                              "kmos.kmo_combine.filename"));
00493         }
00494 
00495         KMO_TRY_EXIT_IF_ERROR(
00496             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_combine.method"));
00497 
00498         ifus_txt = kmo_dfs_get_parameter_string(parlist,
00499                                                   "kmos.kmo_combine.ifus");
00500         KMO_TRY_CHECK_ERROR_STATE();
00501 
00502         name = (char*)kmo_dfs_get_parameter_string(parlist, "kmos.kmo_combine.name");
00503         KMO_TRY_CHECK_ERROR_STATE();
00504 
00505         if (strcmp(ifus_txt, "") != 0) {
00506             KMO_TRY_ASSURE(strcmp(name, "") == 0,
00507                            CPL_ERROR_ILLEGAL_INPUT,
00508                            "name parameter must be NULL if IFU indices are "
00509                            "provided!");
00510 
00511             KMO_TRY_EXIT_IF_NULL(
00512                 ifus = kmo_identify_values(ifus_txt));
00513 
00514             KMO_TRY_ASSURE(cpl_vector_get_size(ifus) == nr_frames,
00515                            CPL_ERROR_ILLEGAL_INPUT,
00516                            "ifus parameter must have the same number of values "
00517                            "than frames provided ) (%lld!=%d)",
00518                            cpl_vector_get_size(ifus), nr_frames);
00519         }
00520 
00521         if (strcmp(name, "") != 0) {
00522             KMO_TRY_ASSURE(strcmp(ifus_txt, "") == 0,
00523                            CPL_ERROR_ILLEGAL_INPUT,
00524                            "ifus parameter must be NULL if name is provided!");
00525         }
00526 
00527         flux = kmo_dfs_get_parameter_bool(parlist,
00528                                           "kmos.kmo_combine.flux");
00529         KMO_TRY_CHECK_ERROR_STATE();
00530         KMO_TRY_EXIT_IF_ERROR(
00531             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_combine.flux"));
00532 
00533         KMO_TRY_ASSURE((flux == TRUE) || (flux == FALSE),
00534                        CPL_ERROR_ILLEGAL_INPUT,
00535                        "flux must be TRUE or FALSE!");
00536 
00537         edge_nan = kmo_dfs_get_parameter_bool(parlist,
00538                                           "kmos.kmo_combine.edge_nan");
00539         KMO_TRY_CHECK_ERROR_STATE();
00540         KMO_TRY_EXIT_IF_ERROR(
00541             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_combine.edge_nan"));
00542 
00543         KMO_TRY_ASSURE((edge_nan == TRUE) || (edge_nan == FALSE),
00544                        CPL_ERROR_ILLEGAL_INPUT,
00545                        "edge_nan must be TRUE or FALSE!");
00546 
00547         KMO_TRY_EXIT_IF_ERROR(
00548             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_combine.ifus"));
00549 
00550         KMO_TRY_EXIT_IF_ERROR(
00551             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_combine.name"));
00552 
00553         KMO_TRY_EXIT_IF_ERROR(
00554             kmo_combine_pars_load(parlist,
00555                                   "kmos.kmo_combine",
00556                                   &cmethod,
00557                                   &cpos_rej,
00558                                   &cneg_rej,
00559                                   &citer,
00560                                   &cmin,
00561                                   &cmax,
00562                                   FALSE));
00563 
00564         cpl_msg_info("", "-------------------------------------------");
00565 
00566         // load data and noise
00567         KMO_TRY_EXIT_IF_NULL(
00568             data_cube_list = cpl_calloc(nr_frames*KMOS_NR_IFUS,
00569                                         sizeof(cpl_imagelist*)));
00570 
00571         KMO_TRY_EXIT_IF_NULL(
00572             data_header_list = cpl_calloc(nr_frames*KMOS_NR_IFUS,
00573                                           sizeof(cpl_propertylist*)));
00574 
00575         KMO_TRY_EXIT_IF_NULL(
00576             noise_cube_list = cpl_calloc(nr_frames*KMOS_NR_IFUS,
00577                                          sizeof(cpl_imagelist*)));
00578 
00579         KMO_TRY_EXIT_IF_NULL(
00580             noise_header_list = cpl_calloc(nr_frames*KMOS_NR_IFUS,
00581                                            sizeof(cpl_propertylist*)));
00582 
00583         //
00584         // check for mapping mode
00585         //
00586         cpl_size fs_size = cpl_frameset_get_size(frameset);
00587         KMO_TRY_CHECK_ERROR_STATE();
00588 
00589         for (cpl_size i = 0; i < fs_size; i++) {
00590             KMO_TRY_EXIT_IF_NULL(
00591                 frame = cpl_frameset_get_position(frameset, i));
00592 
00593             KMO_TRY_EXIT_IF_NULL(
00594                 tmp_header = kmclipm_propertylist_load(cpl_frame_get_filename(frame), 0));
00595             if (cpl_propertylist_has(tmp_header, TPL_ID)) {
00596                 KMO_TRY_EXIT_IF_NULL(
00597                     tmp_strc = cpl_propertylist_get_string(tmp_header, TPL_ID));
00598                 if (mapping_mode == NULL) {
00599                     if (strcmp(tmp_strc, MAPPING8) == 0)
00600                     {
00601                         mapping_mode = cpl_sprintf("%s", tmp_strc);
00602                     }
00603                     if (strcmp(tmp_strc, MAPPING24) == 0)
00604                     {
00605                         mapping_mode = cpl_sprintf("%s", tmp_strc);
00606                     }
00607                 } else {
00608                     if (strcmp(tmp_strc, mapping_mode) != 0)
00609                     {
00610                         cpl_msg_warning("","There are different TPL IDs present in "
00611                                            "the set of frames: %s and %s",
00612                                            tmp_strc, mapping_mode);
00613                     }
00614                 }
00615             }
00616             cpl_propertylist_delete(tmp_header); tmp_header = NULL;
00617         }
00618 
00619         if (mapping_mode != NULL) {
00620             if ((strcmp(ifus_txt, "") == 0)  && (strcmp(name, "") == 0)) {
00621                 cpl_msg_info("","**************************************************");
00622                 cpl_msg_info("","*  A map containing all IFUs will be generated!  *");
00623                 cpl_msg_info("","**************************************************");
00624                 extrapol_enum = BCS_NATURAL;
00625             } else {
00626                 cpl_msg_info("","The frames aren't combined into a map although they originate "
00627                                 "from a mapping template. But since the name- or ifu-parameter "
00628                                 "has been specified, the default behaviour is overridden.");
00629                 cpl_free(mapping_mode); mapping_mode = NULL;
00630             }
00631         }
00632 
00633         //
00634         // create name/ifu map...
00635         //
00636         KMO_TRY_EXIT_IF_NULL(
00637             name_vec = cpl_calloc(nr_frames*KMOS_NR_IFUS, sizeof(char*)));
00638 
00639         if ((strcmp(ifus_txt, "") == 0) &&
00640             (strcmp(name, "") == 0) &&
00641             (mapping_mode == NULL))
00642         {
00643             // all available names should be combined in one go
00644             name_vec_size = 0;
00645             for (int i = 0; i < nr_frames; i++) {
00646                 KMO_TRY_EXIT_IF_NULL(
00647                     tmp_str = cpl_sprintf("%d", i));
00648                 KMO_TRY_EXIT_IF_NULL(
00649                     frame = kmo_dfs_get_frame(frameset, tmp_str));
00650                 cpl_free(tmp_str); tmp_str = NULL;
00651 
00652                 for (int ifu_nr = 1; ifu_nr <= KMOS_NR_IFUS; ifu_nr++) {
00653                     tmp_str = kmo_get_name_from_ocs_ifu(frame, ifu_nr);
00654                     KMO_TRY_CHECK_ERROR_STATE();
00655                     found = 0;
00656                     for (int j = 0; j < name_vec_size; j++) {
00657                         if (strcmp(name_vec[j], tmp_str) == 0) {
00658                             found = TRUE;
00659                             break;
00660                         }
00661                     }
00662                     if (!found) {
00663                         name_vec[name_vec_size++] = tmp_str;
00664                     } else {
00665                         cpl_free(tmp_str); tmp_str = NULL;
00666                     }
00667                 }
00668             }
00669         } else {
00670             // standard behavior: either ifu_nr- or name- or mapping-case
00671             name_vec_size = 1;
00672             if (mapping_mode != NULL) {
00673                 KMO_TRY_EXIT_IF_NULL(
00674                     name_vec[0] = cpl_sprintf("mapping"));
00675             } else {
00676                 if (ifus != NULL) {
00677                     KMO_TRY_EXIT_IF_NULL(
00678                         name_vec[0] = cpl_sprintf("IFU%s", ifus_txt));
00679                 } else {
00680                     KMO_TRY_EXIT_IF_NULL(
00681                         name_vec[0] = cpl_sprintf("%s", name));
00682                 }
00683             }
00684         }
00685 
00686         //
00687         // load all data (and noise if existent) cubes and store them
00688         //
00689         for (int nv = 0; nv < name_vec_size; nv++){
00690             name = name_vec[nv];
00691 
00692             data_cube_counter = 0;
00693             noise_cube_counter = 0;
00694             for (int i = 0; i < nr_frames; i++) {
00695                 KMO_TRY_EXIT_IF_NULL(
00696                     tmp_str = cpl_sprintf("%d", i));
00697 
00698                 KMO_TRY_EXIT_IF_NULL(
00699                     frame = kmo_dfs_get_frame(frameset, tmp_str));
00700 
00701                 KMO_TRY_EXIT_IF_NULL(
00702                     frame_filename = cpl_frame_get_filename(frame));
00703 
00704                 kmo_init_fits_desc(&desc);
00705 
00706                 desc = kmo_identify_fits_header(frame_filename);
00707                 KMO_TRY_CHECK_ERROR_STATE_MSG("Provided fits file doesn't seem to "
00708                                               "be in KMOS-format!");
00709 
00710                 KMO_TRY_ASSURE(desc.fits_type == f3i_fits,
00711                                CPL_ERROR_ILLEGAL_INPUT,
00712                                "Frame No. %d hasn't correct data type "
00713                                "(must be of type F3I)!", i+1);
00714 
00715                 if (mapping_mode != NULL) {
00716                     // we are in mapping mode
00717                     for (int j = 1; j <= KMOS_NR_IFUS; j++) {
00718                         //loop over all IFUs
00719                         if (desc.sub_desc[j-1].valid_data == TRUE) {
00720                             // load data frames
00721                             override_err_msg = TRUE;
00722                             data_cube_list[data_cube_counter] =
00723                                 kmo_dfs_load_cube(frameset, tmp_str, j, FALSE);
00724                             override_err_msg = FALSE;
00725                             if (data_cube_list[data_cube_counter] == NULL) {
00726                                 // no data found for this IFU
00727                                 cpl_error_reset();
00728                             } else {
00729                                 if (edge_nan) {
00730                                     KMO_TRY_EXIT_IF_ERROR(
00731                                         kmo_edge_nan(data_cube_list[data_cube_counter], j));
00732                                 }
00733                                 KMO_TRY_EXIT_IF_NULL(
00734                                     data_header_list[data_cube_counter] =
00735                                         kmo_dfs_load_sub_header(frameset, tmp_str, j, FALSE));
00736                                 cpl_propertylist_update_string(data_header_list[data_cube_counter],
00737                                                         "ESO PRO FRNAME",
00738                                                         frame_filename);
00739                                 cpl_propertylist_update_int(data_header_list[data_cube_counter],
00740                                                         "ESO PRO IFUNR",
00741                                                         j);
00742                                 data_cube_counter++;
00743                             }
00744 
00745                             // load noise frames
00746                             override_err_msg = TRUE;
00747                             noise_cube_list[noise_cube_counter] =
00748                                 kmo_dfs_load_cube(frameset, tmp_str, j, TRUE);
00749 
00750                             override_err_msg = FALSE;
00751                             if (noise_cube_list[noise_cube_counter] == NULL) {
00752                                 // no noise found for this IFU
00753                                 cpl_error_reset();
00754                             } else {
00755                                 if (edge_nan) {
00756                                     KMO_TRY_EXIT_IF_ERROR(
00757                                         kmo_edge_nan(noise_cube_list[noise_cube_counter], j));
00758                                 }
00759                                 KMO_TRY_EXIT_IF_NULL(
00760                                     noise_header_list[noise_cube_counter] =
00761                                         kmo_dfs_load_sub_header(frameset, tmp_str, j, TRUE));
00762                                 noise_cube_counter++;
00763                             }
00764 
00765                             // check for every iteration if number of data and noise
00766                             // frames is the same
00767                             if (noise_cube_counter > 0) {
00768                                 KMO_TRY_ASSURE(data_cube_counter == noise_cube_counter,
00769                                                CPL_ERROR_ILLEGAL_INPUT,
00770                                                "Frame No. %d (%s) has no noise frame "
00771                                                "while the preceeding ones had!",
00772                                                i+1, frame_filename);
00773                             }
00774                         } // end if valid_data
00775                     }
00776                 } else {
00777                     // we are in name/ifu mode (single)
00778                     if (ifus != NULL) {
00779                         ifu_nr = cpl_vector_get(ifus, i);
00780                         KMO_TRY_CHECK_ERROR_STATE();
00781                     } else {
00782                         ifu_nr = kmo_get_index_from_ocs_name(frame, name);
00783                         KMO_TRY_CHECK_ERROR_STATE();
00784                     }
00785 
00786                     if (ifu_nr > 0) {
00787                         index = kmo_identify_index(frame_filename, ifu_nr , FALSE);
00788                         KMO_TRY_CHECK_ERROR_STATE();
00789 
00790                         if (desc.sub_desc[index-1].valid_data == TRUE) {
00791                             // load data frames
00792                             override_err_msg = TRUE;
00793                             data_cube_list[data_cube_counter] =
00794                                 kmo_dfs_load_cube(frameset, tmp_str, ifu_nr, FALSE);
00795                             override_err_msg = FALSE;
00796                             if (data_cube_list[data_cube_counter] == NULL) {
00797                                 // no data found for this IFU
00798                                 cpl_error_reset();
00799                                 if (ifus != NULL) {
00800                                     cpl_msg_warning(cpl_func, "Frame No. %d (%s) "
00801                                                     "doesn't contain IFU No. %d!", i+1,
00802                                                     frame_filename, ifu_nr);
00803                                 } else {
00804                                     cpl_msg_warning(cpl_func, "Frame No. %d (%s) "
00805                                                     "doesn't contain IFU with object "
00806                                                     "name '%s'!", i+1,
00807                                                     frame_filename, name);
00808                                 }
00809                             } else {
00810                                 if (edge_nan) {
00811                                     KMO_TRY_EXIT_IF_ERROR(
00812                                         kmo_edge_nan(data_cube_list[data_cube_counter], ifu_nr));
00813                                 }
00814 
00815                                 KMO_TRY_EXIT_IF_NULL(
00816                                     data_header_list[data_cube_counter] =
00817                                         kmo_dfs_load_sub_header(frameset, tmp_str,
00818                                                                 ifu_nr, FALSE));
00819                                 cpl_propertylist_update_string(data_header_list[data_cube_counter],
00820                                                                "ESO PRO FRNAME",
00821                                                                frame_filename);
00822                                 cpl_propertylist_update_int(data_header_list[data_cube_counter],
00823                                                             "ESO PRO IFUNR",
00824                                                             ifu_nr);
00825                                 data_cube_counter++;
00826                             }
00827 
00828                             // load noise frames
00829                             override_err_msg = TRUE;
00830                             noise_cube_list[noise_cube_counter] =
00831                                 kmo_dfs_load_cube(frameset, tmp_str, ifu_nr, TRUE);
00832                             override_err_msg = FALSE;
00833                             if (noise_cube_list[noise_cube_counter] == NULL) {
00834                                 // no noise found for this IFU
00835                                 cpl_error_reset();
00836                             } else {
00837                                 if (edge_nan) {
00838                                     KMO_TRY_EXIT_IF_ERROR(
00839                                         kmo_edge_nan(noise_cube_list[noise_cube_counter], ifu_nr));
00840                                 }
00841 
00842                                 KMO_TRY_EXIT_IF_NULL(
00843                                     noise_header_list[noise_cube_counter] =
00844                                         kmo_dfs_load_sub_header(frameset, tmp_str,
00845                                                                 ifu_nr, TRUE));
00846                                 noise_cube_counter++;
00847                             }
00848 
00849                             // check for every iteration if number of data and noise
00850                             // frames is the same
00851                             if (noise_cube_counter > 0) {
00852                                 KMO_TRY_ASSURE(data_cube_counter == noise_cube_counter,
00853                                                CPL_ERROR_ILLEGAL_INPUT,
00854                                                "Frame No. %d (%s) has no noise frame "
00855                                                "while the preceeding ones had!",
00856                                                i+1, frame_filename);
00857                             }
00858                         } // end if valid_data
00859                     } // end if (ifu_nr > 0)
00860                 }
00861 
00862                 kmo_free_fits_desc(&desc);
00863                 cpl_free(tmp_str); tmp_str = NULL;
00864             } // for i = nr_frames
00865             KMO_TRY_CHECK_ERROR_STATE();
00866 
00867             //
00868             // combine data
00869             //
00870             KMO_TRY_EXIT_IF_ERROR(
00871                 kmo_priv_combine(data_cube_list,
00872                                  noise_cube_list,
00873                                  data_header_list,
00874                                  noise_header_list,
00875                                  data_cube_counter,
00876                                  noise_cube_counter,
00877                                  name,
00878                                  ifus_txt,
00879                                  method,
00880                                  "BCS",
00881                                  fmethod,
00882                                  filename,
00883                                  cmethod,
00884                                  cpos_rej,
00885                                  cneg_rej,
00886                                  citer,
00887                                  cmin,
00888                                  cmax,
00889                                  extrapol_enum,
00890                                  flux,
00891                                  &cube_combined_data,
00892                                  &cube_combined_noise));
00893 
00894             //
00895             // save data
00896             //
00897             /* save data and noise (if existing) */
00898             // --- load, update & save primary header ---
00899 
00900             // setup output category COMBINE + ESO PRO CATG
00901             KMO_TRY_EXIT_IF_NULL(
00902                 main_header = kmo_dfs_load_primary_header(frameset, "0"));
00903             KMO_TRY_EXIT_IF_NULL(
00904                 tmp_str = cpl_sprintf("%s_%s_%s",
00905                                       COMBINE,
00906                                       cpl_propertylist_get_string(main_header, CPL_DFS_PRO_CATG),
00907                                       name_vec[nv]));
00908             cpl_propertylist_delete(main_header); main_header = NULL;
00909 
00910             frame = cpl_frameset_get_first(frameset);
00911             KMO_TRY_EXIT_IF_ERROR(
00912                 kmo_dfs_save_main_header(frameset, tmp_str, "", frame, NULL,
00913                                          parlist, cpl_func));
00914 
00915             if (data_header_list[0] != NULL) {
00916                 if (cpl_propertylist_has(data_header_list[0], "ESO PRO FRNAME")) {
00917                     cpl_propertylist_erase(data_header_list[0], "ESO PRO FRNAME");
00918                 }
00919                 if (cpl_propertylist_has(data_header_list[0], "ESO PRO IFUNR")) {
00920                     cpl_propertylist_erase(data_header_list[0], "ESO PRO IFUNR");
00921                 }
00922             }
00923             KMO_TRY_CHECK_ERROR_STATE();
00924 
00925             KMO_TRY_EXIT_IF_ERROR(
00926                 kmo_dfs_save_cube(cube_combined_data, tmp_str, "",
00927                                   data_header_list[0], 0./0.));
00928 
00929             KMO_TRY_EXIT_IF_ERROR(
00930                 kmo_dfs_save_cube(cube_combined_noise, tmp_str, "",
00931                                   noise_header_list[0], 0./0.));
00932 
00933             cpl_imagelist_delete(cube_combined_data); cube_combined_data = NULL;
00934             cpl_imagelist_delete(cube_combined_noise); cube_combined_noise = NULL;
00935             if (data_cube_list != NULL) {
00936                 for (int i = 0; i < nr_frames*KMOS_NR_IFUS; i++) {
00937                     cpl_imagelist_delete(data_cube_list[i]); data_cube_list[i] = NULL;
00938                 }
00939             }
00940             if (noise_cube_list != NULL) {
00941                 for (int i = 0; i < nr_frames*KMOS_NR_IFUS; i++) {
00942                     cpl_imagelist_delete(noise_cube_list[i]); noise_cube_list[i] = NULL;
00943                 }
00944             }
00945             if (data_header_list != NULL) {
00946                 for (int i = 0; i < nr_frames*KMOS_NR_IFUS; i++) {
00947                     cpl_propertylist_delete(data_header_list[i]);
00948                     data_header_list[i] = NULL;
00949                 }
00950             }
00951             if (noise_header_list != NULL) {
00952                 for (int i = 0; i < nr_frames*KMOS_NR_IFUS; i++) {
00953                     cpl_propertylist_delete(noise_header_list[i]);
00954                     noise_header_list[i] = NULL;
00955                 }
00956             }
00957             cpl_free(tmp_str); tmp_str = NULL;
00958         }
00959     }
00960     KMO_CATCH
00961     {
00962         KMO_CATCH_MSG();
00963         ret_val = -1;
00964     }
00965 
00966     cpl_propertylist_delete(main_header); main_header = NULL;
00967     cpl_vector_delete(ifus); ifus = NULL;
00968     cpl_imagelist_delete(cube_combined_data); cube_combined_data = NULL;
00969     cpl_imagelist_delete(cube_combined_noise); cube_combined_noise = NULL;
00970 
00971     if (data_cube_list != NULL) {
00972         for (int i = 0; i < nr_frames*KMOS_NR_IFUS; i++) {
00973             cpl_imagelist_delete(data_cube_list[i]); data_cube_list[i] = NULL;
00974         }
00975         cpl_free(data_cube_list); data_cube_list = NULL;
00976     }
00977 
00978     if (noise_cube_list != NULL) {
00979         for (int i = 0; i < nr_frames*KMOS_NR_IFUS; i++) {
00980             cpl_imagelist_delete(noise_cube_list[i]); noise_cube_list[i] = NULL;
00981         }
00982         cpl_free(noise_cube_list); noise_cube_list = NULL;
00983     }
00984 
00985     if (data_header_list != NULL) {
00986         for (int i = 0; i < nr_frames*KMOS_NR_IFUS; i++) {
00987             cpl_propertylist_delete(data_header_list[i]);
00988             data_header_list[i] = NULL;
00989         }
00990         cpl_free(data_header_list); data_header_list = NULL;
00991     }
00992 
00993     if (noise_header_list != NULL) {
00994         for (int i = 0; i < nr_frames*KMOS_NR_IFUS; i++) {
00995             cpl_propertylist_delete(noise_header_list[i]);
00996             noise_header_list[i] = NULL;
00997         }
00998         cpl_free(noise_header_list); noise_header_list = NULL;
00999     }
01000 
01001     if (name_vec != NULL) {
01002         for (int i = 0; i < nr_frames*KMOS_NR_IFUS; i++) {
01003             cpl_free(name_vec[i]); name_vec[i] = NULL;
01004         }
01005         cpl_free(name_vec); name_vec = NULL;
01006     }
01007     cpl_free(mapping_mode);mapping_mode = NULL;
01008 
01009     return ret_val;
01010 }
01011