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