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