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