KMOS Pipeline Reference Manual  1.1.3
kmo_multi_reconstruct.c
00001 /* $Id: kmo_multi_reconstruct.c,v 1.27 2013/05/07 08:36:03 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/07 08:36:03 $
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_multi_reconstruct.h"
00046 #include "kmo_priv_reconstruct.h"
00047 
00048 static int kmo_multi_reconstruct_create(cpl_plugin *);
00049 static int kmo_multi_reconstruct_exec(cpl_plugin *);
00050 static int kmo_multi_reconstruct_destroy(cpl_plugin *);
00051 static int kmo_multi_reconstruct(cpl_parameterlist *, cpl_frameset *);
00052 
00053 static char kmo_multi_reconstruct_description[] =
00054 "This recipe shifts several exposures of an object and combines them. The diffe-\n"
00055 "rent methods to match the exposures are described below (--smethod parameter).\n"
00056 "The output cube is larger than the input cubes, according to the shifts to be\n"
00057 "applied. Additionally a border of NaN values is added. The WCS is the same as\n"
00058 "for the first exposure.\n"
00059 "For each spatial/spectral pixel a new value will be calculated (according the\n"
00060 "--cmethod parameter) and written into the output cube.\n"
00061 "Only exposures with equal orientation regarding the WCS can be combined (except\n"
00062 "-–smethod=”none”), north must point to the same direction. It is recommended to\n"
00063 "apply any rotation possibly after combining.\n"
00064 "The default mapping mode is done via the --name parameter, where the name of\n"
00065 "the object has to be provided. The recipe searches in all input data cubes IFUs\n"
00066 "pointing to that object.\n"
00067 "\n"
00068 "BASIC PARAMETERS:\n"
00069 "-----------------\n"
00070 "--name\n"
00071 "--ifus\n"
00072 "Since an object can be present only once per exposure and since it can be\n"
00073 "located in different IFUs for the existing exposures, there are two modes to\n"
00074 "identify the objects:\n"
00075 "   * Combine by object names (default)\n"
00076 "   In this case the object name must be provided via the --name parameter. The\n"
00077 "   object name will be searched for in all primary headers of all provided frames\n"
00078 "   in the keyword ESO OCS ARMx NAME.\n"
00079 "\n"
00080 "   * Combine by index (advanced)\n"
00081 "   In this case the --ifus parameter must be provided. The parameter must have\n"
00082 "   the same number of entries as frames are provided, e.g. \"3;1;24\" for 3 expo-\n"
00083 "   sures. The index doesn't reference the extension in the frame but the real\n"
00084 "   index of the IFU as defined in the EXTNAME keyword (e.g. 'IFU.3.DATA').\n"
00085 "\n"
00086 "--smethod\n"
00087 "There are following sources to get the shift parameters from:\n"
00088 "   * 'none' (default)\n"
00089 "   The cubes are directly recombined, not shifting at all. The ouput frame will\n"
00090 "   have the same dimensions as the input cubes.\n"
00091 "   If the size differs a warning will be emitted and the cubes will be aligned\n"
00092 "   to the lower left corner. If the orientation differs a warning will be emit-\n"
00093 "   ted, but the cubes are combined anyway.\n"
00094 "\n"
00095 "   * 'header'\n"
00096 "   The shifts are calculated according to the WCS information stored in the\n"
00097 "   header of every IFU. The output frame will get larger, except the object is\n"
00098 "   at the exact same position for all exposures. The size of the exposures can\n"
00099 "   differ, but the orientation must be the same for all exposures.\n"
00100 "\n"
00101 "   * 'user'\n"
00102 "   Read the shifts from a user specified file. The path of the file must be pro-\n"
00103 "   vided using the --filename parameter. For every exposure (except the first one)\n"
00104 "   two shift values are expected per line, they have to be separated with simple\n"
00105 "   spaces. The values indicate pixel shifts and are referenced to the first\n"
00106 "   frame. The 1st value is the shift in x-direction to the left, the 2nd the\n"
00107 "   shift in y-direction upwards. The size of the exposures can differ, but the\n"
00108 "   orientation must be the same for all exposures.\n"
00109 "\n"
00110 "   * 'center'\n"
00111 "   The shifts are calculated using a centering algorithm. The detector exposures\""
00112 "   will be reconstructed and the resulting data cubes will be collapsed to an image.\n"
00113 "   A 2D profile of the image will be fitted to it to identify the centre. With \n"
00114 "   the parameter --fmethod the function to fit can be provided. The size of the\n"
00115 "   exposures can differ, but the orientation must be the same for all exposures.\n"
00116 "\n"
00117 "--fmethod\n"
00118 "The type of function that should be fitted spatially to the collapsed image.\n"
00119 "This fit is used to create a mask to extract the spectrum of the object. Valid\n"
00120 "values are “gauss” and “moffat”.\n"
00121 "\n"
00122 "ADVANCED PARAMETERS\n"
00123 "-------------------\n"
00124 "--b_samples\n"
00125 "The number of samples in spectral direction for the reconstructed cube. Ideal-\n"
00126 "ly this number should be greater than 2048, the detector size.\n"
00127 "\n"
00128 "--b_start\n"
00129 "--b_end\n"
00130 "Used to define manually the start and end wavelength for the reconstructed\n"
00131 "cube. By default the internally defined values are used.\n"
00132 "\n"
00133 "-------------------------------------------------------------------------------\n"
00134 "  Input files:\n"
00135 "\n"
00136 "   DO            DO      KMOS                                                  \n"
00137 "   category      group   Type   Explanation                    Required #Frames\n"
00138 "   --------      -----   -----  -----------                    -------- -------\n"
00139 "   OBJECT or             RAW    The science frames                Y      >=2   \n"
00140 "   STD                   RAW                                                   \n"
00141 "   XCAL                  F2D    x calibration frame               Y       1    \n"
00142 "   YCAL                  F2D    y calibration frame               Y       1    \n"
00143 "   LCAL                  F2D    Wavelength calib. frame           Y       1    \n"
00144 "   WAVE_BAND             F2L    Table with start-/end-wavelengths Y       1    \n"
00145 "\n"
00146 "  Output files:\n"
00147 "\n"
00148 "   DO                    KMOS\n"
00149 "   category              Type   Explanation\n"
00150 "   --------              -----  -----------\n"
00151 "   SCI_COMBINED          F3I    Combined cubes with noise\n"
00152 "   SCI_RECONSTRUCTED     F3I    Reconstructed cube with noise\n"
00153 
00154 
00155 
00156 "   <none or any>   -     F3I    data frame                         Y      2-n  \n"
00157 "   WAVE_BAND             F2L    Table with start-/end-wavelengths  Y       1   \n"
00158 "\n"
00159 "  Output files:\n"
00160 "\n"
00161 "   DO                    KMOS\n"
00162 "   category              Type   Explanation\n"
00163 "   --------              -----  -----------\n"
00164 "   CUBE_MULTI_<name/ifu> F3I    Combined data cube\n"
00165 "-------------------------------------------------------------------------------\n"
00166 "\n";
00167 
00184 int cpl_plugin_get_info(cpl_pluginlist *list)
00185 {
00186     cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe);
00187     cpl_plugin *plugin = &recipe->interface;
00188 
00189     cpl_plugin_init(plugin,
00190                         CPL_PLUGIN_API,
00191                         KMOS_BINARY_VERSION,
00192                         CPL_PLUGIN_TYPE_RECIPE,
00193                         "kmo_multi_reconstruct",
00194                         "Combine reconstructed cubes",
00195                         kmo_multi_reconstruct_description,
00196                         "Alex Agudo Berbel",
00197                         "agudo@mpe.mpg.de",
00198                         kmos_get_license(),
00199                         kmo_multi_reconstruct_create,
00200                         kmo_multi_reconstruct_exec,
00201                         kmo_multi_reconstruct_destroy);
00202 
00203     cpl_pluginlist_append(list, plugin);
00204 
00205     return 0;
00206 }
00207 
00215 static int kmo_multi_reconstruct_create(cpl_plugin *plugin)
00216 {
00217     cpl_recipe *recipe;
00218     cpl_parameter *p;
00219 
00220     /* Check that the plugin is part of a valid recipe */
00221     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00222         recipe = (cpl_recipe *)plugin;
00223     else
00224         return -1;
00225 
00226     /* Create the parameters list in the cpl_recipe object */
00227     recipe->parameters = cpl_parameterlist_new();
00228 
00229     /* Fill the parameters list */
00230     /* --name */
00231     p = cpl_parameter_new_value("kmos.kmo_multi_reconstruct.name",
00232                                 CPL_TYPE_STRING,
00233                                 "Name of the object to combine.",
00234                                 "kmos.kmo_multi_reconstruct",
00235                                 "");
00236     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "name");
00237     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00238     cpl_parameterlist_append(recipe->parameters, p);
00239 
00240     /* --ifus */
00241     p = cpl_parameter_new_value("kmos.kmo_multi_reconstruct.ifus",
00242                                 CPL_TYPE_STRING,
00243                                 "The indices of the IFUs to combine. "
00244                                 "\"ifu1;ifu2;...\"",
00245                                 "kmos.kmo_multi_reconstruct",
00246                                 "");
00247     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "ifus");
00248     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00249     cpl_parameterlist_append(recipe->parameters, p);
00250 
00251     /* --size */
00252     p = cpl_parameter_new_value("kmos.kmo_multi_reconstruct.size",
00253                                 CPL_TYPE_STRING,
00254                                 "Spatial size of the output cube.",
00255                                 "kmos.kmo_multi_reconstruct",
00256                                 "max");
00257     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "size");
00258     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00259     cpl_parameterlist_append(recipe->parameters, p);
00260 
00261 
00262     /* --smethod  shift method*/
00263     p = cpl_parameter_new_value("kmos.kmo_multi_reconstruct.smethod",
00264                                 CPL_TYPE_STRING,
00265                                 "The shifting method:   "
00266                                 "'none': no shifting, combined directly "
00267                                                                   "(default), "
00268                                 "'header': shift according to WCS, "
00269                                 "'center': centering algorithm, "
00270                                 "'user': read shifts from file",
00271                                 "kmos.kmo_multi_reconstruct",
00272                                 "none");
00273     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "smethod");
00274     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00275     cpl_parameterlist_append(recipe->parameters, p);
00276 
00277     /* --fmethod */
00278     p = cpl_parameter_new_value("kmos.kmo_multi_reconstruct.fmethod",
00279                                 CPL_TYPE_STRING,
00280                                 "The fitting method (applies only when "
00281                                 "method='center'):   "
00282                                 "'gauss': fit a gauss function to collapsed "
00283                                 "image (default), "
00284                                 "'moffat': fit a moffat function to collapsed"
00285                                 " image",
00286                                 "kmos.kmo_combine",
00287                                 "gauss");
00288     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "fmethod");
00289     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00290     cpl_parameterlist_append(recipe->parameters, p);
00291 
00292     /* --imethod interpolation method */
00293     p = cpl_parameter_new_value("kmos.kmo_multi_reconstruct.imethod",
00294                                 CPL_TYPE_STRING,
00295                                 "Method to use for interpolation. "
00296                                 "[\"NN\" (nearest neighbour), "
00297                                 "\"lwNN\" (linear weighted nearest neighbor), "
00298                                 "\"swNN\" (square weighted nearest neighbor), "
00299                                 "\"MS\" (Modified Shepard's method)"
00300                                 "\"CS\" (Cubic spline)]",
00301                                 "kmos.kmo_multi_reconstruct",
00302                                 "NN");
00303     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "imethod");
00304     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00305     cpl_parameterlist_append(recipe->parameters, p);
00306 
00307     /* --neighborhoodRange */
00308     p = cpl_parameter_new_value("kmos.kmo_reconstruct.neighborhoodRange",
00309                                 CPL_TYPE_DOUBLE,
00310                                 "Defines the range to search for neighbors. "
00311                                 "in pixels",
00312                                 "kmos.kmo_reconstruct",
00313                                 1.001);
00314     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "neighborhoodRange");
00315     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00316     cpl_parameterlist_append(recipe->parameters, p);
00317 
00318     /* --filename */
00319     p = cpl_parameter_new_value("kmos.kmo_multi_reconstruct.filename",
00320                                 CPL_TYPE_STRING,
00321                                 "The path to the file with the shift vectors."
00322                                 "(Applies only to smethod='user')",
00323                                 "kmos.kmo_multi_reconstruct",
00324                                 "");
00325     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "filename");
00326     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00327     cpl_parameterlist_append(recipe->parameters, p);
00328 
00329     // add parameters for band-definition
00330     kmo_band_pars_create(recipe->parameters,
00331                          "kmos.kmo_multi_reconstruct");
00332 
00333     return kmo_combine_pars_create(recipe->parameters,
00334                                    "kmos.kmo_multi_reconstruct",
00335                                    DEF_REJ_METHOD,
00336                                    FALSE);
00337 }
00338 
00344 static int kmo_multi_reconstruct_exec(cpl_plugin *plugin)
00345 {
00346     cpl_recipe  *recipe;
00347 
00348     /* Get the recipe out of the plugin */
00349     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00350         recipe = (cpl_recipe *)plugin;
00351     else return -1 ;
00352 
00353     return kmo_multi_reconstruct(recipe->parameters, recipe->frames);
00354 }
00355 
00361 static int kmo_multi_reconstruct_destroy(cpl_plugin *plugin)
00362 {
00363     cpl_recipe *recipe;
00364 
00365     /* Get the recipe out of the plugin */
00366     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00367         recipe = (cpl_recipe *)plugin;
00368     else return -1 ;
00369 
00370     cpl_parameterlist_delete(recipe->parameters);
00371     return 0 ;
00372 }
00373 
00374 //int kmo_tolerance_round(double x, double tol)
00375 //{
00376 //    int ret = 0;
00377 
00378 //    KMO_TRY
00379 //    {
00380 //        if (fabs(x - floor(x)) < tol) {
00381 //            // value is slightly greater than the real int value
00382 //            ret = floor(x);
00383 //        } else {
00384 //            if (fabs(x - floor(x+tol)) < tol) {
00385 //                // value is slightly greater than the real int value
00386 //                ret = floor(x+tol);
00387 //            } else {
00388 //                // error: sub pixel shift
00389 //                KMO_TRY_ASSURE(1 == 0,
00390 //                               CPL_ERROR_ILLEGAL_INPUT,
00391 //                               "Please apply only whole pixel shifts here "
00392 //                               "and no subpixel shifts!");
00393 //            }
00394 //        }
00395 //    }
00396 //    KMO_CATCH
00397 //    {
00398 //        KMO_CATCH_MSG();
00399 
00400 //        ret = 0;
00401 //    }
00402 
00403 //    return ret;
00404 //}
00405 
00420 static int kmo_multi_reconstruct(cpl_parameterlist *parlist, cpl_frameset *frameset)
00421 {
00422     const char       *smethod               = NULL,
00423                      *cmethod               = NULL,
00424                      *fmethod               = NULL,
00425                      *imethod               = NULL,
00426                      *filename              = NULL,
00427                      *ifus_txt              = NULL,
00428                      *name                  = NULL,
00429                      *size                  = NULL,
00430                      *filter_id             = NULL;
00431 
00432     char             *tmp_str               = NULL,
00433                      *filename_output_cube  = NULL,
00434                      *extname               = NULL,
00435                      *keyword               = NULL,
00436                      *tmp_ocs               = NULL;
00437 
00438     cpl_imagelist    **data_cube_list       = NULL,
00439                      **noise_cube_list      = NULL,
00440                      *cube_combined_data    = NULL,
00441                      *cube_combined_noise   = NULL;
00442 
00443     cpl_vector       *ifus                  = NULL;
00444 
00445     int              ret_val                = 0,
00446                      nr_exposures           = 0,
00447                      device_nr              = 0,
00448                      citer                  = 0,
00449                      cmin                   = 0,
00450                      cmax                   = 0,
00451                      nr_alloc               = 0;
00452 
00453     double           neighborhoodRange      = 1.001,
00454                      cpos_rej               = 0.0,
00455                      cneg_rej               = 0.0;
00456 
00457     char             **exposure_filename    = NULL,
00458                      **exposure_objectname  = NULL;
00459     int              *exposure_ifus         = NULL,
00460                      nr_object_frames       = 0,
00461                      nr_std_frames          = 0;
00462 
00463     double           *xshifts               = NULL,
00464                      *yshifts               = NULL,
00465                      cd1_1                  = 0.0,
00466                      cd1_2                  = 0.0,
00467                      ang1                   = 0.0,
00468                      ang2                   = 0.0,
00469                      exposure_rotangle      = 0.0;
00470 
00471     cpl_propertylist *pl                    = NULL,
00472                      *main_header           = NULL,
00473                      *ref_main_header       = NULL,
00474                      *ref_sub_header        = NULL,
00475                      *tmp_header            = NULL,
00476                      **header_data          = NULL,
00477                      **data_header_list     = NULL,
00478                      **noise_header_list    = NULL;
00479 
00480     cpl_frame        *frame                 = NULL,
00481                      *lcal_frame            = NULL;
00482 
00483     cpl_table        *band_table            = NULL;
00484 
00485     cpl_image        *lcalImg               = NULL;
00486 
00487     main_fits_desc   desc;
00488 
00489     cpl_frameset     *exposures             = NULL;
00490 
00491     cpl_frame        **empty_frames         = NULL,
00492                      *tmp_frame             = NULL,
00493                      *ref_frame             = NULL;
00494 
00495     gridDefinition   gd;
00496 
00497     KMO_TRY
00498     {
00499         /* --- check input --- */
00500         KMO_TRY_ASSURE((parlist != NULL) &&
00501                        (frameset != NULL),
00502                        CPL_ERROR_NULL_INPUT,
00503                        "Not all input data is provided!");
00504 
00505         KMO_TRY_ASSURE(kmo_dfs_set_groups(frameset, "kmo_multi_reconstruct") == 1,
00506                        CPL_ERROR_ILLEGAL_INPUT,
00507                        "Cannot identify RAW and CALIB frames!");
00508 
00509         KMO_TRY_ASSURE(! ((cpl_frameset_count_tags(frameset, XCAL) == 0) &&
00510                           (cpl_frameset_count_tags(frameset, YCAL) == 0) &&
00511                           (cpl_frameset_count_tags(frameset, LCAL) == 0) &&
00512                           (cpl_frameset_count_tags(frameset, WAVE_BAND) == 0)),
00513                           CPL_ERROR_FILE_NOT_FOUND,
00514                           "XCAL, YCAL, LCAL or WAVE_BAND frames missing in "
00515                           "frameset!!");
00516 
00517         KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, XCAL) == 1,
00518                        CPL_ERROR_FILE_NOT_FOUND,
00519                        "Exactly one XCAL frame is expected in frameset!");
00520 
00521         KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, YCAL) == 1,
00522                        CPL_ERROR_FILE_NOT_FOUND,
00523                        "Exactly one YCAL frame is expected in frameset!");
00524 
00525         KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, LCAL) == 1,
00526                        CPL_ERROR_FILE_NOT_FOUND,
00527                        "Exactly one LCAL frame is expected in frameset!");
00528 
00529         KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, WAVE_BAND) == 1,
00530                        CPL_ERROR_FILE_NOT_FOUND,
00531                        "Exactly one WAVE_BAND frame is expected in frameset!");
00532 
00533         // assert that at least two OBJECT or STD frames are available and create
00534         // intermediate frameset just with these science frames
00535         nr_object_frames = cpl_frameset_count_tags(frameset, OBJECT);
00536         nr_std_frames = cpl_frameset_count_tags(frameset, STD);
00537         KMO_TRY_CHECK_ERROR_STATE();
00538         nr_exposures = nr_object_frames + nr_std_frames;
00539 
00540         KMO_TRY_ASSURE(((nr_object_frames > 1) && (nr_std_frames == 0)) ||
00541                        ((nr_object_frames == 0) && (nr_std_frames > 1)),
00542                        CPL_ERROR_ILLEGAL_INPUT,
00543                        "OBJECT and STD frames mustn't be intermixed and at "
00544                        "least two frames (OBJECT or STD) must be provided "
00545                        "to combine!");
00546         KMO_TRY_EXIT_IF_NULL(
00547             exposures = cpl_frameset_new());
00548         if (nr_object_frames > 1) {
00549             KMO_TRY_EXIT_IF_NULL(
00550                 tmp_frame = kmo_dfs_get_frame(frameset, OBJECT));
00551         } else {
00552             KMO_TRY_EXIT_IF_NULL(
00553                 tmp_frame = kmo_dfs_get_frame(frameset, STD));
00554         }
00555 
00556         for (int i = 0; i < nr_exposures; i++) {
00557             KMO_TRY_EXIT_IF_ERROR(
00558                 cpl_frameset_insert(exposures, cpl_frame_duplicate(tmp_frame)));
00559             KMO_TRY_CHECK_ERROR_STATE();
00560 
00561             tmp_frame = kmo_dfs_get_frame(frameset, NULL);
00562         }
00563 
00564         cpl_msg_info("", "--- Parameter setup for kmo_multi_reconstruct -------");
00565 
00566         KMO_TRY_EXIT_IF_NULL(
00567             imethod = kmo_dfs_get_parameter_string(parlist,
00568                                          "kmos.kmo_multi_reconstruct.imethod"));
00569 
00570         KMO_TRY_ASSURE((strcmp(imethod, "NN") == 0) ||
00571                        (strcmp(imethod, "lwNN") == 0) ||
00572                        (strcmp(imethod, "swNN") == 0) ||
00573                        (strcmp(imethod, "MS") == 0) ||
00574                        (strcmp(imethod, "CS") == 0),
00575                        CPL_ERROR_ILLEGAL_INPUT,
00576                        "imethod must be either \"NN\", \"lwNN\", "
00577                        "\"swNN\", \"MS\" or \"CS\"!");
00578 
00579         KMO_TRY_EXIT_IF_ERROR(
00580             kmo_dfs_print_parameter_help(parlist,
00581                                         "kmos.kmo_multi_reconstruct.imethod"));
00582 
00583         neighborhoodRange = kmo_dfs_get_parameter_double(parlist,
00584                 "kmos.kmo_reconstruct.neighborhoodRange");
00585         KMO_TRY_CHECK_ERROR_STATE();
00586 
00587         KMO_TRY_ASSURE(neighborhoodRange > 0.0,
00588                        CPL_ERROR_ILLEGAL_INPUT,
00589                        "neighborhoodRange must be greater than 0.0");
00590 
00591         KMO_TRY_EXIT_IF_ERROR(
00592             kmo_dfs_print_parameter_help(parlist,
00593                                      "kmos.kmo_reconstruct.neighborhoodRange"));
00594 
00595         KMO_TRY_EXIT_IF_NULL(
00596             size = kmo_dfs_get_parameter_string(parlist,
00597                                             "kmos.kmo_multi_reconstruct.size"));
00598 
00599         KMO_TRY_EXIT_IF_NULL(
00600             smethod = kmo_dfs_get_parameter_string(parlist,
00601                                          "kmos.kmo_multi_reconstruct.smethod"));
00602 
00603         KMO_TRY_EXIT_IF_NULL(
00604             fmethod = kmo_dfs_get_parameter_string(parlist,
00605                                          "kmos.kmo_multi_reconstruct.fmethod"));
00606 
00607         KMO_TRY_ASSURE((strcmp(size, "max") == 0) ||
00608                        (strcmp(size, "std") == 0),
00609                        CPL_ERROR_ILLEGAL_INPUT,
00610                        "Following output cube size specifications are available: "
00611                        "'std' or 'max'");
00612 
00613 
00614         KMO_TRY_ASSURE((strcmp(smethod, "none") == 0) ||
00615                        (strcmp(smethod, "header") == 0) ||
00616                        (strcmp(smethod, "center") == 0) ||
00617                        (strcmp(smethod, "user") == 0),
00618                        CPL_ERROR_ILLEGAL_INPUT,
00619                        "Following shift methods are available : 'none', "
00620                        "'header', 'center' or 'user'");
00621 
00622         if (strcmp(smethod, "user") == 0) {
00623             filename = kmo_dfs_get_parameter_string(parlist,
00624                                          "kmos.kmo_multi_reconstruct.filename");
00625             KMO_TRY_CHECK_ERROR_STATE();
00626 
00627             KMO_TRY_ASSURE(strcmp(filename, "") != 0,
00628                            CPL_ERROR_ILLEGAL_INPUT,
00629                            "path of file with shift information must be "
00630                            "provided!");
00631 
00632             KMO_TRY_EXIT_IF_ERROR(
00633                 kmo_dfs_print_parameter_help(parlist,
00634                                         "kmos.kmo_multi_reconstruct.filename"));
00635         }
00636 
00637         KMO_TRY_EXIT_IF_ERROR(
00638             kmo_dfs_print_parameter_help(parlist,
00639                                          "kmos.kmo_multi_reconstruct.smethod"));
00640 
00641         ifus_txt = kmo_dfs_get_parameter_string(parlist,
00642                                              "kmos.kmo_multi_reconstruct.ifus");
00643         KMO_TRY_CHECK_ERROR_STATE();
00644 
00645         name = kmo_dfs_get_parameter_string(parlist,
00646                                             "kmos.kmo_multi_reconstruct.name");
00647         KMO_TRY_CHECK_ERROR_STATE();
00648 
00649         if (strcmp(ifus_txt, "") != 0) {
00650             KMO_TRY_ASSURE(strcmp(name, "") == 0,
00651                            CPL_ERROR_ILLEGAL_INPUT,
00652                            "name parameter must be NULL if IFU indices are "
00653                            "provided!");
00654 
00655             KMO_TRY_EXIT_IF_NULL(
00656                 ifus = kmo_identify_values(ifus_txt));
00657 
00658             KMO_TRY_ASSURE(cpl_vector_get_size(ifus) == nr_exposures,
00659                            CPL_ERROR_ILLEGAL_INPUT,
00660                            "ifus parameter must have the same number of values "
00661                            "than frames provided ) (%lld!=%d)",
00662                            cpl_vector_get_size(ifus), nr_exposures);
00663 
00664             for (int i = 0; i < nr_exposures; i++) {
00665                 KMO_TRY_ASSURE((cpl_vector_get(ifus, i) > 0.5 &&
00666                                cpl_vector_get(ifus, i) < 24.5 ),
00667                                CPL_ERROR_ILLEGAL_INPUT,
00668                                "IFU numbers must be in the range 1..24");
00669             }
00670         }
00671 
00672         if (strcmp(name, "") != 0) {
00673             KMO_TRY_ASSURE(strcmp(ifus_txt, "") == 0,
00674                            CPL_ERROR_ILLEGAL_INPUT,
00675                            "ifus parameter must be NULL if name is provided!");
00676         }
00677 
00678         KMO_TRY_ASSURE((strcmp(name, "") != 0) || (strcmp(ifus_txt, "") != 0),
00679                        CPL_ERROR_ILLEGAL_INPUT,
00680                        "Either the name of the object or the numbers of the "
00681                        "IFUs to combine must be provided (--name or --ifus "
00682                        "parameters)");
00683 
00684         KMO_TRY_EXIT_IF_ERROR(
00685             kmo_dfs_print_parameter_help(parlist,
00686                                          "kmos.kmo_multi_reconstruct.ifus"));
00687 
00688         KMO_TRY_EXIT_IF_ERROR(
00689             kmo_dfs_print_parameter_help(parlist,
00690                                          "kmos.kmo_multi_reconstruct.name"));
00691 
00692         KMO_TRY_EXIT_IF_ERROR(
00693             kmo_combine_pars_load(parlist,
00694                                   "kmos.kmo_multi_reconstruct",
00695                                   &cmethod,
00696                                   &cpos_rej,
00697                                   &cneg_rej,
00698                                   &citer,
00699                                   &cmin,
00700                                   &cmax,
00701                                   FALSE));
00702 
00703         kmo_band_pars_load(parlist, "kmos.kmo_multi_reconstruct");
00704 
00705         cpl_msg_info("", "-------------------------------------------");
00706 
00707         // assure that filters and grating  match for
00708         // XCAL, YCAL, LCAL and for data frames to reconstruct
00709         KMO_TRY_EXIT_IF_ERROR(
00710             kmo_check_frameset_setup(frameset, XCAL,
00711                                        TRUE, FALSE, FALSE));
00712         KMO_TRY_EXIT_IF_ERROR(
00713             kmo_check_frameset_setup(frameset, YCAL,
00714                                        TRUE, FALSE, FALSE));
00715         KMO_TRY_EXIT_IF_ERROR(
00716             kmo_check_frameset_setup(frameset, LCAL,
00717                                        TRUE, FALSE, FALSE));
00718         KMO_TRY_EXIT_IF_ERROR(
00719             kmo_check_frame_setup(frameset, XCAL, YCAL,
00720                                        TRUE, FALSE, TRUE));
00721         KMO_TRY_EXIT_IF_ERROR(
00722             kmo_check_frame_setup(frameset, XCAL, LCAL,
00723                                        TRUE, FALSE, TRUE));
00724         if (nr_object_frames > 1) {
00725             KMO_TRY_EXIT_IF_ERROR(
00726                 kmo_check_frameset_setup(frameset, OBJECT,
00727                                            TRUE, FALSE, FALSE));
00728             KMO_TRY_EXIT_IF_ERROR(
00729                 kmo_check_frame_setup(frameset, XCAL, OBJECT,
00730                                            TRUE, FALSE, TRUE));
00731         } else {
00732             KMO_TRY_EXIT_IF_ERROR(
00733                 kmo_check_frameset_setup(frameset, STD,
00734                                            TRUE, FALSE, FALSE));
00735             KMO_TRY_EXIT_IF_ERROR(
00736                 kmo_check_frame_setup(frameset, XCAL, STD,
00737                                            TRUE, FALSE, TRUE));
00738         }
00739 
00740         KMO_TRY_EXIT_IF_ERROR(
00741             kmo_check_frame_setup_md5_xycal(frameset));
00742         KMO_TRY_EXIT_IF_ERROR(
00743             kmo_check_frame_setup_md5(frameset));
00744 
00745 //        KMO_TRY_EXIT_IF_ERROR(
00746 //            kmo_check_cal_frames_rotangle(frameset, XCAL, YCAL));
00747 //        KMO_TRY_EXIT_IF_ERROR(
00748 //            kmo_check_cal_frames_rotangle(frameset, XCAL, LCAL));
00749 
00750 
00751         nr_alloc = nr_exposures;
00752         KMO_TRY_EXIT_IF_NULL(
00753             exposure_filename = cpl_malloc(nr_alloc * sizeof(char *)));
00754         KMO_TRY_EXIT_IF_NULL(
00755             exposure_objectname = cpl_malloc(nr_alloc * sizeof(char *)));
00756         KMO_TRY_EXIT_IF_NULL(
00757             exposure_ifus  = cpl_malloc(nr_alloc * sizeof(int)));
00758 
00759         // check exposure frames
00760         for (int i = 0; i < nr_exposures; i++) {
00761             KMO_TRY_EXIT_IF_NULL(
00762                 tmp_str = cpl_sprintf("%d", i));
00763 
00764             KMO_TRY_EXIT_IF_NULL(
00765                 frame = kmo_dfs_get_frame(exposures, tmp_str));
00766             cpl_free(tmp_str);
00767 
00768             KMO_TRY_EXIT_IF_NULL(
00769                 exposure_filename[i] = (char*)cpl_frame_get_filename(frame));
00770 
00771             kmo_init_fits_desc(&desc);
00772 
00773             desc = kmo_identify_fits_header(exposure_filename[i]);
00774             KMO_TRY_CHECK_ERROR_STATE_MSG("Provided fits file doesn't seem to "
00775                                           "be in KMOS-format!");
00776 
00777             KMO_TRY_ASSURE(((desc.nr_ext == KMOS_NR_DETECTORS) ||
00778                             ((desc.nr_ext == 2*KMOS_NR_DETECTORS))) &&
00779                            (desc.ex_badpix == FALSE) &&
00780                            ((desc.fits_type == raw_fits) ||
00781                             (desc.fits_type == f2d_fits)) &&
00782                            (desc.frame_type == detector_frame),
00783                            CPL_ERROR_ILLEGAL_INPUT,
00784                            "The frame to reconstruct isn't in the correct "
00785                            "format!!!");
00786             kmo_free_fits_desc(&desc);
00787         }
00788 
00789         // select IFU for each exposure
00790         KMO_TRY_EXIT_IF_NULL(
00791             empty_frames = cpl_malloc(nr_alloc * sizeof(cpl_frame *)));
00792         int found=0;
00793         for (int i = 0; i < nr_exposures; i++) {
00794             empty_frames[i] = NULL;
00795             if (strcmp(ifus_txt, "") != 0) { //IFU selected by user given list
00796                 found = 1;
00797                 const char *tmpString;
00798                 exposure_ifus[i] = (int) (cpl_vector_get(ifus, i) + 0.1);
00799                 KMO_TRY_EXIT_IF_NULL(
00800                     pl = kmclipm_propertylist_load(exposure_filename[i], 0));
00801                 KMO_TRY_EXIT_IF_NULL(
00802                     tmp_ocs = cpl_sprintf("%s%d%s", IFU_NAME_PREFIX,
00803                                           exposure_ifus[i], IFU_NAME_POSTFIX));
00804                 if (cpl_propertylist_has(pl, tmp_ocs)) {
00805                     tmpString = cpl_propertylist_get_string(pl, tmp_ocs);
00806                 } else {
00807                     tmpString = "";
00808                 }
00809                 cpl_free(tmp_ocs);
00810                 int len = strlen(tmpString);
00811                 const int maxLen = 40;
00812                 if (len > maxLen) {
00813                     len = maxLen;
00814                 }
00815                 exposure_objectname[i] = (char *) cpl_malloc(len * sizeof(char));
00816                 strncpy(exposure_objectname[i], tmpString, len-1);
00817                 if (len > 0) {
00818                     (exposure_objectname[i])[len-1] = '\0';
00819                 }
00820                 cpl_propertylist_delete(pl); pl = NULL;
00821             }  else {                   //IFU selected by user given object name
00822                 exposure_objectname[i] = (char*)name;
00823                 KMO_TRY_EXIT_IF_NULL(
00824                     tmp_str = cpl_sprintf("%d", i));
00825 
00826                 KMO_TRY_EXIT_IF_NULL(
00827                     frame = kmo_dfs_get_frame(exposures, tmp_str));
00828                 cpl_free(tmp_str);
00829 
00830                 KMO_TRY_CHECK_ERROR_STATE();
00831                 int this_ifu = kmo_get_index_from_ocs_name(frame, name);
00832                 KMO_TRY_CHECK_ERROR_STATE();
00833                 if (this_ifu > 0) {
00834                     found = 1;
00835                     exposure_ifus[i] = this_ifu;
00836                 } else {
00837                     empty_frames[i] = frame;
00838                     exposure_ifus[i] = -1;
00839                     cpl_msg_warning("",
00840                                     "Could not find any IFU with an object "
00841                                     "named '%s' in file %s",
00842                                     name, exposure_filename[i]);
00843                 }
00844             }
00845             KMO_TRY_CHECK_ERROR_STATE();
00846         }
00847         if (! found) {
00848             cpl_msg_error("",
00849                           "Could not find any IFU with an object named '%s' in "
00850                           "any input file", name);
00851             KMO_TRY_EXIT_WITH_ERROR(CPL_ERROR_ILLEGAL_INPUT);
00852         }
00853         int j = 0;
00854         for (int i = 0; i < nr_alloc; i++) {
00855             if (empty_frames[i] != NULL) {
00856                 KMO_TRY_EXIT_IF_ERROR(
00857                     cpl_frameset_erase_frame(exposures, empty_frames[i]));
00858                 nr_exposures--;
00859                 exposure_ifus[j] = exposure_ifus[i];
00860             } else {
00861                 exposure_ifus[j] = exposure_ifus[i];
00862                 j++;
00863             }
00864         }
00865         for (int i = 0; i < nr_exposures; i++) {
00866             KMO_TRY_EXIT_IF_NULL(
00867                 tmp_str = cpl_sprintf("%d", i));
00868 
00869             KMO_TRY_EXIT_IF_NULL(
00870                 frame = kmo_dfs_get_frame(exposures, tmp_str));
00871             cpl_free(tmp_str);
00872 
00873             KMO_TRY_EXIT_IF_NULL(
00874                 exposure_filename[i] = (char*)cpl_frame_get_filename(frame));
00875         }
00876 
00877         cpl_free(empty_frames); empty_frames = NULL;
00878 
00879         // get reference header, subheader and set grid definition
00880         device_nr = ((exposure_ifus[0] -1) / KMOS_IFUS_PER_DETECTOR) + 1;
00881 
00882         KMO_TRY_EXIT_IF_NULL(
00883             ref_main_header = kmclipm_propertylist_load(exposure_filename[0],0));
00884         KMO_TRY_EXIT_IF_NULL(
00885             ref_frame = cpl_frameset_get_first(exposures));
00886         KMO_TRY_EXIT_IF_NULL(
00887             ref_sub_header = kmclipm_propertylist_load(exposure_filename[0],
00888                                                        device_nr));
00889         KMO_TRY_EXIT_IF_ERROR(
00890             kmclipm_setup_grid(&gd, imethod, neighborhoodRange, KMOS_PIX_RESOLUTION));
00891 
00892         exposure_rotangle = kmo_mr_get_rot_angle(kmo_dfs_get_frame(exposures, "0"));
00893         KMO_TRY_EXIT_IF_NULL(
00894             lcal_frame = kmo_mr_get_closest_cal_frame(frameset, LCAL,
00895                                                       exposure_rotangle));
00896         KMO_TRY_EXIT_IF_NULL(
00897             lcalImg = kmo_dfs_load_image_frame(lcal_frame, device_nr, 0,
00898                                                FALSE, NULL));
00899 
00900         KMO_TRY_EXIT_IF_NULL(
00901             tmp_header = kmclipm_propertylist_load(
00902                                         cpl_frame_get_filename(lcal_frame), 0));
00903         KMO_TRY_EXIT_IF_NULL(
00904             keyword = cpl_sprintf("%s%d%s", IFU_FILTID_PREFIX, device_nr,
00905                                   IFU_FILTID_POSTFIX));
00906         KMO_TRY_EXIT_IF_NULL(
00907             filter_id = cpl_propertylist_get_string(tmp_header, keyword));
00908 
00909         int band_method = 0;
00910         KMO_TRY_EXIT_IF_NULL(
00911             band_table = kmo_dfs_load_table(frameset, WAVE_BAND, 1, 0));
00912 
00913         KMO_TRY_EXIT_IF_ERROR(
00914             kmclipm_setup_grid_band_lcal(&gd, lcalImg, filter_id,
00915                                          band_method, band_table));
00916         cpl_image_delete(lcalImg); lcalImg = NULL;
00917         cpl_propertylist_delete(tmp_header); tmp_header = NULL;
00918         cpl_free(keyword); keyword = NULL;
00919         cpl_table_delete(band_table); band_table = NULL;
00920 
00921         //extract sub-headers for each exposures, calculate WCS
00922         KMO_TRY_EXIT_IF_NULL(
00923             header_data = cpl_malloc(nr_exposures*sizeof(cpl_propertylist*)));
00924         for (int i = 0; i < nr_exposures; i++) {
00925            device_nr = ((exposure_ifus[0] -1) / KMOS_IFUS_PER_DETECTOR) + 1;
00926            KMO_TRY_EXIT_IF_NULL(
00927                header_data[i] = kmclipm_propertylist_load(exposure_filename[i],
00928                                                           device_nr));
00929            KMO_TRY_EXIT_IF_ERROR(
00930                 kmclipm_update_property_int(header_data[i],"NAXIS", 3,""));
00931            KMO_TRY_EXIT_IF_ERROR(
00932                 kmclipm_update_property_int(header_data[i],"NAXIS1",gd.x.dim,""));
00933            KMO_TRY_EXIT_IF_ERROR(
00934                 kmclipm_update_property_int(header_data[i],"NAXIS2",gd.y.dim,""));
00935            KMO_TRY_EXIT_IF_ERROR(
00936                 kmclipm_update_property_int(header_data[i],"NAXIS3",gd.l.dim,""));
00937            cpl_propertylist *tmpHeader;
00938            KMO_TRY_EXIT_IF_NULL(
00939                 tmpHeader = kmclipm_propertylist_load(exposure_filename[i],0));
00940            KMO_TRY_EXIT_IF_ERROR(
00941                 kmo_calc_wcs_gd(tmpHeader, header_data[i], exposure_ifus[i], gd));
00942            cpl_propertylist_delete(tmpHeader);
00943         }
00944 
00945         // check rotation angle
00946         cd1_1 = kmo_dfs_get_property_double(header_data[0], CD1_1);
00947         cd1_2 = kmo_dfs_get_property_double(header_data[0], CD1_2);
00948         KMO_TRY_CHECK_ERROR_STATE();
00949         ang1 = atan(cd1_2/cd1_1)*180/CPL_MATH_PI;
00950         for (int i = 1; i < nr_exposures; i++) {
00951             cd1_1 = kmo_dfs_get_property_double(header_data[i], CD1_1);
00952             cd1_2 = kmo_dfs_get_property_double(header_data[i], CD1_2);
00953             KMO_TRY_CHECK_ERROR_STATE();
00954             ang2 = atan(cd1_2/cd1_1)*180/CPL_MATH_PI;
00955 
00956             if (strcmp(smethod, "none") != 0) {
00957                 // center, header, user
00958                 KMO_TRY_ASSURE(fabs(ang1-ang2) <= 0.5,
00959                                CPL_ERROR_ILLEGAL_INPUT,
00960                                "Orientation of cube 1 (%gdeg) and cube %d "
00961                                "(%gdeg) differ! "
00962                                "Align the orientation of this cube with "
00963                                "kmo_rotate before applying this recipe.",
00964                                ang1, i+1, ang2);
00965             } else {
00966                 // none
00967                 if (fabs(ang1-ang2) > 0.5) {
00968                     cpl_msg_warning("",
00969                                     "Orientation of cube 1 (%gdeg) and cube %d "
00970                                     "(%gdeg) differ! Processing anyway.",
00971                                     ang1, i+1, ang2);
00972                 }
00973             }
00974         }
00975 
00976         // set x/y shifts
00977         KMO_TRY_EXIT_IF_NULL(
00978             xshifts = cpl_malloc(nr_exposures * sizeof(double)));
00979         KMO_TRY_EXIT_IF_NULL(
00980             yshifts = cpl_malloc(nr_exposures * sizeof(double)));
00981         KMO_TRY_EXIT_IF_ERROR(
00982             kmo_mr_get_offsets(nr_exposures, smethod, imethod, neighborhoodRange,
00983                                filename, frameset, exposures, exposure_ifus,
00984                                (const cpl_propertylist**)header_data,
00985                                fmethod,
00986                                cmethod,
00987                                cpos_rej,
00988                                cneg_rej,
00989                                citer,
00990                                cmin,
00991                                cmax,
00992                                xshifts, yshifts));
00993 
00994         for (int i = 0; i < nr_exposures; i++) {
00995             printf("exposure %d: filename %s, selected IFU %d, object name "
00996                    "\"%s\", xshift %f, yshift %f\n", i, exposure_filename[i],
00997                    exposure_ifus[i], exposure_objectname[i], xshifts[i], yshifts[i]);
00998         }
00999 
01000         //
01001         // set spatial part of the grid
01002         //
01003 //        size = "max";
01004         if (strcmp(size, "max") == 0) {
01005             double xmin=0, xmax=0, ymin=0, ymax=0;
01006             double gxshift, gyshift, gxdim, gydim;
01007             double pixel_resolution = KMOS_PIXEL_RESOLUTION;
01008             int xdim, ydim;
01009 
01010             for (int i = 0; i < nr_exposures; i++) {
01011                 if (xmin > xshifts[i]) { xmin = xshifts[i]; }
01012                 if (xmax < xshifts[i]) { xmax = xshifts[i]; }
01013                 if (ymin > yshifts[i]) { ymin = yshifts[i]; }
01014                 if (ymax < yshifts[i]) { ymax = yshifts[i]; }
01015             }
01016             if (xmax > 0.0001) {
01017                 gxshift = - ceil(xmax);
01018             } else {
01019                 gxshift = 0.;
01020             }
01021             if (ymin < -0.0001) {
01022                 gyshift = floor(ymin);
01023             } else {
01024                 gyshift = 0.;
01025             }
01026             if (xmin < -0.0001) {
01027                 gxdim = - floor(xmin);
01028             } else {
01029                 gxdim = 0.;
01030             }
01031             if (ymax > 0.0001) {
01032                 gydim = ceil(ymax);
01033             } else {
01034                 gydim = 0.;
01035             }
01036 
01037             xdim = (int) (gxdim - gxshift + .5);
01038             ydim = (int) (gydim - gyshift + .5);
01039             gd.x.start += gxshift * pixel_resolution;
01040             gd.y.start += gyshift * pixel_resolution;
01041             gd.x.dim += xdim;
01042             gd.y.dim += ydim;
01043 //            printf("X: %f < %f      Y: %f < %f \n",xmin,xmax,ymin,ymax);
01044 //            printf("gxshift: %f  gxdim: %f   xdim: %d        gyshift: %f  gydim: %f  ydim: %d \n",
01045 //                    gxshift, gxdim, xdim, gyshift, gydim, ydim);
01046 //            printf("GD: %f  %d     %f %d\n", gd.x.start, gd.x.dim, gd.y.start, gd.y.dim);
01047         }
01048 
01049         //
01050         // reconstruct multiple detector images
01051         //
01052 
01053 //        printf("GD: %f %f %d     %f %f %d     %f %f %d\n",
01054 //                gd.x.start, gd.x.delta, gd.x.dim,
01055 //                gd.y.start, gd.y.delta, gd.y.dim,
01056 //                gd.l.start, gd.l.delta, gd.l.dim);
01057 
01058         KMO_TRY_EXIT_IF_ERROR(
01059             kmo_priv_multi_reconstruct(frameset,
01060                                        exposures,
01061                                        exposure_ifus,
01062                                        xshifts,
01063                                        yshifts,
01064                                        gd,
01065                                        &cube_combined_data,
01066                                        &cube_combined_noise));
01067 
01068         // setup output category COMBINE + ESO PRO CATG
01069         if (strcmp(ifus_txt, "") != 0) { //IFU selected by user given list
01070             KMO_TRY_EXIT_IF_NULL(
01071                 tmp_str = cpl_sprintf("IFU"));
01072         } else {
01073             KMO_TRY_EXIT_IF_NULL(
01074                 tmp_str = cpl_sprintf("%s", name));
01075         }
01076 
01077         KMO_TRY_EXIT_IF_NULL(
01078             filename_output_cube = cpl_sprintf("%s_%s", CUBE_MULTI, tmp_str));
01079         cpl_free(tmp_str); tmp_str = NULL;
01080 
01081         KMO_TRY_EXIT_IF_ERROR(
01082             kmo_dfs_save_main_header(frameset, filename_output_cube, "",
01083                                      ref_frame, NULL, parlist, cpl_func));
01084         // save output
01085         KMO_TRY_EXIT_IF_NULL(
01086             extname = kmo_extname_creator(ifu_frame, exposure_ifus[0],
01087                                           EXT_DATA));
01088 
01089         // calculate WCS
01090         KMO_TRY_EXIT_IF_ERROR(
01091             kmo_calc_wcs_gd(ref_main_header, ref_sub_header, exposure_ifus[0], gd));
01092 
01093         KMO_TRY_EXIT_IF_ERROR(
01094             kmclipm_update_property_string(ref_sub_header,
01095                                            EXTNAME,
01096                                            extname,
01097                                            "FITS extension name"));
01098         cpl_free(extname); extname = NULL;
01099 
01100         KMO_TRY_EXIT_IF_ERROR(
01101             kmo_dfs_save_cube(cube_combined_data, filename_output_cube,
01102                               "", ref_sub_header, 0./0.));
01103 
01104         if (cube_combined_noise != NULL) {
01105             KMO_TRY_EXIT_IF_NULL(
01106                 extname = kmo_extname_creator(ifu_frame, exposure_ifus[0],
01107                                               EXT_NOISE));
01108 
01109             KMO_TRY_EXIT_IF_ERROR(
01110                 kmclipm_update_property_string(ref_sub_header,
01111                                         EXTNAME,
01112                                         extname,
01113                                         "FITS extension name"));
01114             cpl_free(extname); extname = NULL;
01115 
01116             KMO_TRY_EXIT_IF_ERROR(
01117                 kmo_dfs_save_cube(cube_combined_noise, filename_output_cube,
01118                                   "", ref_sub_header, 0./0.));
01119         }
01120     }
01121     KMO_CATCH
01122     {
01123         KMO_CATCH_MSG();
01124         ret_val = -1;
01125     }
01126 
01127     cpl_free(filename_output_cube); filename_output_cube = NULL;
01128     cpl_propertylist_delete(main_header); main_header = NULL;
01129     cpl_vector_delete(ifus); ifus = NULL;
01130     cpl_imagelist_delete(cube_combined_data); cube_combined_data = NULL;
01131     cpl_imagelist_delete(cube_combined_noise); cube_combined_noise = NULL;
01132     if (exposures != NULL) {cpl_frameset_delete(exposures);}
01133     if (exposure_filename != NULL) {cpl_free(exposure_filename);}
01134     if ((ifus_txt != NULL) && (strcmp(ifus_txt, "") != 0)) { //IFU selected by user given list
01135         for (int i = 0; i < nr_alloc; i++) {
01136             cpl_free(exposure_objectname[i]);
01137         }
01138     }
01139     if (exposure_objectname != NULL) {cpl_free(exposure_objectname);}
01140     if (exposure_ifus != NULL) {cpl_free(exposure_ifus);}
01141     if (ref_main_header != NULL) {cpl_propertylist_delete(ref_main_header);}
01142     if (ref_sub_header != NULL) {cpl_propertylist_delete(ref_sub_header);}
01143     if (xshifts != NULL) {cpl_free(xshifts);}
01144     if (yshifts != NULL) {cpl_free(yshifts);}
01145 
01146     if (data_cube_list != NULL) {
01147         for (int i = 0; i < nr_exposures; i++) {
01148             cpl_imagelist_delete(data_cube_list[i]); data_cube_list[i] = NULL;
01149         }
01150         cpl_free(data_cube_list); data_cube_list = NULL;
01151     }
01152 
01153     if (noise_cube_list != NULL) {
01154         for (int i = 0; i < nr_exposures; i++) {
01155             cpl_imagelist_delete(noise_cube_list[i]); noise_cube_list[i] = NULL;
01156         }
01157         cpl_free(noise_cube_list); noise_cube_list = NULL;
01158     }
01159 
01160     if (data_header_list != NULL) {
01161         for (int i = 0; i < nr_exposures; i++) {
01162             cpl_propertylist_delete(data_header_list[i]);
01163             data_header_list[i] = NULL;
01164         }
01165         cpl_free(data_header_list); data_header_list = NULL;
01166     }
01167 
01168     if (noise_header_list != NULL) {
01169         for (int i = 0; i < nr_exposures; i++) {
01170             cpl_propertylist_delete(noise_header_list[i]);
01171             noise_header_list[i] = NULL;
01172         }
01173         cpl_free(noise_header_list); noise_header_list = NULL;
01174     }
01175 
01176     if (header_data != NULL) {
01177         for (int i = 0; i < nr_exposures; i++) {
01178             cpl_propertylist_delete(header_data[i]);
01179             header_data[i] = NULL;
01180         }
01181         cpl_free(header_data); header_data = NULL;
01182     }
01183 
01184     return ret_val;
01185 }
01186