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