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