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