KMOS Pipeline Reference Manual  1.3.0
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         if (cpl_frameset_count_tags(frameset, OH_SPEC) > 0) {
00896             KMO_TRY_EXIT_IF_ERROR(kmo_check_oh_spec_setup(frameset, XCAL));
00897         }   
00898 
00899         // check descriptors of all frames
00900         KMO_TRY_EXIT_IF_NULL(
00901             xcal_frame = kmo_dfs_get_frame(frameset, XCAL));
00902 
00903         desc1 = kmo_identify_fits_header(cpl_frame_get_filename(xcal_frame));
00904         KMO_TRY_CHECK_ERROR_STATE();
00905 
00906         KMO_TRY_ASSURE((desc1.nr_ext % KMOS_NR_DETECTORS == 0) &&
00907                        (desc1.ex_badpix == FALSE) &&
00908                        (desc1.fits_type == f2d_fits) &&
00909                        (desc1.frame_type == detector_frame),
00910                        CPL_ERROR_ILLEGAL_INPUT,
00911                        "XCAL isn't in the correct format!!!");
00912 
00913         KMO_TRY_EXIT_IF_NULL(
00914             ycal_frame = kmo_dfs_get_frame(frameset, YCAL));
00915         desc2 = kmo_identify_fits_header(cpl_frame_get_filename(ycal_frame));
00916         KMO_TRY_CHECK_ERROR_STATE();
00917 
00918         KMO_TRY_ASSURE((desc1.nr_ext == desc2.nr_ext) &&
00919                        (desc1.ex_badpix == desc2.ex_badpix) &&
00920                        (desc1.fits_type == desc2.fits_type) &&
00921                        (desc1.frame_type == desc2.frame_type),
00922                        CPL_ERROR_ILLEGAL_INPUT,
00923                        "YCAL isn't in the correct format!!!");
00924         kmo_free_fits_desc(&desc2);
00925         kmo_init_fits_desc(&desc2);
00926 
00927         KMO_TRY_EXIT_IF_NULL(
00928             lcal_frame = kmo_dfs_get_frame(frameset, LCAL));
00929         desc2 = kmo_identify_fits_header(cpl_frame_get_filename(lcal_frame));
00930         KMO_TRY_CHECK_ERROR_STATE();
00931 
00932         KMO_TRY_ASSURE((desc2.nr_ext % KMOS_NR_DETECTORS == 0) &&
00933                        (desc1.ex_badpix == desc2.ex_badpix) &&
00934                        (desc1.fits_type == desc2.fits_type) &&
00935                        (desc1.frame_type == desc2.frame_type),
00936                        CPL_ERROR_ILLEGAL_INPUT,
00937                        "LCAL isn't in the correct format!!!");
00938         kmo_free_fits_desc(&desc2);
00939         kmo_init_fits_desc(&desc2);
00940 
00941         if (has_master_flat) {
00942             KMO_TRY_EXIT_IF_NULL(
00943                 flat_frame = kmo_dfs_get_frame(frameset, MASTER_FLAT));
00944             desc2 = kmo_identify_fits_header(cpl_frame_get_filename(flat_frame));
00945             KMO_TRY_CHECK_ERROR_STATE();
00946 
00947             KMO_TRY_ASSURE((desc2.nr_ext % (2*KMOS_NR_DETECTORS) == 0) &&
00948                            (desc1.ex_badpix == desc2.ex_badpix) &&
00949                            (desc1.fits_type == desc2.fits_type) &&
00950                            (desc1.frame_type == desc2.frame_type),
00951                            CPL_ERROR_ILLEGAL_INPUT,
00952                            "MASTER_FLAT isn't in the correct format!!!");
00953             kmo_free_fits_desc(&desc2);
00954             kmo_init_fits_desc(&desc2);
00955         }
00956 
00957         if (has_illum_corr) {
00958             KMO_TRY_EXIT_IF_NULL(
00959                 illum_frame = kmo_dfs_get_frame(frameset, ILLUM_CORR));
00960             desc2 = kmo_identify_fits_header(
00961                         cpl_frame_get_filename(illum_frame));
00962             KMO_TRY_CHECK_ERROR_STATE();
00963             KMO_TRY_ASSURE(((desc2.nr_ext == 24) || (desc2.nr_ext == 48)) &&
00964                            (desc2.ex_badpix == FALSE) &&
00965                            (desc2.fits_type == f2i_fits) &&
00966                            (desc2.frame_type == ifu_frame),
00967                            CPL_ERROR_ILLEGAL_INPUT,
00968                            "ILLUM_CORR isn't in the correct format!!!");
00969             kmo_free_fits_desc(&desc2);
00970             kmo_init_fits_desc(&desc2);
00971         }
00972 
00973         if (has_telluric) {
00974             KMO_TRY_EXIT_IF_NULL(
00975                 telluric_frame = kmo_dfs_get_frame(frameset, TELLURIC));
00976             desc_telluric = kmo_identify_fits_header(
00977                         cpl_frame_get_filename(telluric_frame));
00978             KMO_TRY_CHECK_ERROR_STATE();
00979             KMO_TRY_ASSURE(((desc_telluric.nr_ext == 24) || (desc_telluric.nr_ext == 48)) &&
00980                            (desc_telluric.ex_badpix == FALSE) &&
00981                            (desc_telluric.fits_type == f1i_fits) &&
00982                            (desc_telluric.frame_type == ifu_frame),
00983                            CPL_ERROR_ILLEGAL_INPUT,
00984                            "TELLURIC isn't in the correct format!!!");
00985         }
00986 
00987         KMO_TRY_EXIT_IF_NULL(
00988             science_frame = kmo_dfs_get_frame(frameset, SCIENCE));
00989         while (science_frame != NULL ) {
00990             desc2 = kmo_identify_fits_header(cpl_frame_get_filename(science_frame));
00991             KMO_TRY_CHECK_ERROR_STATE();
00992             KMO_TRY_ASSURE((desc2.nr_ext == 3) &&
00993                            (desc2.ex_badpix == FALSE) &&
00994                            (desc2.fits_type == raw_fits) &&
00995                            (desc2.frame_type == detector_frame),
00996                            CPL_ERROR_ILLEGAL_INPUT,
00997                            "SCIENCE isn't in the correct format!!!");
00998             kmo_free_fits_desc(&desc2);
00999             kmo_init_fits_desc(&desc2);
01000 
01001             if (mapping_mode == NULL) {
01002                 KMO_TRY_EXIT_IF_NULL(
01003                     tmp_header =
01004                           kmclipm_propertylist_load(
01005                                          cpl_frame_get_filename(science_frame), 0));
01006                 if (cpl_propertylist_has(tmp_header, TPL_ID)) {
01007                     KMO_TRY_EXIT_IF_NULL(
01008                         tmp_str = cpl_propertylist_get_string(tmp_header,
01009                                                               TPL_ID));
01010                     if (strcmp(tmp_str, MAPPING8) == 0)
01011                     {
01012                         mapping_mode = cpl_sprintf("%s", "mapping8");
01013                     }
01014                     if (strcmp(tmp_str, MAPPING24) == 0)
01015                     {
01016                         mapping_mode = cpl_sprintf("%s", "mapping24");
01017                     }
01018                 }
01019 
01020                 // when mapping-mode should be supported, remove this if-statement...
01021                 if (mapping_mode != NULL) {
01022                     cpl_msg_error("", "*******************************************************");
01023                     cpl_msg_error("", "*******************************************************");
01024                     cpl_msg_error("", "***                                                 ***");
01025                     cpl_msg_error("", "*** The provided SCIENCE frames have been produced  ***");
01026                     cpl_msg_error("", "*** with template %s           ***", tmp_str);
01027                     cpl_msg_error("", "***                                                 ***");
01028                     cpl_msg_error("", "*** kmo_multi_reconstruct doesn't support yet this  ***");
01029                     cpl_msg_error("", "*** observation mode. Please use recipe kmo_sci_red ***");
01030                     cpl_msg_error("", "*** instead!                                        ***");
01031                     cpl_msg_error("", "***                                                 ***");
01032                     cpl_msg_error("", "*******************************************************");
01033                     cpl_msg_error("", "*******************************************************");
01034                     KMO_TRY_ASSURE(1==0,
01035                                    CPL_ERROR_ILLEGAL_INPUT,
01036                                    " ");
01037                 }
01038 
01039                 cpl_propertylist_delete(tmp_header); tmp_header = NULL;
01040             }
01041 
01042             science_frame = kmo_dfs_get_frame(frameset, NULL);
01043             KMO_TRY_CHECK_ERROR_STATE();
01044         }
01045 
01046         if ((mapping_mode != NULL) && ((ifus != NULL) || (strcmp(name, "") != 0))) {
01047             cpl_msg_warning("","The SCIENCE frames have been taken in one of the "
01048                                "mapping modes AND specific IFUs have been "
01049                                "specified! --> Only processing these!");
01050         }
01051 
01052         KMO_TRY_EXIT_IF_NULL(
01053             suffix = kmo_dfs_get_suffix(xcal_frame, TRUE, FALSE));
01054 
01055         KMO_TRY_EXIT_IF_ERROR(
01056             kmo_check_frame_setup_md5_xycal(frameset));
01057         KMO_TRY_EXIT_IF_ERROR(
01058             kmo_check_frame_setup_md5(frameset));
01059         KMO_TRY_EXIT_IF_ERROR(
01060             kmo_check_frame_setup_sampling(frameset));
01061 
01062         cpl_msg_info("", "Detected instrument setup:   %s", suffix+1);
01063         cpl_msg_info("", "(grating 1, 2 & 3)");
01064         cpl_msg_info("", "-------------------------------------------");
01065         cpl_free(suffix); suffix = NULL;
01066 
01067         if (cpl_frameset_count_tags(frameset, OH_SPEC) != 0) {
01068             int         is_all_obs          = TRUE,
01069                         has_all_origfile    = TRUE;
01070             cpl_frame   *tmp_frame          = NULL;
01071 
01072             KMO_TRY_EXIT_IF_NULL(
01073                 tmp_frame = kmo_dfs_get_frame(frameset, SCIENCE));
01074             while (tmp_frame != NULL ) {
01075                 KMO_TRY_EXIT_IF_NULL(
01076                     tmp_header = kmclipm_propertylist_load(cpl_frame_get_filename(tmp_frame), 0));
01077 
01078                 if (cpl_propertylist_has(tmp_header, ORIGFILE)) {
01079                     KMO_TRY_EXIT_IF_NULL(
01080                         tmp_str = cpl_propertylist_get_string(tmp_header, ORIGFILE));
01081                     if (strstr(tmp_str, "OBS") == NULL) {
01082                         is_all_obs = FALSE;
01083                     }
01084                 } else {
01085                     has_all_origfile = FALSE;
01086                 }
01087                 cpl_propertylist_delete(tmp_header); tmp_header = NULL;
01088                 tmp_frame = kmo_dfs_get_frame(frameset, NULL);
01089                 KMO_TRY_CHECK_ERROR_STATE();
01090             }
01091 
01092             if (has_all_origfile) {
01093                 if (is_all_obs) {
01094                     // we are reconstructing an OBS-frame, allow OH_SPEC correction
01095                     KMO_TRY_EXIT_IF_NULL(
01096                         ref_spectrum_frame = kmo_dfs_get_frame(frameset, OH_SPEC));
01097                 } else {
01098                     cpl_msg_warning("", "Supplied OH_SPEC is ignored since a calibration "
01099                                         "frame is being used as SCIENCE frame.");
01100                 }
01101             } else {
01102                 cpl_msg_warning("", "The supplied SCIENCE frames are all assumed to be "
01103                                     "science frames. If any of them is a calibration frame, "
01104                                     "omit OH_SPEC from sof-file");
01105                 KMO_TRY_EXIT_IF_NULL(
01106                     ref_spectrum_frame = kmo_dfs_get_frame(frameset, OH_SPEC));
01107             }
01108         }
01109 
01110         //
01111         // check which IFUs are active for all frames
01112         //
01113         KMO_TRY_EXIT_IF_NULL(
01114             unused_ifus_before = kmo_get_unused_ifus(frameset, 1, 1));
01115 
01116         KMO_TRY_EXIT_IF_NULL(
01117             unused_ifus_after = kmo_duplicate_unused_ifus(unused_ifus_before));
01118 
01119         kmo_print_unused_ifus(unused_ifus_before, FALSE);
01120 
01121         //
01122         // get bounds, setup grid, setup arm_name-struct
01123         //
01124 
01125         // get left and right bounds of IFUs
01126         KMO_TRY_EXIT_IF_NULL(
01127             tmp_header = kmo_dfs_load_primary_header(frameset, XCAL));
01128         KMO_TRY_EXIT_IF_NULL(
01129             bounds = kmclipm_extract_bounds(tmp_header));
01130         cpl_propertylist_delete(tmp_header); tmp_header = NULL;
01131 
01132         // setup grid definition, wavelength start and end points will be set
01133         // in the detector loop
01134         KMO_TRY_EXIT_IF_ERROR(
01135             kmclipm_setup_grid(&gd, imethod, neighborhoodRange, pix_scale, 0.));
01136         KMO_TRY_EXIT_IF_ERROR(
01137             kmclipm_setup_grid(&gd_14x14, imethod, neighborhoodRange, pix_scale, 0.));
01138 
01139         KMO_TRY_EXIT_IF_NULL(
01140             band_table = kmo_dfs_load_table(frameset, WAVE_BAND, 1, 0));
01141         KMO_TRY_EXIT_IF_NULL(
01142             tmp_header = kmo_dfs_load_primary_header(frameset, LCAL));
01143         KMO_TRY_EXIT_IF_NULL(
01144             filter_id = cpl_sprintf("%s", cpl_propertylist_get_string(tmp_header, filter_keyword)));
01145         KMO_TRY_EXIT_IF_ERROR(
01146             kmclipm_setup_grid_band_lcal(&gd, filter_id, band_table));
01147         KMO_TRY_EXIT_IF_ERROR(
01148             kmclipm_setup_grid_band_lcal(&gd_14x14, filter_id, band_table));
01149         cpl_propertylist_delete(tmp_header); tmp_header = NULL;
01150         cpl_table_delete(band_table); band_table = NULL;
01151 
01152         //
01153         // get valid object names to process, either one object name across
01154         // several SCIENCE frames, or all object names
01155         //
01156         if (strcmp(fn_obj_sky_table, "") == 0) {
01157             KMO_TRY_EXIT_IF_NULL(
01158                 arm_name_struct = kmo_create_armNameStruct(frameset,
01159                                                            SCIENCE,
01160                                                            ifus,
01161                                                            name,
01162                                                            unused_ifus_after,
01163                                                            bounds,
01164                                                            mapping_mode,
01165                                                            no_subtract));
01166             KMO_TRY_EXIT_IF_ERROR(
01167                 kmo_save_objSkyStruct(arm_name_struct->obj_sky_struct));
01168         } else {
01169             // read in obj/sky-table
01170             objSkyStruct *obj_sky_struct = NULL;
01171 
01172             KMO_TRY_EXIT_IF_NULL(
01173                 obj_sky_struct = kmo_read_objSkyStruct(fn_obj_sky_table,
01174                                                        frameset,
01175                                                        SCIENCE));
01176 
01177             KMO_TRY_EXIT_IF_NULL(
01178                 arm_name_struct = kmo_create_armNameStruct2(obj_sky_struct,
01179                                                             frameset,
01180                                                             SCIENCE,
01181                                                             ifus,
01182                                                             name,
01183                                                             unused_ifus_after,
01184                                                             bounds,
01185                                                             mapping_mode,
01186                                                             no_subtract));
01187 
01188         }
01189         kmo_print_armNameStruct(frameset, arm_name_struct);
01190         cpl_free(bounds); bounds = NULL;
01191 
01192         //
01193         // check availability of tellurics for the different IFUs used
01194         //
01195         if (has_telluric && (mapping_mode != NULL)) {
01196             // in mapping-mode check if for all IFUs there is either no telluric at all
01197             // or the same number of tellurics than object names
01198             int telluric_ok = TRUE;
01199             for (cnt = 0; cnt < arm_name_struct->nrNames; cnt++) {
01200                 if (!((arm_name_struct->telluricCnt[cnt] == arm_name_struct->namesCnt[cnt]) ||
01201                     (arm_name_struct->telluricCnt[cnt] == 0)))
01202                 {
01203                     telluric_ok = FALSE;
01204                     break;
01205                 }
01206             }
01207             if (!telluric_ok) {
01208                 KMO_TRY_ASSURE(1==0,
01209                                CPL_ERROR_UNSUPPORTED_MODE,
01210                                "Mosaics need a TELLURIC frame with at least a telluric correction per detector available! "
01211                                "Omit the TELLURIC from your sof-file or choose another TELLURIC!");
01212             }
01213         }
01214 
01215         //
01216         // loop over all object names
01217         //   (for mapping template only once,)
01218         //   (when ifus or name is set as well only once)
01219         //
01220         for (arm_index = 0; arm_index < arm_name_struct->nrNames; arm_index++) {
01221 
01222             nr_frames = arm_name_struct->namesCnt[arm_index];
01223 
01224             KMO_TRY_EXIT_IF_NULL(
01225                 sub_headers = kmo_mr_get_headers(arm_name_struct,
01226                                                  arm_index+1,
01227                                                  frameset,
01228                                                  gd_14x14));
01229 
01230             if ((strcmp(comb_method, "center") == 0) ||
01231                 (ref_spectrum_frame != NULL))
01232             {
01233                 //
01234                 // reconstruct preliminary cubes
01235                 //
01236                 KMO_TRY_EXIT_IF_NULL(
01237                     pre_data_cube_list = kmo_mr_create_datacubes(arm_name_struct,
01238                                                                  arm_index+1,
01239                                                                  frameset,
01240                                                                  gd_14x14,
01241                                                                  xcal_interpolation));
01242                 //
01243                 // calculate lambda-correction coefficients
01244                 //
01245                 if (ref_spectrum_frame != NULL) {
01246                     KMO_TRY_EXIT_IF_NULL(
01247                         lcorr_coeffs = cpl_calloc(nr_frames, sizeof(cpl_polynomial*)));
01248 
01249                     cnt = 0;
01250                     for (iy = 0; iy < arm_name_struct->size; iy++) {
01251                         for (ix = 0; ix < KMOS_NR_IFUS; ix++) {
01252                             ifu_nr = ix + 1;
01253                             if (arm_name_struct->name_ids[ix+iy*KMOS_NR_IFUS] == arm_index+1) {
01254                                 KMO_TRY_EXIT_IF_NULL(
01255                                     lcorr_coeffs[cnt] = kmo_lcorr_get(pre_data_cube_list[cnt],
01256                                                                       sub_headers[cnt],
01257                                                                       ref_spectrum_frame,
01258                                                                       gd_14x14,
01259                                                                       filter_id,
01260                                                                       ifu_nr));
01261                                 cnt++;
01262                             }
01263                         }
01264                     }
01265                 } // end if (lcorr)
01266             } // end if (center, lcorr)
01267 
01268             //
01269             // calculate offsets
01270             //
01271             KMO_TRY_EXIT_IF_ERROR(
01272                 kmo_mr_get_offsets(arm_name_struct,
01273                                    arm_index+1,
01274                                    comb_method,
01275                                    imethod,
01276                                    filename,
01277                                    frameset,
01278                                    pre_data_cube_list,
01279                                    sub_headers,
01280                                    fmethod,
01281                                    cmethod,
01282                                    cpos_rej,
01283                                    cneg_rej,
01284                                    citer,
01285                                    cmin,
01286                                    cmax,
01287                                    dev_cal,
01288                                    mapping_mode,
01289                                    &xshifts,
01290                                    &yshifts));
01291 
01292             KMO_TRY_EXIT_IF_NULL(
01293                 ref_sub_header = cpl_propertylist_duplicate(sub_headers[0]));
01294 
01295             for (cnt = 0; cnt < nr_frames; cnt++) {
01296                 cpl_propertylist_delete(sub_headers[cnt]); sub_headers[cnt] = NULL;
01297             }
01298             cpl_free(sub_headers); sub_headers = NULL;
01299 
01300             if (pre_data_cube_list != NULL) {
01301                 for (cnt = 0; cnt < nr_frames; cnt++) {
01302                     cpl_imagelist_delete(pre_data_cube_list[cnt]);
01303                 }
01304                 cpl_free(pre_data_cube_list); pre_data_cube_list = NULL;
01305             }
01306 
01307             //
01308             // set spatial part of the grid
01309             //
01310             for (cnt = 0; cnt < nr_frames; cnt++) {
01311                 if (xmin > xshifts[cnt]) {
01312                     xmin = xshifts[cnt];
01313                 }
01314                 if (xmax < xshifts[cnt]) {
01315                     xmax = xshifts[cnt];
01316                 }
01317                 if (ymin > yshifts[cnt]) {
01318                     ymin = yshifts[cnt];
01319                 }
01320                 if (ymax < yshifts[cnt]) {
01321                     ymax = yshifts[cnt];
01322                 }
01323             }
01324 
01325             if (xmax > 0.0001) {
01326                 gxshift = -rint(xmax);      //(int)xmax;   // gxshift = - ceil(xmax);
01327             } else {
01328                 gxshift = 0.;
01329             }
01330             if (ymin < -0.0001) {
01331                 gyshift = rint(ymin);   //(int)ymin;    // gyshift = floor(ymin);
01332             } else {
01333                 gyshift = 0.;
01334             }
01335             if (xmin < -0.0001) {
01336                 gxdim = - floor(xmin);
01337             } else {
01338                 gxdim = 0.;
01339             }
01340             if (ymax > 0.0001) {
01341                 gydim = ceil(ymax);
01342             } else {
01343                 gydim = 0.;
01344             }
01345 
01346             xdim = (int)(gxdim - gxshift + .5);
01347             ydim = (int)(gydim - gyshift + .5);
01348             gd.x.start += gxshift * pix_scale*1000;
01349             gd.y.start += gyshift * pix_scale*1000;
01350             gd.x.dim += xdim;
01351             gd.y.dim += ydim;
01352 
01353 //            cpl_msg_set_level(CPL_MSG_DEBUG);
01354 //            cpl_msg_debug(cpl_func,"x: %f < %f,   y: %f < %f",
01355 //                              xmin,xmax,ymin,ymax);
01356 //            cpl_msg_debug(cpl_func,"gxshift: %f gxdim: %f xdim: %d,   gyshift: %f gydim: %f ydim: %d",
01357 //                              gxshift, gxdim, xdim, gyshift, gydim, ydim);
01358 //            cpl_msg_debug(cpl_func,"gd: start          delta            dim");
01359 //            cpl_msg_debug(cpl_func," x: %f      %f      %d", gd.x.start, gd.x.delta, gd.x.dim);
01360 //            cpl_msg_debug(cpl_func," y: %f      %f      %d", gd.y.start, gd.y.delta, gd.y.dim);
01361 //            cpl_msg_debug(cpl_func," l: %f      %f      %d", gd.l.start, gd.l.delta, gd.l.dim);
01362 //            cpl_msg_set_level(CPL_MSG_INFO);
01363 
01364             //
01365             // reconstruct multiple detector images
01366             //
01367             KMO_TRY_EXIT_IF_ERROR(
01368                 kmo_mr_reconstruct(frameset,
01369                                    arm_name_struct,
01370                                    arm_index+1,
01371                                    xshifts,
01372                                    yshifts,
01373                                    gd,
01374                                    gd_14x14,
01375                                    pix_scale,
01376                                    xcal_interpolation,
01377                                    lcorr_coeffs,
01378                                    &cube_combined_data,
01379                                    &cube_combined_noise,
01380                                    no_subtract,
01381                                    flux,
01382                                    background));
01383 
01384             if (lcorr_coeffs != NULL) {
01385                 for (cnt = 0; cnt < nr_frames; cnt++) {
01386                     cpl_polynomial_delete(lcorr_coeffs[cnt]); lcorr_coeffs[cnt] = NULL;
01387                 }
01388                 cpl_free(lcorr_coeffs); lcorr_coeffs = NULL;
01389             }
01390 
01391             //
01392             // identify ifu_nr of current object name in first SCIENCE frame
01393             // containing this object name (e.g. first frame could contain skies only)
01394             //
01395             ifu_nr = -1;
01396             science_frame = NULL;
01397             for (iy = 0; iy < arm_name_struct->size; iy++) {
01398                 for (ix = 0; ix < KMOS_NR_IFUS; ix++) {
01399                     if (arm_name_struct->name_ids[ix+iy*KMOS_NR_IFUS] == arm_index+1) {
01400                         if (ifu_nr == -1) {
01401                             KMO_TRY_EXIT_IF_NULL(
01402                                 science_frame = arm_name_struct->obj_sky_struct->table[iy].objFrame);
01403 
01404                             ifu_nr = ix + 1;
01405                             break;
01406                         }
01407                     }
01408                 }
01409                 if (ifu_nr != -1) { break; }
01410             }
01411 
01412             //
01413             // divide cube by telluric correction
01414             //
01415             if (has_telluric &&
01416                 (arm_name_struct->sameTelluric[arm_index] > 0))
01417             {
01418                 telluric_data = kmo_tweak_load_telluric(frameset, ifu_nr, FALSE, no_subtract);
01419                 KMO_TRY_CHECK_ERROR_STATE();
01420                 if (telluric_data != NULL) {
01421                     int index = kmo_identify_index_desc(desc_telluric, ifu_nr, TRUE);
01422                     KMO_TRY_CHECK_ERROR_STATE();
01423                     if (desc_telluric.sub_desc[index-1].valid_data == TRUE) {
01424                         // load noise if present
01425                         telluric_noise = kmo_tweak_load_telluric(frameset, ifu_nr, TRUE, no_subtract);
01426                         KMO_TRY_CHECK_ERROR_STATE();
01427                     } else {
01428                         if (print_warning_once_tweak_std_noise && (cube_combined_noise != NULL)) {
01429                             cpl_msg_warning("","************************************************************");
01430                             cpl_msg_warning("","* Noise cubes were calculated, but won't be divided by     *");
01431                             cpl_msg_warning("","* telluric error since it is missing.                      *");
01432                             cpl_msg_warning("","* In order to get a telluric with errors, execute          *");
01433                             cpl_msg_warning("","* kmo_std_star with one of the nearest neighbour methods   *");
01434                             cpl_msg_warning("","* (set --imethod to NN, lwNN or swNN)                      *");
01435                             cpl_msg_warning("","************************************************************");
01436                             print_warning_once_tweak_std_noise = FALSE;
01437                         }
01438                     }
01439 
01440                     KMO_TRY_EXIT_IF_ERROR(
01441                         kmo_arithmetic_3D_1D(
01442                                 cube_combined_data, telluric_data,
01443                                 cube_combined_noise, telluric_noise, "/"));
01444                 }
01445                 kmclipm_vector_delete(telluric_data); telluric_data = NULL;
01446                 kmclipm_vector_delete(telluric_noise); telluric_noise = NULL;
01447             }
01448 
01449             //
01450             // saving
01451             //
01452             fn_cube = CUBE_MULTI;
01453             if (!suppress_extension) {
01454                 char tmp_suffix[1024];
01455                 tmp_suffix[0] = '\0';
01456 
01457                 if (arm_name_struct->telluricCnt[arm_index] == nr_frames) {
01458                     strcat(tmp_suffix, "_telluric");
01459                 }
01460                 if (has_illum_corr) {
01461                     strcat(tmp_suffix, "_illum");
01462                 }
01463 //                if (sky_tweak) {
01464 //                    strcat(tmp_suffix, "_skytweak");
01465 //                }
01466 
01467                 if (strlen(tmp_suffix) > 0) {
01468                     KMO_TRY_EXIT_IF_NULL(
01469                         fn_suffix = cpl_sprintf("_%s_%s", arm_name_struct->names[arm_index], tmp_suffix));
01470                 } else {
01471                     KMO_TRY_EXIT_IF_NULL(
01472                         fn_suffix = cpl_sprintf("_%s", arm_name_struct->names[arm_index]));
01473                 }
01474             } else {
01475                 KMO_TRY_EXIT_IF_NULL(
01476                     fn_suffix = cpl_sprintf("_%d", suppress_index++));
01477             }
01478 
01479             //
01480             // calculate WCS
01481             //
01482             KMO_TRY_EXIT_IF_NULL(
01483                 science_frame_header = kmclipm_propertylist_load(cpl_frame_get_filename(science_frame), 0));
01484 
01485             KMO_TRY_EXIT_IF_ERROR(
01486                 kmo_calc_wcs_gd(science_frame_header, ref_sub_header, ifu_nr, gd));
01487 
01488             cpl_propertylist_delete(science_frame_header); science_frame_header = NULL;
01489 
01490             //
01491             // save product
01492             //
01493             KMO_TRY_EXIT_IF_ERROR(
01494                 kmo_dfs_save_main_header(frameset, fn_cube, fn_suffix,
01495                                          science_frame, NULL, parlist, cpl_func));
01496 
01497             KMO_TRY_EXIT_IF_NULL(
01498                 extname = cpl_sprintf("%s.DATA", arm_name_struct->names[arm_index]));
01499             KMO_TRY_EXIT_IF_ERROR(
01500                 kmclipm_update_property_string(ref_sub_header,
01501                                                EXTNAME,
01502                                                extname,
01503                                                "FITS extension name"));
01504             cpl_free(extname); extname = NULL;
01505 
01506             KMO_TRY_EXIT_IF_ERROR(
01507                 kmo_dfs_save_cube(cube_combined_data, fn_cube, fn_suffix,
01508                                   ref_sub_header, 0./0.));
01509 
01510             if (cube_combined_noise != NULL) {
01511                 KMO_TRY_EXIT_IF_NULL(
01512                     extname = cpl_sprintf("%s.NOISE", arm_name_struct->names[arm_index]));
01513                 KMO_TRY_EXIT_IF_ERROR(
01514                     kmclipm_update_property_string(ref_sub_header,
01515                                                    EXTNAME,
01516                                                    extname,
01517                                                    "FITS extension name"));
01518                 cpl_free(extname); extname = NULL;
01519 
01520                 KMO_TRY_EXIT_IF_ERROR(
01521                     kmo_dfs_save_cube(cube_combined_noise, fn_cube, fn_suffix,
01522                                       ref_sub_header, 0./0.));
01523             }
01524 
01525             cpl_imagelist_delete(cube_combined_data); cube_combined_data = NULL;
01526             cpl_imagelist_delete(cube_combined_noise); cube_combined_noise = NULL;
01527             cpl_propertylist_delete(ref_sub_header); ref_sub_header = NULL;
01528             cpl_free(fn_suffix); fn_suffix = NULL;
01529             cpl_free(xshifts); xshifts = NULL;
01530             cpl_free(yshifts); yshifts = NULL;
01531         }  // for (arm_index = nrNames)
01532 
01533         kmo_print_unused_ifus(unused_ifus_after, TRUE);
01534     }
01535     KMO_CATCH
01536     {
01537         KMO_CATCH_MSG();
01538         ret_val = -1;
01539     }
01540 
01541     kmo_free_fits_desc(&desc1);
01542     kmo_free_fits_desc(&desc2);
01543     kmo_free_fits_desc(&desc_telluric);
01544     cpl_vector_delete(ifus); ifus = NULL;
01545     cpl_free(mapping_mode); mapping_mode = NULL;
01546     if (unused_ifus_before != NULL) {
01547         kmo_free_unused_ifus(unused_ifus_before); unused_ifus_before = NULL;
01548     }
01549     if (unused_ifus_after != NULL) {
01550         kmo_free_unused_ifus(unused_ifus_after); unused_ifus_after = NULL;
01551     }
01552     if (bounds != NULL) {
01553         cpl_free(bounds); bounds = NULL;
01554     }
01555 
01556     kmo_delete_armNameStruct(arm_name_struct);
01557 
01558     // frees for the case of errors
01559     kmclipm_vector_delete(telluric_data); telluric_data = NULL;
01560     kmclipm_vector_delete(telluric_noise); telluric_noise = NULL;
01561     cpl_propertylist_delete(tmp_header); tmp_header = NULL;
01562     cpl_table_delete(band_table); band_table = NULL;
01563     cpl_free(suffix); suffix = NULL;
01564     cpl_free(fn_suffix); fn_suffix = NULL;
01565     cpl_free(filter_id); filter_id = NULL;
01566 
01567     return ret_val;
01568 }
01569