KMOS Pipeline Reference Manual  1.1.1
kmo_combine.c
00001 /* $Id: kmo_combine.c,v 1.26 2013/04/10 12:12:21 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/04/10 12:12:21 $
00024  * $Revision: 1.26 $
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 
00403     char             *tmp_str            = NULL,
00404                      *name               = NULL;
00405 
00406     cpl_imagelist    **data_cube_list    = NULL,
00407                      **noise_cube_list   = NULL,
00408                      *cube_combined_data = NULL,
00409                      *cube_combined_noise= NULL;
00410 
00411     cpl_vector       *ifus               = NULL;
00412 
00413     int              ret_val             = 0,
00414                      nr_frames           = 0,
00415                      index               = 0,
00416                      data_cube_counter   = 0,
00417                      noise_cube_counter  = 0,
00418                      ifu_nr              = 0,
00419                      citer               = 0,
00420                      cmin                = 0,
00421                      cmax                = 0,
00422                      flux                = FALSE,
00423                      edge_nan            = FALSE;
00424 
00425     double           cpos_rej            = 0.0,
00426                      cneg_rej            = 0.0;
00427 
00428     cpl_propertylist *main_header        = NULL,
00429                      **data_header_list  = NULL,
00430                      **noise_header_list = NULL;
00431 
00432     cpl_frame        *frame              = NULL;
00433 
00434     main_fits_desc   desc;
00435 
00436     enum extrapolationType extrapol_enum = NONE_CLIPPING;
00437 
00438     KMO_TRY
00439     {
00440         /* --- check input --- */
00441         KMO_TRY_ASSURE((parlist != NULL) &&
00442                        (frameset != NULL),
00443                        CPL_ERROR_NULL_INPUT,
00444                        "Not all input data is provided!");
00445 
00446         nr_frames = cpl_frameset_get_size(frameset);
00447 
00448         KMO_TRY_ASSURE(nr_frames >= 2,
00449                        CPL_ERROR_NULL_INPUT,
00450                        "At least two frames must be provided to combine!");
00451 
00452         KMO_TRY_ASSURE(kmo_dfs_set_groups(frameset, "kmo_combine") == 1,
00453                        CPL_ERROR_ILLEGAL_INPUT,
00454                        "Cannot identify RAW and CALIB frames!");
00455 
00456         cpl_msg_info("", "--- Parameter setup for kmo_combine -------");
00457 
00458         KMO_TRY_EXIT_IF_NULL(
00459             method = kmo_dfs_get_parameter_string(parlist,
00460                                            "kmos.kmo_combine.method"));
00461 
00462         KMO_TRY_EXIT_IF_NULL(
00463             fmethod = kmo_dfs_get_parameter_string(parlist,
00464                                            "kmos.kmo_combine.fmethod"));
00465 
00466         KMO_TRY_ASSURE((strcmp(method, "none") == 0) ||
00467                        (strcmp(method, "header") == 0) ||
00468                        (strcmp(method, "center") == 0) ||
00469                        (strcmp(method, "user") == 0),
00470                        CPL_ERROR_ILLEGAL_INPUT,
00471                        "Following shift methods are available : 'none', "
00472                        "'header', 'center' or 'user'");
00473 
00474         if (strcmp(method, "user") == 0) {
00475             filename = kmo_dfs_get_parameter_string(parlist,
00476                                                    "kmos.kmo_combine.filename");
00477             KMO_TRY_CHECK_ERROR_STATE();
00478 
00479             KMO_TRY_ASSURE(strcmp(filename, "") != 0,
00480                            CPL_ERROR_ILLEGAL_INPUT,
00481                            "path of file with shift information must be "
00482                            "provided!");
00483 
00484             KMO_TRY_EXIT_IF_ERROR(
00485                 kmo_dfs_print_parameter_help(parlist,
00486                                              "kmos.kmo_combine.filename"));
00487         }
00488 
00489         KMO_TRY_EXIT_IF_ERROR(
00490             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_combine.method"));
00491 
00492         ifus_txt = kmo_dfs_get_parameter_string(parlist,
00493                                                   "kmos.kmo_combine.ifus");
00494         KMO_TRY_CHECK_ERROR_STATE();
00495 
00496         name = (char*)kmo_dfs_get_parameter_string(parlist, "kmos.kmo_combine.name");
00497         KMO_TRY_CHECK_ERROR_STATE();
00498 
00499         if (strcmp(ifus_txt, "") != 0) {
00500             KMO_TRY_ASSURE(strcmp(name, "") == 0,
00501                            CPL_ERROR_ILLEGAL_INPUT,
00502                            "name parameter must be NULL if IFU indices are "
00503                            "provided!");
00504 
00505             KMO_TRY_EXIT_IF_NULL(
00506                 ifus = kmo_identify_values(ifus_txt));
00507 
00508             KMO_TRY_ASSURE(cpl_vector_get_size(ifus) == nr_frames,
00509                            CPL_ERROR_ILLEGAL_INPUT,
00510                            "ifus parameter must have the same number of values "
00511                            "than frames provided ) (%lld!=%d)",
00512                            cpl_vector_get_size(ifus), nr_frames);
00513         }
00514 
00515         if (strcmp(name, "") != 0) {
00516             KMO_TRY_ASSURE(strcmp(ifus_txt, "") == 0,
00517                            CPL_ERROR_ILLEGAL_INPUT,
00518                            "ifus parameter must be NULL if name is provided!");
00519         }
00520 
00521         flux = kmo_dfs_get_parameter_bool(parlist,
00522                                           "kmos.kmo_combine.flux");
00523         KMO_TRY_CHECK_ERROR_STATE();
00524         KMO_TRY_EXIT_IF_ERROR(
00525             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_combine.flux"));
00526 
00527         KMO_TRY_ASSURE((flux == TRUE) || (flux == FALSE),
00528                        CPL_ERROR_ILLEGAL_INPUT,
00529                        "flux must be TRUE or FALSE!");
00530 
00531         edge_nan = kmo_dfs_get_parameter_bool(parlist,
00532                                           "kmos.kmo_combine.edge_nan");
00533         KMO_TRY_CHECK_ERROR_STATE();
00534         KMO_TRY_EXIT_IF_ERROR(
00535             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_combine.edge_nan"));
00536 
00537         KMO_TRY_ASSURE((edge_nan == TRUE) || (edge_nan == FALSE),
00538                        CPL_ERROR_ILLEGAL_INPUT,
00539                        "edge_nan must be TRUE or FALSE!");
00540 
00541         if ((strcmp(name, "") == 0) && (strcmp(ifus_txt, "") == 0)) {
00542             cpl_msg_info("","**************************************************");
00543             cpl_msg_info("","*  A map containing all IFUs will be generated!  *");
00544             cpl_msg_info("","**************************************************");
00545             name = cpl_sprintf("mapping");
00546             extrapol_enum = BCS_NATURAL;
00547         }
00548 
00549         KMO_TRY_EXIT_IF_ERROR(
00550             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_combine.ifus"));
00551 
00552         KMO_TRY_EXIT_IF_ERROR(
00553             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_combine.name"));
00554 
00555         KMO_TRY_EXIT_IF_ERROR(
00556             kmo_combine_pars_load(parlist,
00557                                   "kmos.kmo_combine",
00558                                   &cmethod,
00559                                   &cpos_rej,
00560                                   &cneg_rej,
00561                                   &citer,
00562                                   &cmin,
00563                                   &cmax,
00564                                   FALSE));
00565 
00566         cpl_msg_info("", "-------------------------------------------");
00567 
00568         // load data and noise
00569         KMO_TRY_EXIT_IF_NULL(
00570             data_cube_list = cpl_calloc(nr_frames*KMOS_NR_IFUS,
00571                                         sizeof(cpl_imagelist*)));
00572 
00573         KMO_TRY_EXIT_IF_NULL(
00574             data_header_list = cpl_calloc(nr_frames*KMOS_NR_IFUS,
00575                                           sizeof(cpl_propertylist*)));
00576 
00577         KMO_TRY_EXIT_IF_NULL(
00578             noise_cube_list = cpl_calloc(nr_frames*KMOS_NR_IFUS,
00579                                          sizeof(cpl_imagelist*)));
00580 
00581         KMO_TRY_EXIT_IF_NULL(
00582             noise_header_list = cpl_calloc(nr_frames*KMOS_NR_IFUS,
00583                                            sizeof(cpl_propertylist*)));
00584 
00585         //
00586         // load all data (and noise if existent) cubes and store them
00587         //
00588         data_cube_counter = 0;
00589         noise_cube_counter = 0;
00590         for (int i = 0; i < nr_frames; i++) {
00591             KMO_TRY_EXIT_IF_NULL(
00592                 tmp_str = cpl_sprintf("%d", i));
00593 
00594             KMO_TRY_EXIT_IF_NULL(
00595                 frame = kmo_dfs_get_frame(frameset, tmp_str));
00596 
00597             KMO_TRY_EXIT_IF_NULL(
00598                 frame_filename = cpl_frame_get_filename(frame));
00599 
00600             kmo_init_fits_desc(&desc);
00601 
00602             desc = kmo_identify_fits_header(frame_filename);
00603             KMO_TRY_CHECK_ERROR_STATE_MSG("Provided fits file doesn't seem to "
00604                                           "be in KMOS-format!");
00605 
00606             KMO_TRY_ASSURE(desc.fits_type == f3i_fits,
00607                            CPL_ERROR_ILLEGAL_INPUT,
00608                            "Frame No. %d hasn't correct data type "
00609                            "(must be of type F3I)!", i+1);
00610 
00611             if (strcmp(name, "mapping") == 0) {
00612                 // we are in mapping mode
00613                 for (int j = 1; j <= KMOS_NR_IFUS; j++) {
00614                     //loop over all IFUs
00615                     if (desc.sub_desc[j-1].valid_data == TRUE) {
00616                         // load data frames
00617                         override_err_msg = TRUE;
00618                         data_cube_list[data_cube_counter] =
00619                             kmo_dfs_load_cube(frameset, tmp_str, j, FALSE);
00620                         override_err_msg = FALSE;
00621                         if (data_cube_list[data_cube_counter] == NULL) {
00622                             // no data found for this IFU
00623                             cpl_error_reset();
00624                         } else {
00625                             if (edge_nan) {
00626                                 KMO_TRY_EXIT_IF_ERROR(
00627                                     kmo_edge_nan(data_cube_list[data_cube_counter], j));
00628                             }
00629                             KMO_TRY_EXIT_IF_NULL(
00630                                 data_header_list[data_cube_counter] =
00631                                     kmo_dfs_load_sub_header(frameset, tmp_str, j, FALSE));
00632                             cpl_propertylist_update_string(data_header_list[data_cube_counter],
00633                                                     "ESO PRO FRNAME",
00634                                                     frame_filename);
00635                             cpl_propertylist_update_int(data_header_list[data_cube_counter],
00636                                                     "ESO PRO IFUNR",
00637                                                     j);
00638                             data_cube_counter++;
00639                         }
00640 
00641                         // load noise frames
00642                         override_err_msg = TRUE;
00643                         noise_cube_list[noise_cube_counter] =
00644                             kmo_dfs_load_cube(frameset, tmp_str, j, TRUE);
00645 
00646                         override_err_msg = FALSE;
00647                         if (noise_cube_list[noise_cube_counter] == NULL) {
00648                             // no noise found for this IFU
00649                             cpl_error_reset();
00650                         } else {
00651                             if (edge_nan) {
00652                                 KMO_TRY_EXIT_IF_ERROR(
00653                                     kmo_edge_nan(noise_cube_list[noise_cube_counter], j));
00654                             }
00655                             KMO_TRY_EXIT_IF_NULL(
00656                                 noise_header_list[noise_cube_counter] =
00657                                     kmo_dfs_load_sub_header(frameset, tmp_str, j, TRUE));
00658                             noise_cube_counter++;
00659                         }
00660 
00661                         // check for every iteration if number of data and noise
00662                         // frames is the same
00663                         if (noise_cube_counter > 0) {
00664                             KMO_TRY_ASSURE(data_cube_counter == noise_cube_counter,
00665                                            CPL_ERROR_ILLEGAL_INPUT,
00666                                            "Frame No. %d (%s) has no noise frame "
00667                                            "while the preceeding ones had!",
00668                                            i+1, frame_filename);
00669                         }
00670                     } // end if valid_data
00671                 }
00672             } else {
00673                 if (ifus != NULL) {
00674                     ifu_nr = cpl_vector_get(ifus, i);
00675                     KMO_TRY_CHECK_ERROR_STATE();
00676                 } else {
00677                     ifu_nr = kmo_get_index_from_ocs_name(frame, name);
00678                     KMO_TRY_CHECK_ERROR_STATE();
00679                 }
00680 
00681                 if (ifu_nr > 0) {
00682                     index = kmo_identify_index(frame_filename, ifu_nr , FALSE);
00683                     KMO_TRY_CHECK_ERROR_STATE();
00684 
00685                     if (desc.sub_desc[index-1].valid_data == TRUE) {
00686                         // load data frames
00687                         override_err_msg = TRUE;
00688                         data_cube_list[data_cube_counter] =
00689                             kmo_dfs_load_cube(frameset, tmp_str, ifu_nr, FALSE);
00690                         override_err_msg = FALSE;
00691                         if (data_cube_list[data_cube_counter] == NULL) {
00692                             // no data found for this IFU
00693                             cpl_error_reset();
00694                             if (ifus != NULL) {
00695                                 cpl_msg_warning(cpl_func, "Frame No. %d (%s) "
00696                                                 "doesn't contain IFU No. %d!", i+1,
00697                                                 frame_filename, ifu_nr);
00698                             } else {
00699                                 cpl_msg_warning(cpl_func, "Frame No. %d (%s) "
00700                                                 "doesn't contain IFU with object "
00701                                                 "name '%s'!", i+1,
00702                                                 frame_filename, name);
00703                             }
00704                         } else {
00705                             if (edge_nan) {
00706                                 KMO_TRY_EXIT_IF_ERROR(
00707                                     kmo_edge_nan(data_cube_list[data_cube_counter], ifu_nr));
00708                             }
00709 
00710                             KMO_TRY_EXIT_IF_NULL(
00711                                 data_header_list[data_cube_counter] =
00712                                     kmo_dfs_load_sub_header(frameset, tmp_str,
00713                                                             ifu_nr, FALSE));
00714                             cpl_propertylist_update_string(data_header_list[data_cube_counter],
00715                                                            "ESO PRO FRNAME",
00716                                                            frame_filename);
00717                             cpl_propertylist_update_int(data_header_list[data_cube_counter],
00718                                                         "ESO PRO IFUNR",
00719                                                         ifu_nr);
00720                             data_cube_counter++;
00721                         }
00722 
00723                         // load noise frames
00724                         override_err_msg = TRUE;
00725                         noise_cube_list[noise_cube_counter] =
00726                             kmo_dfs_load_cube(frameset, tmp_str, ifu_nr, TRUE);
00727                         override_err_msg = FALSE;
00728                         if (noise_cube_list[noise_cube_counter] == NULL) {
00729                             // no noise found for this IFU
00730                             cpl_error_reset();
00731                         } else {
00732                             if (edge_nan) {
00733                                 KMO_TRY_EXIT_IF_ERROR(
00734                                     kmo_edge_nan(noise_cube_list[noise_cube_counter], ifu_nr));
00735                             }
00736 
00737                             KMO_TRY_EXIT_IF_NULL(
00738                                 noise_header_list[noise_cube_counter] =
00739                                     kmo_dfs_load_sub_header(frameset, tmp_str,
00740                                                             ifu_nr, TRUE));
00741                             noise_cube_counter++;
00742                         }
00743 
00744                         // check for every iteration if number of data and noise
00745                         // frames is the same
00746                         if (noise_cube_counter > 0) {
00747                             KMO_TRY_ASSURE(data_cube_counter == noise_cube_counter,
00748                                            CPL_ERROR_ILLEGAL_INPUT,
00749                                            "Frame No. %d (%s) has no noise frame "
00750                                            "while the preceeding ones had!",
00751                                            i+1, frame_filename);
00752                         }
00753                     } // end if valid_data
00754                 } // end if (ifu_nr > 0)
00755             }
00756 
00757             kmo_free_fits_desc(&desc);
00758             cpl_free(tmp_str); tmp_str = NULL;
00759         } // for i = nr_frames
00760         KMO_TRY_CHECK_ERROR_STATE();
00761 
00762         //
00763         // combine data
00764         //
00765         KMO_TRY_EXIT_IF_ERROR(
00766             kmo_priv_combine(data_cube_list,
00767                              noise_cube_list,
00768                              data_header_list,
00769                              noise_header_list,
00770                              data_cube_counter,
00771                              noise_cube_counter,
00772                              name,
00773                              ifus_txt,
00774                              method,
00775                              "BCS",
00776                              fmethod,
00777                              filename,
00778                              cmethod,
00779                              cpos_rej,
00780                              cneg_rej,
00781                              citer,
00782                              cmin,
00783                              cmax,
00784                              extrapol_enum,
00785                              flux,
00786                              &cube_combined_data,
00787                              &cube_combined_noise));
00788 
00789         //
00790         // save data
00791         //
00792         /* save data and noise (if existing) */
00793         // --- load, update & save primary header ---
00794 
00795         // setup output category COMBINE + ESO PRO CATG
00796         KMO_TRY_EXIT_IF_NULL(
00797             main_header = kmo_dfs_load_primary_header(frameset, "0"));
00798         KMO_TRY_EXIT_IF_NULL(
00799             tmp_str = cpl_sprintf("%s_%s",
00800                               COMBINE,
00801                               cpl_propertylist_get_string(main_header,
00802                                                           CPL_DFS_PRO_CATG)));
00803         cpl_propertylist_delete(main_header); main_header = NULL;
00804 
00805         frame = cpl_frameset_get_first(frameset);
00806         KMO_TRY_EXIT_IF_ERROR(
00807             kmo_dfs_save_main_header(frameset, tmp_str, "", frame, NULL,
00808                                      parlist, cpl_func));
00809 
00810         if (data_header_list[0] != NULL) {
00811             if (cpl_propertylist_has(data_header_list[0], "ESO PRO FRNAME")) {
00812                 cpl_propertylist_erase(data_header_list[0], "ESO PRO FRNAME");
00813             }
00814             if (cpl_propertylist_has(data_header_list[0], "ESO PRO IFUNR")) {
00815                 cpl_propertylist_erase(data_header_list[0], "ESO PRO IFUNR");
00816             }
00817         }
00818         KMO_TRY_CHECK_ERROR_STATE();
00819 
00820         KMO_TRY_EXIT_IF_ERROR(
00821             kmo_dfs_save_cube(cube_combined_data, tmp_str, "",
00822                               data_header_list[0], 0./0.));
00823 
00824         KMO_TRY_EXIT_IF_ERROR(
00825             kmo_dfs_save_cube(cube_combined_noise, tmp_str, "",
00826                               noise_header_list[0], 0./0.));
00827 
00828         cpl_free(tmp_str); tmp_str = NULL;
00829         if (strcmp(name, "mapping") == 0) {
00830             cpl_free(name); name = NULL;
00831         }
00832     }
00833     KMO_CATCH
00834     {
00835         KMO_CATCH_MSG();
00836         ret_val = -1;
00837     }
00838 
00839     cpl_propertylist_delete(main_header); main_header = NULL;
00840     cpl_vector_delete(ifus); ifus = NULL;
00841     cpl_imagelist_delete(cube_combined_data); cube_combined_data = NULL;
00842     cpl_imagelist_delete(cube_combined_noise); cube_combined_noise = NULL;
00843 
00844     if (data_cube_list != NULL) {
00845         for (int i = 0; i < nr_frames*KMOS_NR_IFUS; i++) {
00846             cpl_imagelist_delete(data_cube_list[i]); data_cube_list[i] = NULL;
00847         }
00848         cpl_free(data_cube_list); data_cube_list = NULL;
00849     }
00850 
00851     if (noise_cube_list != NULL) {
00852         for (int i = 0; i < nr_frames*KMOS_NR_IFUS; i++) {
00853             cpl_imagelist_delete(noise_cube_list[i]); noise_cube_list[i] = NULL;
00854         }
00855         cpl_free(noise_cube_list); noise_cube_list = NULL;
00856     }
00857 
00858     if (data_header_list != NULL) {
00859         for (int i = 0; i < nr_frames*KMOS_NR_IFUS; i++) {
00860             cpl_propertylist_delete(data_header_list[i]);
00861             data_header_list[i] = NULL;
00862         }
00863         cpl_free(data_header_list); data_header_list = NULL;
00864     }
00865 
00866     if (noise_header_list != NULL) {
00867         for (int i = 0; i < nr_frames*KMOS_NR_IFUS; i++) {
00868             cpl_propertylist_delete(noise_header_list[i]);
00869             noise_header_list[i] = NULL;
00870         }
00871         cpl_free(noise_header_list); noise_header_list = NULL;
00872     }
00873 
00874     return ret_val;
00875 }
00876