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