KMOS Pipeline Reference Manual  1.2.7
kmo_sci_red.c
00001 /* $Id: kmo_sci_red.c,v 1.92 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.92 $
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_sky_tweak.h"
00055 
00056 /*-----------------------------------------------------------------------------
00057  *              Types
00058  *-----------------------------------------------------------------------------*/
00059 
00060 /*-----------------------------------------------------------------------------
00061  *                          Functions prototypes
00062  *----------------------------------------------------------------------------*/
00063 
00064 static int kmo_sci_red_create(cpl_plugin *);
00065 static int kmo_sci_red_exec(cpl_plugin *);
00066 static int kmo_sci_red_destroy(cpl_plugin *);
00067 static int kmo_sci_red(cpl_parameterlist *, cpl_frameset *);
00068 
00069 /*-----------------------------------------------------------------------------
00070  *                          Static variables
00071  *----------------------------------------------------------------------------*/
00072 
00073 static char kmo_sci_red_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 "Every IFU containing an object will be reconstructed and divided by telluric\n"
00079 "and illumination correction. By default these intermediate cubes are saved to\n"
00080 "disk. Frames just containing skies won’t produce an output here, so the number\n"
00081 "of output frames can be smaller than the number of input frames.\n"
00082 "Then the reconstructed objects with the same object name are combined. These\n"
00083 "outputs are also saved to disk, the number of created files depends on the\n"
00084 "number of reconstructed objects of different name. If the user just wants to\n"
00085 "combine a certain object, the parameters --name or --ifus can be used.\n"
00086 "For exposures taken with the templates KMOS_spec_obs_mapping8 and\n"
00087 "KMOS_spec_obs_mapping24 the recipe behaves a bit different: All active IFUs\n"
00088 "will be combined, regardless of the object names.\n"
00089 "\n"
00090 "BASIC PARAMETERS:\n"
00091 "-----------------\n"
00092 "--imethod\n"
00093 "The interpolation method used for reconstruction.\n"
00094 "\n"
00095 "--smethod\n"
00096 "The interpolation method used for shifting.\n"
00097 "\n"
00098 "--name\n"
00099 "--ifus\n"
00100 "Since an object can be present only once per exposure and since it can be\n"
00101 "located in different IFUs for the existing exposures, there are two modes to\n"
00102 "identify the objects:\n"
00103 "   * Combine by object names (default)\n"
00104 "   In this case the object name must be provided via the --name parameter. The\n"
00105 "   object name will be searched for in all primary headers of all provided\n"
00106 "   frames in the keyword ESO OCS ARMx NAME.\n"
00107 "\n"
00108 "   * Combine by index (advanced)\n"
00109 "   In this case the --ifus parameter must be provided. The parameter must have\n"
00110 "   the same number of entries as frames are provided, e.g. \"3;1;24\" for 3\n"
00111 "   exposures. The index doesn't reference the extension in the frame but the\n"
00112 "   real index of the IFU as defined in the EXTNAME keyword.\n"
00113 "   (e.g. 'IFU.3.DATA')\n"
00114 "\n"
00115 "ADVANCED PARAMETERS\n"
00116 "-------------------\n"
00117 "--flux\n"
00118 "Specify if flux conservation should be applied.\n"
00119 "\n"
00120 "--background\n"
00121 "Specify if background removal should be applied.\n"
00122 "\n"
00123 "--suppress_extension\n"
00124 "If set to TRUE, the arbitrary filename extensions are supressed. If multiple\n"
00125 "products with the same category are produced, they will be numered consecutively\n"
00126 "starting from 0.\n"
00127 "\n"
00128 "--sky_tweak\n"
00129 "If set to TRUE sky substraction is not done by subtracting the corresponding\n"
00130 "detector images but subtracting a modified sky cube from the object cube.\n"
00131 "It is not allowed that \"--sky_tweak\" and \"--no_subtract\" both are TRUE.\n"
00132 "\n"
00133 "--tbsub\n"
00134 "If set to TRUE subtract the thermal background from the cube resulting from sky tweaking.\n"
00135 "Default value is TRUE.\n"
00136 "\n"
00137 "--obj_sky_table\n"
00138 "The automatic obj-sky-associations can be modified by indicating a file with\n"
00139 "the desired associations. Therefore the file written to disk by default\n"
00140 "(without setting this option) can be edited manually. The formatting must\n"
00141 "absolutely be retained, just the type codes ('O' and'S') and the associated\n"
00142 "frame indices should be altered\n"
00143 "\n"
00144 "  Advanced reconstruction parameters\n"
00145 "  ----------------------------------\n"
00146 "--neighborhoodRange\n"
00147 "Defines the range to search for neighbors during reconstruction\n"
00148 "\n"
00149 "--b_samples\n"
00150 "The number of samples in spectral direction for the reconstructed cube.\n"
00151 "Ideally this number should be greater than 2048, the detector size.\n"
00152 "\n"
00153 "--b_start\n"
00154 "--b_end\n"
00155 "Used to define manually the start and end wavelength for the reconstructed\n"
00156 "cube. By default the internally defined values are used.\n"
00157 "\n"
00158 "--fast_mode\n"
00159 "If set to TRUE, the reconstructed cubes will be collapsed (using median) and\n"
00160 "only then be shifted and combined.\n"
00161 "\n"
00162 "--pix_scale\n"
00163 "Change the pixel scale [arcsec]. Default of 0.2\" results into cubes of\n"
00164 "14x14pix, a scale of 0.1\" results into cubes of 28x28pix, etc.\n"
00165 "\n"
00166 "--no_subtract\n"
00167 "If set to TRUE, the found objects and references won't be sky subtracted. \n"
00168 "Additionally all IFUs will be reconstructed, even the ones containing skies. \n"
00169 "This option sets the parameter no_combine to TRUE automatically.\n"
00170 "\n"
00171 "--xcal_interpolation\n"
00172 "If true interpolate the pixel position in the slitlet (xcal) using the two\n"
00173 "closest rotator angles in the calibration file. Otherwise take the values\n"
00174 "of the closest rotator angle\n"
00175 "\n"
00176 "--extrapolate\n"
00177 "By default no extrapolation is applied. This means that the intermediate\n"
00178 "reconstructed cubes will shrink at most one pixel, which is ok for templates\n"
00179 "like KMOS_spec_obs_nodtosky or KMOS_spec_obs_freedither. When the cubes will be\n"
00180 "arranged as a map, a grid is likely to occur between the IFUs. Therefore extra-\n"
00181 "polation during the shifting process can be switched on in order to get IFUs of\n"
00182 "original size. For frames taken with mapping templates, extrapolation is\n"
00183 "switched on automatically.\n"
00184 "\n"
00185 "  Advanced combining parameters\n"
00186 "  ----------------------------------\n"
00187 "--edge_nan\n"
00188 "Set borders of two sides of the cubes to NaN before combining them. This minimises\n"
00189 "unwanted border effects when dithering.\n"
00190 "\n"
00191 "--no_combine\n"
00192 "If set to TRUE, the reconstructed cubes will not be combined.\n"
00193 "\n"
00194 "--method\n"
00195 "There are following sources to get the shift parameters from:\n"
00196 "   * 'header' (default)\n"
00197 "   The shifts are calculated according to the WCS information stored in the\n"
00198 "   header of every IFU. The output frame will get larger, except the object is\n"
00199 "   at the exact same position for all exposures. The size of the exposures can\n"
00200 "   differ, but the orientation must be the same for all exposures.\n"
00201 "\n"
00202 "   * 'none'\n"
00203 "   The cubes are directly recombined, not shifting at all. The ouput frame\n"
00204 "   will have the same dimensions as the input cubes.\n"
00205 "   If the size differs a warning will be emitted and the cubes will be aligned\n"
00206 "   to the lower left corner. If the orientation differs a warning will be\n"
00207 "   emitted, but the cubes are combined anyway.\n"
00208 "\n"
00209 "   * 'center'\n"
00210 "   The shifts are calculated using a centering algorithm. The cube will be\n"
00211 "   collapsed and a 2D profile will be fitted to it to identify the centre.\n"
00212 "   With the parameter --fmethod the function to fit can be provided. The size\n"
00213 "   of the exposures can differ, but the orientation must be the same for all\n"
00214 "   exposures.\n"
00215 "\n"
00216 "   * 'user'\n"
00217 "   Read the shifts from a user specified file. The path of the file must be\n"
00218 "   provided using the --filename parameter. For every exposure (except the\n"
00219 "   first one) two shift values are expected per line, they have to be separa-\n"
00220 "   ted with simple spaces. The values indicate pixel shifts and are referenced\n"
00221 "   to the first frame. The 1st value is the shift in x-direction to the left,\n"
00222 "   the 2nd the shift in y-direction upwards. The size of the exposures can\n"
00223 "   differ, but the orientation must be the same for all exposures.\n"
00224 "\n"
00225 "--fmethod\n"
00226 "see --method='center'\n"
00227 "The type of function that should be fitted spatially to the collapsed image.\n"
00228 "This fit is used to create a mask to extract the spectrum of the object. Valid\n"
00229 "values are 'gauss' and 'moffat'.\n"
00230 "\n"
00231 "--filename\n"
00232 "see --method='user'\n"
00233 "\n"
00234 "--cmethod\n"
00235 "Following methods of frame combination are available:\n"
00236 "   * 'ksigma' (Default)\n"
00237 "   An iterative sigma clipping. For each position all pixels in the spectrum\n"
00238 "   are examined. If they deviate significantly, they will be rejected according\n"
00239 "   to the conditions:\n"
00240 "       val > mean + stdev * cpos_rej\n"
00241 "   and\n"
00242 "       val < mean - stdev * cneg_rej\n"
00243 "   where --cpos_rej, --cneg_rej and --citer are the corresponding configuration\n"
00244 "   parameters. In the first iteration median and percentile level are used.\n"
00245 "\n"
00246 "   * 'median'\n"
00247 "   At each pixel position the median is calculated.\n"
00248 "\n"
00249 "   * 'average'\n"
00250 "   At each pixel position the average is calculated.\n"
00251 "\n"
00252 "   * 'sum'\n"
00253 "   At each pixel position the sum is calculated.\n"
00254 "\n"
00255 "   * 'min_max'\n"
00256 "   The specified number of minimum and maximum pixel values will be rejected.\n"
00257 "   --cmax and --cmin apply to this method.\n"
00258 "\n"
00259 "--cpos_rej\n"
00260 "--cneg_rej\n"
00261 "--citer\n"
00262 "see --cmethod='ksigma'\n"
00263 "\n"
00264 "--cmax\n"
00265 "--cmin\n"
00266 "see --cmethod='min_max'\n"
00267 "\n"
00268 "------------------------------------------------------------------------------\n"
00269 "  Input files:\n"
00270 "\n"
00271 "   DO                    KMOS                                                  \n"
00272 "   category              Type   Explanation                   Required #Frames\n"
00273 "   --------              -----  -----------                   -------- -------\n"
00274 "   SCIENCE               RAW    The science frames                Y      >=1  \n"
00275 "   XCAL                  F2D    x calibration frame               Y       1   \n"
00276 "   YCAL                  F2D    y calibration frame               Y       1   \n"
00277 "   LCAL                  F2D    Wavelength calib. frame           Y       1   \n"
00278 "   WAVE_BAND             F2L    Table with start-/end-wavelengths Y       1   \n"
00279 "   MASTER_FLAT           F2D    Master flat                       Y      0,1  \n"
00280 "   ILLUM_CORR            F2I    Illumination correction           N      0,1  \n"
00281 "   TELLURIC              F1I    normalised telluric spectrum      N      0,1  \n"
00282 "   OH_SPEC               F1S    Vector holding OH lines           N      0,1  \n"
00283 "\n"
00284 "  Output files:\n"
00285 "\n"
00286 "   DO                    KMOS\n"
00287 "   category              Type   Explanation\n"
00288 "   --------              -----  -----------\n"
00289 "   SCI_COMBINED          F3I    Combined cubes with noise\n"
00290 "   SCI_RECONSTRUCTED     F3I    Reconstructed cube with noise\n"
00291 "   EXP_MASK              F3I    Exposure time mask (not for mapping-templates!)\n"
00292 "------------------------------------------------------------------------------\n"
00293 "\n";
00294 
00295 /*-----------------------------------------------------------------------------
00296  *                              Functions code
00297  *----------------------------------------------------------------------------*/
00298 
00315 int cpl_plugin_get_info(cpl_pluginlist *list)
00316 {
00317     cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe);
00318     cpl_plugin *plugin = &recipe->interface;
00319 
00320     cpl_plugin_init(plugin,
00321                         CPL_PLUGIN_API,
00322                         KMOS_BINARY_VERSION,
00323                         CPL_PLUGIN_TYPE_RECIPE,
00324                         "kmo_sci_red",
00325                         "Reconstruct obj/sky-pairs individually and combine "
00326                         "them afterwards",
00327                         kmo_sci_red_description,
00328                         "Alex Agudo Berbel",
00329                         "kmos-spark@mpe.mpg.de",
00330                         kmos_get_license(),
00331                         kmo_sci_red_create,
00332                         kmo_sci_red_exec,
00333                         kmo_sci_red_destroy);
00334 
00335     cpl_pluginlist_append(list, plugin);
00336 
00337     return 0;
00338 }
00339 
00347 static int kmo_sci_red_create(cpl_plugin *plugin)
00348 {
00349     cpl_recipe *recipe;
00350     cpl_parameter *p;
00351 
00352     /* Check that the plugin is part of a valid recipe */
00353     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00354         recipe = (cpl_recipe *)plugin;
00355     else
00356         return -1;
00357 
00358     /* Create the parameters list in the cpl_recipe object */
00359     recipe->parameters = cpl_parameterlist_new();
00360 
00361     /* --imethod (interpolation method) */
00362     p = cpl_parameter_new_value("kmos.kmo_sci_red.imethod",
00363                                 CPL_TYPE_STRING,
00364                                 "Method to use for interpolation during reconstruction. "
00365                                 "[\"NN\" (nearest neighbour), "
00366                                 "\"lwNN\" (linear weighted nearest neighbor), "
00367                                 "\"swNN\" (square weighted nearest neighbor), "
00368                                 "\"MS\" (Modified Shepard's method)"
00369                                 "\"CS\" (Cubic spline)]",
00370                                 "kmos.kmo_sci_red",
00371                                 "CS");
00372     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "imethod");
00373     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00374     cpl_parameterlist_append(recipe->parameters, p);
00375 
00376     /* --smethod  (shift interpolation method) */
00377     p = cpl_parameter_new_value("kmos.kmo_sci_red.smethod",
00378                                 CPL_TYPE_STRING,
00379                                 "Method to use for interpolation during shifting. "
00380                                 "[\"NN\" (nearest neighbour), "
00381                                 "\"CS\" (Cubic spline)]",
00382                                 "kmos.kmo_sci_red",
00383                                 "CS");
00384     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "smethod");
00385     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00386     cpl_parameterlist_append(recipe->parameters, p);
00387 
00388     /* --method  (shift method) */
00389     p = cpl_parameter_new_value("kmos.kmo_sci_red.method",
00390                                 CPL_TYPE_STRING,
00391                                 "The shifting method:   "
00392                                 "'none': no shifting, combined directly, "
00393                                 "'header': shift according to WCS (default), "
00394                                 "'center': centering algorithm, "
00395                                 "'user': read shifts from file",
00396                                 "kmos.kmo_sci_red",
00397                                 "header");
00398     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "method");
00399     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00400     cpl_parameterlist_append(recipe->parameters, p);
00401 
00402     /* --fmethod */
00403     p = cpl_parameter_new_value("kmos.kmo_sci_red.fmethod",
00404                                 CPL_TYPE_STRING,
00405                                 "The fitting method (applies only when "
00406                                 "method='center'):   "
00407                                 "'gauss': fit a gauss function to collapsed "
00408                                 "image (default), "
00409                                 "'moffat': fit a moffat function to collapsed"
00410                                 " image",
00411                                 "kmos.kmo_sci_red",
00412                                 "gauss");
00413     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "fmethod");
00414     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00415     cpl_parameterlist_append(recipe->parameters, p);
00416 
00417     /* --name */
00418     p = cpl_parameter_new_value("kmos.kmo_sci_red.name",
00419                                 CPL_TYPE_STRING,
00420                                 "Name of the object to combine.",
00421                                 "kmos.kmo_sci_red",
00422                                 "");
00423     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "name");
00424     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00425     cpl_parameterlist_append(recipe->parameters, p);
00426 
00427     /* --ifus */
00428     p = cpl_parameter_new_value("kmos.kmo_sci_red.ifus",
00429                                 CPL_TYPE_STRING,
00430                                 "The indices of the IFUs to combine. "
00431                                 "\"ifu1;ifu2;...\"",
00432                                 "kmos.kmo_sci_red",
00433                                 "");
00434     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "ifus");
00435     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00436     cpl_parameterlist_append(recipe->parameters, p);
00437 
00438     /* --pix_scale */
00439     p = cpl_parameter_new_value("kmos.kmo_sci_red.pix_scale",
00440                                 CPL_TYPE_DOUBLE,
00441                                 "Change the pixel scale [arcsec]. "
00442                                 "Default of 0.2\" results into cubes of 14x14pix, "
00443                                 "a scale of 0.1\" results into cubes of 28x28pix, "
00444                                 "etc.",
00445                                 "kmos.kmo_sci_red",
00446                                 KMOS_PIX_RESOLUTION);
00447     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "pix_scale");
00448     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00449     cpl_parameterlist_append(recipe->parameters, p);
00450 
00451     /* --suppress_extension */
00452     p = cpl_parameter_new_value("kmos.kmo_sci_red.suppress_extension",
00453                                 CPL_TYPE_BOOL,
00454                                 "Suppress arbitrary filename extension."
00455                                 "(TRUE (apply) or FALSE (don't apply)",
00456                                 "kmos.kmo_sci_red",
00457                                 FALSE);
00458     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "suppress_extension");
00459     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00460     cpl_parameterlist_append(recipe->parameters, p);
00461 
00462     /* --neighborhoodRange */
00463     p = cpl_parameter_new_value("kmos.kmo_sci_red.neighborhoodRange",
00464                                 CPL_TYPE_DOUBLE,
00465                                 "Defines the range to search for neighbors "
00466                                 "in pixels",
00467                                 "kmos.kmo_sci_red",
00468                                 1.001);
00469     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "neighborhoodRange");
00470     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00471     cpl_parameterlist_append(recipe->parameters, p);
00472 
00473     /* --filename */
00474     p = cpl_parameter_new_value("kmos.kmo_sci_red.filename",
00475                                 CPL_TYPE_STRING,
00476                                 "The path to the file with the shift vectors."
00477                                 "(Applies only to method='user')",
00478                                 "kmos.kmo_sci_red",
00479                                 "");
00480     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "filename");
00481     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00482     cpl_parameterlist_append(recipe->parameters, p);
00483 
00484     /* --flux */
00485     p = cpl_parameter_new_value("kmos.kmo_sci_red.flux",
00486                                 CPL_TYPE_BOOL,
00487                                 "TRUE: Apply flux conservation. FALSE: otherwise",
00488                                 "kmos.kmo_sci_red",
00489                                 FALSE);
00490     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "flux");
00491     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00492     cpl_parameterlist_append(recipe->parameters, p);
00493 
00494     /* --background */
00495     p = cpl_parameter_new_value("kmos.kmo_sci_red.background",
00496                                 CPL_TYPE_BOOL,
00497                                 "TRUE: Apply background removal. FALSE: otherwise",
00498                                 "kmos.kmo_sci_red",
00499                                 FALSE);
00500     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "background");
00501     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00502     cpl_parameterlist_append(recipe->parameters, p);
00503 
00504     /* --fast_mode */
00505     p = cpl_parameter_new_value("kmos.kmo_sci_red.fast_mode",
00506                                 CPL_TYPE_BOOL,
00507                                 "FALSE: cubes are shifted and combined,"
00508                                 "TRUE: cubes are collapsed and then shifted and combined",
00509                                 "kmos.kmo_sci_red",
00510                                 FALSE);
00511     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "fast_mode");
00512     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00513     cpl_parameterlist_append(recipe->parameters, p);
00514 
00515     /* --extrapolate */
00516     p = cpl_parameter_new_value("kmos.kmo_sci_red.extrapolate",
00517                                 CPL_TYPE_BOOL,
00518                                 "Applies only to 'smethod=CS' when doing sub-"
00519                                 "pixel shifts: "
00520                                 "FALSE: shifted IFU will be filled with NaN's "
00521                                 "at the borders,"
00522                                 "TRUE: shifted IFU will be extrapolated at "
00523                                 "the borders",
00524                                 "kmos.kmo_sci_red",
00525                                 FALSE);
00526     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "extrapolate");
00527     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00528     cpl_parameterlist_append(recipe->parameters, p);
00529 
00530     /* --xcal_interpolation */
00531     p = cpl_parameter_new_value("kmos.kmo_sci_red.xcal_interpolation",
00532                                 CPL_TYPE_BOOL,
00533                                 "TRUE: Interpolate xcal between rotator angles. FALSE: otherwise",
00534                                 "kmos.kmo_sci_red",
00535                                 TRUE);
00536     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "xcal_interpolation");
00537     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00538     cpl_parameterlist_append(recipe->parameters, p);
00539 
00540     /* --edge_nan */
00541     p = cpl_parameter_new_value("kmos.kmo_sci_red.edge_nan",
00542                                 CPL_TYPE_BOOL,
00543                                 "Set borders of cubes to NaN before combining them."
00544                                 "(TRUE (apply) or "
00545                                 "FALSE (don't apply)",
00546                                 "kmos.kmo_sci_red",
00547                                 FALSE);
00548     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "edge_nan");
00549     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00550     cpl_parameterlist_append(recipe->parameters, p);
00551 
00552     /* --no_combine */
00553     p = cpl_parameter_new_value("kmos.kmo_sci_red.no_combine",
00554                                 CPL_TYPE_BOOL,
00555                                 "Don't combine cubes after reconstruction."
00556                                 "(TRUE (apply) or "
00557                                 "FALSE (don't apply)",
00558                                 "kmos.kmo_sci_red",
00559                                 FALSE);
00560     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "no_combine");
00561     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00562     cpl_parameterlist_append(recipe->parameters, p);
00563 
00564     /* --no_subtract */
00565     p = cpl_parameter_new_value("kmos.kmo_sci_red.no_subtract",
00566                                 CPL_TYPE_BOOL,
00567                                 "Don't sky subtract object and references."
00568                                 "(TRUE (apply) or "
00569                                 "FALSE (don't apply)",
00570                                 "kmos.kmo_sci_red",
00571                                 FALSE);
00572     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "no_subtract");
00573     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00574     cpl_parameterlist_append(recipe->parameters, p);
00575 
00576     /* --sky_tweak */
00577     p = cpl_parameter_new_value("kmos.kmo_sci_red.sky_tweak",
00578                                 CPL_TYPE_BOOL,
00579                                 "Use modified sky cube for sky subtraction."
00580                                 "(TRUE (apply) or "
00581                                 "FALSE (don't apply)",
00582                                 "kmos.kmo_sci_red",
00583                                 FALSE);
00584     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "sky_tweak");
00585     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00586     cpl_parameterlist_append(recipe->parameters, p);
00587 
00588     /* --tbsub */
00589     p = cpl_parameter_new_value("kmos.kmo_sci_red.tbsub",
00590                                 CPL_TYPE_BOOL,
00591                                 "Subtract thermal background from input cube."
00592                                 "(TRUE (apply) or "
00593                                 "FALSE (don't apply)",
00594                                 "kmos.kmo_sci_red",
00595                                 TRUE);
00596     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "tbsub");
00597     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00598     cpl_parameterlist_append(recipe->parameters, p);
00599 
00600     // add parameters for band-definition
00601     kmo_band_pars_create(recipe->parameters,
00602                          "kmos.kmo_sci_red");
00603 
00604     /* --obj_sky_table */
00605     p = cpl_parameter_new_value("kmos.kmo_sci_red.obj_sky_table",
00606                                 CPL_TYPE_STRING,
00607                                 "The path to the file with the modified obj/sky associations.",
00608                                 "kmos.kmo_sci_red",
00609                                 "");
00610     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "obj_sky_table");
00611     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00612     cpl_parameterlist_append(recipe->parameters, p);
00613 
00614     return kmo_combine_pars_create(recipe->parameters,
00615                                    "kmos.kmo_sci_red",
00616                                    DEF_REJ_METHOD,
00617                                    FALSE);
00618 }
00619 
00625 static int kmo_sci_red_exec(cpl_plugin *plugin)
00626 {
00627     cpl_recipe  *recipe;
00628 
00629     /* Get the recipe out of the plugin */
00630     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00631         recipe = (cpl_recipe *)plugin;
00632     else return -1 ;
00633 
00634     return kmo_sci_red(recipe->parameters, recipe->frames);
00635 }
00636 
00642 static int kmo_sci_red_destroy(cpl_plugin *plugin)
00643 {
00644     cpl_recipe *recipe;
00645 
00646     /* Get the recipe out of the plugin */
00647     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00648         recipe = (cpl_recipe *)plugin;
00649     else return -1 ;
00650 
00651     cpl_parameterlist_delete(recipe->parameters);
00652     return 0 ;
00653 }
00654 
00669 static int kmo_sci_red(cpl_parameterlist *parlist, cpl_frameset *frameset)
00670 {
00671     int                     ret_val                     = 0,
00672                             nr_science_frames           = 0,
00673                             nr_reconstructed_frames     = 0,
00674                             has_illum_corr              = 0,
00675                             has_master_flat             = 0,
00676                             has_telluric                = 0,
00677                             telluric_ok                 = 0,
00678                             *bounds                     = NULL,
00679                             det_nr                      = 0,
00680                             actual_msg_level            = 0,
00681                             print_once                  = FALSE,
00682                             cube_counter_data           = 0,
00683                             cube_counter_noise          = 0,
00684                             citer                       = 0,
00685                             cmin                        = 0,
00686                             cmax                        = 0,
00687                             extrapolate                 = 0,
00688                             flux                        = FALSE,
00689                             background                  = FALSE,
00690                             index                       = 0,
00691                             nr_data_alloc               = 0,
00692                             tmp_int                     = 0,
00693                             fast_mode                   = FALSE,
00694                             edge_nan                    = FALSE,
00695                             no_combine                  = FALSE,
00696                             no_subtract                 = FALSE,
00697                             do_sky_subtraction          = FALSE,
00698                             sky_tweak                   = FALSE,
00699                             tbsub                       = TRUE,
00700                             xcal_interpolation          = FALSE,
00701                             suppress_extension          = FALSE,
00702                             suppress_index              = 0,
00703                             i                           = 0,
00704                             sf                          = 0,
00705                             jj                          = 0,
00706                             ifu_nr                      = 0;
00707     double                  neighborhoodRange           = 1.001,
00708                             cpos_rej                    = 0.0,
00709                             cneg_rej                    = 0.0,
00710                             pix_scale                   = 0.0;
00711     char                    *suffix                     = NULL,
00712                             *keyword                    = NULL,
00713                             *extname                    = NULL,
00714                             *fn_suffix                  = NULL,
00715                             *mapping_mode               = NULL,
00716                             **split                     = NULL,
00717                             content[256];
00718     const char              *imethod                    = NULL,
00719                             *smethod                    = NULL,
00720                             *ifus_txt                   = NULL,
00721                             *name                       = NULL,
00722                             *filter_id                  = NULL,
00723                             *tmp_str                    = NULL,
00724                             *filename                   = NULL,
00725                             *fn_obj_sky_table           = NULL,
00726                             *fn_out                     = NULL,
00727                             *fn_out_mask                = NULL,
00728                             *fn_obj                     = NULL,
00729                             *fn_sky                     = NULL,
00730                             *fn_reconstr                = NULL,
00731                             *comb_method                = NULL,
00732                             *cmethod                    = NULL,
00733                             *fmethod                    = NULL;
00734     cpl_array               **unused_ifus_before        = NULL,
00735                             **unused_ifus_after         = NULL;
00736     cpl_frame               *xcal_frame                 = NULL,
00737                             *ycal_frame                 = NULL,
00738                             *lcal_frame                 = NULL,
00739                             *flat_frame                 = NULL,
00740                             *illum_frame                = NULL,
00741                             *telluric_frame             = NULL,
00742                             *tmp_frame                  = NULL;
00743     cpl_propertylist        *tmp_header                 = NULL,
00744                             *main_header                = NULL,
00745                             **header_data               = NULL,
00746                             **header_noise              = NULL;
00747     cpl_vector              *ifus                       = NULL;
00748     kmclipm_vector          *telluric_data              = NULL,
00749                             *telluric_noise             = NULL;
00750     cpl_image               **lcal                      = NULL,
00751                             *illum_data                 = NULL,
00752                             *illum_noise                = NULL,
00753                             *tmpImg                     = NULL,
00754                             *exp_mask                   = NULL;
00755     cpl_imagelist           **cube_data                 = NULL,
00756                             **cube_noise                = NULL,
00757                             *sky_data                   = NULL,
00758                             *sky_noise                  = NULL,
00759                             *combined_data              = NULL,
00760                             *combined_noise             = NULL,
00761                             *tmpCube                    = NULL;
00762     cpl_table               *band_table                 = NULL;
00763     cpl_frame               *sky_frame                  = NULL,
00764                             *sky_as_object_frame        = NULL,
00765                             *ref_spectrum_frame         = NULL;
00766     cpl_polynomial          *lcorr_coeffs               = NULL;
00767     main_fits_desc          desc1,
00768                             desc2,
00769                             desc_telluric;
00770     gridDefinition          gd;
00771     armNameStruct           *arm_name_struct            = NULL;
00772     enum extrapolationType  extrapol_enum               = 0;
00773     enum kmo_frame_type     ft                          = 0;
00774 
00775     KMO_TRY
00776     {
00777         kmo_init_fits_desc(&desc1);
00778         kmo_init_fits_desc(&desc2);
00779         kmo_init_fits_desc(&desc_telluric);
00780 
00781         //
00782         // check frameset
00783         //
00784         KMO_TRY_ASSURE((parlist != NULL) &&
00785                        (frameset != NULL),
00786                        CPL_ERROR_NULL_INPUT,
00787                        "Not all input data is provided!");
00788 
00789         nr_science_frames = cpl_frameset_count_tags(frameset, SCIENCE);
00790         KMO_TRY_ASSURE(nr_science_frames >= 1,
00791                        CPL_ERROR_ILLEGAL_INPUT,
00792                        "At least one SCIENCE frame is required!");
00793         if (nr_science_frames == 1) {
00794             cpl_msg_warning("", "At least two SCIENCE frames should be provided "
00795                                 "in order to apply sky subtraction!");
00796             cpl_msg_warning("", "All IFUs will be reconstructed regardless if "
00797                                 "they contain object, reference or sky!");
00798         }
00799 
00800         KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, XCAL) == 1,
00801                        CPL_ERROR_FILE_NOT_FOUND,
00802                        "Exactly one XCAL frame is required!");
00803 
00804         KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, YCAL) == 1,
00805                        CPL_ERROR_FILE_NOT_FOUND,
00806                        "Exactly one YCAL frame is required!");
00807 
00808         KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, LCAL) == 1,
00809                        CPL_ERROR_FILE_NOT_FOUND,
00810                        "Exactly one LCAL frame is required!");
00811 
00812         has_master_flat = cpl_frameset_count_tags(frameset, MASTER_FLAT);
00813         KMO_TRY_ASSURE((has_master_flat == 0) || (has_master_flat == 1),
00814                        CPL_ERROR_FILE_NOT_FOUND,
00815                        "At most one MASTER_FLAT frame can be provided!");
00816 
00817         KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, WAVE_BAND) == 1,
00818                        CPL_ERROR_FILE_NOT_FOUND,
00819                        "Exactly one WAVE_BAND frame is required!");
00820 
00821         has_illum_corr = cpl_frameset_count_tags(frameset, ILLUM_CORR);
00822         KMO_TRY_ASSURE((has_illum_corr == 0) || (has_illum_corr == 1),
00823                        CPL_ERROR_FILE_NOT_FOUND,
00824                        "At most one ILLUM_CORR frame can be provided!");
00825 
00826         has_telluric = cpl_frameset_count_tags(frameset, TELLURIC);
00827         KMO_TRY_ASSURE((has_telluric == 0) || (has_telluric == 1),
00828                        CPL_ERROR_FILE_NOT_FOUND,
00829                        "At most one TELLURIC frame can be provided!");
00830 
00831         KMO_TRY_ASSURE(kmo_dfs_set_groups(frameset, "kmo_sci_red") == 1,
00832                        CPL_ERROR_ILLEGAL_INPUT,
00833                        "Cannot identify RAW and CALIB frames!");
00834 
00835         KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, OH_SPEC) == 0 ||
00836                        cpl_frameset_count_tags(frameset, OH_SPEC) == 1,
00837                        CPL_ERROR_ILLEGAL_INPUT,
00838                        "Only a single reference spectrum can be provided!");
00839         //
00840         // get parameters
00841         //
00842         cpl_msg_info("", "--- Parameter setup for kmo_sci_red ------");
00843 
00844         flux = kmo_dfs_get_parameter_bool(parlist,
00845                                           "kmos.kmo_sci_red.flux");
00846 
00847         KMO_TRY_ASSURE((flux == 0) ||
00848                        (flux == 1),
00849                        CPL_ERROR_ILLEGAL_INPUT,
00850                        "flux must be either FALSE or TRUE! %d", flux);
00851 
00852         KMO_TRY_EXIT_IF_ERROR(
00853             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_sci_red.flux"));
00854 
00855         background = kmo_dfs_get_parameter_bool(parlist,
00856                                           "kmos.kmo_sci_red.background");
00857 
00858         KMO_TRY_ASSURE((background == 0) ||
00859                        (background == 1),
00860                        CPL_ERROR_ILLEGAL_INPUT,
00861                        "background must be either FALSE or TRUE! %d", background);
00862 
00863         KMO_TRY_EXIT_IF_ERROR(
00864             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_sci_red.background"));
00865 
00866         KMO_TRY_EXIT_IF_NULL(
00867             imethod = kmo_dfs_get_parameter_string(parlist,
00868                                                    "kmos.kmo_sci_red.imethod"));
00869 
00870         KMO_TRY_ASSURE((strcmp(imethod, "NN") == 0) ||
00871                        (strcmp(imethod, "lwNN") == 0) ||
00872                        (strcmp(imethod, "swNN") == 0) ||
00873                        (strcmp(imethod, "MS") == 0) ||
00874                        (strcmp(imethod, "CS") == 0),
00875                        CPL_ERROR_ILLEGAL_INPUT,
00876                        "imethod must be either \"NN\", \"lwNN\", "
00877                        "\"swNN\", \"MS\" or \"CS\"!");
00878 
00879         KMO_TRY_EXIT_IF_ERROR(
00880             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_sci_red.imethod"));
00881 
00882         KMO_TRY_EXIT_IF_NULL(
00883             smethod = kmo_dfs_get_parameter_string(parlist,
00884                                                    "kmos.kmo_sci_red.smethod"));
00885 
00886         KMO_TRY_ASSURE((strcmp(smethod, "NN") == 0) ||
00887                        (strcmp(smethod, "CS") == 0),
00888                        CPL_ERROR_ILLEGAL_INPUT,
00889                        "smethod must be either \"NN\" or \"CS\"!");
00890 
00891         KMO_TRY_EXIT_IF_ERROR(
00892             kmo_dfs_print_parameter_help(parlist,
00893                                          "kmos.kmo_sci_red.smethod"));
00894 
00895         neighborhoodRange = kmo_dfs_get_parameter_double(parlist,
00896                                           "kmos.kmo_sci_red.neighborhoodRange");
00897         KMO_TRY_CHECK_ERROR_STATE();
00898 
00899         KMO_TRY_ASSURE(neighborhoodRange > 0.0,
00900                        CPL_ERROR_ILLEGAL_INPUT,
00901                        "neighborhoodRange must be greater than 0.0");
00902 
00903         KMO_TRY_EXIT_IF_ERROR(
00904             kmo_dfs_print_parameter_help(parlist,
00905                                          "kmos.kmo_sci_red.neighborhoodRange"));
00906 
00907         KMO_TRY_EXIT_IF_NULL(
00908             comb_method = kmo_dfs_get_parameter_string(parlist,
00909                                            "kmos.kmo_sci_red.method"));
00910 
00911         KMO_TRY_EXIT_IF_NULL(
00912             fmethod = kmo_dfs_get_parameter_string(parlist,
00913                                            "kmos.kmo_sci_red.fmethod"));
00914 
00915         KMO_TRY_ASSURE((strcmp(comb_method, "none") == 0) ||
00916                        (strcmp(comb_method, "header") == 0) ||
00917                        (strcmp(comb_method, "center") == 0) ||
00918                        (strcmp(comb_method, "user") == 0),
00919                        CPL_ERROR_ILLEGAL_INPUT,
00920                        "Following shift methods are available : 'none', "
00921                        "'header', 'center' or 'user'");
00922 
00923         if (strcmp(comb_method, "user") == 0) {
00924             filename = kmo_dfs_get_parameter_string(parlist,
00925                                                    "kmos.kmo_sci_red.filename");
00926             KMO_TRY_CHECK_ERROR_STATE();
00927 
00928             KMO_TRY_ASSURE(strcmp(filename, "") != 0,
00929                            CPL_ERROR_ILLEGAL_INPUT,
00930                            "path of file with shift information must be "
00931                            "provided!");
00932 
00933             KMO_TRY_EXIT_IF_ERROR(
00934                 kmo_dfs_print_parameter_help(parlist,
00935                                              "kmos.kmo_sci_red.filename"));
00936         }
00937 
00938         KMO_TRY_EXIT_IF_ERROR(
00939             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_sci_red.method"));
00940 
00941         ifus_txt = kmo_dfs_get_parameter_string(parlist,
00942                                                   "kmos.kmo_sci_red.ifus");
00943         KMO_TRY_CHECK_ERROR_STATE();
00944 
00945         name = kmo_dfs_get_parameter_string(parlist, "kmos.kmo_sci_red.name");
00946         KMO_TRY_CHECK_ERROR_STATE();
00947 
00948         if (strcmp(ifus_txt, "") != 0) {
00949             KMO_TRY_ASSURE(strcmp(name, "") == 0,
00950                            CPL_ERROR_ILLEGAL_INPUT,
00951                            "name parameter must be NULL if IFU indices are "
00952                            "provided!");
00953 
00954             KMO_TRY_EXIT_IF_NULL(
00955                 ifus = kmo_identify_values(ifus_txt));
00956 
00957             KMO_TRY_ASSURE(cpl_vector_get_size(ifus) == nr_science_frames,
00958                            CPL_ERROR_ILLEGAL_INPUT,
00959                            "ifus parameter must have the same number of values "
00960                            "than frames provided (for frames just containing "
00961                            "skies insert 0)) (%lld!=%d)",
00962                            cpl_vector_get_size(ifus), nr_science_frames);
00963         }
00964 
00965         if (strcmp(name, "") != 0) {
00966             KMO_TRY_ASSURE(strcmp(ifus_txt, "") == 0,
00967                            CPL_ERROR_ILLEGAL_INPUT,
00968                            "ifus parameter must be NULL if name is provided!");
00969         }
00970 
00971         KMO_TRY_EXIT_IF_ERROR(
00972             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_sci_red.ifus"));
00973 
00974         KMO_TRY_EXIT_IF_ERROR(
00975             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_sci_red.name"));
00976 
00977         kmo_band_pars_load(parlist, "kmos.kmo_sci_red");
00978 
00979         extrapolate = kmo_dfs_get_parameter_bool(parlist,
00980                                                 "kmos.kmo_sci_red.extrapolate");
00981         KMO_TRY_CHECK_ERROR_STATE();
00982 
00983         if (strcmp(smethod, "NN") == 0) {
00984             if (extrapolate == TRUE) {
00985                 cpl_msg_warning("", "extrapolation for smethod='NN' not available!");
00986             }
00987             extrapol_enum = NONE_NANS;
00988         } else if (strcmp(smethod, "CS") == 0) {
00989             if (extrapolate == FALSE) {
00990                 extrapol_enum = NONE_NANS;
00991             } else if (extrapolate == TRUE) {
00992                 extrapol_enum = BCS_NATURAL;
00993             } else {
00994                 KMO_TRY_ASSURE(1 == 0,
00995                                CPL_ERROR_ILLEGAL_INPUT,
00996                                "extrapolate must be either FALSE or TRUE!");
00997             }
00998             smethod = "BCS";
00999         } else {
01000             KMO_TRY_ASSURE(1 == 0,
01001                            CPL_ERROR_ILLEGAL_INPUT,
01002                            "method must be either \"CS\" or \"NN\" !");
01003         }
01004         KMO_TRY_CHECK_ERROR_STATE();
01005 
01006         KMO_TRY_EXIT_IF_ERROR(
01007             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_sci_red.extrapolate"));
01008 
01009         fast_mode = kmo_dfs_get_parameter_bool(parlist,
01010                                                 "kmos.kmo_sci_red.fast_mode");
01011         KMO_TRY_CHECK_ERROR_STATE();
01012         KMO_TRY_ASSURE((fast_mode == TRUE) ||
01013                        (fast_mode == FALSE),
01014                        CPL_ERROR_ILLEGAL_INPUT,
01015                        "fast_mode must be either FALSE or TRUE!");
01016         KMO_TRY_EXIT_IF_ERROR(
01017             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_sci_red.fast_mode"));
01018 
01019         edge_nan = kmo_dfs_get_parameter_bool(parlist,
01020                                           "kmos.kmo_sci_red.edge_nan");
01021         KMO_TRY_CHECK_ERROR_STATE();
01022         KMO_TRY_EXIT_IF_ERROR(
01023             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_sci_red.edge_nan"));
01024 
01025         KMO_TRY_ASSURE((edge_nan == TRUE) || (edge_nan == FALSE),
01026                        CPL_ERROR_ILLEGAL_INPUT,
01027                        "edge_nan must be TRUE or FALSE!");
01028 
01029         no_combine = kmo_dfs_get_parameter_bool(parlist,
01030                                                 "kmos.kmo_sci_red.no_combine");
01031         KMO_TRY_CHECK_ERROR_STATE();
01032 
01033         KMO_TRY_EXIT_IF_ERROR(
01034             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_sci_red.no_combine"));
01035 
01036         KMO_TRY_ASSURE((no_combine == TRUE) || (no_combine == FALSE),
01037                        CPL_ERROR_ILLEGAL_INPUT,
01038                        "no_combine must be TRUE or FALSE!");
01039 
01040         no_subtract = kmo_dfs_get_parameter_bool(parlist,
01041                                                 "kmos.kmo_sci_red.no_subtract");
01042         KMO_TRY_CHECK_ERROR_STATE();
01043 
01044         KMO_TRY_EXIT_IF_ERROR(
01045             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_sci_red.no_subtract"));
01046 
01047         KMO_TRY_ASSURE((no_subtract == TRUE) || (no_subtract == FALSE),
01048                        CPL_ERROR_ILLEGAL_INPUT,
01049                        "no_subtract must be TRUE or FALSE!");
01050 
01051         sky_tweak = kmo_dfs_get_parameter_bool(parlist,
01052                                                 "kmos.kmo_sci_red.sky_tweak");
01053         KMO_TRY_CHECK_ERROR_STATE();
01054 
01055         KMO_TRY_EXIT_IF_ERROR(
01056             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_sci_red.sky_tweak"));
01057 
01058         KMO_TRY_ASSURE((sky_tweak == TRUE) || (sky_tweak == FALSE),
01059                        CPL_ERROR_ILLEGAL_INPUT,
01060                        "sky_tweak must be TRUE or FALSE!");
01061 
01062         KMO_TRY_ASSURE(!((no_subtract == TRUE) && (sky_tweak == TRUE)),
01063                 CPL_ERROR_ILLEGAL_INPUT,
01064                 "Either no_subtract or sky_tweak or both must be FALSE");
01065 
01066         tbsub = kmo_dfs_get_parameter_bool(parlist, "kmos.kmo_sci_red.tbsub");
01067         KMO_TRY_CHECK_ERROR_STATE();
01068 
01069         pix_scale = kmo_dfs_get_parameter_double(parlist,
01070                                                  "kmos.kmo_sci_red.pix_scale");
01071         KMO_TRY_CHECK_ERROR_STATE();
01072         KMO_TRY_EXIT_IF_ERROR(
01073            kmo_dfs_print_parameter_help(parlist,
01074                                        "kmos.kmo_sci_red.pix_scale"));
01075         KMO_TRY_ASSURE((pix_scale >= 0.01) &&
01076                        (pix_scale <= 0.4),
01077                        CPL_ERROR_ILLEGAL_INPUT,
01078                        "pix_scale must be between 0.01 and 0.4 (results in cubes "
01079                        "with 7x7 to 280x280 pixels)!");
01080 
01081         xcal_interpolation = kmo_dfs_get_parameter_bool(parlist,
01082                                            "kmos.kmo_sci_red.xcal_interpolation");
01083         KMO_TRY_CHECK_ERROR_STATE();
01084         KMO_TRY_EXIT_IF_ERROR(
01085             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_sci_red.xcal_interpolation"));
01086         KMO_TRY_ASSURE((xcal_interpolation == TRUE) ||
01087                        (xcal_interpolation == FALSE),
01088                        CPL_ERROR_ILLEGAL_INPUT,
01089                        "xcal_interpolation must be TRUE or FALSE!");
01090 
01091         suppress_extension = kmo_dfs_get_parameter_bool(parlist,
01092                                           "kmos.kmo_sci_red.suppress_extension");
01093         KMO_TRY_CHECK_ERROR_STATE();
01094         KMO_TRY_EXIT_IF_ERROR(
01095             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_sci_red.suppress_extension"));
01096 
01097         KMO_TRY_ASSURE((suppress_extension == TRUE) || (suppress_extension == FALSE),
01098                        CPL_ERROR_ILLEGAL_INPUT,
01099                        "suppress_extension must be TRUE or FALSE!");
01100 
01101         fn_obj_sky_table = kmo_dfs_get_parameter_string(parlist,
01102                                                         "kmos.kmo_sci_red.obj_sky_table");
01103         KMO_TRY_CHECK_ERROR_STATE();
01104 
01105         KMO_TRY_EXIT_IF_ERROR(
01106             kmo_dfs_print_parameter_help(parlist,
01107                                         "kmos.kmo_sci_red.obj_sky_table"));
01108 
01109         KMO_TRY_EXIT_IF_ERROR(
01110             kmo_combine_pars_load(parlist,
01111                                   "kmos.kmo_sci_red",
01112                                   &cmethod,
01113                                   &cpos_rej,
01114                                   &cneg_rej,
01115                                   &citer,
01116                                   &cmin,
01117                                   &cmax,
01118                                   FALSE));
01119 
01120         cpl_msg_info("", "-------------------------------------------");
01121 
01122         //
01123         // assure that filters, grating and rotation offsets match for
01124         // XCAL, YCAL, LCAL and for data frame to reconstruct (except DARK
01125         // frames)
01126         //
01127 
01128         // check if filter_id and grating_id match for all detectors
01129         KMO_TRY_EXIT_IF_ERROR(
01130             kmo_check_frameset_setup(frameset, SCIENCE, TRUE, FALSE, TRUE));
01131         KMO_TRY_EXIT_IF_ERROR(
01132             kmo_check_frame_setup(frameset, SCIENCE, YCAL, TRUE, FALSE, TRUE));
01133         KMO_TRY_EXIT_IF_ERROR(
01134             kmo_check_frame_setup(frameset, XCAL, YCAL, TRUE, FALSE, TRUE));
01135         KMO_TRY_EXIT_IF_ERROR(
01136             kmo_check_frame_setup(frameset, XCAL, LCAL, TRUE, FALSE, TRUE));
01137         if (has_master_flat) {
01138             KMO_TRY_EXIT_IF_ERROR(
01139                 kmo_check_frame_setup(frameset, XCAL, MASTER_FLAT, TRUE, FALSE, TRUE));
01140         }
01141         if (has_telluric) {
01142             KMO_TRY_EXIT_IF_ERROR(
01143                 kmo_check_frame_setup(frameset, XCAL, TELLURIC,
01144                                            TRUE, FALSE, TRUE));
01145         }
01146 
01147         // check descriptors of all frames
01148         KMO_TRY_EXIT_IF_NULL(
01149             xcal_frame = kmo_dfs_get_frame(frameset, XCAL));
01150 
01151         desc1 = kmo_identify_fits_header(cpl_frame_get_filename(xcal_frame));
01152         KMO_TRY_CHECK_ERROR_STATE();
01153 
01154         KMO_TRY_ASSURE((desc1.nr_ext % KMOS_NR_DETECTORS == 0) &&
01155                        (desc1.ex_badpix == FALSE) &&
01156                        (desc1.fits_type == f2d_fits) &&
01157                        (desc1.frame_type == detector_frame),
01158                        CPL_ERROR_ILLEGAL_INPUT,
01159                        "XCAL isn't in the correct format!!!");
01160 
01161         KMO_TRY_EXIT_IF_NULL(
01162             ycal_frame = kmo_dfs_get_frame(frameset, YCAL));
01163         desc2 = kmo_identify_fits_header(cpl_frame_get_filename(ycal_frame));
01164         KMO_TRY_CHECK_ERROR_STATE();
01165 
01166         KMO_TRY_ASSURE((desc1.nr_ext == desc2.nr_ext) &&
01167                        (desc1.ex_badpix == desc2.ex_badpix) &&
01168                        (desc1.fits_type == desc2.fits_type) &&
01169                        (desc1.frame_type == desc2.frame_type),
01170                        CPL_ERROR_ILLEGAL_INPUT,
01171                        "YCAL isn't in the correct format!!!");
01172         kmo_free_fits_desc(&desc2);
01173         kmo_init_fits_desc(&desc2);
01174 
01175         KMO_TRY_EXIT_IF_NULL(
01176             lcal_frame = kmo_dfs_get_frame(frameset, LCAL));
01177         desc2 = kmo_identify_fits_header(cpl_frame_get_filename(lcal_frame));
01178         KMO_TRY_CHECK_ERROR_STATE();
01179 
01180         KMO_TRY_ASSURE((desc2.nr_ext % KMOS_NR_DETECTORS == 0) &&
01181                        (desc1.ex_badpix == desc2.ex_badpix) &&
01182                        (desc1.fits_type == desc2.fits_type) &&
01183                        (desc1.frame_type == desc2.frame_type),
01184                        CPL_ERROR_ILLEGAL_INPUT,
01185                        "LCAL isn't in the correct format!!!");
01186         kmo_free_fits_desc(&desc2);
01187         kmo_init_fits_desc(&desc2);
01188 
01189         if (has_master_flat) {
01190             KMO_TRY_EXIT_IF_NULL(
01191                 flat_frame = kmo_dfs_get_frame(frameset, MASTER_FLAT));
01192             desc2 = kmo_identify_fits_header(cpl_frame_get_filename(flat_frame));
01193             KMO_TRY_CHECK_ERROR_STATE();
01194 
01195             KMO_TRY_ASSURE((desc2.nr_ext % (2*KMOS_NR_DETECTORS) == 0) &&
01196                            (desc1.ex_badpix == desc2.ex_badpix) &&
01197                            (desc1.fits_type == desc2.fits_type) &&
01198                            (desc1.frame_type == desc2.frame_type),
01199                            CPL_ERROR_ILLEGAL_INPUT,
01200                            "MASTER_FLAT isn't in the correct format!!!");
01201             kmo_free_fits_desc(&desc2);
01202             kmo_init_fits_desc(&desc2);
01203         }
01204 
01205         if (has_illum_corr) {
01206             KMO_TRY_EXIT_IF_NULL(
01207                 illum_frame = kmo_dfs_get_frame(frameset, ILLUM_CORR));
01208             desc2 = kmo_identify_fits_header(
01209                         cpl_frame_get_filename(illum_frame));
01210             KMO_TRY_CHECK_ERROR_STATE();
01211             KMO_TRY_ASSURE(((desc2.nr_ext == 24) || (desc2.nr_ext == 48)) &&
01212                            (desc2.ex_badpix == FALSE) &&
01213                            (desc2.fits_type == f2i_fits) &&
01214                            (desc2.frame_type == ifu_frame),
01215                            CPL_ERROR_ILLEGAL_INPUT,
01216                            "ILLUM_CORR isn't in the correct format!!!");
01217             kmo_free_fits_desc(&desc2);
01218             kmo_init_fits_desc(&desc2);
01219         }
01220 
01221         if (has_telluric) {
01222             KMO_TRY_EXIT_IF_NULL(
01223                 telluric_frame = kmo_dfs_get_frame(frameset, TELLURIC));
01224             desc_telluric = kmo_identify_fits_header(
01225                                         cpl_frame_get_filename(telluric_frame));
01226             KMO_TRY_CHECK_ERROR_STATE();
01227             KMO_TRY_ASSURE(((desc_telluric.nr_ext == 24) || (desc_telluric.nr_ext == 48)) &&
01228                            (desc_telluric.ex_badpix == FALSE) &&
01229                            (desc_telluric.fits_type == f1i_fits) &&
01230                            (desc_telluric.frame_type == ifu_frame),
01231                            CPL_ERROR_ILLEGAL_INPUT,
01232                            "TELLURIC isn't in the correct format!!!");
01233         }
01234         kmo_free_fits_desc(&desc2);
01235 
01236         KMO_TRY_EXIT_IF_NULL(
01237             tmp_frame = kmo_dfs_get_frame(frameset, SCIENCE));
01238         while (tmp_frame != NULL ) {
01239             desc2 = kmo_identify_fits_header(cpl_frame_get_filename(tmp_frame));
01240             KMO_TRY_CHECK_ERROR_STATE();
01241             KMO_TRY_ASSURE((desc2.nr_ext == 3) &&
01242                            (desc2.ex_badpix == FALSE) &&
01243                            (desc2.fits_type == raw_fits) &&
01244                            (desc2.frame_type == detector_frame),
01245                            CPL_ERROR_ILLEGAL_INPUT,
01246                            "SCIENCE isn't in the correct format!!!");
01247             kmo_free_fits_desc(&desc2);
01248             kmo_init_fits_desc(&desc2);
01249 
01250             if (mapping_mode == NULL) {
01251                 KMO_TRY_EXIT_IF_NULL(
01252                     tmp_header =
01253                           kmclipm_propertylist_load(
01254                                          cpl_frame_get_filename(tmp_frame), 0));
01255                 if (cpl_propertylist_has(tmp_header, TPL_ID)) {
01256                     KMO_TRY_EXIT_IF_NULL(
01257                         tmp_str = cpl_propertylist_get_string(tmp_header,
01258                                                               TPL_ID));
01259 
01260                     if (strcmp(tmp_str, MAPPING8) == 0)
01261                     {
01262                         mapping_mode = cpl_sprintf("%s", "mapping8");
01263                     }
01264                     if (strcmp(tmp_str, MAPPING24) == 0)
01265                     {
01266                         mapping_mode = cpl_sprintf("%s", "mapping24");
01267                     }
01268                 }
01269                 cpl_propertylist_delete(tmp_header); tmp_header = NULL;
01270             }
01271 
01272             tmp_frame = kmo_dfs_get_frame(frameset, NULL);
01273             KMO_TRY_CHECK_ERROR_STATE();
01274         }
01275 
01276         if (mapping_mode != NULL) {
01277             // we are in mapping mode
01278             if ((ifus != NULL) || (strcmp(name, "") != 0))
01279             {
01280                 cpl_msg_warning("","The SCIENCE frames have been taken in one of the "
01281                                    "mapping modes AND specific IFUs have been "
01282                                    "specified! --> Only processing these!");
01283             } else {
01284                 if (strcmp(smethod, "BCS") == 0) {
01285                     extrapol_enum = BCS_NATURAL;
01286                     cpl_msg_info("","Detected frames taken in mapping mode. "
01287                                     "Changing extrapolation mode to TRUE.");
01288                 }
01289             }
01290             if (fast_mode) {
01291                 cpl_msg_info("", "Creating map in fast_mode.");
01292             }
01293         } else {
01294             if (fast_mode) {
01295                 cpl_msg_info("", "fast_mode has been selected but we aren't in "
01296                              "mapping mode. So your choice for fast_mode is ignored.");
01297             }
01298         }
01299 
01300         KMO_TRY_EXIT_IF_NULL(
01301             suffix = kmo_dfs_get_suffix(xcal_frame, TRUE, FALSE));
01302 
01303         KMO_TRY_EXIT_IF_ERROR(
01304             kmo_check_frame_setup_md5_xycal(frameset));
01305         KMO_TRY_EXIT_IF_ERROR(
01306             kmo_check_frame_setup_md5(frameset));
01307         KMO_TRY_EXIT_IF_ERROR(
01308             kmo_check_frame_setup_sampling(frameset));
01309 
01310         cpl_msg_info("", "Detected instrument setup:   %s", suffix+1);
01311         cpl_msg_info("", "(grating 1, 2 & 3)");
01312 
01313         //
01314         // check which IFUs are active for all frames
01315         //
01316         KMO_TRY_EXIT_IF_NULL(
01317             unused_ifus_before = kmo_get_unused_ifus(frameset, 1, 1));
01318 
01319         KMO_TRY_EXIT_IF_NULL(
01320             unused_ifus_after = kmo_duplicate_unused_ifus(unused_ifus_before));
01321 
01322         kmo_print_unused_ifus(unused_ifus_before, FALSE);
01323 
01324         //
01325         // get bounds, setup grid, setup arm_name-struct
01326         //
01327 
01328         // get left and right bounds of IFUs
01329         KMO_TRY_EXIT_IF_NULL(
01330             tmp_header = kmo_dfs_load_primary_header(frameset, XCAL));
01331         KMO_TRY_EXIT_IF_NULL(
01332             bounds = kmclipm_extract_bounds(tmp_header));
01333         cpl_propertylist_delete(tmp_header); tmp_header = NULL;
01334 
01335         // setup grid definition, wavelength start and end points will be set
01336         // in the detector loop
01337         KMO_TRY_EXIT_IF_ERROR(
01338             kmclipm_setup_grid(&gd, imethod, neighborhoodRange, pix_scale, 0.));
01339 
01340         // get valid STD frames with objects in it and associated sky exposures and
01341         // get valid object names to process, either one object name across
01342         // several SCIENCE frames, or all object names
01343         if (strcmp(fn_obj_sky_table, "") == 0) {
01344             KMO_TRY_EXIT_IF_NULL(
01345                 arm_name_struct = kmo_create_armNameStruct(frameset,
01346                                                            SCIENCE,
01347                                                            ifus,
01348                                                            name,
01349                                                            unused_ifus_after,
01350                                                            bounds,
01351                                                            mapping_mode,
01352                                                            no_subtract));
01353             KMO_TRY_EXIT_IF_ERROR(
01354                 kmo_save_objSkyStruct(arm_name_struct->obj_sky_struct, "obj_sky_table.txt"));
01355         } else {
01356             // read in obj/sky-table
01357             objSkyStruct *obj_sky_struct = NULL;
01358 
01359             KMO_TRY_EXIT_IF_NULL(
01360                 obj_sky_struct = kmo_read_objSkyStruct(fn_obj_sky_table,
01361                                                        frameset,
01362                                                        SCIENCE));
01363 
01364             KMO_TRY_EXIT_IF_NULL(
01365                 arm_name_struct = kmo_create_armNameStruct2(obj_sky_struct,
01366                                                             frameset,
01367                                                             SCIENCE,
01368                                                             ifus,
01369                                                             name,
01370                                                             unused_ifus_after,
01371                                                             bounds,
01372                                                             mapping_mode,
01373                                                             no_subtract));
01374 
01375         }
01376         kmo_print_armNameStruct(frameset, arm_name_struct);
01377 
01378         // in mapping-mode check if for all IFUs there is either no telluric at all
01379         // or the same number of tellurics than object names
01380         if ((has_telluric) && (mapping_mode != NULL)) {
01381             telluric_ok = TRUE;
01382             for (jj = 0; jj < arm_name_struct->nrNames; jj++) {
01383                 if (!((arm_name_struct->telluricCnt[jj] == arm_name_struct->namesCnt[jj]) ||
01384                     (arm_name_struct->telluricCnt[jj] == 0)))
01385                 {
01386                     telluric_ok = FALSE;
01387                     break;
01388                 }
01389             }
01390             if (!telluric_ok) {
01391                 KMO_TRY_ASSURE(1==0,
01392                                CPL_ERROR_UNSUPPORTED_MODE,
01393                                "Mosaics need a TELLURIC frame with at least a telluric correction per detector available! "
01394                                "Omit the TELLURIC from your sof-file or choose another TELLURIC!");
01395             }
01396         }
01397 
01398         //
01399         // load lcal-frames
01400         //
01401         KMO_TRY_EXIT_IF_NULL(
01402             lcal = (cpl_image**) cpl_calloc(KMOS_NR_DETECTORS, sizeof(cpl_image*)));
01403         for (i = 0; i < KMOS_NR_DETECTORS; i++) {
01404             KMO_TRY_EXIT_IF_NULL(
01405                 lcal[i] = kmo_dfs_load_image(frameset, LCAL, i+1, FALSE, FALSE, NULL));
01406         }
01407 
01408         nr_data_alloc = KMOS_NR_IFUS;
01409         KMO_TRY_EXIT_IF_NULL(
01410             cube_data =  (cpl_imagelist**)cpl_calloc(nr_data_alloc,
01411                                                      sizeof(cpl_imagelist*)));
01412         KMO_TRY_EXIT_IF_NULL(
01413             cube_noise = (cpl_imagelist**)cpl_calloc(nr_data_alloc,
01414                                                      sizeof(cpl_imagelist*)));
01415         KMO_TRY_EXIT_IF_NULL(
01416             header_data =  (cpl_propertylist**)cpl_calloc(nr_data_alloc,
01417                                                      sizeof(cpl_propertylist*)));
01418         KMO_TRY_EXIT_IF_NULL(
01419             header_noise = (cpl_propertylist**)cpl_calloc(nr_data_alloc,
01420                                                      sizeof(cpl_propertylist*)));
01421 
01422         if (cpl_frameset_count_tags(frameset, SCIENCE) == 1) {
01423             no_combine = TRUE;
01424             cpl_msg_info("", "--no_combine has been set to TRUE since there is only one SCIENCE frame!");
01425         }
01426 
01427         if (no_subtract) {
01428             no_combine = TRUE;
01429             cpl_msg_info("", "--no_combine has been set to TRUE since --no_subtract has been specified by the user!");
01430             cpl_msg_info("", "Combining cubes would combine skies and objects which is meaningless.");
01431             cpl_msg_info("", "This can be done manually with the recipe kmo_combine afterwards!");
01432         }
01433 
01434         actual_msg_level = cpl_msg_get_level();
01435 
01436         cpl_msg_info("", "-------------------------------------------");
01437 
01438         if (cpl_frameset_count_tags(frameset, OH_SPEC) != 0) {
01439             int is_all_obs = TRUE,
01440                 has_all_origfile = TRUE;
01441 
01442             KMO_TRY_EXIT_IF_NULL(
01443                 tmp_frame = kmo_dfs_get_frame(frameset, SCIENCE));
01444             while (tmp_frame != NULL ) {
01445                 KMO_TRY_EXIT_IF_NULL(
01446                     tmp_header = kmclipm_propertylist_load(cpl_frame_get_filename(tmp_frame), 0));
01447 
01448                 if (cpl_propertylist_has(tmp_header, ORIGFILE)) {
01449                     KMO_TRY_EXIT_IF_NULL(
01450                         tmp_str = cpl_propertylist_get_string(tmp_header, ORIGFILE));
01451                     if (strstr(tmp_str, "OBS") == NULL) {
01452                         is_all_obs = FALSE;
01453                     }
01454                 } else {
01455                     has_all_origfile = FALSE;
01456                 }
01457                 cpl_propertylist_delete(tmp_header); tmp_header = NULL;
01458                 tmp_frame = kmo_dfs_get_frame(frameset, NULL);
01459                 KMO_TRY_CHECK_ERROR_STATE();
01460             }
01461 
01462             if (has_all_origfile) {
01463                 if (is_all_obs) {
01464                     // we are reconstructing an OBS-frame, allow OH_SPEC correction
01465                     KMO_TRY_EXIT_IF_NULL(
01466                         ref_spectrum_frame = kmo_dfs_get_frame(frameset, OH_SPEC));
01467                 } else {
01468                     cpl_msg_warning("", "Supplied OH_SPEC is ignored since a calibration "
01469                                     "frame is being used as SCIENCE frame.");
01470                 }
01471             } else {
01472                 cpl_msg_warning("", "The supplied SCIENCE frames are all assumed to be "
01473                                     "science frames. If any of them is a calibration frame, "
01474                                     "omit OH_SPEC from sof-file");
01475                 KMO_TRY_EXIT_IF_NULL(
01476                     ref_spectrum_frame = kmo_dfs_get_frame(frameset, OH_SPEC));
01477             }
01478         }
01479 
01480         //
01481         // loop all science frames containing at least one object
01482         //
01483         cpl_msg_info("", "Reconstructing & saving cubes containing objects");
01484         cpl_msg_info("", " ");
01485         for (sf = 0; sf < arm_name_struct->size; sf++) {
01486             KMO_TRY_EXIT_IF_NULL(
01487                 fn_obj = cpl_frame_get_filename(arm_name_struct->obj_sky_struct->table[sf].objFrame));
01488 
01489             KMO_TRY_EXIT_IF_NULL(
01490                 main_header = kmclipm_propertylist_load(fn_obj, 0));
01491 
01492             actual_msg_level = cpl_msg_get_level();
01493 
01494             //
01495             // reconstruct science frame
01496             //
01497             cpl_msg_info("", "   > processing frame: %s", fn_obj);
01498             for (ifu_nr = 1; ifu_nr <= KMOS_NR_IFUS; ifu_nr++)
01499             {
01500                 det_nr = (ifu_nr - 1)/KMOS_IFUS_PER_DETECTOR + 1;
01501 
01502                 KMO_TRY_ASSURE((det_nr >= 1) &&
01503                                (det_nr <= KMOS_NR_DETECTORS),
01504                                CPL_ERROR_ILLEGAL_INPUT,
01505                                "The provided ifu-numbers are incorrect! They "
01506                                "must be between 1 and %d", KMOS_NR_IFUS);
01507 
01508                 // get subheader data
01509                 KMO_TRY_EXIT_IF_NULL(
01510                     header_data[ifu_nr-1] = kmclipm_propertylist_load(fn_obj,
01511                                                                       det_nr));
01512                 KMO_TRY_EXIT_IF_NULL(
01513                     extname = kmo_extname_creator(ifu_frame, ifu_nr,
01514                                                   EXT_DATA));
01515                 KMO_TRY_EXIT_IF_ERROR(
01516                     kmclipm_update_property_string(header_data[ifu_nr-1],
01517                                                    EXTNAME, extname,
01518                                                    "FITS extension name"));
01519                 cpl_free(extname); extname = NULL;
01520 
01521                 if (arm_name_struct->name_ids[ifu_nr-1+sf*KMOS_NR_IFUS] >= 1) {
01522                     // IFU is valid
01523 
01524                     if ((arm_name_struct->obj_sky_struct->table[sf].skyFrames[ifu_nr-1] != NO_CORRESPONDING_SKYFRAME) &&
01525                         (cpl_frameset_count_tags(frameset, SCIENCE) != 1) &&
01526                         !no_subtract)
01527                     {
01528                         do_sky_subtraction = TRUE;
01529                         if (no_subtract) {
01530                             sky_frame = NULL;
01531                             cpl_msg_warning("", "      > Omit sky subtraction on IFU %d", ifu_nr);
01532                         } else {
01533                             sky_frame = arm_name_struct->obj_sky_struct->table[sf].skyFrames[ifu_nr-1];
01534                             KMO_TRY_EXIT_IF_NULL(
01535                                 fn_sky = cpl_frame_get_filename(sky_frame));
01536                             cpl_msg_info("", "      > IFU %d (with sky in frame: %s)", ifu_nr, fn_sky);
01537                         }
01538                         if (sky_tweak){
01539                             sky_as_object_frame = sky_frame;
01540                             sky_frame = NULL;
01541                         }
01542                     } else {
01543                         do_sky_subtraction = FALSE;
01544                         sky_frame = NULL;
01545                         if ((cpl_frameset_count_tags(frameset, SCIENCE) != 1) && (!no_subtract)) {
01546                             cpl_msg_warning("", "      > IFU %d with no corresponding sky frame", ifu_nr);
01547                         }
01548                     }
01549 
01550                     // get filter for this detector and setup grid definition
01551                     // ESO INS FILTi ID
01552                     char *tmp_band_method = getenv("KMO_BAND_METHOD");
01553                     int band_method = 0;
01554                     if (tmp_band_method != NULL) {
01555                         band_method = atoi(tmp_band_method);
01556                     }
01557 
01558                     KMO_TRY_EXIT_IF_NULL(
01559                         keyword = cpl_sprintf("%s%d%s",
01560                                               IFU_FILTID_PREFIX, det_nr,
01561                                               IFU_FILTID_POSTFIX));
01562                     KMO_TRY_EXIT_IF_NULL(
01563                         filter_id = cpl_propertylist_get_string(main_header,
01564                                                                 keyword));
01565                     cpl_free(keyword); keyword = NULL;
01566 
01567                     if (print_once) {
01568                         cpl_msg_set_level(CPL_MSG_WARNING);
01569                     }
01570 
01571                     KMO_TRY_EXIT_IF_NULL(
01572                         band_table = kmo_dfs_load_table(frameset, WAVE_BAND,
01573                                                         1, 0));
01574                     // lcal just needed when band_method==1
01575                     KMO_TRY_EXIT_IF_ERROR(
01576                         kmclipm_setup_grid_band_lcal(&gd, lcal[det_nr-1],
01577                                                      filter_id, band_method,
01578                                                      band_table));
01579                     cpl_table_delete(band_table); band_table = NULL;
01580 
01581                     print_once = TRUE;
01582                     cpl_msg_set_level(actual_msg_level);
01583 
01584                     //
01585                     // calc WCS & update subheader
01586                     //
01587                     KMO_TRY_EXIT_IF_ERROR(
01588                         kmo_calc_wcs_gd(main_header, header_data[ifu_nr-1], ifu_nr, gd));
01589 
01590                     KMO_TRY_EXIT_IF_ERROR(
01591                         kmclipm_update_property_int(header_data[ifu_nr-1],
01592                                                     NAXIS, 3,
01593                                                     "number of data axes"));
01594                     KMO_TRY_EXIT_IF_ERROR(
01595                         kmclipm_update_property_int(header_data[ifu_nr-1],
01596                                                     NAXIS1, gd.x.dim,
01597                                                     "length of data axis 1"));
01598                     KMO_TRY_EXIT_IF_ERROR(
01599                         kmclipm_update_property_int(header_data[ifu_nr-1],
01600                                                     NAXIS2, gd.y.dim,
01601                                                     "length of data axis 2"));
01602                     KMO_TRY_EXIT_IF_ERROR(
01603                         kmclipm_update_property_int(header_data[ifu_nr-1],
01604                                                     NAXIS3, gd.l.dim,
01605                                                     "length of data axis 3"));
01606 
01607                     //
01608                     // reconstruct object
01609                     //
01610 
01611                     if (ref_spectrum_frame == NULL) { // no lambda correction using OH lines
01612                         KMO_TRY_EXIT_IF_ERROR(
01613                                 kmo_reconstruct_sci(ifu_nr,
01614                                                     bounds[2*(ifu_nr-1)],
01615                                                     bounds[2*(ifu_nr-1)+1],
01616                                                     arm_name_struct->obj_sky_struct->table[sf].objFrame,
01617                                                     SCIENCE,
01618                                                     sky_frame,
01619                                                     SCIENCE,
01620                                                     flat_frame,
01621                                                     xcal_frame,
01622                                                     ycal_frame,
01623                                                     lcal_frame,
01624                                                     NULL,
01625                                                     &gd,
01626                                                     &cube_data[ifu_nr-1],
01627                                                     &cube_noise[ifu_nr-1],
01628                                                     flux,
01629                                                     background,
01630                                                     xcal_interpolation));
01631 
01632                     } else {                    //  lambda correction using OH lines
01633                         KMO_TRY_EXIT_IF_ERROR(
01634                                 kmo_reconstruct_sci(ifu_nr,
01635                                                     bounds[2*(ifu_nr-1)],
01636                                                     bounds[2*(ifu_nr-1)+1],
01637                                                     arm_name_struct->obj_sky_struct->table[sf].objFrame,
01638                                                     SCIENCE,
01639                                                     NULL,
01640                                                     NULL,
01641                                                     flat_frame,
01642                                                     xcal_frame,
01643                                                     ycal_frame,
01644                                                     lcal_frame,
01645                                                     NULL,
01646                                                     &gd,
01647                                                     &cube_data[ifu_nr-1],
01648                                                     &cube_noise[ifu_nr-1],
01649                                                     FALSE,
01650                                                     FALSE,
01651                                                     xcal_interpolation));
01652 
01653 
01654                         if (cube_data[ifu_nr-1] != NULL) {
01655                             KMO_TRY_EXIT_IF_NULL(
01656                                 lcorr_coeffs = kmo_lcorr_get(cube_data[ifu_nr-1],
01657                                                              header_data[ifu_nr-1],
01658                                                              ref_spectrum_frame,
01659                                                              gd,
01660                                                              filter_id,
01661                                                              ifu_nr));
01662 
01663                             cpl_imagelist_delete(cube_data[ifu_nr-1]); cube_data[ifu_nr-1] = NULL;
01664                             if (cube_noise[ifu_nr-1] != NULL) {
01665                                 cpl_imagelist_delete(cube_noise[ifu_nr-1]); cube_noise[ifu_nr-1] = NULL;
01666                             }
01667 
01668                             KMO_TRY_EXIT_IF_ERROR(
01669                                     kmo_reconstruct_sci(ifu_nr,
01670                                                         bounds[2*(ifu_nr-1)],
01671                                                         bounds[2*(ifu_nr-1)+1],
01672                                                         arm_name_struct->obj_sky_struct->table[sf].objFrame,
01673                                                         SCIENCE,
01674                                                         sky_frame,
01675                                                         SCIENCE,
01676                                                         flat_frame,
01677                                                         xcal_frame,
01678                                                         ycal_frame,
01679                                                         lcal_frame,
01680                                                         lcorr_coeffs,
01681                                                         &gd,
01682                                                         &cube_data[ifu_nr-1],
01683                                                         &cube_noise[ifu_nr-1],
01684                                                         flux,
01685                                                         background,
01686                                                         xcal_interpolation));
01687 
01688                             cpl_polynomial_delete(lcorr_coeffs); lcorr_coeffs = NULL;
01689                         }
01690                     }
01691 
01692                     // if sky_tweak is set to TRUE reconstruct sky frame as object
01693                     // ans use kmo_priv_sky_tweak to subtract a modified sky cube
01694                     if (do_sky_subtraction && sky_tweak) {
01695                         if (ref_spectrum_frame == NULL) { // no lambda correction using OH lines
01696                             KMO_TRY_EXIT_IF_ERROR(
01697                                     kmo_reconstruct_sci(ifu_nr,
01698                                                         bounds[2*(ifu_nr-1)],
01699                                                         bounds[2*(ifu_nr-1)+1],
01700                                                         sky_as_object_frame,
01701                                                         SCIENCE,
01702                                                         sky_frame,
01703                                                         SCIENCE,
01704                                                         flat_frame,
01705                                                         xcal_frame,
01706                                                         ycal_frame,
01707                                                         lcal_frame,
01708                                                         NULL,
01709                                                         &gd,
01710                                                         &sky_data,
01711                                                         &sky_noise,
01712                                                         flux,
01713                                                         background,
01714                                                         xcal_interpolation));
01715 
01716                         } else {                    //  lambda correction using OH lines
01717                             KMO_TRY_EXIT_IF_ERROR(
01718                                     kmo_reconstruct_sci(ifu_nr,
01719                                                         bounds[2*(ifu_nr-1)],
01720                                                         bounds[2*(ifu_nr-1)+1],
01721                                                         sky_as_object_frame,
01722                                                         SCIENCE,
01723                                                         NULL,
01724                                                         NULL,
01725                                                         flat_frame,
01726                                                         xcal_frame,
01727                                                         ycal_frame,
01728                                                         lcal_frame,
01729                                                         NULL,
01730                                                         &gd,
01731                                                         &sky_data,
01732                                                         &sky_noise,
01733                                                         FALSE,
01734                                                         FALSE,
01735                                                         xcal_interpolation));
01736 
01737 
01738                             if (sky_data != NULL) {
01739                                 KMO_TRY_EXIT_IF_NULL(
01740                                     lcorr_coeffs = kmo_lcorr_get(sky_data,
01741                                                                  header_data[ifu_nr-1],
01742                                                                  ref_spectrum_frame,
01743                                                                  gd,
01744                                                                  filter_id,
01745                                                                  ifu_nr));
01746 
01747                                 cpl_imagelist_delete(sky_data); sky_data = NULL;
01748                                 if (sky_noise != NULL) {
01749                                     cpl_imagelist_delete(sky_noise); sky_noise = NULL;
01750                                 }
01751 
01752                                 KMO_TRY_EXIT_IF_ERROR(
01753                                         kmo_reconstruct_sci(ifu_nr,
01754                                                             bounds[2*(ifu_nr-1)],
01755                                                             bounds[2*(ifu_nr-1)+1],
01756                                                             sky_as_object_frame,
01757                                                             SCIENCE,
01758                                                             sky_frame,
01759                                                             SCIENCE,
01760                                                             flat_frame,
01761                                                             xcal_frame,
01762                                                             ycal_frame,
01763                                                             lcal_frame,
01764                                                             lcorr_coeffs,
01765                                                             &gd,
01766                                                             &sky_data,
01767                                                             &sky_noise,
01768                                                             flux,
01769                                                             background,
01770                                                             xcal_interpolation));
01771 
01772                                 cpl_polynomial_delete(lcorr_coeffs); lcorr_coeffs = NULL;
01773                             }
01774                         }
01775 
01776                         cpl_imagelist *tmp_object_cube = cube_data[ifu_nr-1];
01777                         KMO_TRY_EXIT_IF_NULL(
01778                                 cube_data[ifu_nr-1] = kmo_priv_sky_tweak (tmp_object_cube,
01779                                                                    sky_data,
01780                                                                    header_data[ifu_nr-1],
01781                                                                    .3, tbsub));
01782                         if (tmp_object_cube != NULL) {
01783                             cpl_imagelist_delete(tmp_object_cube); tmp_object_cube = NULL;
01784                         }
01785                         if (sky_data != NULL) {
01786                             cpl_imagelist_delete(sky_data); sky_data = NULL;
01787                         }
01788                         if (sky_noise != NULL) {
01789                             cpl_imagelist_delete(sky_noise); sky_noise = NULL;
01790                         }
01791                     }
01792 
01793                     // scale flux according to pixel_scale
01794                     KMO_TRY_EXIT_IF_NULL(
01795                         tmpImg = cpl_imagelist_get(cube_data[ifu_nr-1], 0));
01796                     double scaling = (cpl_image_get_size_x(tmpImg)*cpl_image_get_size_y(tmpImg)) /
01797                                      (KMOS_SLITLET_X*KMOS_SLITLET_Y);
01798                     KMO_TRY_EXIT_IF_ERROR(
01799                         cpl_imagelist_divide_scalar(cube_data[ifu_nr-1], scaling));
01800                     if (cube_noise[ifu_nr-1] != NULL) {
01801                         KMO_TRY_EXIT_IF_ERROR(
01802                             cpl_imagelist_divide_scalar(cube_noise[ifu_nr-1], scaling));
01803                     }
01804 
01805                     // get object name
01806                     KMO_TRY_EXIT_IF_NULL(
01807                         keyword = cpl_sprintf("%s%d%s", IFU_NAME_PREFIX, ifu_nr,
01808                                               IFU_NAME_POSTFIX));
01809                     KMO_TRY_EXIT_IF_NULL(
01810                         tmp_str = cpl_propertylist_get_string(header_data[ifu_nr-1],
01811                                                               keyword));
01812                     cpl_free(keyword); keyword = NULL;
01813 
01814                     //
01815                     // divide cube by telluric correction
01816                     //
01817                     if (has_telluric) {
01818                         // check if the number of occurences of the actual object name is the
01819                         // same as the number of found tellurics for this object (which can be on different arms)
01820                         telluric_ok = FALSE;
01821                         for (jj = 0; jj < arm_name_struct->nrNames; jj++) {
01822                             if (((strcmp(arm_name_struct->names[jj], tmp_str) == 0) ||
01823                                  (strcmp(arm_name_struct->names[jj], IFUS_USER_DEFINED) == 0)) &&
01824                                 (arm_name_struct->telluricCnt[jj] == arm_name_struct->namesCnt[jj]))
01825                             {
01826                                 telluric_ok = TRUE;
01827                                 break;
01828                             }
01829                         }
01830 
01831                         if (telluric_ok) {
01832                             telluric_data = kmo_tweak_load_telluric(frameset, ifu_nr, FALSE, no_subtract);
01833                             KMO_TRY_CHECK_ERROR_STATE();
01834                             if (telluric_data != NULL) {
01835                                 index = kmo_identify_index_desc(desc_telluric, ifu_nr, TRUE);
01836                                 KMO_TRY_CHECK_ERROR_STATE();
01837                                 if (desc_telluric.sub_desc[index-1].valid_data == TRUE) {
01838                                     // load noise if present
01839                                     telluric_noise = kmo_tweak_load_telluric(frameset, ifu_nr, TRUE, no_subtract);
01840                                     KMO_TRY_CHECK_ERROR_STATE();
01841                                 } else {
01842                                     if (print_warning_once_tweak_std_noise && (cube_noise[ifu_nr-1] != NULL)) {
01843                                         cpl_msg_warning("","************************************************************");
01844                                         cpl_msg_warning("","* Noise cubes were calculated, but won't be divided by     *");
01845                                         cpl_msg_warning("","* telluric error since it is missing.                      *");
01846                                         cpl_msg_warning("","* In order to get a telluric with errors, execute          *");
01847                                         cpl_msg_warning("","* kmo_std_star with one of the nearest neighbour methods   *");
01848                                         cpl_msg_warning("","* (set --imethod to NN, lwNN or swNN)                      *");
01849                                         cpl_msg_warning("","************************************************************");
01850                                         print_warning_once_tweak_std_noise = FALSE;
01851                                     }
01852                                 }
01853 
01854                                 KMO_TRY_EXIT_IF_ERROR(
01855                                     kmo_arithmetic_3D_1D(
01856                                             cube_data[ifu_nr-1], telluric_data,
01857                                             cube_noise[ifu_nr-1], telluric_noise, "/"));
01858                             }
01859                         }
01860                     }
01861 
01862                     //
01863                     // divide cube by illumination correction
01864                     //
01865                     if (has_illum_corr) {
01866                         illum_data = kmo_dfs_load_image(frameset, ILLUM_CORR,
01867                                                         ifu_nr, FALSE, FALSE, NULL);
01868                         if (cpl_error_get_code() != CPL_ERROR_NONE) {
01869                             cpl_msg_warning("","No illumination correction for IFU %d available! "
01870                                             "Proceeding anyway.", ifu_nr);
01871                             cpl_error_reset();
01872                         } else {
01873                             illum_noise = kmo_dfs_load_image(frameset,
01874                                                              ILLUM_CORR,
01875                                                              ifu_nr, TRUE,
01876                                                              FALSE, NULL);
01877                             if (cpl_error_get_code() != CPL_ERROR_NONE) {
01878                                 cpl_msg_warning("","No illumination correction for IFU %d "
01879                                                 "available! Proceeding anyway.", ifu_nr);
01880                                 cpl_image_delete(illum_data); illum_data = NULL;
01881                                 cpl_error_reset();
01882                             }
01883                         }
01884 
01885                         if (illum_data != NULL) {
01886                             KMO_TRY_EXIT_IF_ERROR(
01887                                 kmo_arithmetic_3D_2D(
01888                                             cube_data[ifu_nr-1], illum_data,
01889                                             cube_noise[ifu_nr-1], illum_noise, "/"));
01890                             cpl_image_delete(illum_data); illum_data = NULL;
01891                             cpl_image_delete(illum_noise); illum_noise = NULL;
01892                         }
01893                     }
01894 
01895                     // get object name and store if not already present
01896                     KMO_TRY_EXIT_IF_NULL(
01897                         keyword = cpl_sprintf("%s%d%s", IFU_NAME_PREFIX, ifu_nr,
01898                                               IFU_NAME_POSTFIX));
01899                     KMO_TRY_EXIT_IF_NULL(
01900                         tmp_str = cpl_propertylist_get_string(header_data[ifu_nr-1],
01901                                                               keyword));
01902                     cpl_free(keyword); keyword = NULL;
01903 
01904                     kmclipm_vector_delete(telluric_data); telluric_data = NULL;
01905                     kmclipm_vector_delete(telluric_noise); telluric_noise = NULL;
01906                 } else {
01907                     // IFU is invalid
01908                 }
01909 
01910                 // duplicate subheader data
01911                 KMO_TRY_EXIT_IF_NULL(
01912                     header_noise[ifu_nr-1] =
01913                          cpl_propertylist_duplicate(header_data[ifu_nr-1]));
01914 
01915                 KMO_TRY_EXIT_IF_NULL(
01916                     extname = kmo_extname_creator(ifu_frame, ifu_nr, EXT_NOISE));
01917                 KMO_TRY_EXIT_IF_ERROR(
01918                     kmclipm_update_property_string(header_noise[ifu_nr-1],
01919                                                    EXTNAME, extname,
01920                                                    "FITS extension name"));
01921                 cpl_free(extname); extname = NULL;
01922             } // end for ifu_nr
01923 
01924             //
01925             // count number of reconstructed data- and noise-cubes
01926             //
01927             for (ifu_nr = 1; ifu_nr <= nr_data_alloc; ifu_nr++) {
01928                 if (cube_data[ifu_nr-1] != NULL) {
01929                     cube_counter_data++;
01930                 }
01931                 if (cube_noise[ifu_nr-1] != NULL) {
01932                     cube_counter_noise++;
01933                 }
01934             }
01935 
01936             //
01937             // save reconstructed cubes of science frame
01938             //
01939             if (cube_counter_data > 0) {
01940                 cpl_msg_info("", "   > saving...");
01941 
01942                 if (!suppress_extension) {
01943                     fn_out = fn_obj;
01944 
01945                     int nr_found = 0;
01946                     // remove any path-elements from filename and use it as
01947                     // suffix
01948                     split = kmo_strsplit(fn_out, "/", &nr_found);
01949 
01950                     fn_suffix = cpl_sprintf("_%s", split[nr_found-1]);
01951                     kmo_strfreev(split);
01952 
01953                     // remove '.fits' at the end if there is any
01954                     char *fff = fn_suffix;
01955                     fff += strlen(fn_suffix)-5;
01956                     if (strcmp(fff, ".fits") == 0) {
01957                         fn_suffix[strlen(fn_suffix)-5] = '\0';
01958                     }
01959                 } else {
01960                     KMO_TRY_EXIT_IF_NULL(
01961                         fn_suffix = cpl_sprintf("_%d", suppress_index++));
01962                 }
01963 
01964                 fn_out = RECONSTRUCTED_CUBE;
01965 
01966                 KMO_TRY_EXIT_IF_ERROR(
01967                     kmo_dfs_save_main_header(frameset, fn_out, fn_suffix,
01968                                              arm_name_struct->obj_sky_struct->table[sf].objFrame,
01969                                              NULL, parlist, cpl_func));
01970 
01971                 for (ifu_nr = 1; ifu_nr <= KMOS_NR_IFUS; ifu_nr++) {
01972                     KMO_TRY_EXIT_IF_ERROR(
01973                         kmo_dfs_save_cube(cube_data[ifu_nr-1], fn_out,
01974                                           fn_suffix, header_data[ifu_nr-1], 0./0.));
01975 
01976                     if (cube_counter_noise > 0) {
01977                         KMO_TRY_EXIT_IF_ERROR(
01978                             kmo_dfs_save_cube(cube_noise[ifu_nr-1], fn_out,
01979                                               fn_suffix, header_noise[ifu_nr-1],
01980                                               0./0.));
01981                     }
01982 
01983                     cpl_imagelist_delete(cube_data[ifu_nr-1]); cube_data[ifu_nr-1] = NULL;
01984                     cpl_imagelist_delete(cube_noise[ifu_nr-1]); cube_noise[ifu_nr-1] = NULL;
01985                     cpl_propertylist_delete(header_data[ifu_nr-1]); header_data[ifu_nr-1] = NULL;
01986                     cpl_propertylist_delete(header_noise[ifu_nr-1]); header_noise[ifu_nr-1] = NULL;
01987                 } // end for ifu_nr
01988                 cpl_free(fn_suffix); fn_suffix = NULL;
01989             } else {
01990                 cpl_msg_info("", "   > all IFUs invalid, don't save");
01991             } // if (cube_counter_data > 0) {
01992 
01993             cpl_propertylist_delete(main_header); main_header = NULL;
01994         } // end for sf (arm_name_struct->obj_sky_struct->size)
01995         cpl_free(cube_data);    cube_data = NULL;
01996         cpl_free(cube_noise);    cube_noise = NULL;
01997         cpl_free(header_data);    header_data = NULL;
01998         cpl_free(header_noise);    header_noise = NULL;
01999 
02000         kmo_print_unused_ifus(unused_ifus_after, TRUE);
02001 
02002         cpl_msg_info("", "-------------------------------------------");
02003 
02004         if (lcal != NULL) {
02005             for (i = 0; i < KMOS_NR_DETECTORS; i++) {
02006                 cpl_image_delete(lcal[i]);
02007             }
02008         }
02009         cpl_free(lcal); lcal = NULL;
02010 
02011         //
02012         // combine
02013         //
02014         suppress_index = 0;
02015         if (!no_combine) {
02016             cpl_msg_info("", "Combining reconstructed objects");
02017             cpl_msg_info("", " ");
02018 
02019             nr_reconstructed_frames = cpl_frameset_count_tags(frameset, RECONSTRUCTED_CUBE);
02020 
02021             if ( (mapping_mode == NULL) || ((mapping_mode != NULL) &&
02022                                             ((ifus != NULL) || (strcmp(name, "") != 0)))
02023                )
02024             {
02025                 // loop all available objects
02026                 for (i = 0; i < arm_name_struct->nrNames; i++) {
02027                     cpl_msg_info("", "   > object: %s", arm_name_struct->names[i]);
02028                     nr_data_alloc = arm_name_struct->namesCnt[i];
02029                     KMO_TRY_EXIT_IF_NULL(
02030                         cube_data =  (cpl_imagelist**)cpl_calloc(nr_data_alloc,
02031                                                            sizeof(cpl_imagelist*)));
02032                     KMO_TRY_EXIT_IF_NULL(
02033                         cube_noise = (cpl_imagelist**)cpl_calloc(nr_data_alloc,
02034                                                            sizeof(cpl_imagelist*)));
02035                     KMO_TRY_EXIT_IF_NULL(
02036                         header_data =  (cpl_propertylist**)cpl_calloc(nr_data_alloc,
02037                                                         sizeof(cpl_propertylist*)));
02038                     KMO_TRY_EXIT_IF_NULL(
02039                         header_noise = (cpl_propertylist**)cpl_calloc(nr_data_alloc,
02040                                                         sizeof(cpl_propertylist*)));
02041 
02042                     // setup cube-list and header-list for kmo_priv_combine()
02043                     cube_counter_data = 0;
02044                     cube_counter_noise = 0;
02045                     KMO_TRY_EXIT_IF_NULL(
02046                         tmp_frame = kmo_dfs_get_frame(frameset, RECONSTRUCTED_CUBE));
02047                     while (tmp_frame != NULL ) {
02048                         KMO_TRY_EXIT_IF_NULL(
02049                             fn_reconstr = cpl_frame_get_filename(tmp_frame));
02050 
02051                         KMO_TRY_EXIT_IF_NULL(
02052                             tmp_header = kmclipm_propertylist_load(fn_reconstr, 0));
02053 
02054                         kmo_free_fits_desc(&desc1);
02055                         kmo_init_fits_desc(&desc1);
02056                         desc1 = kmo_identify_fits_header(fn_reconstr);
02057 
02058                         for (ifu_nr = 1; ifu_nr <= KMOS_NR_IFUS; ifu_nr++) {
02059                             // check if object-name equals the one in our list
02060                             KMO_TRY_EXIT_IF_NULL(
02061                                 keyword = cpl_sprintf("%s%d%s", IFU_NAME_PREFIX,
02062                                                       ifu_nr, IFU_NAME_POSTFIX));
02063                             KMO_TRY_EXIT_IF_NULL(
02064                                 tmp_str = cpl_propertylist_get_string(tmp_header,
02065                                                                       keyword));
02066                             cpl_free(keyword); keyword = NULL;
02067 
02068                             if ((strcmp(arm_name_struct->names[i], tmp_str) == 0) ||
02069                                 (strcmp(arm_name_struct->names[i], IFUS_USER_DEFINED) == 0))
02070                             {
02071                                 // found object-IFU with matching name
02072                                 // load data & subheader
02073                                 index = kmo_identify_index(fn_reconstr, ifu_nr, FALSE);
02074                                 KMO_TRY_CHECK_ERROR_STATE();
02075 
02076                                 if (desc1.sub_desc[index-1].valid_data) {
02077                                     KMO_TRY_EXIT_IF_NULL(
02078                                         cube_data[cube_counter_data] =
02079                                             kmclipm_imagelist_load(fn_reconstr,
02080                                                                    CPL_TYPE_FLOAT,
02081                                                                    index));
02082                                     if (edge_nan) {
02083                                         KMO_TRY_EXIT_IF_ERROR(
02084                                             kmo_edge_nan(cube_data[cube_counter_data], ifu_nr));
02085                                     }
02086 
02087                                     KMO_TRY_EXIT_IF_NULL(
02088                                         header_data[cube_counter_data] =
02089                                             kmclipm_propertylist_load(fn_reconstr,
02090                                                                       index));
02091                                     cpl_propertylist_update_string(header_data[cube_counter_data],
02092                                                                    "ESO PRO FRNAME",
02093                                                                    fn_reconstr);
02094                                     cpl_propertylist_update_int(header_data[cube_counter_data],
02095                                                                 "ESO PRO IFUNR",
02096                                                                 index);
02097                                     cube_counter_data++;
02098                                 }
02099 
02100                                 // load noise & subheader (if existing)
02101                                 if (desc1.ex_noise) {
02102                                     index = kmo_identify_index(fn_reconstr, ifu_nr, TRUE);
02103                                     KMO_TRY_CHECK_ERROR_STATE();
02104 
02105                                     if (desc1.sub_desc[index-1].valid_data) {
02106                                         KMO_TRY_EXIT_IF_NULL(
02107                                             cube_noise[cube_counter_noise] =
02108                                                 kmclipm_imagelist_load(fn_reconstr,
02109                                                                        CPL_TYPE_FLOAT,
02110                                                                        index));
02111                                         if (edge_nan) {
02112                                             KMO_TRY_EXIT_IF_ERROR(
02113                                                 kmo_edge_nan(cube_noise[cube_counter_noise], ifu_nr));
02114                                         }
02115                                         KMO_TRY_EXIT_IF_NULL(
02116                                             header_noise[cube_counter_noise] =
02117                                                 kmclipm_propertylist_load(fn_reconstr,
02118                                                                           index));
02119                                         cube_counter_noise++;
02120                                     }
02121                                 }
02122                                 cpl_error_reset();
02123                             } // end if found obj
02124                         } // end for ifu_nr
02125 
02126                         cpl_propertylist_delete(tmp_header); tmp_header = NULL;
02127                         tmp_frame = kmo_dfs_get_frame(frameset, NULL);
02128                         KMO_TRY_CHECK_ERROR_STATE();
02129                     } // end while-loop RECONSTRUCTED_CUBE frames
02130 
02131                     if (cube_counter_data > 1) {
02132                         if (cube_counter_data == cube_counter_noise) {
02133                             KMO_TRY_EXIT_IF_ERROR(
02134                                 kmo_priv_combine(cube_data,
02135                                                  cube_noise,
02136                                                  header_data,
02137                                                  header_noise,
02138                                                  cube_counter_data,
02139                                                  cube_counter_noise,
02140                                                  arm_name_struct->names[i],
02141                                                  "",
02142                                                  comb_method,
02143                                                  smethod,
02144                                                  fmethod,
02145                                                  filename,
02146                                                  cmethod,
02147                                                  cpos_rej,
02148                                                  cneg_rej,
02149                                                  citer,
02150                                                  cmin,
02151                                                  cmax,
02152                                                  extrapol_enum,
02153                                                  flux,
02154                                                  &combined_data,
02155                                                  &combined_noise,
02156                                                  &exp_mask));
02157                         } else if (cube_counter_noise == 0) {
02158                             // if imethod == "CS"
02159                             KMO_TRY_EXIT_IF_ERROR(
02160                                 kmo_priv_combine(cube_data,
02161                                                  NULL,
02162                                                  header_data,
02163                                                  header_noise,
02164                                                  cube_counter_data,
02165                                                  cube_counter_noise,
02166                                                  arm_name_struct->names[i],
02167                                                  "",
02168                                                  comb_method,
02169                                                  smethod,
02170                                                  fmethod,
02171                                                  filename,
02172                                                  cmethod,
02173                                                  cpos_rej,
02174                                                  cneg_rej,
02175                                                  citer,
02176                                                  cmin,
02177                                                  cmax,
02178                                                  extrapol_enum,
02179                                                  flux,
02180                                                  &combined_data,
02181                                                  &combined_noise,
02182                                                  &exp_mask));
02183                         } else {
02184                             KMO_TRY_ASSURE(1 == 0,
02185                                            CPL_ERROR_ILLEGAL_INPUT,
02186                                            "The number of cube-data and cube-noise "
02187                                            "isn't the same (%d vs. %d)!",
02188                                            cube_counter_data, cube_counter_noise);
02189                         }
02190                     } else if (cube_counter_data == 1) {
02191                         cpl_msg_warning("", "There is only one reconstructed cube with "
02192                                         "this object! Saving it as it is.");
02193                         KMO_TRY_EXIT_IF_NULL(
02194                             combined_data = cpl_imagelist_duplicate(cube_data[0]));
02195                         KMO_TRY_EXIT_IF_NULL(
02196                             tmpImg = cpl_imagelist_get(combined_data, 0));
02197                         KMO_TRY_EXIT_IF_NULL(
02198                             exp_mask = cpl_image_new(cpl_image_get_size_x(tmpImg),
02199                                                      cpl_image_get_size_y(tmpImg),
02200                                                      CPL_TYPE_FLOAT));
02201                         KMO_TRY_EXIT_IF_ERROR(
02202                             kmo_image_fill(exp_mask, 1.));
02203 
02204                         if (cube_noise[0] != NULL) {
02205                             KMO_TRY_EXIT_IF_NULL(
02206                                 combined_noise = cpl_imagelist_duplicate(cube_noise[0]));
02207                         }
02208                     } else {
02209                         KMO_TRY_ASSURE(1==0,
02210                                        CPL_ERROR_ILLEGAL_INPUT,
02211                                        "No cubes found with this object name!");
02212                     } // end if (cube_counter_data > 1)
02213 
02214                     fn_out = COMBINED_CUBE;
02215                     fn_out_mask = EXP_MASK;
02216                     if (!suppress_extension) {
02217                         char tmp_suffix[1024];
02218                         tmp_suffix[0] = '\0';
02219 
02220                         if (arm_name_struct->telluricCnt[i] == arm_name_struct->namesCnt[i]) {
02221                             strcat(tmp_suffix, "_telluric");
02222                         }
02223                         if (has_illum_corr) {
02224                             strcat(tmp_suffix, "_illum");
02225                         }
02226                         if (sky_tweak) {
02227                             strcat(tmp_suffix, "_skytweak");
02228                         }
02229 
02230                         if (strlen(tmp_suffix) > 0) {
02231                             KMO_TRY_EXIT_IF_NULL(
02232                                 fn_suffix = cpl_sprintf("_%s_%s", arm_name_struct->names[i], tmp_suffix));
02233                         } else {
02234                             KMO_TRY_EXIT_IF_NULL(
02235                                 fn_suffix = cpl_sprintf("_%s", arm_name_struct->names[i]));
02236                         }
02237                     } else {
02238                         KMO_TRY_EXIT_IF_NULL(
02239                             fn_suffix = cpl_sprintf("_%d", suppress_index++));
02240                     }
02241 
02242                     // save combined cube
02243                     KMO_TRY_EXIT_IF_NULL(
02244                         tmp_frame = kmo_dfs_get_frame(frameset, RECONSTRUCTED_CUBE));
02245                     KMO_TRY_EXIT_IF_ERROR(
02246                         kmo_dfs_save_main_header(frameset, fn_out, fn_suffix, tmp_frame, NULL, parlist, cpl_func));
02247                     KMO_TRY_EXIT_IF_ERROR(
02248                         kmo_dfs_save_main_header(frameset, fn_out_mask, fn_suffix, tmp_frame, NULL, parlist, cpl_func));
02249 
02250                     KMO_TRY_EXIT_IF_ERROR(
02251                         kmo_dfs_save_cube(combined_data, fn_out, fn_suffix, header_data[0], 0./0.));
02252                     KMO_TRY_EXIT_IF_ERROR(
02253                         kmo_dfs_save_image(exp_mask, fn_out_mask, fn_suffix, header_data[0], 0./0.));
02254 
02255     //                if (combined_noise != NULL) {
02256                         if (header_noise[0] == NULL) {
02257                             KMO_TRY_EXIT_IF_NULL(
02258                                 header_noise[0] = cpl_propertylist_duplicate(header_data[0]));
02259 
02260                             KMO_TRY_EXIT_IF_NULL(
02261                                 tmp_str = cpl_propertylist_get_string(header_data[0], EXTNAME));
02262                             KMO_TRY_EXIT_IF_ERROR(
02263                                 kmo_extname_extractor(tmp_str, &ft, &tmp_int, content));
02264                             KMO_TRY_EXIT_IF_NULL(
02265                                 extname = kmo_extname_creator(ifu_frame, tmp_int, EXT_NOISE));
02266                             KMO_TRY_EXIT_IF_ERROR(
02267                                 kmclipm_update_property_string(header_noise[0], EXTNAME, extname,
02268                                                                "FITS extension name"));
02269                             cpl_free(extname); extname = NULL;
02270                         }
02271                         KMO_TRY_EXIT_IF_ERROR(
02272                             kmo_dfs_save_cube(combined_noise, fn_out, fn_suffix, header_noise[0], 0./0.));
02273     //                }
02274 
02275                     for (jj = 0; jj < nr_data_alloc; jj++) {
02276                         cpl_imagelist_delete(cube_data[jj]); cube_data[jj] = NULL;
02277                         cpl_imagelist_delete(cube_noise[jj]); cube_noise[jj] = NULL;
02278                         cpl_propertylist_delete(header_data[jj]); header_data[jj] = NULL;
02279                         cpl_propertylist_delete(header_noise[jj]); header_noise[jj] = NULL;
02280                     }
02281                     cpl_free(cube_data);    cube_data = NULL;
02282                     cpl_free(cube_noise);   cube_noise = NULL;
02283                     cpl_free(header_data);  header_data = NULL;
02284                     cpl_free(header_noise); header_noise = NULL;
02285                     cpl_free(fn_suffix); fn_suffix = NULL;
02286                     cpl_imagelist_delete(combined_data); combined_data = NULL;
02287                     cpl_imagelist_delete(combined_noise); combined_noise = NULL;
02288                     cpl_image_delete(exp_mask); exp_mask = NULL;
02289                 } // for i = nr_avail_obj_names
02290             } else {
02291                 // we are in mapping_mode
02292                 nr_data_alloc = nr_reconstructed_frames*KMOS_NR_IFUS;
02293                 KMO_TRY_EXIT_IF_NULL(
02294                     cube_data = (cpl_imagelist**)cpl_calloc(nr_data_alloc, sizeof(cpl_imagelist*)));
02295                 KMO_TRY_EXIT_IF_NULL(
02296                     cube_noise = (cpl_imagelist**)cpl_calloc(nr_data_alloc, sizeof(cpl_imagelist*)));
02297                 KMO_TRY_EXIT_IF_NULL(
02298                     header_data = (cpl_propertylist**)cpl_calloc(nr_data_alloc, sizeof(cpl_propertylist*)));
02299                 KMO_TRY_EXIT_IF_NULL(
02300                     header_noise = (cpl_propertylist**)cpl_calloc(nr_data_alloc, sizeof(cpl_propertylist*)));
02301 
02302                 cube_counter_data = 0;
02303                 cube_counter_noise = 0;
02304                 KMO_TRY_EXIT_IF_NULL(
02305                     tmp_frame = kmo_dfs_get_frame(frameset, RECONSTRUCTED_CUBE));
02306                 while (tmp_frame != NULL ) {
02307                     KMO_TRY_EXIT_IF_NULL(
02308                         fn_reconstr = cpl_frame_get_filename(tmp_frame));
02309 
02310                     KMO_TRY_EXIT_IF_NULL(
02311                         tmp_header = kmclipm_propertylist_load(fn_reconstr, 0));
02312 
02313                     kmo_free_fits_desc(&desc1);
02314                     kmo_init_fits_desc(&desc1);
02315                     desc1 = kmo_identify_fits_header(fn_reconstr);
02316                     for (ifu_nr = 1; ifu_nr <= KMOS_NR_IFUS; ifu_nr++) {
02317                         index = kmo_identify_index(fn_reconstr, ifu_nr, FALSE);
02318                         KMO_TRY_CHECK_ERROR_STATE();
02319 
02320                         if (desc1.sub_desc[index-1].valid_data) {
02321                             KMO_TRY_EXIT_IF_NULL(
02322                                 cube_data[cube_counter_data] =
02323                                     kmclipm_imagelist_load(fn_reconstr, CPL_TYPE_FLOAT, index));
02324                             if (edge_nan) {
02325                                 KMO_TRY_EXIT_IF_ERROR(
02326                                     kmo_edge_nan(cube_data[cube_counter_data], ifu_nr));
02327                             }
02328 
02329                             if (fast_mode) {
02330                                 KMO_TRY_EXIT_IF_NULL(
02331                                     tmpImg = cpl_imagelist_collapse_median_create(cube_data[cube_counter_data]));
02332                                 KMO_TRY_EXIT_IF_NULL(
02333                                     tmpCube = cpl_imagelist_new());
02334                                 KMO_TRY_EXIT_IF_ERROR(
02335                                     cpl_imagelist_set(tmpCube, tmpImg, 0));
02336                                 cpl_imagelist_delete(cube_data[cube_counter_data]);
02337                                 cube_data[cube_counter_data] = tmpCube;
02338                             }
02339 
02340                             KMO_TRY_EXIT_IF_NULL(
02341                                 header_data[cube_counter_data] =
02342                                     kmclipm_propertylist_load(fn_reconstr, index));
02343                             cpl_propertylist_update_string(header_data[cube_counter_data], "ESO PRO FRNAME", fn_reconstr);
02344                             cpl_propertylist_update_int(header_data[cube_counter_data], "ESO PRO IFUNR", index);
02345                             cube_counter_data++;
02346                         }
02347 
02348                         // load noise & subheader (if existing)
02349                         if (desc1.ex_noise) {
02350                             index = kmo_identify_index(fn_reconstr, ifu_nr, TRUE);
02351                             KMO_TRY_CHECK_ERROR_STATE();
02352                             if (desc1.sub_desc[index-1].valid_data) {
02353                                 KMO_TRY_EXIT_IF_NULL(
02354                                     cube_noise[cube_counter_noise] =
02355                                         kmclipm_imagelist_load(fn_reconstr, CPL_TYPE_FLOAT, index));
02356 
02357                                 if (edge_nan) {
02358                                     KMO_TRY_EXIT_IF_ERROR(
02359                                         kmo_edge_nan(cube_noise[cube_counter_noise], ifu_nr));
02360                                 }
02361 
02362                                 if (fast_mode) {
02363                                     KMO_TRY_EXIT_IF_NULL(
02364                                         tmpImg = cpl_imagelist_collapse_median_create(cube_noise[cube_counter_noise]));
02365                                     KMO_TRY_EXIT_IF_NULL(
02366                                         tmpCube = cpl_imagelist_new());
02367                                     KMO_TRY_EXIT_IF_ERROR(
02368                                         cpl_imagelist_set(tmpCube, tmpImg, 0));
02369                                     cpl_imagelist_delete(cube_noise[cube_counter_noise]);
02370                                     cube_noise[cube_counter_noise] = tmpCube;
02371                                 }
02372                                 KMO_TRY_EXIT_IF_NULL(
02373                                     header_noise[cube_counter_noise] = kmclipm_propertylist_load(fn_reconstr, index));
02374                                 cube_counter_noise++;
02375                             }
02376                         }
02377                         cpl_error_reset();
02378                     } // end for ifu_nr
02379 
02380                     cpl_propertylist_delete(tmp_header); tmp_header = NULL;
02381                     tmp_frame = kmo_dfs_get_frame(frameset, NULL);
02382                     KMO_TRY_CHECK_ERROR_STATE();
02383                 } // end while-loop RECONSTRUCTED_CUBE frames
02384 
02385                 if (cube_counter_data > 1) {
02386                     if (cube_counter_data == cube_counter_noise) {
02387                         KMO_TRY_EXIT_IF_ERROR(
02388                             kmo_priv_combine(cube_data,
02389                                              cube_noise,
02390                                              header_data,
02391                                              header_noise,
02392                                              cube_counter_data,
02393                                              cube_counter_noise,
02394                                              mapping_mode,
02395                                              "",
02396                                              comb_method,
02397                                              smethod,
02398                                              fmethod,
02399                                              filename,
02400                                              cmethod,
02401                                              cpos_rej,
02402                                              cneg_rej,
02403                                              citer,
02404                                              cmin,
02405                                              cmax,
02406                                              extrapol_enum,
02407                                              flux,
02408                                              &combined_data,
02409                                              &combined_noise,
02410                                              NULL));
02411                     } else if (cube_counter_noise == 0) {
02412                         // if imethod == "CS"
02413                         KMO_TRY_EXIT_IF_ERROR(
02414                             kmo_priv_combine(cube_data,
02415                                              NULL,
02416                                              header_data,
02417                                              header_noise,
02418                                              cube_counter_data,
02419                                              cube_counter_noise,
02420                                              mapping_mode,
02421                                              "",
02422                                              comb_method,
02423                                              smethod,
02424                                              fmethod,
02425                                              filename,
02426                                              cmethod,
02427                                              cpos_rej,
02428                                              cneg_rej,
02429                                              citer,
02430                                              cmin,
02431                                              cmax,
02432                                              extrapol_enum,
02433                                              flux,
02434                                              &combined_data,
02435                                              &combined_noise,
02436                                              NULL));
02437                     } else {
02438                         KMO_TRY_ASSURE(1 == 0,
02439                                        CPL_ERROR_ILLEGAL_INPUT,
02440                                        "The number of cube-data and cube-noise "
02441                                        "isn't the same (%d vs. %d)!",
02442                                        cube_counter_data, cube_counter_noise);
02443                     }
02444                 } else {
02445                     cpl_msg_warning("", "There is only one reconstructed cube! "
02446                                         "Saving it as it is.");
02447                     KMO_TRY_EXIT_IF_NULL(
02448                         combined_data = cpl_imagelist_duplicate(cube_data[0]));
02449 
02450                     if (cube_noise[0] != NULL) {
02451                         KMO_TRY_EXIT_IF_NULL(
02452                             combined_noise = cpl_imagelist_duplicate(cube_noise[0]));
02453                     }
02454                 }
02455 
02456                 fn_out = COMBINED_CUBE;
02457                 KMO_TRY_EXIT_IF_NULL(
02458                     fn_suffix = cpl_sprintf("_%s", mapping_mode));
02459 
02460                 // save combined cube
02461                 KMO_TRY_EXIT_IF_NULL(
02462                     tmp_frame = kmo_dfs_get_frame(frameset, RECONSTRUCTED_CUBE));
02463                 KMO_TRY_EXIT_IF_ERROR(
02464                     kmo_dfs_save_main_header(frameset, fn_out, fn_suffix, tmp_frame,
02465                                              NULL, parlist, cpl_func));
02466 
02467                 KMO_TRY_EXIT_IF_ERROR(
02468                     kmo_dfs_save_cube(combined_data, fn_out, fn_suffix, header_data[0], 0./0.));
02469 
02470     //            if (combined_noise != NULL) {
02471                     if (header_noise[0] == NULL) {
02472                         KMO_TRY_EXIT_IF_NULL(
02473                             header_noise[0] =
02474                                  cpl_propertylist_duplicate(header_data[0]));
02475 
02476                         KMO_TRY_EXIT_IF_NULL(
02477                             tmp_str = cpl_propertylist_get_string(header_data[0], EXTNAME));
02478                         KMO_TRY_EXIT_IF_ERROR(
02479                             kmo_extname_extractor(tmp_str, &ft, &tmp_int, content));
02480                         KMO_TRY_EXIT_IF_NULL(
02481                             extname = kmo_extname_creator(ifu_frame, tmp_int, EXT_NOISE));
02482                         KMO_TRY_EXIT_IF_ERROR(
02483                             kmclipm_update_property_string(header_noise[0], EXTNAME, extname,
02484                                                            "FITS extension name"));
02485                         cpl_free(extname); extname = NULL;
02486                     }
02487                     KMO_TRY_EXIT_IF_ERROR(
02488                         kmo_dfs_save_cube(combined_noise, fn_out, fn_suffix, header_noise[0], 0./0.));
02489     //            }
02490 
02491                 for (i = 0; i < nr_data_alloc; i++) {
02492                     cpl_imagelist_delete(cube_data[i]); cube_data[i] = NULL;
02493                     cpl_imagelist_delete(cube_noise[i]); cube_noise[i] = NULL;
02494                     cpl_propertylist_delete(header_data[i]); header_data[i] = NULL;
02495                     cpl_propertylist_delete(header_noise[i]); header_noise[i] = NULL;
02496                 }
02497                 cpl_free(cube_data);    cube_data = NULL;
02498                 cpl_free(cube_noise);   cube_noise = NULL;
02499                 cpl_free(header_data);  header_data = NULL;
02500                 cpl_free(header_noise); header_noise = NULL;
02501                 cpl_free(fn_suffix); fn_suffix = NULL;
02502                 cpl_imagelist_delete(combined_data); combined_data = NULL;
02503                 cpl_imagelist_delete(combined_noise); combined_noise = NULL;
02504             } // if mapping_mode
02505         } else {
02506             cpl_msg_info("", "NOT combining reconstructed objects (--no_combine is set)");
02507         } // if (!no_combine)
02508 
02509         cpl_msg_info("", "-------------------------------------------");
02510     }
02511     KMO_CATCH
02512     {
02513         KMO_CATCH_MSG();
02514         ret_val = -1;
02515     }
02516 
02517     if (cube_data != NULL) {
02518         for (ifu_nr = 1; ifu_nr <= nr_data_alloc; ifu_nr++) {
02519             cpl_imagelist_delete(cube_data[ifu_nr-1]); cube_data[ifu_nr-1] = NULL;
02520         }
02521     }
02522     cpl_free(cube_data);    cube_data = NULL;
02523     if (cube_noise != NULL) {
02524         for (ifu_nr = 1; ifu_nr <= nr_data_alloc; ifu_nr++) {
02525             cpl_imagelist_delete(cube_noise[ifu_nr-1]); cube_noise[ifu_nr-1] = NULL;
02526         }
02527     }
02528     cpl_free(cube_noise);   cube_noise = NULL;
02529     if (header_data != NULL) {
02530         for (ifu_nr = 1; ifu_nr <= nr_data_alloc; ifu_nr++) {
02531             cpl_propertylist_delete(header_data[ifu_nr-1]); header_data[ifu_nr-1] = NULL;
02532         }
02533     }
02534     cpl_free(header_data);  header_data = NULL;
02535     if (header_noise != NULL) {
02536         for (ifu_nr = 1; ifu_nr <= nr_data_alloc; ifu_nr++) {
02537             cpl_propertylist_delete(header_noise[ifu_nr-1]); header_noise[ifu_nr-1] = NULL;
02538         }
02539     }
02540     cpl_free(header_noise); header_noise = NULL;
02541 
02542 
02543     kmo_free_fits_desc(&desc1);
02544     kmo_free_fits_desc(&desc2);
02545     kmo_free_fits_desc(&desc_telluric);
02546 
02547     cpl_vector_delete(ifus); ifus = NULL;
02548     cpl_free(mapping_mode); mapping_mode = NULL;
02549     if (unused_ifus_before != NULL) {
02550         kmo_free_unused_ifus(unused_ifus_before); unused_ifus_before = NULL;
02551     }
02552     if (unused_ifus_after != NULL) {
02553         kmo_free_unused_ifus(unused_ifus_after); unused_ifus_after = NULL;
02554     }
02555     if (bounds != NULL) {
02556         cpl_free(bounds); bounds = NULL;
02557     }
02558 
02559     // frees for the case of errors
02560     kmclipm_vector_delete(telluric_data); telluric_data = NULL;
02561     kmclipm_vector_delete(telluric_noise); telluric_noise = NULL;
02562     cpl_image_delete(illum_data); illum_data = NULL;
02563     cpl_image_delete(illum_noise); illum_noise = NULL;
02564     cpl_propertylist_delete(tmp_header); tmp_header = NULL;
02565     cpl_table_delete(band_table); band_table = NULL;
02566     cpl_propertylist_delete(main_header); main_header = NULL;
02567     if (lcal != NULL) {
02568         for (i = 0; i < KMOS_NR_DETECTORS; i++) {
02569             cpl_image_delete(lcal[i]);
02570         }
02571     }
02572     cpl_free(lcal); lcal = NULL;
02573     cpl_free(fn_suffix); fn_suffix = NULL;
02574     cpl_free(suffix); suffix = NULL;
02575 
02576     kmo_delete_armNameStruct(arm_name_struct);
02577 
02578     return ret_val;
02579 }
02580