KMOS Pipeline Reference Manual  1.1.5
kmo_combine.c
00001 /* $Id: kmo_combine.c,v 1.29 2013/05/24 14:32:23 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/24 14:32:23 $
00024  * $Revision: 1.29 $
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 "--suppress_extension\n"
00142 "If set to TRUE, the arbitrary filename extensions are supressed. If multiple\n"
00143 "products with the same category are produced, they will be numered consecutively\n"
00144 "starting from 0.\n"
00145 "\n"
00146 "-------------------------------------------------------------------------------\n"
00147 "  Input files:\n"
00148 "\n"
00149 "   DO                      KMOS                                                \n"
00150 "   category                Type   Explanation                  Required #Frames\n"
00151 "   --------                -----  -----------                  -------- -------\n"
00152 "   <none or any>           F3I    data frame                       Y      2-n  \n"
00153 "\n"
00154 "  Output files:\n"
00155 "\n"
00156 "   DO                      KMOS\n"
00157 "   category                Type   Explanation\n"
00158 "   --------                -----  -----------\n"
00159 "   COMBINE_<ESO PRO CATG>  F3I    Combined data cube\n"
00160 "-------------------------------------------------------------------------------\n"
00161 "\n";
00162 
00179 int cpl_plugin_get_info(cpl_pluginlist *list)
00180 {
00181     cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe);
00182     cpl_plugin *plugin = &recipe->interface;
00183 
00184     cpl_plugin_init(plugin,
00185                         CPL_PLUGIN_API,
00186                         KMOS_BINARY_VERSION,
00187                         CPL_PLUGIN_TYPE_RECIPE,
00188                         "kmo_combine",
00189                         "Combine reconstructed cubes",
00190                         kmo_combine_description,
00191                         "Alex Agudo Berbel",
00192                         "kmos-spark@mpe.mpg.de",
00193                         kmos_get_license(),
00194                         kmo_combine_create,
00195                         kmo_combine_exec,
00196                         kmo_combine_destroy);
00197 
00198     cpl_pluginlist_append(list, plugin);
00199 
00200     return 0;
00201 }
00202 
00210 static int kmo_combine_create(cpl_plugin *plugin)
00211 {
00212     cpl_recipe *recipe;
00213     cpl_parameter *p;
00214 
00215     /* Check that the plugin is part of a valid recipe */
00216     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00217         recipe = (cpl_recipe *)plugin;
00218     else
00219         return -1;
00220 
00221     /* Create the parameters list in the cpl_recipe object */
00222     recipe->parameters = cpl_parameterlist_new();
00223 
00224     /* Fill the parameters list */
00225     /* --name */
00226     p = cpl_parameter_new_value("kmos.kmo_combine.name",
00227                                 CPL_TYPE_STRING,
00228                                 "Name of the object to combine.",
00229                                 "kmos.kmo_combine",
00230                                 "");
00231     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "name");
00232     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00233     cpl_parameterlist_append(recipe->parameters, p);
00234 
00235     /* --ifus */
00236     p = cpl_parameter_new_value("kmos.kmo_combine.ifus",
00237                                 CPL_TYPE_STRING,
00238                                 "The indices of the IFUs to combine. "
00239                                 "\"ifu1;ifu2;...\"",
00240                                 "kmos.kmo_combine",
00241                                 "");
00242     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "ifus");
00243     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00244     cpl_parameterlist_append(recipe->parameters, p);
00245 
00246     /* --method */
00247     p = cpl_parameter_new_value("kmos.kmo_combine.method",
00248                                 CPL_TYPE_STRING,
00249                                 "The shifting method:   "
00250                                 "'none': no shifting, combined directly "
00251                                                                   "(default), "
00252                                 "'header': shift according to WCS, "
00253                                 "'center': centering algorithm, "
00254                                 "'user': read shifts from file",
00255                                 "kmos.kmo_combine",
00256                                 "none");
00257     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "method");
00258     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00259     cpl_parameterlist_append(recipe->parameters, p);
00260 
00261     /* --fmethod */
00262     p = cpl_parameter_new_value("kmos.kmo_combine.fmethod",
00263                                 CPL_TYPE_STRING,
00264                                 "The fitting method (applies only when "
00265                                 "method='center'):   "
00266                                 "'gauss': fit a gauss function to collapsed "
00267                                 "image (default), "
00268                                 "'moffat': fit a moffat function to collapsed"
00269                                 " image",
00270                                 "kmos.kmo_combine",
00271                                 "gauss");
00272     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "fmethod");
00273     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00274     cpl_parameterlist_append(recipe->parameters, p);
00275 
00276     /* --filename */
00277     p = cpl_parameter_new_value("kmos.kmo_combine.filename",
00278                                 CPL_TYPE_STRING,
00279                                 "The path to the file with the shift vectors."
00280                                 "(Applies only to method='user')",
00281                                 "kmos.kmo_combine",
00282                                 "");
00283     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "filename");
00284     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00285     cpl_parameterlist_append(recipe->parameters, p);
00286 
00287     /* --flux */
00288     p = cpl_parameter_new_value("kmos.kmo_combine.flux",
00289                                 CPL_TYPE_BOOL,
00290                                 "Apply flux conservation: "
00291                                 "(TRUE (apply) or "
00292                                 "FALSE (don't apply)",
00293                                 "kmos.kmo_combine",
00294                                 FALSE);
00295     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "flux");
00296     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00297     cpl_parameterlist_append(recipe->parameters, p);
00298 
00299     /* --edge_nan */
00300     p = cpl_parameter_new_value("kmos.kmo_combine.edge_nan",
00301                                 CPL_TYPE_BOOL,
00302                                 "Set borders of cubes to NaN before combining them."
00303                                 "(TRUE (apply) or "
00304                                 "FALSE (don't apply)",
00305                                 "kmos.kmo_combine",
00306                                 FALSE);
00307     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "edge_nan");
00308     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00309     cpl_parameterlist_append(recipe->parameters, p);
00310 
00311     /* --suppress_extension */
00312     p = cpl_parameter_new_value("kmos.kmo_combine.suppress_extension",
00313                                 CPL_TYPE_BOOL,
00314                                 "Suppress arbitrary filename extension."
00315                                 "(TRUE (apply) or FALSE (don't apply)",
00316                                 "kmos.kmo_combine",
00317                                 FALSE);
00318     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "suppress_extension");
00319     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00320     cpl_parameterlist_append(recipe->parameters, p);
00321 
00322     return kmo_combine_pars_create(recipe->parameters,
00323                                    "kmos.kmo_combine",
00324                                    DEF_REJ_METHOD,
00325                                    FALSE);
00326 }
00327 
00333 static int kmo_combine_exec(cpl_plugin *plugin)
00334 {
00335     cpl_recipe  *recipe;
00336 
00337     /* Get the recipe out of the plugin */
00338     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00339         recipe = (cpl_recipe *)plugin;
00340     else return -1 ;
00341 
00342     return kmo_combine(recipe->parameters, recipe->frames);
00343 }
00344 
00350 static int kmo_combine_destroy(cpl_plugin *plugin)
00351 {
00352     cpl_recipe *recipe;
00353 
00354     /* Get the recipe out of the plugin */
00355     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00356         recipe = (cpl_recipe *)plugin;
00357     else return -1 ;
00358 
00359     cpl_parameterlist_delete(recipe->parameters);
00360     return 0 ;
00361 }
00362 
00363 //int kmo_tolerance_round(double x, double tol)
00364 //{
00365 //    int ret = 0;
00366 
00367 //    KMO_TRY
00368 //    {
00369 //        if (fabs(x - floor(x)) < tol) {
00370 //            // value is slightly greater than the real int value
00371 //            ret = floor(x);
00372 //        } else {
00373 //            if (fabs(x - floor(x+tol)) < tol) {
00374 //                // value is slightly greater than the real int value
00375 //                ret = floor(x+tol);
00376 //            } else {
00377 //                // error: sub pixel shift
00378 //                KMO_TRY_ASSURE(1 == 0,
00379 //                               CPL_ERROR_ILLEGAL_INPUT,
00380 //                               "Please apply only whole pixel shifts here "
00381 //                               "and no subpixel shifts!");
00382 //            }
00383 //        }
00384 //    }
00385 //    KMO_CATCH
00386 //    {
00387 //        KMO_CATCH_MSG();
00388 
00389 //        ret = 0;
00390 //    }
00391 
00392 //    return ret;
00393 //}
00394 
00409 static int kmo_combine(cpl_parameterlist *parlist, cpl_frameset *frameset)
00410 {
00411     const char       *method             = NULL,
00412                      *cmethod            = NULL,
00413                      *fmethod            = NULL,
00414                      *filename           = NULL,
00415                      *frame_filename     = NULL,
00416                      *ifus_txt           = NULL,
00417                      *tmp_strc           = NULL;
00418 
00419     char             *tmp_str            = NULL,
00420                      *mapping_mode       = NULL,
00421                      *name               = NULL,
00422                      **name_vec          = NULL;
00423 
00424     cpl_imagelist    **data_cube_list    = NULL,
00425                      **noise_cube_list   = NULL,
00426                      *cube_combined_data = NULL,
00427                      *cube_combined_noise= NULL;
00428 
00429     cpl_vector       *ifus               = NULL;
00430 
00431     int              ret_val             = 0,
00432                      nr_frames           = 0,
00433                      index               = 0,
00434                      data_cube_counter   = 0,
00435                      noise_cube_counter  = 0,
00436                      ifu_nr              = 0,
00437                      citer               = 0,
00438                      cmin                = 0,
00439                      cmax                = 0,
00440                      flux                = FALSE,
00441                      edge_nan            = FALSE,
00442                      name_vec_size       = 0,
00443                      found               = 0,
00444                      suppress_extension  = FALSE,
00445                      suppress_index      = 0;
00446 
00447     double           cpos_rej            = 0.0,
00448                      cneg_rej            = 0.0;
00449 
00450     cpl_propertylist *main_header        = NULL,
00451                      **data_header_list  = NULL,
00452                      **noise_header_list = NULL,
00453                      *tmp_header         = NULL;
00454 
00455     cpl_frame        *frame              = NULL;
00456 
00457     main_fits_desc   desc;
00458 
00459     enum extrapolationType extrapol_enum = NONE_CLIPPING;
00460 
00461     KMO_TRY
00462     {
00463         /* --- check input --- */
00464         KMO_TRY_ASSURE((parlist != NULL) &&
00465                        (frameset != NULL),
00466                        CPL_ERROR_NULL_INPUT,
00467                        "Not all input data is provided!");
00468 
00469         nr_frames = cpl_frameset_get_size(frameset);
00470 
00471         KMO_TRY_ASSURE(nr_frames >= 2,
00472                        CPL_ERROR_NULL_INPUT,
00473                        "At least two frames must be provided to combine!");
00474 
00475         KMO_TRY_ASSURE(kmo_dfs_set_groups(frameset, "kmo_combine") == 1,
00476                        CPL_ERROR_ILLEGAL_INPUT,
00477                        "Cannot identify RAW and CALIB frames!");
00478 
00479         cpl_msg_info("", "--- Parameter setup for kmo_combine -------");
00480 
00481         KMO_TRY_EXIT_IF_NULL(
00482             method = kmo_dfs_get_parameter_string(parlist,
00483                                            "kmos.kmo_combine.method"));
00484 
00485         KMO_TRY_EXIT_IF_NULL(
00486             fmethod = kmo_dfs_get_parameter_string(parlist,
00487                                            "kmos.kmo_combine.fmethod"));
00488 
00489         KMO_TRY_ASSURE((strcmp(method, "none") == 0) ||
00490                        (strcmp(method, "header") == 0) ||
00491                        (strcmp(method, "center") == 0) ||
00492                        (strcmp(method, "user") == 0),
00493                        CPL_ERROR_ILLEGAL_INPUT,
00494                        "Following shift methods are available : 'none', "
00495                        "'header', 'center' or 'user'");
00496 
00497         if (strcmp(method, "user") == 0) {
00498             filename = kmo_dfs_get_parameter_string(parlist,
00499                                                    "kmos.kmo_combine.filename");
00500             KMO_TRY_CHECK_ERROR_STATE();
00501 
00502             KMO_TRY_ASSURE(strcmp(filename, "") != 0,
00503                            CPL_ERROR_ILLEGAL_INPUT,
00504                            "path of file with shift information must be "
00505                            "provided!");
00506 
00507             KMO_TRY_EXIT_IF_ERROR(
00508                 kmo_dfs_print_parameter_help(parlist,
00509                                              "kmos.kmo_combine.filename"));
00510         }
00511 
00512         KMO_TRY_EXIT_IF_ERROR(
00513             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_combine.method"));
00514 
00515         ifus_txt = kmo_dfs_get_parameter_string(parlist,
00516                                                   "kmos.kmo_combine.ifus");
00517         KMO_TRY_CHECK_ERROR_STATE();
00518 
00519         name = (char*)kmo_dfs_get_parameter_string(parlist, "kmos.kmo_combine.name");
00520         KMO_TRY_CHECK_ERROR_STATE();
00521 
00522         if (strcmp(ifus_txt, "") != 0) {
00523             KMO_TRY_ASSURE(strcmp(name, "") == 0,
00524                            CPL_ERROR_ILLEGAL_INPUT,
00525                            "name parameter must be NULL if IFU indices are "
00526                            "provided!");
00527 
00528             KMO_TRY_EXIT_IF_NULL(
00529                 ifus = kmo_identify_values(ifus_txt));
00530 
00531             KMO_TRY_ASSURE(cpl_vector_get_size(ifus) == nr_frames,
00532                            CPL_ERROR_ILLEGAL_INPUT,
00533                            "ifus parameter must have the same number of values "
00534                            "than frames provided ) (%lld!=%d)",
00535                            cpl_vector_get_size(ifus), nr_frames);
00536         }
00537 
00538         if (strcmp(name, "") != 0) {
00539             KMO_TRY_ASSURE(strcmp(ifus_txt, "") == 0,
00540                            CPL_ERROR_ILLEGAL_INPUT,
00541                            "ifus parameter must be NULL if name is provided!");
00542         }
00543 
00544         flux = kmo_dfs_get_parameter_bool(parlist,
00545                                           "kmos.kmo_combine.flux");
00546         KMO_TRY_CHECK_ERROR_STATE();
00547         KMO_TRY_EXIT_IF_ERROR(
00548             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_combine.flux"));
00549 
00550         KMO_TRY_ASSURE((flux == TRUE) || (flux == FALSE),
00551                        CPL_ERROR_ILLEGAL_INPUT,
00552                        "flux must be TRUE or FALSE!");
00553 
00554         edge_nan = kmo_dfs_get_parameter_bool(parlist,
00555                                           "kmos.kmo_combine.edge_nan");
00556         KMO_TRY_CHECK_ERROR_STATE();
00557         KMO_TRY_EXIT_IF_ERROR(
00558             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_combine.edge_nan"));
00559 
00560         KMO_TRY_ASSURE((edge_nan == TRUE) || (edge_nan == FALSE),
00561                        CPL_ERROR_ILLEGAL_INPUT,
00562                        "edge_nan must be TRUE or FALSE!");
00563 
00564         suppress_extension = kmo_dfs_get_parameter_bool(parlist,
00565                                           "kmos.kmo_combine.suppress_extension");
00566         KMO_TRY_CHECK_ERROR_STATE();
00567         KMO_TRY_EXIT_IF_ERROR(
00568             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_combine.suppress_extension"));
00569 
00570         KMO_TRY_ASSURE((suppress_extension == TRUE) || (suppress_extension == FALSE),
00571                        CPL_ERROR_ILLEGAL_INPUT,
00572                        "suppress_extension must be TRUE or FALSE!");
00573 
00574         KMO_TRY_EXIT_IF_ERROR(
00575             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_combine.ifus"));
00576 
00577         KMO_TRY_EXIT_IF_ERROR(
00578             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_combine.name"));
00579 
00580         KMO_TRY_EXIT_IF_ERROR(
00581             kmo_combine_pars_load(parlist,
00582                                   "kmos.kmo_combine",
00583                                   &cmethod,
00584                                   &cpos_rej,
00585                                   &cneg_rej,
00586                                   &citer,
00587                                   &cmin,
00588                                   &cmax,
00589                                   FALSE));
00590 
00591         cpl_msg_info("", "-------------------------------------------");
00592 
00593         // load data and noise
00594         KMO_TRY_EXIT_IF_NULL(
00595             data_cube_list = cpl_calloc(nr_frames*KMOS_NR_IFUS,
00596                                         sizeof(cpl_imagelist*)));
00597 
00598         KMO_TRY_EXIT_IF_NULL(
00599             data_header_list = cpl_calloc(nr_frames*KMOS_NR_IFUS,
00600                                           sizeof(cpl_propertylist*)));
00601 
00602         KMO_TRY_EXIT_IF_NULL(
00603             noise_cube_list = cpl_calloc(nr_frames*KMOS_NR_IFUS,
00604                                          sizeof(cpl_imagelist*)));
00605 
00606         KMO_TRY_EXIT_IF_NULL(
00607             noise_header_list = cpl_calloc(nr_frames*KMOS_NR_IFUS,
00608                                            sizeof(cpl_propertylist*)));
00609 
00610         //
00611         // check for mapping mode
00612         //
00613         cpl_size fs_size = cpl_frameset_get_size(frameset);
00614         KMO_TRY_CHECK_ERROR_STATE();
00615 
00616         for (cpl_size i = 0; i < fs_size; i++) {
00617             KMO_TRY_EXIT_IF_NULL(
00618                 frame = cpl_frameset_get_position(frameset, i));
00619 
00620             KMO_TRY_EXIT_IF_NULL(
00621                 tmp_header = kmclipm_propertylist_load(cpl_frame_get_filename(frame), 0));
00622             if (cpl_propertylist_has(tmp_header, TPL_ID)) {
00623                 KMO_TRY_EXIT_IF_NULL(
00624                     tmp_strc = cpl_propertylist_get_string(tmp_header, TPL_ID));
00625                 if (mapping_mode == NULL) {
00626                     if (strcmp(tmp_strc, MAPPING8) == 0)
00627                     {
00628                         mapping_mode = cpl_sprintf("%s", tmp_strc);
00629                     }
00630                     if (strcmp(tmp_strc, MAPPING24) == 0)
00631                     {
00632                         mapping_mode = cpl_sprintf("%s", tmp_strc);
00633                     }
00634                 } else {
00635                     if (strcmp(tmp_strc, mapping_mode) != 0)
00636                     {
00637                         cpl_msg_warning("","There are different TPL IDs present in "
00638                                            "the set of frames: %s and %s",
00639                                            tmp_strc, mapping_mode);
00640                     }
00641                 }
00642             }
00643             cpl_propertylist_delete(tmp_header); tmp_header = NULL;
00644         }
00645 
00646         if (mapping_mode != NULL) {
00647             if ((strcmp(ifus_txt, "") == 0)  && (strcmp(name, "") == 0)) {
00648                 cpl_msg_info("","**************************************************");
00649                 cpl_msg_info("","*  A map containing all IFUs will be generated!  *");
00650                 cpl_msg_info("","**************************************************");
00651                 extrapol_enum = BCS_NATURAL;
00652             } else {
00653                 cpl_msg_info("","The frames aren't combined into a map although they originate "
00654                                 "from a mapping template. But since the name- or ifu-parameter "
00655                                 "has been specified, the default behaviour is overridden.");
00656                 cpl_free(mapping_mode); mapping_mode = NULL;
00657             }
00658         }
00659 
00660         //
00661         // create name/ifu map...
00662         //
00663         KMO_TRY_EXIT_IF_NULL(
00664             name_vec = cpl_calloc(nr_frames*KMOS_NR_IFUS, sizeof(char*)));
00665 
00666         if ((strcmp(ifus_txt, "") == 0) &&
00667             (strcmp(name, "") == 0) &&
00668             (mapping_mode == NULL))
00669         {
00670             // all available names should be combined in one go
00671             name_vec_size = 0;
00672             for (int i = 0; i < nr_frames; i++) {
00673                 KMO_TRY_EXIT_IF_NULL(
00674                     tmp_str = cpl_sprintf("%d", i));
00675                 KMO_TRY_EXIT_IF_NULL(
00676                     frame = kmo_dfs_get_frame(frameset, tmp_str));
00677                 cpl_free(tmp_str); tmp_str = NULL;
00678 
00679                 for (int ifu_nr = 1; ifu_nr <= KMOS_NR_IFUS; ifu_nr++) {
00680                     tmp_str = kmo_get_name_from_ocs_ifu(frame, ifu_nr);
00681                     KMO_TRY_CHECK_ERROR_STATE();
00682                     found = 0;
00683                     for (int j = 0; j < name_vec_size; j++) {
00684                         if (strcmp(name_vec[j], tmp_str) == 0) {
00685                             found = TRUE;
00686                             break;
00687                         }
00688                     }
00689                     if (!found) {
00690                         name_vec[name_vec_size++] = tmp_str;
00691                     } else {
00692                         cpl_free(tmp_str); tmp_str = NULL;
00693                     }
00694                 }
00695             }
00696         } else {
00697             // standard behavior: either ifu_nr- or name- or mapping-case
00698             name_vec_size = 1;
00699             if (mapping_mode != NULL) {
00700                 KMO_TRY_EXIT_IF_NULL(
00701                     name_vec[0] = cpl_sprintf("mapping"));
00702             } else {
00703                 if (ifus != NULL) {
00704                     KMO_TRY_EXIT_IF_NULL(
00705                         name_vec[0] = cpl_sprintf("IFU%s", ifus_txt));
00706                 } else {
00707                     KMO_TRY_EXIT_IF_NULL(
00708                         name_vec[0] = cpl_sprintf("%s", name));
00709                 }
00710             }
00711         }
00712 
00713         //
00714         // load all data (and noise if existent) cubes and store them
00715         //
00716         for (int nv = 0; nv < name_vec_size; nv++){
00717             name = name_vec[nv];
00718 
00719             data_cube_counter = 0;
00720             noise_cube_counter = 0;
00721             for (int i = 0; i < nr_frames; i++) {
00722                 KMO_TRY_EXIT_IF_NULL(
00723                     tmp_str = cpl_sprintf("%d", i));
00724 
00725                 KMO_TRY_EXIT_IF_NULL(
00726                     frame = kmo_dfs_get_frame(frameset, tmp_str));
00727 
00728                 KMO_TRY_EXIT_IF_NULL(
00729                     frame_filename = cpl_frame_get_filename(frame));
00730 
00731                 kmo_init_fits_desc(&desc);
00732 
00733                 desc = kmo_identify_fits_header(frame_filename);
00734                 KMO_TRY_CHECK_ERROR_STATE_MSG("Provided fits file doesn't seem to "
00735                                               "be in KMOS-format!");
00736 
00737                 KMO_TRY_ASSURE(desc.fits_type == f3i_fits,
00738                                CPL_ERROR_ILLEGAL_INPUT,
00739                                "Frame No. %d hasn't correct data type "
00740                                "(must be of type F3I)!", i+1);
00741 
00742                 if (mapping_mode != NULL) {
00743                     // we are in mapping mode
00744                     for (int j = 1; j <= KMOS_NR_IFUS; j++) {
00745                         //loop over all IFUs
00746                         if (desc.sub_desc[j-1].valid_data == TRUE) {
00747                             // load data frames
00748                             override_err_msg = TRUE;
00749                             data_cube_list[data_cube_counter] =
00750                                 kmo_dfs_load_cube(frameset, tmp_str, j, FALSE);
00751                             override_err_msg = FALSE;
00752                             if (data_cube_list[data_cube_counter] == NULL) {
00753                                 // no data found for this IFU
00754                                 cpl_error_reset();
00755                             } else {
00756                                 if (edge_nan) {
00757                                     KMO_TRY_EXIT_IF_ERROR(
00758                                         kmo_edge_nan(data_cube_list[data_cube_counter], j));
00759                                 }
00760                                 KMO_TRY_EXIT_IF_NULL(
00761                                     data_header_list[data_cube_counter] =
00762                                         kmo_dfs_load_sub_header(frameset, tmp_str, j, FALSE));
00763                                 cpl_propertylist_update_string(data_header_list[data_cube_counter],
00764                                                         "ESO PRO FRNAME",
00765                                                         frame_filename);
00766                                 cpl_propertylist_update_int(data_header_list[data_cube_counter],
00767                                                         "ESO PRO IFUNR",
00768                                                         j);
00769                                 data_cube_counter++;
00770                             }
00771 
00772                             // load noise frames
00773                             override_err_msg = TRUE;
00774                             noise_cube_list[noise_cube_counter] =
00775                                 kmo_dfs_load_cube(frameset, tmp_str, j, TRUE);
00776 
00777                             override_err_msg = FALSE;
00778                             if (noise_cube_list[noise_cube_counter] == NULL) {
00779                                 // no noise found for this IFU
00780                                 cpl_error_reset();
00781                             } else {
00782                                 if (edge_nan) {
00783                                     KMO_TRY_EXIT_IF_ERROR(
00784                                         kmo_edge_nan(noise_cube_list[noise_cube_counter], j));
00785                                 }
00786                                 KMO_TRY_EXIT_IF_NULL(
00787                                     noise_header_list[noise_cube_counter] =
00788                                         kmo_dfs_load_sub_header(frameset, tmp_str, j, TRUE));
00789                                 noise_cube_counter++;
00790                             }
00791 
00792                             // check for every iteration if number of data and noise
00793                             // frames is the same
00794                             if (noise_cube_counter > 0) {
00795                                 KMO_TRY_ASSURE(data_cube_counter == noise_cube_counter,
00796                                                CPL_ERROR_ILLEGAL_INPUT,
00797                                                "Frame No. %d (%s) has no noise frame "
00798                                                "while the preceeding ones had!",
00799                                                i+1, frame_filename);
00800                             }
00801                         } // end if valid_data
00802                     }
00803                 } else {
00804                     // we are in name/ifu mode (single)
00805                     if (ifus != NULL) {
00806                         ifu_nr = cpl_vector_get(ifus, i);
00807                         KMO_TRY_CHECK_ERROR_STATE();
00808                     } else {
00809                         ifu_nr = kmo_get_index_from_ocs_name(frame, name);
00810                         KMO_TRY_CHECK_ERROR_STATE();
00811                     }
00812 
00813                     if (ifu_nr > 0) {
00814                         index = kmo_identify_index(frame_filename, ifu_nr , FALSE);
00815                         KMO_TRY_CHECK_ERROR_STATE();
00816 
00817                         if (desc.sub_desc[index-1].valid_data == TRUE) {
00818                             // load data frames
00819                             override_err_msg = TRUE;
00820                             data_cube_list[data_cube_counter] =
00821                                 kmo_dfs_load_cube(frameset, tmp_str, ifu_nr, FALSE);
00822                             override_err_msg = FALSE;
00823                             if (data_cube_list[data_cube_counter] == NULL) {
00824                                 // no data found for this IFU
00825                                 cpl_error_reset();
00826                                 if (ifus != NULL) {
00827                                     cpl_msg_warning(cpl_func, "Frame No. %d (%s) "
00828                                                     "doesn't contain IFU No. %d!", i+1,
00829                                                     frame_filename, ifu_nr);
00830                                 } else {
00831                                     cpl_msg_warning(cpl_func, "Frame No. %d (%s) "
00832                                                     "doesn't contain IFU with object "
00833                                                     "name '%s'!", i+1,
00834                                                     frame_filename, name);
00835                                 }
00836                             } else {
00837                                 if (edge_nan) {
00838                                     KMO_TRY_EXIT_IF_ERROR(
00839                                         kmo_edge_nan(data_cube_list[data_cube_counter], ifu_nr));
00840                                 }
00841 
00842                                 KMO_TRY_EXIT_IF_NULL(
00843                                     data_header_list[data_cube_counter] =
00844                                         kmo_dfs_load_sub_header(frameset, tmp_str,
00845                                                                 ifu_nr, FALSE));
00846                                 cpl_propertylist_update_string(data_header_list[data_cube_counter],
00847                                                                "ESO PRO FRNAME",
00848                                                                frame_filename);
00849                                 cpl_propertylist_update_int(data_header_list[data_cube_counter],
00850                                                             "ESO PRO IFUNR",
00851                                                             ifu_nr);
00852                                 data_cube_counter++;
00853                             }
00854 
00855                             // load noise frames
00856                             override_err_msg = TRUE;
00857                             noise_cube_list[noise_cube_counter] =
00858                                 kmo_dfs_load_cube(frameset, tmp_str, ifu_nr, TRUE);
00859                             override_err_msg = FALSE;
00860                             if (noise_cube_list[noise_cube_counter] == NULL) {
00861                                 // no noise found for this IFU
00862                                 cpl_error_reset();
00863                             } else {
00864                                 if (edge_nan) {
00865                                     KMO_TRY_EXIT_IF_ERROR(
00866                                         kmo_edge_nan(noise_cube_list[noise_cube_counter], ifu_nr));
00867                                 }
00868 
00869                                 KMO_TRY_EXIT_IF_NULL(
00870                                     noise_header_list[noise_cube_counter] =
00871                                         kmo_dfs_load_sub_header(frameset, tmp_str,
00872                                                                 ifu_nr, TRUE));
00873                                 noise_cube_counter++;
00874                             }
00875 
00876                             // check for every iteration if number of data and noise
00877                             // frames is the same
00878                             if (noise_cube_counter > 0) {
00879                                 KMO_TRY_ASSURE(data_cube_counter == noise_cube_counter,
00880                                                CPL_ERROR_ILLEGAL_INPUT,
00881                                                "Frame No. %d (%s) has no noise frame "
00882                                                "while the preceeding ones had!",
00883                                                i+1, frame_filename);
00884                             }
00885                         } // end if valid_data
00886                     } // end if (ifu_nr > 0)
00887                 }
00888 
00889                 kmo_free_fits_desc(&desc);
00890                 cpl_free(tmp_str); tmp_str = NULL;
00891             } // for i = nr_frames
00892             KMO_TRY_CHECK_ERROR_STATE();
00893 
00894             //
00895             // combine data
00896             //
00897             KMO_TRY_EXIT_IF_ERROR(
00898                 kmo_priv_combine(data_cube_list,
00899                                  noise_cube_list,
00900                                  data_header_list,
00901                                  noise_header_list,
00902                                  data_cube_counter,
00903                                  noise_cube_counter,
00904                                  name,
00905                                  ifus_txt,
00906                                  method,
00907                                  "BCS",
00908                                  fmethod,
00909                                  filename,
00910                                  cmethod,
00911                                  cpos_rej,
00912                                  cneg_rej,
00913                                  citer,
00914                                  cmin,
00915                                  cmax,
00916                                  extrapol_enum,
00917                                  flux,
00918                                  &cube_combined_data,
00919                                  &cube_combined_noise));
00920 
00921             //
00922             // save data
00923             //
00924             /* save data and noise (if existing) */
00925             // --- load, update & save primary header ---
00926 
00927 
00928             if (!suppress_extension) {
00929                 // setup output category COMBINE + ESO PRO CATG
00930                 KMO_TRY_EXIT_IF_NULL(
00931                     main_header = kmo_dfs_load_primary_header(frameset, "0"));
00932                 KMO_TRY_EXIT_IF_NULL(
00933                     tmp_str = cpl_sprintf("%s_%s_%s",
00934                                           COMBINE,
00935                                           cpl_propertylist_get_string(main_header, CPL_DFS_PRO_CATG),
00936                                           name_vec[nv]));
00937                 cpl_propertylist_delete(main_header); main_header = NULL;
00938             } else {
00939                 KMO_TRY_EXIT_IF_NULL(
00940                     tmp_str = cpl_sprintf("%s_%d", COMBINE, suppress_index++));
00941             }
00942 
00943             frame = cpl_frameset_get_first(frameset);
00944             KMO_TRY_EXIT_IF_ERROR(
00945                 kmo_dfs_save_main_header(frameset, tmp_str, "", frame, NULL,
00946                                          parlist, cpl_func));
00947 
00948             if (data_header_list[0] != NULL) {
00949                 if (cpl_propertylist_has(data_header_list[0], "ESO PRO FRNAME")) {
00950                     cpl_propertylist_erase(data_header_list[0], "ESO PRO FRNAME");
00951                 }
00952                 if (cpl_propertylist_has(data_header_list[0], "ESO PRO IFUNR")) {
00953                     cpl_propertylist_erase(data_header_list[0], "ESO PRO IFUNR");
00954                 }
00955             }
00956             KMO_TRY_CHECK_ERROR_STATE();
00957 
00958             KMO_TRY_EXIT_IF_ERROR(
00959                 kmo_dfs_save_cube(cube_combined_data, tmp_str, "",
00960                                   data_header_list[0], 0./0.));
00961 
00962             KMO_TRY_EXIT_IF_ERROR(
00963                 kmo_dfs_save_cube(cube_combined_noise, tmp_str, "",
00964                                   noise_header_list[0], 0./0.));
00965 
00966             cpl_imagelist_delete(cube_combined_data); cube_combined_data = NULL;
00967             cpl_imagelist_delete(cube_combined_noise); cube_combined_noise = NULL;
00968             if (data_cube_list != NULL) {
00969                 for (int i = 0; i < nr_frames*KMOS_NR_IFUS; i++) {
00970                     cpl_imagelist_delete(data_cube_list[i]); data_cube_list[i] = NULL;
00971                 }
00972             }
00973             if (noise_cube_list != NULL) {
00974                 for (int i = 0; i < nr_frames*KMOS_NR_IFUS; i++) {
00975                     cpl_imagelist_delete(noise_cube_list[i]); noise_cube_list[i] = NULL;
00976                 }
00977             }
00978             if (data_header_list != NULL) {
00979                 for (int i = 0; i < nr_frames*KMOS_NR_IFUS; i++) {
00980                     cpl_propertylist_delete(data_header_list[i]);
00981                     data_header_list[i] = NULL;
00982                 }
00983             }
00984             if (noise_header_list != NULL) {
00985                 for (int i = 0; i < nr_frames*KMOS_NR_IFUS; i++) {
00986                     cpl_propertylist_delete(noise_header_list[i]);
00987                     noise_header_list[i] = NULL;
00988                 }
00989             }
00990             cpl_free(tmp_str); tmp_str = NULL;
00991         }
00992     }
00993     KMO_CATCH
00994     {
00995         KMO_CATCH_MSG();
00996         ret_val = -1;
00997     }
00998 
00999     cpl_propertylist_delete(main_header); main_header = NULL;
01000     cpl_vector_delete(ifus); ifus = NULL;
01001     cpl_imagelist_delete(cube_combined_data); cube_combined_data = NULL;
01002     cpl_imagelist_delete(cube_combined_noise); cube_combined_noise = NULL;
01003 
01004     if (data_cube_list != NULL) {
01005         for (int i = 0; i < nr_frames*KMOS_NR_IFUS; i++) {
01006             cpl_imagelist_delete(data_cube_list[i]); data_cube_list[i] = NULL;
01007         }
01008         cpl_free(data_cube_list); data_cube_list = NULL;
01009     }
01010 
01011     if (noise_cube_list != NULL) {
01012         for (int i = 0; i < nr_frames*KMOS_NR_IFUS; i++) {
01013             cpl_imagelist_delete(noise_cube_list[i]); noise_cube_list[i] = NULL;
01014         }
01015         cpl_free(noise_cube_list); noise_cube_list = NULL;
01016     }
01017 
01018     if (data_header_list != NULL) {
01019         for (int i = 0; i < nr_frames*KMOS_NR_IFUS; i++) {
01020             cpl_propertylist_delete(data_header_list[i]);
01021             data_header_list[i] = NULL;
01022         }
01023         cpl_free(data_header_list); data_header_list = NULL;
01024     }
01025 
01026     if (noise_header_list != NULL) {
01027         for (int i = 0; i < nr_frames*KMOS_NR_IFUS; i++) {
01028             cpl_propertylist_delete(noise_header_list[i]);
01029             noise_header_list[i] = NULL;
01030         }
01031         cpl_free(noise_header_list); noise_header_list = NULL;
01032     }
01033 
01034     if (name_vec != NULL) {
01035         for (int i = 0; i < nr_frames*KMOS_NR_IFUS; i++) {
01036             cpl_free(name_vec[i]); name_vec[i] = NULL;
01037         }
01038         cpl_free(name_vec); name_vec = NULL;
01039     }
01040     cpl_free(mapping_mode);mapping_mode = NULL;
01041 
01042     return ret_val;
01043 }
01044