KMOS Pipeline Reference Manual  1.3.0b1
kmo_multi_reconstruct.c
00001 /*
00002  * This file is part of the KMOS Pipeline
00003  * Copyright (C) 2002,2003 European Southern Observatory
00004  *
00005  * This program is free software; you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License as published by
00007  * the Free Software Foundation; either version 2 of the License, or
00008  * (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program; if not, write to the Free Software
00017  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018  */
00019 
00020 #ifdef HAVE_CONFIG_H
00021 #include <config.h>
00022 #endif
00023 
00024 /*-----------------------------------------------------------------------------
00025  *                              Includes
00026  *----------------------------------------------------------------------------*/
00027 #include <string.h>
00028 #include <math.h>
00029 
00030 #include <cpl.h>
00031 
00032 #include "kmclipm_constants.h"
00033 #include "kmclipm_functions.h"
00034 
00035 #include "kmo_debug.h"
00036 #include "kmo_constants.h"
00037 #include "kmo_cpl_extensions.h"
00038 #include "kmo_priv_lcorr.h"
00039 #include "kmo_utils.h"
00040 #include "kmo_error.h"
00041 #include "kmo_dfs.h"
00042 #include "kmo_functions.h"
00043 #include "kmo_priv_arithmetic.h"
00044 #include "kmo_priv_combine.h"
00045 #include "kmo_priv_functions.h"
00046 #include "kmo_priv_reconstruct.h"
00047 #include "kmo_priv_multi_reconstruct.h"
00048 
00049 /*-----------------------------------------------------------------------------
00050  *              Types
00051  *-----------------------------------------------------------------------------*/
00052 
00053 /*-----------------------------------------------------------------------------
00054  *                          Functions prototypes
00055  *----------------------------------------------------------------------------*/
00056 
00057 static int kmo_multi_reconstruct_create(cpl_plugin *);
00058 static int kmo_multi_reconstruct_exec(cpl_plugin *);
00059 static int kmo_multi_reconstruct_destroy(cpl_plugin *);
00060 static int kmo_multi_reconstruct(cpl_parameterlist *, cpl_frameset *);
00061 
00062 /*-----------------------------------------------------------------------------
00063  *                          Static variables
00064  *----------------------------------------------------------------------------*/
00065 
00066 static char kmo_multi_reconstruct_description[] =
00067 "Ideally at least two data frames have to be provided since we need for each IFU\n"
00068 "pointing to an object as well a sky frame for the same IFU.\n"
00069 "If an OH spectrum is given in the SOF file the lambda axis will be corrected\n"
00070 "using the OH lines as reference.\n"
00071 "All IFUs with the same object name will be reconstructed and combined in one step\n"
00072 "Telluric correction is only supported if the objects have been observed with\n"
00073 "the same IFU on all exposures (dithering).\n"
00074 "The number of created files depends on the number of objects of different name.\n"
00075 "If the user just wants to combine a certain object, the parameters --name or\n"
00076 "--ifus can be used.\n"
00077 "\n"
00078 "Exposures taken with the templates KMOS_spec_obs_mapping8 and\n"
00079 "KMOS_spec_obs_mapping24 can't be processed with this recipe! Use kmo_sci_red\n"
00080 "instead.\n"
00081 "\n"
00082 "BASIC PARAMETERS:\n"
00083 "-----------------\n"
00084 "--imethod\n"
00085 "The interpolation method used for reconstruction.\n"
00086 "\n"
00087 "--name\n"
00088 "--ifus\n"
00089 "Since an object can be present only once per exposure and since it can be\n"
00090 "located in different IFUs for the existing exposures, there are two modes to\n"
00091 "identify the objects:\n"
00092 "   * Combine by object names (default)\n"
00093 "   In this case the object name must be provided via the --name parameter. The\n"
00094 "   object name will be searched for in all primary headers of all provided\n"
00095 "   frames in the keyword ESO OCS ARMx NAME.\n"
00096 "\n"
00097 "   * Combine by index (advanced)\n"
00098 "   In this case the --ifus parameter must be provided. The parameter must have\n"
00099 "   the same number of entries as frames are provided, e.g. \"3;1;24\" for 3\n"
00100 "   exposures. The index doesn't reference the extension in the frame but the\n"
00101 "   real index of the IFU as defined in the EXTNAME keyword.\n"
00102 "   (e.g. 'IFU.3.DATA')\n"
00103 "\n"
00104 "ADVANCED PARAMETERS\n"
00105 "-------------------\n"
00106 "--flux\n"
00107 "Specify if flux conservation should be applied.\n"
00108 "\n"
00109 "--background\n"
00110 "Specify if background removal should be applied.\n"
00111 "\n"
00112 "--suppress_extension\n"
00113 "If set to TRUE, the arbitrary filename extensions are supressed. If multiple\n"
00114 "products with the same category are produced, they will be numered consecutively\n"
00115 "starting from 0.\n"
00116 "\n"
00117 "--obj_sky_table\n"
00118 "The automatic obj-sky-associations can be modified by indicating a file with\n"
00119 "the desired associations. Therefore the file written to disk by default\n"
00120 "(without setting this option) can be edited manually. The formatting must\n"
00121 "absolutely be retained, just the type codes ('O' and'S') and the associated\n"
00122 "frame indices should be altered\n"
00123 "\n"
00124 "  Advanced reconstruction parameters\n"
00125 "  ----------------------------------\n"
00126 "--neighborhoodRange\n"
00127 "Defines the range to search for neighbors during reconstruction\n"
00128 "\n"
00129 "--b_samples\n"
00130 "The number of samples in spectral direction for the reconstructed cube.\n"
00131 "Ideally this number should be greater than 2048, the detector size.\n"
00132 "\n"
00133 "--b_start\n"
00134 "--b_end\n"
00135 "Used to define manually the start and end wavelength for the reconstructed\n"
00136 "cube. By default the internally defined values are used.\n"
00137 "\n"
00138 "--pix_scale\n"
00139 "Change the pixel scale [arcsec]. Default of 0.2\" results into cubes of\n"
00140 "14x14pix, a scale of 0.1\" results into cubes of 28x28pix, etc.\n"
00141 "\n"
00142 "--no_subtract\n"
00143 "If set to TRUE, the found objects and references won't be sky subtracted. \n"
00144 "Additionally all IFUs will be reconstructed, even the ones containing skies. \n"
00145 "\n"
00146 "--xcal_interpolation\n"
00147 "If true interpolate the pixel position in the slitlet (xcal) using the two\n"
00148 "closest rotator angles in the calibration file. Otherwise take the values\n"
00149 "of the closest rotator angle\n"
00150 "\n"
00151 "  Advanced combining parameters\n"
00152 "  ----------------------------------\n"
00153 "--method\n"
00154 "There are following sources to get the shift parameters from:\n"
00155 "   * 'header' (default)\n"
00156 "   The shifts are calculated according to the WCS information stored in the\n"
00157 "   header of every IFU. The output frame will get larger, except the object is\n"
00158 "   at the exact same position for all exposures. The size of the exposures can\n"
00159 "   differ, but the orientation must be the same for all exposures.\n"
00160 "\n"
00161 "   * 'none'\n"
00162 "   The cubes are directly recombined, not shifting at all. The ouput frame\n"
00163 "   will have the same dimensions as the input cubes.\n"
00164 "   If the size differs a warning will be emitted and the cubes will be aligned\n"
00165 "   to the lower left corner. If the orientation differs a warning will be\n"
00166 "   emitted, but the cubes are combined anyway.\n"
00167 "\n"
00168 "   * 'center'\n"
00169 "   The shifts are calculated using a centering algorithm. The cube will be\n"
00170 "   collapsed and a 2D profile will be fitted to it to identify the centre.\n"
00171 "   With the parameter --fmethod the function to fit can be provided. The size\n"
00172 "   of the exposures can differ, but the orientation must be the same for all\n"
00173 "   exposures.\n"
00174 "\n"
00175 "   * 'user'\n"
00176 "   Read the shifts from a user specified file. The path of the file must be\n"
00177 "   provided using the --filename parameter. For every exposure (except the\n"
00178 "   first one) two shift values are expected per line, they have to be separa-\n"
00179 "   ted with simple spaces. The values indicate pixel shifts and are referenced\n"
00180 "   to the first frame. The 1st value is the shift in x-direction to the left,\n"
00181 "   the 2nd the shift in y-direction upwards. The size of the exposures can\n"
00182 "   differ, but the orientation must be the same for all exposures.\n"
00183 "\n"
00184 "--fmethod\n"
00185 "see --method='center'\n"
00186 "The type of function that should be fitted spatially to the collapsed image.\n"
00187 "This fit is used to create a mask to extract the spectrum of the object. Valid\n"
00188 "values are 'gauss' and 'moffat'.\n"
00189 "\n"
00190 "--filename\n"
00191 "see --method='user'\n"
00192 "\n"
00193 "--cmethod\n"
00194 "Following methods of frame combination are available:\n"
00195 "   * 'ksigma' (Default)\n"
00196 "   An iterative sigma clipping. For each position all pixels in the spectrum\n"
00197 "   are examined. If they deviate significantly, they will be rejected according\n"
00198 "   to the conditions:\n"
00199 "       val > mean + stdev * cpos_rej\n"
00200 "   and\n"
00201 "       val < mean - stdev * cneg_rej\n"
00202 "   where --cpos_rej, --cneg_rej and --citer are the corresponding configuration\n"
00203 "   parameters. In the first iteration median and percentile level are used.\n"
00204 "\n"
00205 "   * 'median'\n"
00206 "   At each pixel position the median is calculated.\n"
00207 "\n"
00208 "   * 'average'\n"
00209 "   At each pixel position the average is calculated.\n"
00210 "\n"
00211 "   * 'sum'\n"
00212 "   At each pixel position the sum is calculated.\n"
00213 "\n"
00214 "   * 'min_max'\n"
00215 "   The specified number of minimum and maximum pixel values will be rejected.\n"
00216 "   --cmax and --cmin apply to this method.\n"
00217 "\n"
00218 "--cpos_rej\n"
00219 "--cneg_rej\n"
00220 "--citer\n"
00221 "see --cmethod='ksigma'\n"
00222 "\n"
00223 "--cmax\n"
00224 "--cmin\n"
00225 "see --cmethod='min_max'\n"
00226 "\n"
00227 "------------------------------------------------------------------------------\n"
00228 "  Input files:\n"
00229 "\n"
00230 "   DO                    KMOS                                                  \n"
00231 "   category              Type   Explanation                   Required #Frames\n"
00232 "   --------              -----  -----------                   -------- -------\n"
00233 "   SCIENCE               RAW    The science frames                Y      >=1  \n"
00234 "   XCAL                  F2D    x calibration frame               Y       1   \n"
00235 "   YCAL                  F2D    y calibration frame               Y       1   \n"
00236 "   LCAL                  F2D    Wavelength calib. frame           Y       1   \n"
00237 "   MASTER_FLAT           F2D    Master flat                       Y      0,1  \n"
00238 "   WAVE_BAND             F2L    Table with start-/end-wavelengths Y       1   \n"
00239 "   TELLURIC              F1I    normalised telluric spectrum      N      0,1  \n"
00240 "   OH_SPEC               F1S    Vector holding OH lines           N      0,1  \n"
00241 "\n"
00242 "  Output files:\n"
00243 "\n"
00244 "   DO                    KMOS\n"
00245 "   category              Type   Explanation\n"
00246 "   --------              -----  -----------\n"
00247 "   CUBE_MULTI            F3I    Combined cubes with noise\n"
00248 "------------------------------------------------------------------------------\n"
00249 "\n";
00250 
00251 /*-----------------------------------------------------------------------------
00252  *                              Functions code
00253  *----------------------------------------------------------------------------*/
00254 
00272 int cpl_plugin_get_info(cpl_pluginlist *list)
00273 {
00274     cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe);
00275     cpl_plugin *plugin = &recipe->interface;
00276 
00277     cpl_plugin_init(plugin,
00278                         CPL_PLUGIN_API,
00279                         KMOS_BINARY_VERSION,
00280                         CPL_PLUGIN_TYPE_RECIPE,
00281                         "kmo_multi_reconstruct",
00282                         "Reconstruct and combine obj/sky-pairs in one step.",
00283                         kmo_multi_reconstruct_description,
00284                         "Alex Agudo Berbel",
00285                         "usd-help@eso.org",
00286                         kmos_get_license(),
00287                         kmo_multi_reconstruct_create,
00288                         kmo_multi_reconstruct_exec,
00289                         kmo_multi_reconstruct_destroy);
00290 
00291     cpl_pluginlist_append(list, plugin);
00292 
00293     return 0;
00294 }
00295 
00303 static int kmo_multi_reconstruct_create(cpl_plugin *plugin)
00304 {
00305     cpl_recipe *recipe;
00306     cpl_parameter *p;
00307 
00308     /* Check that the plugin is part of a valid recipe */
00309     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00310         recipe = (cpl_recipe *)plugin;
00311     else
00312         return -1;
00313 
00314     /* Create the parameters list in the cpl_recipe object */
00315     recipe->parameters = cpl_parameterlist_new();
00316 
00317     /* --imethod (interpolation method) */
00318     p = cpl_parameter_new_value("kmos.kmo_multi_reconstruct.imethod",
00319                                 CPL_TYPE_STRING,
00320                                 "Method to use for interpolation during reconstruction. "
00321                                 "[\"NN\" (nearest neighbour), "
00322                                 "\"lwNN\" (linear weighted nearest neighbor), "
00323                                 "\"swNN\" (square weighted nearest neighbor), "
00324                                 "\"MS\" (Modified Shepard's method)",
00325                                 "kmos.kmo_multi_reconstruct",
00326                                 "MS");
00327     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "imethod");
00328     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00329     cpl_parameterlist_append(recipe->parameters, p);
00330 
00331     /* --method  (shift method) */
00332     p = cpl_parameter_new_value("kmos.kmo_multi_reconstruct.method",
00333                                 CPL_TYPE_STRING,
00334                                 "The shifting method:   "
00335                                 "'none': no shifting, combined directly, "
00336                                 "'header': shift according to WCS (default), "
00337                                 "'center': centering algorithm, "
00338                                 "'user': read shifts from file",
00339                                 "kmos.kmo_multi_reconstruct",
00340                                 "header");
00341     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "method");
00342     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00343     cpl_parameterlist_append(recipe->parameters, p);
00344 
00345     /* --fmethod */
00346     p = cpl_parameter_new_value("kmos.kmo_multi_reconstruct.fmethod",
00347                                 CPL_TYPE_STRING,
00348                                 "The fitting method (applies only when "
00349                                 "method='center'):   "
00350                                 "'gauss': fit a gauss function to collapsed "
00351                                 "image (default), "
00352                                 "'moffat': fit a moffat function to collapsed"
00353                                 " image",
00354                                 "kmos.kmo_multi_reconstruct",
00355                                 "gauss");
00356     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "fmethod");
00357     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00358     cpl_parameterlist_append(recipe->parameters, p);
00359 
00360     /* --name */
00361     p = cpl_parameter_new_value("kmos.kmo_multi_reconstruct.name",
00362                                 CPL_TYPE_STRING,
00363                                 "Name of the object to combine.",
00364                                 "kmos.kmo_multi_reconstruct",
00365                                 "");
00366     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "name");
00367     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00368     cpl_parameterlist_append(recipe->parameters, p);
00369 
00370     /* --ifus */
00371     p = cpl_parameter_new_value("kmos.kmo_multi_reconstruct.ifus",
00372                                 CPL_TYPE_STRING,
00373                                 "The indices of the IFUs to combine. "
00374                                 "\"ifu1;ifu2;...\"",
00375                                 "kmos.kmo_multi_reconstruct",
00376                                 "");
00377     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "ifus");
00378     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00379     cpl_parameterlist_append(recipe->parameters, p);
00380 
00381     /* --pix_scale */
00382     p = cpl_parameter_new_value("kmos.kmo_multi_reconstruct.pix_scale",
00383                                 CPL_TYPE_DOUBLE,
00384                                 "Change the pixel scale [arcsec]. "
00385                                 "Default of 0.2\" results into cubes of 14x14pix, "
00386                                 "a scale of 0.1\" results into cubes of 28x28pix, "
00387                                 "etc.",
00388                                 "kmos.kmo_multi_reconstruct",
00389                                 KMOS_PIX_RESOLUTION);
00390     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "pix_scale");
00391     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00392     cpl_parameterlist_append(recipe->parameters, p);
00393 
00394     /* --suppress_extension */
00395     p = cpl_parameter_new_value("kmos.kmo_multi_reconstruct.suppress_extension",
00396                                 CPL_TYPE_BOOL,
00397                                 "Suppress arbitrary filename extension."
00398                                 "(TRUE (apply) or FALSE (don't apply)",
00399                                 "kmos.kmo_multi_reconstruct",
00400                                 FALSE);
00401     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "suppress_extension");
00402     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00403     cpl_parameterlist_append(recipe->parameters, p);
00404 
00405     /* --neighborhoodRange */
00406     p = cpl_parameter_new_value("kmos.kmo_multi_reconstruct.neighborhoodRange",
00407                                 CPL_TYPE_DOUBLE,
00408                                 "Defines the range to search for neighbors "
00409                                 "in pixels",
00410                                 "kmos.kmo_multi_reconstruct",
00411                                 1.001);
00412     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "neighborhoodRange");
00413     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00414     cpl_parameterlist_append(recipe->parameters, p);
00415 
00416     /* --filename */
00417     p = cpl_parameter_new_value("kmos.kmo_multi_reconstruct.filename",
00418                                 CPL_TYPE_STRING,
00419                                 "The path to the file with the shift vectors."
00420                                 "(Applies only to method='user')",
00421                                 "kmos.kmo_multi_reconstruct",
00422                                 "");
00423     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "filename");
00424     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00425     cpl_parameterlist_append(recipe->parameters, p);
00426 
00427     /* --flux */
00428     p = cpl_parameter_new_value("kmos.kmo_multi_reconstruct.flux",
00429                                 CPL_TYPE_BOOL,
00430                                 "TRUE: Apply flux conservation. FALSE: otherwise",
00431                                 "kmos.kmo_multi_reconstruct",
00432                                 FALSE);
00433     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "flux");
00434     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00435     cpl_parameterlist_append(recipe->parameters, p);
00436 
00437     /* --background */
00438     p = cpl_parameter_new_value("kmos.kmo_multi_reconstruct.background",
00439                                 CPL_TYPE_BOOL,
00440                                 "TRUE: Apply background removal. FALSE: otherwise",
00441                                 "kmos.kmo_multi_reconstruct",
00442                                 FALSE);
00443     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "background");
00444     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00445     cpl_parameterlist_append(recipe->parameters, p);
00446 
00447     /* --xcal_interpolation */
00448     p = cpl_parameter_new_value("kmos.kmo_multi_reconstruct.xcal_interpolation",
00449                                 CPL_TYPE_BOOL,
00450                                 "TRUE: Interpolate xcal between rotator angles. FALSE: otherwise",
00451                                 "kmos.kmo_multi_reconstruct",
00452                                 TRUE);
00453     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "xcal_interpolation");
00454     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00455     cpl_parameterlist_append(recipe->parameters, p);
00456 
00457     /* --no_subtract */
00458     p = cpl_parameter_new_value("kmos.kmo_multi_reconstruct.no_subtract",
00459                                 CPL_TYPE_BOOL,
00460                                 "Don't sky subtract object and references."
00461                                 "(TRUE (apply) or "
00462                                 "FALSE (don't apply)",
00463                                 "kmos.kmo_multi_reconstruct",
00464                                 FALSE);
00465     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "no_subtract");
00466     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00467     cpl_parameterlist_append(recipe->parameters, p);
00468 
00469     /* --dev_cal */
00470     p = cpl_parameter_new_value("kmos.kmo_multi_reconstruct.dev_cal",
00471                                 CPL_TYPE_BOOL,
00472                                 "Development only: If calibration data is to be "
00473                                 "reconstructed the ALPHA/DELTA keywords are "
00474                                 "missing. Setting this parameter to TRUE prevents "
00475                                 "according data check",
00476                                 "kmos.kmo_multi_reconstruct",
00477                                 FALSE);
00478     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "dev_cal");
00479     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00480     cpl_parameterlist_append(recipe->parameters, p);
00481 
00482     /* --obj_sky_table */
00483     p = cpl_parameter_new_value("kmos.kmo_multi_reconstruct.obj_sky_table",
00484                                 CPL_TYPE_STRING,
00485                                 "The path to the file with the modified obj/sky associations.",
00486                                 "kmos.kmo_multi_reconstruct",
00487                                 "");
00488     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "obj_sky_table");
00489     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00490     cpl_parameterlist_append(recipe->parameters, p);
00491 
00492 
00493     // add parameters for band-definition
00494     kmo_band_pars_create(recipe->parameters,
00495                          "kmos.kmo_multi_reconstruct");
00496 
00497     return kmo_combine_pars_create(recipe->parameters,
00498                                    "kmos.kmo_multi_reconstruct",
00499                                    DEF_REJ_METHOD,
00500                                    FALSE);
00501 }
00502 
00508 static int kmo_multi_reconstruct_exec(cpl_plugin *plugin)
00509 {
00510     cpl_recipe  *recipe;
00511 
00512     /* Get the recipe out of the plugin */
00513     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00514         recipe = (cpl_recipe *)plugin;
00515     else return -1 ;
00516 
00517     return kmo_multi_reconstruct(recipe->parameters, recipe->frames);
00518 }
00519 
00525 static int kmo_multi_reconstruct_destroy(cpl_plugin *plugin)
00526 {
00527     cpl_recipe *recipe;
00528 
00529     /* Get the recipe out of the plugin */
00530     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00531         recipe = (cpl_recipe *)plugin;
00532     else return -1 ;
00533 
00534     cpl_parameterlist_delete(recipe->parameters);
00535     return 0 ;
00536 }
00537 
00552 static int kmo_multi_reconstruct(cpl_parameterlist *parlist, cpl_frameset *frameset)
00553 {
00554     int                     ret_val                     = 0,
00555                             nr_science_frames           = 0,
00556                             has_illum_corr              = 0,
00557                             has_master_flat             = 0,
00558                             has_telluric                = 0,
00559                             *bounds                     = NULL,
00560                             citer                       = 0,
00561                             cmin                        = 0,
00562                             cmax                        = 0,
00563                             flux                        = FALSE,
00564                             background                  = FALSE,
00565                             no_subtract                 = FALSE,
00566                             xcal_interpolation          = FALSE,
00567                             suppress_extension          = FALSE,
00568                             dev_cal                     = 0,
00569                             cnt                         = 0,
00570                             arm_index                   = 0,
00571                             suppress_index              = 0,
00572                             xdim                        = 0,
00573                             ydim                        = 0,
00574                             iy                          = 0,
00575                             ix                          = 0,
00576                             ifu_nr                      = 0,
00577                             nr_frames                   = 0;
00578     double                  xmin                        = DBL_MAX,
00579                             xmax                        = -DBL_MAX,
00580                             ymin                        = DBL_MAX,
00581                             ymax                        = -DBL_MAX,
00582                             gxshift                     = 0.,
00583                             gyshift                     = 0.,
00584                             gxdim                       = 0.,
00585                             gydim                       = 0.,
00586                             neighborhoodRange           = 1.001,
00587                             cpos_rej                    = 0.0,
00588                             cneg_rej                    = 0.0,
00589                             pix_scale                   = 0.0,
00590                             *xshifts                    = NULL,
00591                             *yshifts                    = NULL;
00592     char                    *suffix                     = NULL,
00593                             *mapping_mode               = NULL,
00594                             *fn_cube                    = NULL,
00595                             *fn_suffix                  = NULL,
00596                             *filter_id                  = NULL,
00597                             *extname                    = NULL;
00598     const char              *imethod                    = NULL,
00599                             *ifus_txt                   = NULL,
00600                             *name                       = NULL,
00601                             *tmp_str                    = NULL,
00602                             *filename                   = NULL,
00603                             *fn_obj_sky_table           = NULL,
00604                             *comb_method                = NULL,
00605                             *cmethod                    = NULL,
00606                             *fmethod                    = NULL,
00607                             *filter_keyword             = "ESO INS FILT1 ID";
00608     cpl_array               **unused_ifus_before        = NULL,
00609                             **unused_ifus_after         = NULL;
00610     cpl_frame               *xcal_frame                 = NULL,
00611                             *ycal_frame                 = NULL,
00612                             *lcal_frame                 = NULL,
00613                             *flat_frame                 = NULL,
00614                             *illum_frame                = NULL,
00615                             *telluric_frame             = NULL,
00616                             *science_frame              = NULL,
00617                             *ref_spectrum_frame         = NULL;
00618     cpl_propertylist        *tmp_header                 = NULL,
00619                             *ref_sub_header             = NULL,
00620                             *science_frame_header       = NULL,
00621                             **sub_headers               = NULL;
00622     cpl_vector              *ifus                       = NULL;
00623     cpl_table               *band_table                 = NULL;
00624 
00625     cpl_polynomial          **lcorr_coeffs              = NULL;
00626     cpl_imagelist           *cube_combined_data         = NULL,
00627                             *cube_combined_noise        = NULL,
00628                             **pre_data_cube_list        = NULL;
00629     kmclipm_vector          *telluric_data              = NULL,
00630                             *telluric_noise             = NULL;
00631     main_fits_desc          desc1,
00632                             desc2,
00633                             desc_telluric;
00634     gridDefinition          gd,
00635                             gd_14x14;
00636     armNameStruct           *arm_name_struct            = NULL;
00637 
00638     KMO_TRY
00639     {
00640 
00641         kmo_init_fits_desc(&desc1);
00642         kmo_init_fits_desc(&desc2);
00643         kmo_init_fits_desc(&desc_telluric);
00644 
00645         //
00646         // check frameset
00647         //
00648         KMO_TRY_ASSURE((parlist != NULL) &&
00649                        (frameset != NULL),
00650                        CPL_ERROR_NULL_INPUT,
00651                        "Not all input data is provided!");
00652 
00653         nr_science_frames = cpl_frameset_count_tags(frameset, SCIENCE);
00654         KMO_TRY_ASSURE(nr_science_frames >= 1,
00655                        CPL_ERROR_ILLEGAL_INPUT,
00656                        "At least one SCIENCE frame is required!");
00657         if (nr_science_frames == 1) {
00658             cpl_msg_warning("", "At least two SCIENCE frames should be provided "
00659                                 "in order to apply sky subtraction!");
00660             cpl_msg_warning("", "All IFUs will be reconstructed regardless if "
00661                                 "they contain object, reference or sky!");
00662         }
00663 
00664         KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, XCAL) == 1,
00665                        CPL_ERROR_FILE_NOT_FOUND,
00666                        "Exactly one XCAL frame is required!");
00667 
00668         KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, YCAL) == 1,
00669                        CPL_ERROR_FILE_NOT_FOUND,
00670                        "Exactly one YCAL frame is required!");
00671 
00672         KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, LCAL) == 1,
00673                        CPL_ERROR_FILE_NOT_FOUND,
00674                        "Exactly one LCAL frame is required!");
00675 
00676         has_master_flat = cpl_frameset_count_tags(frameset, MASTER_FLAT);
00677         KMO_TRY_ASSURE((has_master_flat == 0) || (has_master_flat == 1),
00678                        CPL_ERROR_FILE_NOT_FOUND,
00679                        "At most one MASTER_FLAT frame can be provided!");
00680 
00681         KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, WAVE_BAND) == 1,
00682                        CPL_ERROR_FILE_NOT_FOUND,
00683                        "Exactly one WAVE_BAND frame is required!");
00684 
00685         has_illum_corr = cpl_frameset_count_tags(frameset, ILLUM_CORR);
00686         KMO_TRY_ASSURE((has_illum_corr == 0) || (has_illum_corr == 1),
00687                        CPL_ERROR_FILE_NOT_FOUND,
00688                        "At most one ILLUM_CORR frame can be provided!");
00689 
00690         has_telluric = cpl_frameset_count_tags(frameset, TELLURIC);
00691         KMO_TRY_ASSURE((has_telluric == 0) || (has_telluric == 1),
00692                        CPL_ERROR_FILE_NOT_FOUND,
00693                        "At most one TELLURIC frame can be provided!");
00694 
00695         KMO_TRY_ASSURE(kmo_dfs_set_groups(frameset, "kmo_multi_reconstruct") == 1,
00696                        CPL_ERROR_ILLEGAL_INPUT,
00697                        "Cannot identify RAW and CALIB frames!");
00698 
00699         KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, OH_SPEC) == 0 ||
00700                        cpl_frameset_count_tags(frameset, OH_SPEC) == 1,
00701                        CPL_ERROR_ILLEGAL_INPUT,
00702                        "Only a single reference spectrum can be provided!");
00703         //
00704         // get parameters
00705         //
00706         cpl_msg_info("", "--- Parameter setup for kmo_multi_reconstruct ------");
00707 
00708         flux = kmo_dfs_get_parameter_bool(parlist, "kmos.kmo_multi_reconstruct.flux");
00709         KMO_TRY_ASSURE((flux == 0) ||
00710                        (flux == 1),
00711                        CPL_ERROR_ILLEGAL_INPUT,
00712                        "flux must be either FALSE or TRUE! %d", flux);
00713         KMO_TRY_EXIT_IF_ERROR(
00714             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_multi_reconstruct.flux"));
00715 
00716         background = kmo_dfs_get_parameter_bool(parlist, "kmos.kmo_multi_reconstruct.background");
00717         KMO_TRY_ASSURE((background == 0) ||
00718                        (background == 1),
00719                        CPL_ERROR_ILLEGAL_INPUT,
00720                        "background must be either FALSE or TRUE! %d", background);
00721         KMO_TRY_EXIT_IF_ERROR(
00722             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_multi_reconstruct.background"));
00723 
00724         KMO_TRY_EXIT_IF_NULL(
00725             imethod = kmo_dfs_get_parameter_string(parlist, "kmos.kmo_multi_reconstruct.imethod"));
00726         KMO_TRY_ASSURE((strcmp(imethod, "NN") == 0) ||
00727                        (strcmp(imethod, "lwNN") == 0) ||
00728                        (strcmp(imethod, "swNN") == 0) ||
00729                        (strcmp(imethod, "MS") == 0),
00730                        CPL_ERROR_ILLEGAL_INPUT,
00731                        "imethod must be either \"NN\", \"lwNN\", "
00732                        "\"swNN\" or \"MS\"!");
00733         KMO_TRY_EXIT_IF_ERROR(
00734             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_multi_reconstruct.imethod"));
00735 
00736         neighborhoodRange = kmo_dfs_get_parameter_double(parlist, "kmos.kmo_multi_reconstruct.neighborhoodRange");
00737         KMO_TRY_CHECK_ERROR_STATE();
00738         KMO_TRY_ASSURE(neighborhoodRange > 0.0,
00739                        CPL_ERROR_ILLEGAL_INPUT,
00740                        "neighborhoodRange must be greater than 0.0");
00741         KMO_TRY_EXIT_IF_ERROR(
00742             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_multi_reconstruct.neighborhoodRange"));
00743 
00744         KMO_TRY_EXIT_IF_NULL(
00745             comb_method = kmo_dfs_get_parameter_string(parlist, "kmos.kmo_multi_reconstruct.method"));
00746         KMO_TRY_EXIT_IF_NULL(
00747             fmethod = kmo_dfs_get_parameter_string(parlist, "kmos.kmo_multi_reconstruct.fmethod"));
00748         KMO_TRY_ASSURE((strcmp(comb_method, "none") == 0) ||
00749                        (strcmp(comb_method, "header") == 0) ||
00750                        (strcmp(comb_method, "center") == 0) ||
00751                        (strcmp(comb_method, "user") == 0),
00752                        CPL_ERROR_ILLEGAL_INPUT,
00753                        "Following shift methods are available : 'none', "
00754                        "'header', 'center' or 'user'");
00755 
00756         if (strcmp(comb_method, "user") == 0) {
00757             filename = kmo_dfs_get_parameter_string(parlist, "kmos.kmo_multi_reconstruct.filename");
00758             KMO_TRY_CHECK_ERROR_STATE();
00759             KMO_TRY_ASSURE(strcmp(filename, "") != 0,
00760                            CPL_ERROR_ILLEGAL_INPUT,
00761                            "path of file with shift information must be "
00762                            "provided!");
00763             KMO_TRY_EXIT_IF_ERROR(
00764                 kmo_dfs_print_parameter_help(parlist, "kmos.kmo_multi_reconstruct.filename"));
00765         }
00766 
00767         KMO_TRY_EXIT_IF_ERROR(
00768             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_multi_reconstruct.method"));
00769         ifus_txt = kmo_dfs_get_parameter_string(parlist,
00770                                                   "kmos.kmo_multi_reconstruct.ifus");
00771         KMO_TRY_CHECK_ERROR_STATE();
00772         name = kmo_dfs_get_parameter_string(parlist, "kmos.kmo_multi_reconstruct.name");
00773         KMO_TRY_CHECK_ERROR_STATE();
00774 
00775         if (strcmp(ifus_txt, "") != 0) {
00776             KMO_TRY_ASSURE(strcmp(name, "") == 0,
00777                            CPL_ERROR_ILLEGAL_INPUT,
00778                            "name parameter must be NULL if IFU indices are "
00779                            "provided!");
00780 
00781             KMO_TRY_EXIT_IF_NULL(
00782                 ifus = kmo_identify_values(ifus_txt));
00783 
00784             KMO_TRY_ASSURE(cpl_vector_get_size(ifus) == nr_science_frames,
00785                            CPL_ERROR_ILLEGAL_INPUT,
00786                            "ifus parameter must have the same number of values "
00787                            "than frames provided (for frames just containing "
00788                            "skies insert 0)) (%lld=%d)",
00789                            cpl_vector_get_size(ifus), nr_science_frames);
00790         }
00791 
00792         if (strcmp(name, "") != 0) {
00793             KMO_TRY_ASSURE(strcmp(ifus_txt, "") == 0,
00794                            CPL_ERROR_ILLEGAL_INPUT,
00795                            "ifus parameter must be NULL if name is provided!");
00796         }
00797 
00798         KMO_TRY_EXIT_IF_ERROR(
00799             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_multi_reconstruct.ifus"));
00800         KMO_TRY_EXIT_IF_ERROR(
00801             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_multi_reconstruct.name"));
00802 
00803         kmo_band_pars_load(parlist, "kmos.kmo_multi_reconstruct");
00804 
00805         no_subtract = kmo_dfs_get_parameter_bool(parlist, "kmos.kmo_multi_reconstruct.no_subtract");
00806         KMO_TRY_CHECK_ERROR_STATE();
00807         KMO_TRY_ASSURE((no_subtract == TRUE) || (no_subtract == FALSE),
00808                        CPL_ERROR_ILLEGAL_INPUT,
00809                        "no_subtract must be TRUE or FALSE!");
00810         KMO_TRY_EXIT_IF_ERROR(
00811             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_multi_reconstruct.no_subtract"));
00812 
00813         pix_scale = kmo_dfs_get_parameter_double(parlist, "kmos.kmo_multi_reconstruct.pix_scale");
00814         KMO_TRY_CHECK_ERROR_STATE();
00815         KMO_TRY_ASSURE((pix_scale >= 0.01) &&
00816                        (pix_scale <= 0.4),
00817                        CPL_ERROR_ILLEGAL_INPUT,
00818                        "pix_scale must be between 0.01 and 0.4 (results in cubes "
00819                        "with 7x7 to 280x280 pixels)!");
00820         KMO_TRY_EXIT_IF_ERROR(
00821            kmo_dfs_print_parameter_help(parlist, "kmos.kmo_multi_reconstruct.pix_scale"));
00822 
00823         xcal_interpolation = kmo_dfs_get_parameter_bool(parlist, "kmos.kmo_multi_reconstruct.xcal_interpolation");
00824         KMO_TRY_CHECK_ERROR_STATE();
00825         KMO_TRY_ASSURE((xcal_interpolation == TRUE) ||
00826                        (xcal_interpolation == FALSE),
00827                        CPL_ERROR_ILLEGAL_INPUT,
00828                        "xcal_interpolation must be TRUE or FALSE!");
00829         KMO_TRY_EXIT_IF_ERROR(
00830             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_multi_reconstruct.xcal_interpolation"));
00831 
00832         suppress_extension = kmo_dfs_get_parameter_bool(parlist, "kmos.kmo_multi_reconstruct.suppress_extension");
00833         KMO_TRY_CHECK_ERROR_STATE();
00834         KMO_TRY_ASSURE((suppress_extension == TRUE) || (suppress_extension == FALSE),
00835                        CPL_ERROR_ILLEGAL_INPUT,
00836                        "suppress_extension must be TRUE or FALSE!");
00837         KMO_TRY_EXIT_IF_ERROR(
00838             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_multi_reconstruct.suppress_extension"));
00839 
00840         dev_cal = kmo_dfs_get_parameter_bool(parlist, "kmos.kmo_multi_reconstruct.dev_cal");
00841         KMO_TRY_CHECK_ERROR_STATE();
00842         KMO_TRY_ASSURE((dev_cal == TRUE) || (dev_cal == FALSE),
00843                        CPL_ERROR_ILLEGAL_INPUT,
00844                        "dev_cal must be TRUE or FALSE!");
00845         KMO_TRY_EXIT_IF_ERROR(
00846             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_multi_reconstruct.dev_cal"));
00847 
00848         fn_obj_sky_table = kmo_dfs_get_parameter_string(parlist,
00849                                                         "kmos.kmo_multi_reconstruct.obj_sky_table");
00850         KMO_TRY_CHECK_ERROR_STATE();
00851 
00852         KMO_TRY_EXIT_IF_ERROR(
00853             kmo_dfs_print_parameter_help(parlist,
00854                                         "kmos.kmo_multi_reconstruct.obj_sky_table"));
00855 
00856 
00857         KMO_TRY_EXIT_IF_ERROR(
00858             kmo_combine_pars_load(parlist,
00859                                   "kmos.kmo_multi_reconstruct",
00860                                   &cmethod,
00861                                   &cpos_rej,
00862                                   &cneg_rej,
00863                                   &citer,
00864                                   &cmin,
00865                                   &cmax,
00866                                   FALSE));
00867 
00868         cpl_msg_info("", "-------------------------------------------");
00869 
00870         //
00871         // assure that filters, grating and rotation offsets match for
00872         // XCAL, YCAL, LCAL and for data frame to reconstruct (except DARK
00873         // frames)
00874         //
00875 
00876         // check if filter_id and grating_id match for all detectors
00877         KMO_TRY_EXIT_IF_ERROR(
00878             kmo_check_frameset_setup(frameset, SCIENCE, TRUE, FALSE, TRUE));
00879         KMO_TRY_EXIT_IF_ERROR(
00880             kmo_check_frame_setup(frameset, SCIENCE, YCAL, TRUE, FALSE, TRUE));
00881         KMO_TRY_EXIT_IF_ERROR(
00882             kmo_check_frame_setup(frameset, XCAL, YCAL, TRUE, FALSE, TRUE));
00883         KMO_TRY_EXIT_IF_ERROR(
00884             kmo_check_frame_setup(frameset, XCAL, LCAL, TRUE, FALSE, TRUE));
00885         if (has_master_flat) {
00886             KMO_TRY_EXIT_IF_ERROR(
00887                 kmo_check_frame_setup(frameset, XCAL, MASTER_FLAT, TRUE, FALSE, TRUE));
00888         }
00889         if (has_telluric) {
00890             KMO_TRY_EXIT_IF_ERROR(
00891                 kmo_check_frame_setup(frameset, XCAL, TELLURIC,
00892                                            TRUE, FALSE, TRUE));
00893         }
00894 
00895         // check descriptors of all frames
00896         KMO_TRY_EXIT_IF_NULL(
00897             xcal_frame = kmo_dfs_get_frame(frameset, XCAL));
00898 
00899         desc1 = kmo_identify_fits_header(cpl_frame_get_filename(xcal_frame));
00900         KMO_TRY_CHECK_ERROR_STATE();
00901 
00902         KMO_TRY_ASSURE((desc1.nr_ext % KMOS_NR_DETECTORS == 0) &&
00903                        (desc1.ex_badpix == FALSE) &&
00904                        (desc1.fits_type == f2d_fits) &&
00905                        (desc1.frame_type == detector_frame),
00906                        CPL_ERROR_ILLEGAL_INPUT,
00907                        "XCAL isn't in the correct format!!!");
00908 
00909         KMO_TRY_EXIT_IF_NULL(
00910             ycal_frame = kmo_dfs_get_frame(frameset, YCAL));
00911         desc2 = kmo_identify_fits_header(cpl_frame_get_filename(ycal_frame));
00912         KMO_TRY_CHECK_ERROR_STATE();
00913 
00914         KMO_TRY_ASSURE((desc1.nr_ext == desc2.nr_ext) &&
00915                        (desc1.ex_badpix == desc2.ex_badpix) &&
00916                        (desc1.fits_type == desc2.fits_type) &&
00917                        (desc1.frame_type == desc2.frame_type),
00918                        CPL_ERROR_ILLEGAL_INPUT,
00919                        "YCAL isn't in the correct format!!!");
00920         kmo_free_fits_desc(&desc2);
00921         kmo_init_fits_desc(&desc2);
00922 
00923         KMO_TRY_EXIT_IF_NULL(
00924             lcal_frame = kmo_dfs_get_frame(frameset, LCAL));
00925         desc2 = kmo_identify_fits_header(cpl_frame_get_filename(lcal_frame));
00926         KMO_TRY_CHECK_ERROR_STATE();
00927 
00928         KMO_TRY_ASSURE((desc2.nr_ext % KMOS_NR_DETECTORS == 0) &&
00929                        (desc1.ex_badpix == desc2.ex_badpix) &&
00930                        (desc1.fits_type == desc2.fits_type) &&
00931                        (desc1.frame_type == desc2.frame_type),
00932                        CPL_ERROR_ILLEGAL_INPUT,
00933                        "LCAL isn't in the correct format!!!");
00934         kmo_free_fits_desc(&desc2);
00935         kmo_init_fits_desc(&desc2);
00936 
00937         if (has_master_flat) {
00938             KMO_TRY_EXIT_IF_NULL(
00939                 flat_frame = kmo_dfs_get_frame(frameset, MASTER_FLAT));
00940             desc2 = kmo_identify_fits_header(cpl_frame_get_filename(flat_frame));
00941             KMO_TRY_CHECK_ERROR_STATE();
00942 
00943             KMO_TRY_ASSURE((desc2.nr_ext % (2*KMOS_NR_DETECTORS) == 0) &&
00944                            (desc1.ex_badpix == desc2.ex_badpix) &&
00945                            (desc1.fits_type == desc2.fits_type) &&
00946                            (desc1.frame_type == desc2.frame_type),
00947                            CPL_ERROR_ILLEGAL_INPUT,
00948                            "MASTER_FLAT isn't in the correct format!!!");
00949             kmo_free_fits_desc(&desc2);
00950             kmo_init_fits_desc(&desc2);
00951         }
00952 
00953         if (has_illum_corr) {
00954             KMO_TRY_EXIT_IF_NULL(
00955                 illum_frame = kmo_dfs_get_frame(frameset, ILLUM_CORR));
00956             desc2 = kmo_identify_fits_header(
00957                         cpl_frame_get_filename(illum_frame));
00958             KMO_TRY_CHECK_ERROR_STATE();
00959             KMO_TRY_ASSURE(((desc2.nr_ext == 24) || (desc2.nr_ext == 48)) &&
00960                            (desc2.ex_badpix == FALSE) &&
00961                            (desc2.fits_type == f2i_fits) &&
00962                            (desc2.frame_type == ifu_frame),
00963                            CPL_ERROR_ILLEGAL_INPUT,
00964                            "ILLUM_CORR isn't in the correct format!!!");
00965             kmo_free_fits_desc(&desc2);
00966             kmo_init_fits_desc(&desc2);
00967         }
00968 
00969         if (has_telluric) {
00970             KMO_TRY_EXIT_IF_NULL(
00971                 telluric_frame = kmo_dfs_get_frame(frameset, TELLURIC));
00972             desc_telluric = kmo_identify_fits_header(
00973                         cpl_frame_get_filename(telluric_frame));
00974             KMO_TRY_CHECK_ERROR_STATE();
00975             KMO_TRY_ASSURE(((desc_telluric.nr_ext == 24) || (desc_telluric.nr_ext == 48)) &&
00976                            (desc_telluric.ex_badpix == FALSE) &&
00977                            (desc_telluric.fits_type == f1i_fits) &&
00978                            (desc_telluric.frame_type == ifu_frame),
00979                            CPL_ERROR_ILLEGAL_INPUT,
00980                            "TELLURIC isn't in the correct format!!!");
00981         }
00982 
00983         KMO_TRY_EXIT_IF_NULL(
00984             science_frame = kmo_dfs_get_frame(frameset, SCIENCE));
00985         while (science_frame != NULL ) {
00986             desc2 = kmo_identify_fits_header(cpl_frame_get_filename(science_frame));
00987             KMO_TRY_CHECK_ERROR_STATE();
00988             KMO_TRY_ASSURE((desc2.nr_ext == 3) &&
00989                            (desc2.ex_badpix == FALSE) &&
00990                            (desc2.fits_type == raw_fits) &&
00991                            (desc2.frame_type == detector_frame),
00992                            CPL_ERROR_ILLEGAL_INPUT,
00993                            "SCIENCE isn't in the correct format!!!");
00994             kmo_free_fits_desc(&desc2);
00995             kmo_init_fits_desc(&desc2);
00996 
00997             if (mapping_mode == NULL) {
00998                 KMO_TRY_EXIT_IF_NULL(
00999                     tmp_header =
01000                           kmclipm_propertylist_load(
01001                                          cpl_frame_get_filename(science_frame), 0));
01002                 if (cpl_propertylist_has(tmp_header, TPL_ID)) {
01003                     KMO_TRY_EXIT_IF_NULL(
01004                         tmp_str = cpl_propertylist_get_string(tmp_header,
01005                                                               TPL_ID));
01006                     if (strcmp(tmp_str, MAPPING8) == 0)
01007                     {
01008                         mapping_mode = cpl_sprintf("%s", "mapping8");
01009                     }
01010                     if (strcmp(tmp_str, MAPPING24) == 0)
01011                     {
01012                         mapping_mode = cpl_sprintf("%s", "mapping24");
01013                     }
01014                 }
01015 
01016                 // when mapping-mode should be supported, remove this if-statement...
01017                 if (mapping_mode != NULL) {
01018                     cpl_msg_error("", "*******************************************************");
01019                     cpl_msg_error("", "*******************************************************");
01020                     cpl_msg_error("", "***                                                 ***");
01021                     cpl_msg_error("", "*** The provided SCIENCE frames have been produced  ***");
01022                     cpl_msg_error("", "*** with template %s           ***", tmp_str);
01023                     cpl_msg_error("", "***                                                 ***");
01024                     cpl_msg_error("", "*** kmo_multi_reconstruct doesn't support yet this  ***");
01025                     cpl_msg_error("", "*** observation mode. Please use recipe kmo_sci_red ***");
01026                     cpl_msg_error("", "*** instead!                                        ***");
01027                     cpl_msg_error("", "***                                                 ***");
01028                     cpl_msg_error("", "*******************************************************");
01029                     cpl_msg_error("", "*******************************************************");
01030                     KMO_TRY_ASSURE(1==0,
01031                                    CPL_ERROR_ILLEGAL_INPUT,
01032                                    " ");
01033                 }
01034 
01035                 cpl_propertylist_delete(tmp_header); tmp_header = NULL;
01036             }
01037 
01038             science_frame = kmo_dfs_get_frame(frameset, NULL);
01039             KMO_TRY_CHECK_ERROR_STATE();
01040         }
01041 
01042         if ((mapping_mode != NULL) && ((ifus != NULL) || (strcmp(name, "") != 0))) {
01043             cpl_msg_warning("","The SCIENCE frames have been taken in one of the "
01044                                "mapping modes AND specific IFUs have been "
01045                                "specified! --> Only processing these!");
01046         }
01047 
01048         KMO_TRY_EXIT_IF_NULL(
01049             suffix = kmo_dfs_get_suffix(xcal_frame, TRUE, FALSE));
01050 
01051         KMO_TRY_EXIT_IF_ERROR(
01052             kmo_check_frame_setup_md5_xycal(frameset));
01053         KMO_TRY_EXIT_IF_ERROR(
01054             kmo_check_frame_setup_md5(frameset));
01055         KMO_TRY_EXIT_IF_ERROR(
01056             kmo_check_frame_setup_sampling(frameset));
01057 
01058         cpl_msg_info("", "Detected instrument setup:   %s", suffix+1);
01059         cpl_msg_info("", "(grating 1, 2 & 3)");
01060         cpl_msg_info("", "-------------------------------------------");
01061         cpl_free(suffix); suffix = NULL;
01062 
01063         if (cpl_frameset_count_tags(frameset, OH_SPEC) != 0) {
01064             int         is_all_obs          = TRUE,
01065                         has_all_origfile    = TRUE;
01066             cpl_frame   *tmp_frame          = NULL;
01067 
01068             KMO_TRY_EXIT_IF_NULL(
01069                 tmp_frame = kmo_dfs_get_frame(frameset, SCIENCE));
01070             while (tmp_frame != NULL ) {
01071                 KMO_TRY_EXIT_IF_NULL(
01072                     tmp_header = kmclipm_propertylist_load(cpl_frame_get_filename(tmp_frame), 0));
01073 
01074                 if (cpl_propertylist_has(tmp_header, ORIGFILE)) {
01075                     KMO_TRY_EXIT_IF_NULL(
01076                         tmp_str = cpl_propertylist_get_string(tmp_header, ORIGFILE));
01077                     if (strstr(tmp_str, "OBS") == NULL) {
01078                         is_all_obs = FALSE;
01079                     }
01080                 } else {
01081                     has_all_origfile = FALSE;
01082                 }
01083                 cpl_propertylist_delete(tmp_header); tmp_header = NULL;
01084                 tmp_frame = kmo_dfs_get_frame(frameset, NULL);
01085                 KMO_TRY_CHECK_ERROR_STATE();
01086             }
01087 
01088             if (has_all_origfile) {
01089                 if (is_all_obs) {
01090                     // we are reconstructing an OBS-frame, allow OH_SPEC correction
01091                     KMO_TRY_EXIT_IF_NULL(
01092                         ref_spectrum_frame = kmo_dfs_get_frame(frameset, OH_SPEC));
01093                 } else {
01094                     cpl_msg_warning("", "Supplied OH_SPEC is ignored since a calibration "
01095                                         "frame is being used as SCIENCE frame.");
01096                 }
01097             } else {
01098                 cpl_msg_warning("", "The supplied SCIENCE frames are all assumed to be "
01099                                     "science frames. If any of them is a calibration frame, "
01100                                     "omit OH_SPEC from sof-file");
01101                 KMO_TRY_EXIT_IF_NULL(
01102                     ref_spectrum_frame = kmo_dfs_get_frame(frameset, OH_SPEC));
01103             }
01104         }
01105 
01106         //
01107         // check which IFUs are active for all frames
01108         //
01109         KMO_TRY_EXIT_IF_NULL(
01110             unused_ifus_before = kmo_get_unused_ifus(frameset, 1, 1));
01111 
01112         KMO_TRY_EXIT_IF_NULL(
01113             unused_ifus_after = kmo_duplicate_unused_ifus(unused_ifus_before));
01114 
01115         kmo_print_unused_ifus(unused_ifus_before, FALSE);
01116 
01117         //
01118         // get bounds, setup grid, setup arm_name-struct
01119         //
01120 
01121         // get left and right bounds of IFUs
01122         KMO_TRY_EXIT_IF_NULL(
01123             tmp_header = kmo_dfs_load_primary_header(frameset, XCAL));
01124         KMO_TRY_EXIT_IF_NULL(
01125             bounds = kmclipm_extract_bounds(tmp_header));
01126         cpl_propertylist_delete(tmp_header); tmp_header = NULL;
01127 
01128         // setup grid definition, wavelength start and end points will be set
01129         // in the detector loop
01130         KMO_TRY_EXIT_IF_ERROR(
01131             kmclipm_setup_grid(&gd, imethod, neighborhoodRange, pix_scale, 0.));
01132         KMO_TRY_EXIT_IF_ERROR(
01133             kmclipm_setup_grid(&gd_14x14, imethod, neighborhoodRange, pix_scale, 0.));
01134 
01135         KMO_TRY_EXIT_IF_NULL(
01136             band_table = kmo_dfs_load_table(frameset, WAVE_BAND, 1, 0));
01137         KMO_TRY_EXIT_IF_NULL(
01138             tmp_header = kmo_dfs_load_primary_header(frameset, LCAL));
01139         KMO_TRY_EXIT_IF_NULL(
01140             filter_id = cpl_sprintf("%s", cpl_propertylist_get_string(tmp_header, filter_keyword)));
01141         KMO_TRY_EXIT_IF_ERROR(
01142             kmclipm_setup_grid_band_lcal(&gd, filter_id, band_table));
01143         KMO_TRY_EXIT_IF_ERROR(
01144             kmclipm_setup_grid_band_lcal(&gd_14x14, filter_id, band_table));
01145         cpl_propertylist_delete(tmp_header); tmp_header = NULL;
01146         cpl_table_delete(band_table); band_table = NULL;
01147 
01148         //
01149         // get valid object names to process, either one object name across
01150         // several SCIENCE frames, or all object names
01151         //
01152         if (strcmp(fn_obj_sky_table, "") == 0) {
01153             KMO_TRY_EXIT_IF_NULL(
01154                 arm_name_struct = kmo_create_armNameStruct(frameset,
01155                                                            SCIENCE,
01156                                                            ifus,
01157                                                            name,
01158                                                            unused_ifus_after,
01159                                                            bounds,
01160                                                            mapping_mode,
01161                                                            no_subtract));
01162             KMO_TRY_EXIT_IF_ERROR(
01163                 kmo_save_objSkyStruct(arm_name_struct->obj_sky_struct));
01164         } else {
01165             // read in obj/sky-table
01166             objSkyStruct *obj_sky_struct = NULL;
01167 
01168             KMO_TRY_EXIT_IF_NULL(
01169                 obj_sky_struct = kmo_read_objSkyStruct(fn_obj_sky_table,
01170                                                        frameset,
01171                                                        SCIENCE));
01172 
01173             KMO_TRY_EXIT_IF_NULL(
01174                 arm_name_struct = kmo_create_armNameStruct2(obj_sky_struct,
01175                                                             frameset,
01176                                                             SCIENCE,
01177                                                             ifus,
01178                                                             name,
01179                                                             unused_ifus_after,
01180                                                             bounds,
01181                                                             mapping_mode,
01182                                                             no_subtract));
01183 
01184         }
01185         kmo_print_armNameStruct(frameset, arm_name_struct);
01186         cpl_free(bounds); bounds = NULL;
01187 
01188         //
01189         // check availability of tellurics for the different IFUs used
01190         //
01191         if (has_telluric && (mapping_mode != NULL)) {
01192             // in mapping-mode check if for all IFUs there is either no telluric at all
01193             // or the same number of tellurics than object names
01194             int telluric_ok = TRUE;
01195             for (cnt = 0; cnt < arm_name_struct->nrNames; cnt++) {
01196                 if (!((arm_name_struct->telluricCnt[cnt] == arm_name_struct->namesCnt[cnt]) ||
01197                     (arm_name_struct->telluricCnt[cnt] == 0)))
01198                 {
01199                     telluric_ok = FALSE;
01200                     break;
01201                 }
01202             }
01203             if (!telluric_ok) {
01204                 KMO_TRY_ASSURE(1==0,
01205                                CPL_ERROR_UNSUPPORTED_MODE,
01206                                "Mosaics need a TELLURIC frame with at least a telluric correction per detector available! "
01207                                "Omit the TELLURIC from your sof-file or choose another TELLURIC!");
01208             }
01209         }
01210 
01211         //
01212         // loop over all object names
01213         //   (for mapping template only once,)
01214         //   (when ifus or name is set as well only once)
01215         //
01216         for (arm_index = 0; arm_index < arm_name_struct->nrNames; arm_index++) {
01217 
01218             nr_frames = arm_name_struct->namesCnt[arm_index];
01219 
01220             KMO_TRY_EXIT_IF_NULL(
01221                 sub_headers = kmo_mr_get_headers(arm_name_struct,
01222                                                  arm_index+1,
01223                                                  frameset,
01224                                                  gd_14x14));
01225 
01226             if ((strcmp(comb_method, "center") == 0) ||
01227                 (ref_spectrum_frame != NULL))
01228             {
01229                 //
01230                 // reconstruct preliminary cubes
01231                 //
01232                 KMO_TRY_EXIT_IF_NULL(
01233                     pre_data_cube_list = kmo_mr_create_datacubes(arm_name_struct,
01234                                                                  arm_index+1,
01235                                                                  frameset,
01236                                                                  gd_14x14,
01237                                                                  xcal_interpolation));
01238                 //
01239                 // calculate lambda-correction coefficients
01240                 //
01241                 if (ref_spectrum_frame != NULL) {
01242                     KMO_TRY_EXIT_IF_NULL(
01243                         lcorr_coeffs = cpl_calloc(nr_frames, sizeof(cpl_polynomial*)));
01244 
01245                     cnt = 0;
01246                     for (iy = 0; iy < arm_name_struct->size; iy++) {
01247                         for (ix = 0; ix < KMOS_NR_IFUS; ix++) {
01248                             ifu_nr = ix + 1;
01249                             if (arm_name_struct->name_ids[ix+iy*KMOS_NR_IFUS] == arm_index+1) {
01250                                 KMO_TRY_EXIT_IF_NULL(
01251                                     lcorr_coeffs[cnt] = kmo_lcorr_get(pre_data_cube_list[cnt],
01252                                                                       sub_headers[cnt],
01253                                                                       ref_spectrum_frame,
01254                                                                       gd_14x14,
01255                                                                       filter_id,
01256                                                                       ifu_nr));
01257                                 cnt++;
01258                             }
01259                         }
01260                     }
01261                 } // end if (lcorr)
01262             } // end if (center, lcorr)
01263 
01264             //
01265             // calculate offsets
01266             //
01267             KMO_TRY_EXIT_IF_ERROR(
01268                 kmo_mr_get_offsets(arm_name_struct,
01269                                    arm_index+1,
01270                                    comb_method,
01271                                    imethod,
01272                                    filename,
01273                                    frameset,
01274                                    pre_data_cube_list,
01275                                    sub_headers,
01276                                    fmethod,
01277                                    cmethod,
01278                                    cpos_rej,
01279                                    cneg_rej,
01280                                    citer,
01281                                    cmin,
01282                                    cmax,
01283                                    dev_cal,
01284                                    mapping_mode,
01285                                    &xshifts,
01286                                    &yshifts));
01287 
01288             KMO_TRY_EXIT_IF_NULL(
01289                 ref_sub_header = cpl_propertylist_duplicate(sub_headers[0]));
01290 
01291             for (cnt = 0; cnt < nr_frames; cnt++) {
01292                 cpl_propertylist_delete(sub_headers[cnt]); sub_headers[cnt] = NULL;
01293             }
01294             cpl_free(sub_headers); sub_headers = NULL;
01295 
01296             if (pre_data_cube_list != NULL) {
01297                 for (cnt = 0; cnt < nr_frames; cnt++) {
01298                     cpl_imagelist_delete(pre_data_cube_list[cnt]);
01299                 }
01300                 cpl_free(pre_data_cube_list); pre_data_cube_list = NULL;
01301             }
01302 
01303             //
01304             // set spatial part of the grid
01305             //
01306             for (cnt = 0; cnt < nr_frames; cnt++) {
01307                 if (xmin > xshifts[cnt]) {
01308                     xmin = xshifts[cnt];
01309                 }
01310                 if (xmax < xshifts[cnt]) {
01311                     xmax = xshifts[cnt];
01312                 }
01313                 if (ymin > yshifts[cnt]) {
01314                     ymin = yshifts[cnt];
01315                 }
01316                 if (ymax < yshifts[cnt]) {
01317                     ymax = yshifts[cnt];
01318                 }
01319             }
01320 
01321             if (xmax > 0.0001) {
01322                 gxshift = -rint(xmax);      //(int)xmax;   // gxshift = - ceil(xmax);
01323             } else {
01324                 gxshift = 0.;
01325             }
01326             if (ymin < -0.0001) {
01327                 gyshift = rint(ymin);   //(int)ymin;    // gyshift = floor(ymin);
01328             } else {
01329                 gyshift = 0.;
01330             }
01331             if (xmin < -0.0001) {
01332                 gxdim = - floor(xmin);
01333             } else {
01334                 gxdim = 0.;
01335             }
01336             if (ymax > 0.0001) {
01337                 gydim = ceil(ymax);
01338             } else {
01339                 gydim = 0.;
01340             }
01341 
01342             xdim = (int)(gxdim - gxshift + .5);
01343             ydim = (int)(gydim - gyshift + .5);
01344             gd.x.start += gxshift * pix_scale*1000;
01345             gd.y.start += gyshift * pix_scale*1000;
01346             gd.x.dim += xdim;
01347             gd.y.dim += ydim;
01348 
01349 //            cpl_msg_set_level(CPL_MSG_DEBUG);
01350 //            cpl_msg_debug(cpl_func,"x: %f < %f,   y: %f < %f",
01351 //                              xmin,xmax,ymin,ymax);
01352 //            cpl_msg_debug(cpl_func,"gxshift: %f gxdim: %f xdim: %d,   gyshift: %f gydim: %f ydim: %d",
01353 //                              gxshift, gxdim, xdim, gyshift, gydim, ydim);
01354 //            cpl_msg_debug(cpl_func,"gd: start          delta            dim");
01355 //            cpl_msg_debug(cpl_func," x: %f      %f      %d", gd.x.start, gd.x.delta, gd.x.dim);
01356 //            cpl_msg_debug(cpl_func," y: %f      %f      %d", gd.y.start, gd.y.delta, gd.y.dim);
01357 //            cpl_msg_debug(cpl_func," l: %f      %f      %d", gd.l.start, gd.l.delta, gd.l.dim);
01358 //            cpl_msg_set_level(CPL_MSG_INFO);
01359 
01360             //
01361             // reconstruct multiple detector images
01362             //
01363             KMO_TRY_EXIT_IF_ERROR(
01364                 kmo_mr_reconstruct(frameset,
01365                                    arm_name_struct,
01366                                    arm_index+1,
01367                                    xshifts,
01368                                    yshifts,
01369                                    gd,
01370                                    gd_14x14,
01371                                    pix_scale,
01372                                    xcal_interpolation,
01373                                    lcorr_coeffs,
01374                                    &cube_combined_data,
01375                                    &cube_combined_noise,
01376                                    no_subtract,
01377                                    flux,
01378                                    background));
01379 
01380             if (lcorr_coeffs != NULL) {
01381                 for (cnt = 0; cnt < nr_frames; cnt++) {
01382                     cpl_polynomial_delete(lcorr_coeffs[cnt]); lcorr_coeffs[cnt] = NULL;
01383                 }
01384                 cpl_free(lcorr_coeffs); lcorr_coeffs = NULL;
01385             }
01386 
01387             //
01388             // identify ifu_nr of current object name in first SCIENCE frame
01389             // containing this object name (e.g. first frame could contain skies only)
01390             //
01391             ifu_nr = -1;
01392             science_frame = NULL;
01393             for (iy = 0; iy < arm_name_struct->size; iy++) {
01394                 for (ix = 0; ix < KMOS_NR_IFUS; ix++) {
01395                     if (arm_name_struct->name_ids[ix+iy*KMOS_NR_IFUS] == arm_index+1) {
01396                         if (ifu_nr == -1) {
01397                             KMO_TRY_EXIT_IF_NULL(
01398                                 science_frame = arm_name_struct->obj_sky_struct->table[iy].objFrame);
01399 
01400                             ifu_nr = ix + 1;
01401                             break;
01402                         }
01403                     }
01404                 }
01405                 if (ifu_nr != -1) { break; }
01406             }
01407 
01408             //
01409             // divide cube by telluric correction
01410             //
01411             if (has_telluric &&
01412                 (arm_name_struct->sameTelluric[arm_index] > 0))
01413             {
01414                 telluric_data = kmo_tweak_load_telluric(frameset, ifu_nr, FALSE, no_subtract);
01415                 KMO_TRY_CHECK_ERROR_STATE();
01416                 if (telluric_data != NULL) {
01417                     int index = kmo_identify_index_desc(desc_telluric, ifu_nr, TRUE);
01418                     KMO_TRY_CHECK_ERROR_STATE();
01419                     if (desc_telluric.sub_desc[index-1].valid_data == TRUE) {
01420                         // load noise if present
01421                         telluric_noise = kmo_tweak_load_telluric(frameset, ifu_nr, TRUE, no_subtract);
01422                         KMO_TRY_CHECK_ERROR_STATE();
01423                     } else {
01424                         if (print_warning_once_tweak_std_noise && (cube_combined_noise != NULL)) {
01425                             cpl_msg_warning("","************************************************************");
01426                             cpl_msg_warning("","* Noise cubes were calculated, but won't be divided by     *");
01427                             cpl_msg_warning("","* telluric error since it is missing.                      *");
01428                             cpl_msg_warning("","* In order to get a telluric with errors, execute          *");
01429                             cpl_msg_warning("","* kmo_std_star with one of the nearest neighbour methods   *");
01430                             cpl_msg_warning("","* (set --imethod to NN, lwNN or swNN)                      *");
01431                             cpl_msg_warning("","************************************************************");
01432                             print_warning_once_tweak_std_noise = FALSE;
01433                         }
01434                     }
01435 
01436                     KMO_TRY_EXIT_IF_ERROR(
01437                         kmo_arithmetic_3D_1D(
01438                                 cube_combined_data, telluric_data,
01439                                 cube_combined_noise, telluric_noise, "/"));
01440                 }
01441                 kmclipm_vector_delete(telluric_data); telluric_data = NULL;
01442                 kmclipm_vector_delete(telluric_noise); telluric_noise = NULL;
01443             }
01444 
01445             //
01446             // saving
01447             //
01448             fn_cube = CUBE_MULTI;
01449             if (!suppress_extension) {
01450                 char tmp_suffix[1024];
01451                 tmp_suffix[0] = '\0';
01452 
01453                 if (arm_name_struct->telluricCnt[arm_index] == nr_frames) {
01454                     strcat(tmp_suffix, "_telluric");
01455                 }
01456                 if (has_illum_corr) {
01457                     strcat(tmp_suffix, "_illum");
01458                 }
01459 //                if (sky_tweak) {
01460 //                    strcat(tmp_suffix, "_skytweak");
01461 //                }
01462 
01463                 if (strlen(tmp_suffix) > 0) {
01464                     KMO_TRY_EXIT_IF_NULL(
01465                         fn_suffix = cpl_sprintf("_%s_%s", arm_name_struct->names[arm_index], tmp_suffix));
01466                 } else {
01467                     KMO_TRY_EXIT_IF_NULL(
01468                         fn_suffix = cpl_sprintf("_%s", arm_name_struct->names[arm_index]));
01469                 }
01470             } else {
01471                 KMO_TRY_EXIT_IF_NULL(
01472                     fn_suffix = cpl_sprintf("_%d", suppress_index++));
01473             }
01474 
01475             //
01476             // calculate WCS
01477             //
01478             KMO_TRY_EXIT_IF_NULL(
01479                 science_frame_header = kmclipm_propertylist_load(cpl_frame_get_filename(science_frame), 0));
01480 
01481             KMO_TRY_EXIT_IF_ERROR(
01482                 kmo_calc_wcs_gd(science_frame_header, ref_sub_header, ifu_nr, gd));
01483 
01484             cpl_propertylist_delete(science_frame_header); science_frame_header = NULL;
01485 
01486             //
01487             // save product
01488             //
01489             KMO_TRY_EXIT_IF_ERROR(
01490                 kmo_dfs_save_main_header(frameset, fn_cube, fn_suffix,
01491                                          science_frame, NULL, parlist, cpl_func));
01492 
01493             KMO_TRY_EXIT_IF_NULL(
01494                 extname = cpl_sprintf("%s.DATA", arm_name_struct->names[arm_index]));
01495             KMO_TRY_EXIT_IF_ERROR(
01496                 kmclipm_update_property_string(ref_sub_header,
01497                                                EXTNAME,
01498                                                extname,
01499                                                "FITS extension name"));
01500             cpl_free(extname); extname = NULL;
01501 
01502             KMO_TRY_EXIT_IF_ERROR(
01503                 kmo_dfs_save_cube(cube_combined_data, fn_cube, fn_suffix,
01504                                   ref_sub_header, 0./0.));
01505 
01506             if (cube_combined_noise != NULL) {
01507                 KMO_TRY_EXIT_IF_NULL(
01508                     extname = cpl_sprintf("%s.NOISE", arm_name_struct->names[arm_index]));
01509                 KMO_TRY_EXIT_IF_ERROR(
01510                     kmclipm_update_property_string(ref_sub_header,
01511                                                    EXTNAME,
01512                                                    extname,
01513                                                    "FITS extension name"));
01514                 cpl_free(extname); extname = NULL;
01515 
01516                 KMO_TRY_EXIT_IF_ERROR(
01517                     kmo_dfs_save_cube(cube_combined_noise, fn_cube, fn_suffix,
01518                                       ref_sub_header, 0./0.));
01519             }
01520 
01521             cpl_imagelist_delete(cube_combined_data); cube_combined_data = NULL;
01522             cpl_imagelist_delete(cube_combined_noise); cube_combined_noise = NULL;
01523             cpl_propertylist_delete(ref_sub_header); ref_sub_header = NULL;
01524             cpl_free(fn_suffix); fn_suffix = NULL;
01525             cpl_free(xshifts); xshifts = NULL;
01526             cpl_free(yshifts); yshifts = NULL;
01527         }  // for (arm_index = nrNames)
01528 
01529         kmo_print_unused_ifus(unused_ifus_after, TRUE);
01530     }
01531     KMO_CATCH
01532     {
01533         KMO_CATCH_MSG();
01534         ret_val = -1;
01535     }
01536 
01537     kmo_free_fits_desc(&desc1);
01538     kmo_free_fits_desc(&desc2);
01539     kmo_free_fits_desc(&desc_telluric);
01540     cpl_vector_delete(ifus); ifus = NULL;
01541     cpl_free(mapping_mode); mapping_mode = NULL;
01542     if (unused_ifus_before != NULL) {
01543         kmo_free_unused_ifus(unused_ifus_before); unused_ifus_before = NULL;
01544     }
01545     if (unused_ifus_after != NULL) {
01546         kmo_free_unused_ifus(unused_ifus_after); unused_ifus_after = NULL;
01547     }
01548     if (bounds != NULL) {
01549         cpl_free(bounds); bounds = NULL;
01550     }
01551 
01552     kmo_delete_armNameStruct(arm_name_struct);
01553 
01554     // frees for the case of errors
01555     kmclipm_vector_delete(telluric_data); telluric_data = NULL;
01556     kmclipm_vector_delete(telluric_noise); telluric_noise = NULL;
01557     cpl_propertylist_delete(tmp_header); tmp_header = NULL;
01558     cpl_table_delete(band_table); band_table = NULL;
01559     cpl_free(suffix); suffix = NULL;
01560     cpl_free(fn_suffix); fn_suffix = NULL;
01561     cpl_free(filter_id); filter_id = NULL;
01562 
01563     return ret_val;
01564 }
01565