KMOS Pipeline Reference Manual  1.1.3
kmo_sci_red.c
00001 /* $Id: kmo_sci_red.c,v 1.58 2013/05/13 13:20:27 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/13 13:20:27 $
00024  * $Revision: 1.58 $
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                                                          no_subtract));
01189         //
01190         // load lcal-frames
01191         //
01192         KMO_TRY_EXIT_IF_NULL(
01193             lcal = (cpl_image**)
01194                    cpl_calloc(KMOS_NR_DETECTORS, sizeof(cpl_image*)));
01195         for (int i = 0; i < KMOS_NR_DETECTORS; i++) {
01196             KMO_TRY_EXIT_IF_NULL(
01197                 lcal[i] = kmo_dfs_load_image(frameset, LCAL, i+1, FALSE, FALSE, NULL));
01198         }
01199 
01200         //
01201         // allocate intermediate memory
01202         //
01203         KMO_TRY_EXIT_IF_NULL(
01204             all_obj = (allObjStruct*)cpl_calloc(nr_science_frames * KMOS_NR_IFUS, sizeof(allObjStruct)));
01205 
01206         // initialize intermediate memory
01207         for (int i = 0; i < nr_science_frames * KMOS_NR_IFUS; i++) {
01208             all_obj[i].name = NULL;
01209             all_obj[i].count = 0;
01210         }
01211 
01212         nr_data_alloc = KMOS_NR_IFUS;
01213         KMO_TRY_EXIT_IF_NULL(
01214             cube_data =  (cpl_imagelist**)cpl_calloc(nr_data_alloc,
01215                                                      sizeof(cpl_imagelist*)));
01216         KMO_TRY_EXIT_IF_NULL(
01217             cube_noise = (cpl_imagelist**)cpl_calloc(nr_data_alloc,
01218                                                      sizeof(cpl_imagelist*)));
01219         KMO_TRY_EXIT_IF_NULL(
01220             header_data =  (cpl_propertylist**)cpl_calloc(nr_data_alloc,
01221                                                      sizeof(cpl_propertylist*)));
01222         KMO_TRY_EXIT_IF_NULL(
01223             header_noise = (cpl_propertylist**)cpl_calloc(nr_data_alloc,
01224                                                      sizeof(cpl_propertylist*)));
01225 
01226         if (cpl_frameset_count_tags(frameset, SCIENCE) == 1) {
01227             no_combine = TRUE;
01228             cpl_msg_info("", "--no_combine has been set to TRUE since there is only one SCIENCE frame!");
01229         }
01230 
01231         if (no_subtract) {
01232             no_combine = TRUE;
01233             cpl_msg_info("", "--no_combine has been set to TRUE since --no_subtract has been specified by the user!");
01234             cpl_msg_info("", "Combining cubes would combine skies and obejcts which is meaningless.");
01235             cpl_msg_info("", "This can be done manually with the recipe kmo_combine afterwards!");
01236         }
01237 
01238         //
01239         // loop all science frames containing at least one object
01240         //
01241         cpl_msg_info("", "-------------------------------------------");
01242         cpl_msg_info("", "Reconstructing & saving cubes containing objects");
01243         cpl_msg_info("", " ");
01244         for (int sf = 0; sf < nr_science_frames; sf++) {
01245             KMO_TRY_EXIT_IF_NULL(
01246                 fn_obj = cpl_frame_get_filename(
01247                                                obj_sky_struct[sf].objectFrame));
01248 
01249             KMO_TRY_EXIT_IF_NULL(
01250                 main_header = kmclipm_propertylist_load(fn_obj, 0));
01251 
01252             // get ifu and detector number to work at
01253             actual_msg_level = cpl_msg_get_level();
01254             user_defined_ifu = 0;
01255             if ((ifus != NULL) || (strcmp(name, "") != 0)) {
01256                 if (ifus != NULL) {
01257                     // user specified IFUs
01258                     user_defined_ifu = cpl_vector_get(ifus, sf);
01259                     KMO_TRY_CHECK_ERROR_STATE();
01260 
01261                     if (user_defined_ifu < 1) {
01262                         user_defined_ifu = -1;
01263                     }
01264                 } else {
01265                     // user specified an object name
01266                     cpl_msg_set_level(CPL_MSG_OFF);
01267                     user_defined_ifu =
01268                         kmo_get_index_from_ocs_name(obj_sky_struct[sf].objectFrame,
01269                                                     name);
01270                     cpl_msg_set_level(actual_msg_level);
01271                     if (user_defined_ifu == -1) {
01272                         cpl_error_reset();
01273                     }
01274                     KMO_TRY_CHECK_ERROR_STATE();
01275                 }
01276             }
01277 
01278             //
01279             // reconstruct science frame
01280             //
01281             cpl_msg_info("", "   > processing frame: %s", fn_obj);
01282             for (int ifu_nr = 1; ifu_nr <= KMOS_NR_IFUS; ifu_nr++)
01283             {
01284                 det_nr = (ifu_nr - 1)/KMOS_IFUS_PER_DETECTOR + 1;
01285 
01286                 KMO_TRY_ASSURE((det_nr >= 1) &&
01287                                (det_nr <= KMOS_NR_DETECTORS),
01288                                CPL_ERROR_ILLEGAL_INPUT,
01289                                "The provided ifu-numbers are incorrect! They "
01290                                "must be between 1 and %d", KMOS_NR_IFUS);
01291 
01292                 KMO_TRY_EXIT_IF_NULL(
01293                     punused_ifus = cpl_array_get_data_int_const(
01294                                               unused_ifus[det_nr-1]));
01295 
01296                 // get subheader data
01297                 KMO_TRY_EXIT_IF_NULL(
01298                     header_data[ifu_nr-1] = kmclipm_propertylist_load(fn_obj,
01299                                                                       det_nr));
01300                 KMO_TRY_EXIT_IF_NULL(
01301                     extname = kmo_extname_creator(ifu_frame, ifu_nr,
01302                                                   EXT_DATA));
01303                 KMO_TRY_EXIT_IF_ERROR(
01304                     kmclipm_update_property_string(header_data[ifu_nr-1],
01305                                                    EXTNAME, extname,
01306                                                    "FITS extension name"));
01307                 cpl_free(extname); extname = NULL;
01308 
01309                 // Search for keyword ESO OCS ARMi NOTUSED
01310                 // If not present (CPL_ERROR_DATA_NOT_FOUND), do nothing
01311                 KMO_TRY_EXIT_IF_NULL(
01312                     keyword = cpl_sprintf("%s%d%s", IFU_VALID_PREFIX, ifu_nr,
01313                                           IFU_VALID_POSTFIX));
01314                     tmp_str = cpl_propertylist_get_string(main_header, keyword);
01315                 cpl_free(keyword); keyword = NULL;
01316 
01317                 if ((cpl_error_get_code() == CPL_ERROR_DATA_NOT_FOUND) &&
01318                     (bounds[2*(ifu_nr-1)] != -1) &&
01319                     (bounds[2*(ifu_nr-1)+1] != -1) &&
01320                     ((obj_sky_struct[sf].skyframes[ifu_nr-1] != NULL) || (cpl_frameset_count_tags(frameset, SCIENCE) == 1) || no_subtract) &&
01321                     (punused_ifus[(ifu_nr-1) % KMOS_IFUS_PER_DETECTOR] == 0) &&
01322                     ((user_defined_ifu == 0) || (user_defined_ifu == ifu_nr)))
01323                 {
01324                     // IFU is valid
01325                     cpl_error_reset();
01326 
01327                     if ((obj_sky_struct[sf].skyframes[ifu_nr-1] != NO_CORRESPONDING_SKYFRAME) &&
01328                         (cpl_frameset_count_tags(frameset, SCIENCE) != 1) &&
01329                         !no_subtract)
01330                     {
01331                         if (no_subtract) {
01332                             sky_frame = NULL;
01333                             cpl_msg_warning("", "      > Omit sky subtraction on IFU %d", ifu_nr);
01334                         } else {
01335                             sky_frame = obj_sky_struct[sf].skyframes[ifu_nr-1];
01336                             KMO_TRY_EXIT_IF_NULL(
01337                                 fn_sky = cpl_frame_get_filename(sky_frame));
01338                             cpl_msg_info("", "      > IFU %d (with sky in frame: %s)", ifu_nr, fn_sky);
01339                         }
01340                     } else {
01341                         sky_frame = NULL;
01342                         if ((cpl_frameset_count_tags(frameset, SCIENCE) != 1) && (!no_subtract)) {
01343                             cpl_msg_warning("", "      > IFU %d with no corresponding sky frame", ifu_nr);
01344                         }
01345                     }
01346 
01347                     // get filter for this detector and setup grid definition
01348                     // ESO INS FILTi ID
01349                     char *tmp_band_method = getenv("KMO_BAND_METHOD");
01350                     int band_method = 0;
01351                     if (tmp_band_method != NULL) {
01352                         band_method = atoi(tmp_band_method);
01353                     }
01354 
01355                     KMO_TRY_EXIT_IF_NULL(
01356                         keyword = cpl_sprintf("%s%d%s",
01357                                               IFU_FILTID_PREFIX, det_nr,
01358                                               IFU_FILTID_POSTFIX));
01359                     KMO_TRY_EXIT_IF_NULL(
01360                         filter_id = cpl_propertylist_get_string(main_header,
01361                                                                 keyword));
01362                     cpl_free(keyword); keyword = NULL;
01363 
01364                     if (print_once) {
01365                         cpl_msg_set_level(CPL_MSG_WARNING);
01366                     }
01367 
01368                     KMO_TRY_EXIT_IF_NULL(
01369                         band_table = kmo_dfs_load_table(frameset, WAVE_BAND,
01370                                                         1, 0));
01371                     KMO_TRY_EXIT_IF_ERROR(
01372                         kmclipm_setup_grid_band_lcal(&gd, lcal[det_nr-1],
01373                                                      filter_id, band_method,
01374                                                      band_table));
01375                     cpl_table_delete(band_table); band_table = NULL;
01376 
01377                     print_once = TRUE;
01378                     cpl_msg_set_level(actual_msg_level);
01379 
01380                     //
01381                     // reconstruct
01382                     //
01383                     KMO_TRY_EXIT_IF_ERROR(
01384                         kmo_reconstruct_sci(ifu_nr,
01385                                         bounds[2*(ifu_nr-1)],
01386                                         bounds[2*(ifu_nr-1)+1],
01387                                         obj_sky_struct[sf].objectFrame,
01388                                         SCIENCE,
01389                                         sky_frame,
01390                                         SCIENCE,
01391                                         flat_frame,
01392                                         xcal_frame,
01393                                         ycal_frame,
01394                                         lcal_frame,
01395                                         NULL,
01396                                         &gd,
01397                                         &cube_data[ifu_nr-1],
01398                                         &cube_noise[ifu_nr-1],
01399                                         flux,
01400                                         background));
01401 
01402                     // scale flux according to pixel_scale
01403                     KMO_TRY_EXIT_IF_NULL(
01404                         tmpImg = cpl_imagelist_get(cube_data[ifu_nr-1], 0));
01405                     double scaling = (cpl_image_get_size_x(tmpImg)*cpl_image_get_size_y(tmpImg)) /
01406                                      (KMOS_SLITLET_X*KMOS_SLITLET_Y);
01407                     KMO_TRY_EXIT_IF_ERROR(
01408                         cpl_imagelist_divide_scalar(cube_data[ifu_nr-1], scaling));
01409                     if (cube_noise[ifu_nr-1] != NULL) {
01410                         KMO_TRY_EXIT_IF_ERROR(
01411                             cpl_imagelist_divide_scalar(cube_noise[ifu_nr-1], scaling));
01412                     }
01413 
01414                     //
01415                     // divide cube by telluric correction
01416                     //
01417                     if (has_telluric) {
01418                         telluric_data = kmo_tweak_load_telluric(frameset, ifu_nr, FALSE,
01419                                                                 cube_noise[ifu_nr-1] != NULL);
01420                         KMO_TRY_CHECK_ERROR_STATE();
01421                         if (telluric_data != NULL) {
01422                             // load noise if present
01423                             telluric_noise = kmo_tweak_load_telluric(frameset, ifu_nr, TRUE,
01424                                                                      cube_noise[ifu_nr-1] != NULL);
01425                             KMO_TRY_CHECK_ERROR_STATE();
01426 
01427                             KMO_TRY_EXIT_IF_ERROR(
01428                                 kmo_arithmetic_3D_1D(
01429                                         cube_data[ifu_nr-1], telluric_data,
01430                                         cube_noise[ifu_nr-1], telluric_noise, "/"));
01431 
01432                             kmclipm_vector_delete(telluric_data);
01433                             telluric_data = NULL;
01434                             kmclipm_vector_delete(telluric_noise);
01435                             telluric_noise = NULL;
01436                         }
01437                     }
01438 
01439                     //
01440                     // divide cube by illumination correction
01441                     //
01442                     if (has_illum_corr) {
01443                         cpl_msg_set_level(CPL_MSG_OFF);
01444                         illum_data = kmo_dfs_load_image(frameset, ILLUM_CORR,
01445                                                         ifu_nr, FALSE, FALSE, NULL);
01446                         cpl_msg_set_level(actual_msg_level);
01447                         if (cpl_error_get_code() != CPL_ERROR_NONE) {
01448                             cpl_msg_warning("","No illumination correction for IFU %d available! "
01449                                             "Proceeding anyway.", ifu_nr);
01450                             cpl_error_reset();
01451                         } else {
01452                             cpl_msg_set_level(CPL_MSG_OFF);
01453                             illum_noise = kmo_dfs_load_image(frameset,
01454                                                              ILLUM_CORR,
01455                                                              ifu_nr, TRUE,
01456                                                              FALSE, NULL);
01457                             cpl_msg_set_level(actual_msg_level);
01458                             if (cpl_error_get_code() != CPL_ERROR_NONE) {
01459                                 cpl_msg_warning("","No illumination correction for IFU %d "
01460                                                 "available! Proceeding anyway.", ifu_nr);
01461                                 cpl_image_delete(illum_data); illum_data = NULL;
01462                                 cpl_error_reset();
01463                             }
01464                         }
01465 
01466                         if (illum_data != NULL) {
01467                             KMO_TRY_EXIT_IF_ERROR(
01468                                 kmo_arithmetic_3D_2D(
01469                                             cube_data[ifu_nr-1], illum_data,
01470                                             cube_noise[ifu_nr-1], illum_noise, "/"));
01471                             cpl_image_delete(illum_data); illum_data = NULL;
01472                             cpl_image_delete(illum_noise); illum_noise = NULL;
01473                         }
01474                     }
01475 
01476                     //
01477                     // calc WCS & update subheader
01478                     //
01479                     KMO_TRY_EXIT_IF_ERROR(
01480                         kmo_calc_wcs_gd(main_header, header_data[ifu_nr-1], ifu_nr, gd));
01481 
01482                     KMO_TRY_EXIT_IF_ERROR(
01483                         kmclipm_update_property_int(header_data[ifu_nr-1],
01484                                                     NAXIS, 3,
01485                                                     "number of data axes"));
01486                     KMO_TRY_EXIT_IF_ERROR(
01487                         kmclipm_update_property_int(header_data[ifu_nr-1],
01488                                                     NAXIS1, gd.x.dim,
01489                                                     "length of data axis 1"));
01490                     KMO_TRY_EXIT_IF_ERROR(
01491                         kmclipm_update_property_int(header_data[ifu_nr-1],
01492                                                     NAXIS2, gd.y.dim,
01493                                                     "length of data axis 2"));
01494                     KMO_TRY_EXIT_IF_ERROR(
01495                         kmclipm_update_property_int(header_data[ifu_nr-1],
01496                                                     NAXIS3, gd.l.dim,
01497                                                     "length of data axis 3"));
01498 
01499                     // get object name and store if not already present
01500                     KMO_TRY_EXIT_IF_NULL(
01501                         keyword = cpl_sprintf("%s%d%s", IFU_NAME_PREFIX, ifu_nr,
01502                                               IFU_NAME_POSTFIX));
01503                     KMO_TRY_EXIT_IF_NULL(
01504                         tmp_str = cpl_propertylist_get_string(header_data[ifu_nr-1],
01505                                                               keyword));
01506                     cpl_free(keyword); keyword = NULL;
01507 
01508                     // found keyword, check if it is already in all_obj
01509                     found_name = 0;
01510                     for(int i = 0; i < nr_avail_obj_names; i++) {
01511                         if (strcmp(all_obj[i].name, tmp_str) == 0) {
01512                             found_name = TRUE;
01513                             all_obj[i].count++;
01514                             break;
01515                         }
01516                     }
01517                     if (!found_name) {
01518                         all_obj[nr_avail_obj_names].count++;
01519                         KMO_TRY_EXIT_IF_NULL(
01520                             all_obj[nr_avail_obj_names++].name =
01521                                                     cpl_sprintf("%s", tmp_str));
01522                     }
01523                 } else {
01524                     cpl_error_reset();
01525 
01526                     // IFU is invalid
01527                 }
01528 
01529                 // duplicate subheader data
01530                 KMO_TRY_EXIT_IF_NULL(
01531                     header_noise[ifu_nr-1] =
01532                          cpl_propertylist_duplicate(header_data[ifu_nr-1]));
01533 
01534                 KMO_TRY_EXIT_IF_NULL(
01535                     extname = kmo_extname_creator(ifu_frame, ifu_nr, EXT_NOISE));
01536                 KMO_TRY_EXIT_IF_ERROR(
01537                     kmclipm_update_property_string(header_noise[ifu_nr-1],
01538                                                    EXTNAME, extname,
01539                                                    "FITS extension name"));
01540                 cpl_free(extname); extname = NULL;
01541             } // end for ifu_nr
01542 
01543             //
01544             // count number of reconstructed data- and noise-cubes
01545             //
01546             for (int ifu_nr = 1; ifu_nr <= nr_data_alloc; ifu_nr++) {
01547                 if (cube_data[ifu_nr-1] != NULL) {
01548                     cube_counter_data++;
01549                 }
01550                 if (cube_noise[ifu_nr-1] != NULL) {
01551                     cube_counter_noise++;
01552                 }
01553             }
01554 
01555             //
01556             // save reconstructed cubes of science frame
01557             //
01558             if (cube_counter_data > 0) {
01559                 cpl_msg_info("", "   > saving...");
01560 
01561                 fn_out = fn_obj;
01562 
01563                 int nr_found = 0;
01564                 // remove any path-elements from filename and use it as
01565                 // suffix
01566                 split = kmo_strsplit(fn_out, "/", &nr_found);
01567 
01568                 fn_suffix = cpl_sprintf("_%s", split[nr_found-1]);
01569                 kmo_strfreev(split);
01570 
01571                 // remove '.fits' at the end if there is any
01572                 char *fff = fn_suffix;
01573                 fff += strlen(fn_suffix)-5;
01574                 if (strcmp(fff, ".fits") == 0) {
01575                     fn_suffix[strlen(fn_suffix)-5] = '\0';
01576                 }
01577 
01578                 fn_out = RECONSTRUCTED_CUBE;
01579 
01580                 KMO_TRY_EXIT_IF_ERROR(
01581                     kmo_dfs_save_main_header(frameset, fn_out, fn_suffix,
01582                                              obj_sky_struct[sf].objectFrame,
01583                                              NULL, parlist, cpl_func));
01584 
01585                 for (int ifu_nr = 1; ifu_nr <= KMOS_NR_IFUS; ifu_nr++) {
01586                     KMO_TRY_EXIT_IF_ERROR(
01587                         kmo_dfs_save_cube(cube_data[ifu_nr-1], fn_out,
01588                                           fn_suffix, header_data[ifu_nr-1], 0./0.));
01589 
01590                     if (cube_counter_noise > 0) {
01591                         KMO_TRY_EXIT_IF_ERROR(
01592                             kmo_dfs_save_cube(cube_noise[ifu_nr-1], fn_out,
01593                                               fn_suffix, header_noise[ifu_nr-1],
01594                                               0./0.));
01595                     }
01596 
01597                     cpl_imagelist_delete(cube_data[ifu_nr-1]); cube_data[ifu_nr-1] = NULL;
01598                     cpl_imagelist_delete(cube_noise[ifu_nr-1]); cube_noise[ifu_nr-1] = NULL;
01599                     cpl_propertylist_delete(header_data[ifu_nr-1]); header_data[ifu_nr-1] = NULL;
01600                     cpl_propertylist_delete(header_noise[ifu_nr-1]); header_noise[ifu_nr-1] = NULL;
01601                 } // end for ifu_nr
01602                 cpl_free(fn_suffix); fn_suffix = NULL;
01603             } else {
01604                 cpl_msg_info("", "   > all IFUs invalid, don't save");
01605             } // if (cube_counter_data > 0) {
01606 
01607             cpl_propertylist_delete(main_header); main_header = NULL;
01608         } // end for sf (nr_science_frames)
01609         cpl_free(cube_data);    cube_data = NULL;
01610         cpl_free(cube_noise);    cube_noise = NULL;
01611         cpl_free(header_data);    header_data = NULL;
01612         cpl_free(header_noise);    header_noise = NULL;
01613         cpl_msg_info("", "-------------------------------------------");
01614 
01615         if (lcal != NULL) {
01616             for (int i = 0; i < KMOS_NR_DETECTORS; i++) {
01617                 cpl_image_delete(lcal[i]);
01618             }
01619         }
01620         cpl_free(lcal); lcal = NULL;
01621 
01622         //
01623         // combine
01624         //
01625         if (!no_combine) {
01626             cpl_msg_info("", "Combining reconstructed objects");
01627             cpl_msg_info("", " ");
01628 
01629             nr_reconstructed_frames = cpl_frameset_count_tags(frameset, RECONSTRUCTED_CUBE);
01630 
01631             if ( (mapping_mode == NULL) || ((mapping_mode != NULL) &&
01632                                             ((ifus != NULL) || (strcmp(name, "") != 0)))
01633                )
01634             {
01635                 // loop all available objects
01636                 for (int i = 0; i < nr_avail_obj_names; i++) {
01637                     cpl_msg_info("", "   > object: %s", all_obj[i].name);
01638                     nr_data_alloc = all_obj[i].count;
01639                     KMO_TRY_EXIT_IF_NULL(
01640                         cube_data =  (cpl_imagelist**)cpl_calloc(nr_data_alloc,
01641                                                            sizeof(cpl_imagelist*)));
01642                     KMO_TRY_EXIT_IF_NULL(
01643                         cube_noise = (cpl_imagelist**)cpl_calloc(nr_data_alloc,
01644                                                            sizeof(cpl_imagelist*)));
01645                     KMO_TRY_EXIT_IF_NULL(
01646                         header_data =  (cpl_propertylist**)cpl_calloc(nr_data_alloc,
01647                                                         sizeof(cpl_propertylist*)));
01648                     KMO_TRY_EXIT_IF_NULL(
01649                         header_noise = (cpl_propertylist**)cpl_calloc(nr_data_alloc,
01650                                                         sizeof(cpl_propertylist*)));
01651 
01652                     // setup cube-list and header-list for kmo_priv_combine()
01653                     cube_counter_data = 0;
01654                     cube_counter_noise = 0;
01655                     KMO_TRY_EXIT_IF_NULL(
01656                         tmp_frame = kmo_dfs_get_frame(frameset, RECONSTRUCTED_CUBE));
01657                     while (tmp_frame != NULL ) {
01658                         KMO_TRY_EXIT_IF_NULL(
01659                             fn_reconstr = cpl_frame_get_filename(tmp_frame));
01660 
01661                         KMO_TRY_EXIT_IF_NULL(
01662                             tmp_header = kmclipm_propertylist_load(fn_reconstr, 0));
01663 
01664                         kmo_free_fits_desc(&desc1);
01665                         kmo_init_fits_desc(&desc1);
01666                         desc1 = kmo_identify_fits_header(fn_reconstr);
01667 
01668                         for (int ifu_nr = 1; ifu_nr <= KMOS_NR_IFUS; ifu_nr++) {
01669                             // check if object-name equals the one in our list
01670                             KMO_TRY_EXIT_IF_NULL(
01671                                 keyword = cpl_sprintf("%s%d%s", IFU_NAME_PREFIX,
01672                                                       ifu_nr, IFU_NAME_POSTFIX));
01673                             KMO_TRY_EXIT_IF_NULL(
01674                                 tmp_str = cpl_propertylist_get_string(tmp_header,
01675                                                                       keyword));
01676                             cpl_free(keyword); keyword = NULL;
01677 
01678                             if (strcmp(all_obj[i].name, tmp_str) == 0) {
01679                                 // found object-IFU with matching name
01680                                 // load data & subheader
01681                                 index = kmo_identify_index(fn_reconstr, ifu_nr, FALSE);
01682                                 KMO_TRY_CHECK_ERROR_STATE();
01683 
01684                                 if (desc1.sub_desc[index-1].valid_data) {
01685                                     KMO_TRY_EXIT_IF_NULL(
01686                                         cube_data[cube_counter_data] =
01687                                             kmclipm_imagelist_load(fn_reconstr,
01688                                                                    CPL_TYPE_FLOAT,
01689                                                                    index));
01690                                     if (edge_nan) {
01691                                         KMO_TRY_EXIT_IF_ERROR(
01692                                             kmo_edge_nan(cube_data[cube_counter_data], ifu_nr));
01693                                     }
01694 
01695                                     KMO_TRY_EXIT_IF_NULL(
01696                                         header_data[cube_counter_data] =
01697                                             kmclipm_propertylist_load(fn_reconstr,
01698                                                                       index));
01699                                     cpl_propertylist_update_string(header_data[cube_counter_data],
01700                                                                    "ESO PRO FRNAME",
01701                                                                    fn_reconstr);
01702                                     cpl_propertylist_update_int(header_data[cube_counter_data],
01703                                                                 "ESO PRO IFUNR",
01704                                                                 index);
01705                                     cube_counter_data++;
01706                                 }
01707 
01708                                 // load noise & subheader (if existing)
01709                                 if (desc1.ex_noise) {
01710                                     index = kmo_identify_index(fn_reconstr, ifu_nr, TRUE);
01711                                     KMO_TRY_CHECK_ERROR_STATE();
01712 
01713                                     if (desc1.sub_desc[index-1].valid_data) {
01714                                         KMO_TRY_EXIT_IF_NULL(
01715                                             cube_noise[cube_counter_noise] =
01716                                                 kmclipm_imagelist_load(fn_reconstr,
01717                                                                        CPL_TYPE_FLOAT,
01718                                                                        index));
01719                                         if (edge_nan) {
01720                                             KMO_TRY_EXIT_IF_ERROR(
01721                                                 kmo_edge_nan(cube_noise[cube_counter_noise], ifu_nr));
01722                                         }
01723                                         KMO_TRY_EXIT_IF_NULL(
01724                                             header_noise[cube_counter_noise] =
01725                                                 kmclipm_propertylist_load(fn_reconstr,
01726                                                                           index));
01727                                         cube_counter_noise++;
01728                                     }
01729                                 }
01730                                 cpl_error_reset();
01731                             } // end if found obj
01732                         } // end for ifu_nr
01733 
01734                         cpl_propertylist_delete(tmp_header); tmp_header = NULL;
01735                         tmp_frame = kmo_dfs_get_frame(frameset, NULL);
01736                         KMO_TRY_CHECK_ERROR_STATE();
01737                     } // end while-loop RECONSTRUCTED_CUBE frames
01738 
01739                     if (cube_counter_data > 1) {
01740                         if (cube_counter_data == cube_counter_noise) {
01741                             KMO_TRY_EXIT_IF_ERROR(
01742                                 kmo_priv_combine(cube_data,
01743                                                  cube_noise,
01744                                                  header_data,
01745                                                  header_noise,
01746                                                  cube_counter_data,
01747                                                  cube_counter_noise,
01748                                                  all_obj[i].name,
01749                                                  "",
01750                                                  comb_method,
01751                                                  smethod,
01752                                                  fmethod,
01753                                                  filename,
01754                                                  cmethod,
01755                                                  cpos_rej,
01756                                                  cneg_rej,
01757                                                  citer,
01758                                                  cmin,
01759                                                  cmax,
01760                                                  extrapol_enum,
01761                                                  flux,
01762                                                  &combined_data,
01763                                                  &combined_noise));
01764                         } else if (cube_counter_noise == 0) {
01765                             // if imethod == "CS"
01766                             KMO_TRY_EXIT_IF_ERROR(
01767                                 kmo_priv_combine(cube_data,
01768                                                  NULL,
01769                                                  header_data,
01770                                                  header_noise,
01771                                                  cube_counter_data,
01772                                                  cube_counter_noise,
01773                                                  all_obj[i].name,
01774                                                  "",
01775                                                  comb_method,
01776                                                  smethod,
01777                                                  fmethod,
01778                                                  filename,
01779                                                  cmethod,
01780                                                  cpos_rej,
01781                                                  cneg_rej,
01782                                                  citer,
01783                                                  cmin,
01784                                                  cmax,
01785                                                  extrapol_enum,
01786                                                  flux,
01787                                                  &combined_data,
01788                                                  &combined_noise));
01789                         } else {
01790                             KMO_TRY_ASSURE(1 == 0,
01791                                            CPL_ERROR_ILLEGAL_INPUT,
01792                                            "The number of cube-data and cube-noise "
01793                                            "isn't the same (%d vs. %d)!",
01794                                            cube_counter_data, cube_counter_noise);
01795                         }
01796                     } else {
01797                         cpl_msg_warning("", "There is only one reconstructed cube with "
01798                                         "this object! Saving it as it is.");
01799                         KMO_TRY_EXIT_IF_NULL(
01800                             combined_data = cpl_imagelist_duplicate(cube_data[0]));
01801 
01802                         if (cube_noise[0] != NULL) {
01803                             KMO_TRY_EXIT_IF_NULL(
01804                                 combined_noise = cpl_imagelist_duplicate(cube_noise[0]));
01805                         }
01806                     } // end if (cube_counter_data > 1)
01807 
01808                     fn_out = COMBINED_CUBE;
01809                     KMO_TRY_EXIT_IF_NULL(
01810                         fn_suffix = cpl_sprintf("_%s", all_obj[i].name));
01811 
01812                     // save combined cube
01813                     KMO_TRY_EXIT_IF_NULL(
01814                         tmp_frame = kmo_dfs_get_frame(frameset, RECONSTRUCTED_CUBE));
01815                     KMO_TRY_EXIT_IF_ERROR(
01816                         kmo_dfs_save_main_header(frameset, fn_out, fn_suffix,
01817                                                  tmp_frame, NULL, parlist, cpl_func));
01818 
01819                     KMO_TRY_EXIT_IF_ERROR(
01820                         kmo_dfs_save_cube(combined_data, fn_out, fn_suffix,
01821                                           header_data[0], 0./0.));
01822 
01823     //                if (combined_noise != NULL) {
01824                         if (header_noise[0] == NULL) {
01825                             KMO_TRY_EXIT_IF_NULL(
01826                                 header_noise[0] =
01827                                      cpl_propertylist_duplicate(header_data[0]));
01828 
01829                             KMO_TRY_EXIT_IF_NULL(
01830                                 tmp_str = cpl_propertylist_get_string(header_data[0],
01831                                                                       EXTNAME));
01832                             KMO_TRY_EXIT_IF_ERROR(
01833                                 kmo_extname_extractor(tmp_str, &ft, &tmp_int, content));
01834                             KMO_TRY_EXIT_IF_NULL(
01835                                 extname = kmo_extname_creator(ifu_frame, tmp_int,
01836                                                               EXT_NOISE));
01837                             KMO_TRY_EXIT_IF_ERROR(
01838                                 kmclipm_update_property_string(header_noise[0],
01839                                                                EXTNAME, extname,
01840                                                                "FITS extension name"));
01841                             cpl_free(extname); extname = NULL;
01842                         }
01843                         KMO_TRY_EXIT_IF_ERROR(
01844                             kmo_dfs_save_cube(combined_noise, fn_out, fn_suffix,
01845                                               header_noise[0], 0./0.));
01846     //                }
01847 
01848                     for (int jj = 0; jj < nr_data_alloc; jj++) {
01849                         cpl_imagelist_delete(cube_data[jj]); cube_data[jj] = NULL;
01850                         cpl_imagelist_delete(cube_noise[jj]); cube_noise[jj] = NULL;
01851                         cpl_propertylist_delete(header_data[jj]); header_data[jj] = NULL;
01852                         cpl_propertylist_delete(header_noise[jj]); header_noise[jj] = NULL;
01853                     }
01854                     cpl_free(cube_data);    cube_data = NULL;
01855                     cpl_free(cube_noise);   cube_noise = NULL;
01856                     cpl_free(header_data);  header_data = NULL;
01857                     cpl_free(header_noise); header_noise = NULL;
01858                     cpl_free(fn_suffix); fn_suffix = NULL;
01859                     cpl_imagelist_delete(combined_data); combined_data = NULL;
01860                     cpl_imagelist_delete(combined_noise); combined_noise = NULL;
01861                 } // for i = nr_avail_obj_names
01862             } else {
01863                 // we are in mapping_mode
01864                 nr_data_alloc = nr_reconstructed_frames*KMOS_NR_IFUS;
01865                 KMO_TRY_EXIT_IF_NULL(
01866                     cube_data = (cpl_imagelist**)cpl_calloc(nr_data_alloc,
01867                                                         sizeof(cpl_imagelist*)));
01868                 KMO_TRY_EXIT_IF_NULL(
01869                     cube_noise = (cpl_imagelist**)cpl_calloc(nr_data_alloc,
01870                                                         sizeof(cpl_imagelist*)));
01871                 KMO_TRY_EXIT_IF_NULL(
01872                     header_data = (cpl_propertylist**)cpl_calloc( nr_data_alloc,
01873                                                         sizeof(cpl_propertylist*)));
01874                 KMO_TRY_EXIT_IF_NULL(
01875                     header_noise = (cpl_propertylist**)cpl_calloc(nr_data_alloc,
01876                                                         sizeof(cpl_propertylist*)));
01877 
01878                 cube_counter_data = 0;
01879                 cube_counter_noise = 0;
01880                 KMO_TRY_EXIT_IF_NULL(
01881                     tmp_frame = kmo_dfs_get_frame(frameset, RECONSTRUCTED_CUBE));
01882                 while (tmp_frame != NULL ) {
01883                     KMO_TRY_EXIT_IF_NULL(
01884                         fn_reconstr = cpl_frame_get_filename(tmp_frame));
01885 
01886                     KMO_TRY_EXIT_IF_NULL(
01887                         tmp_header = kmclipm_propertylist_load(fn_reconstr, 0));
01888 
01889                     kmo_free_fits_desc(&desc1);
01890                     kmo_init_fits_desc(&desc1);
01891                     desc1 = kmo_identify_fits_header(fn_reconstr);
01892                     for (int ifu_nr = 1; ifu_nr <= KMOS_NR_IFUS; ifu_nr++) {
01893                         index = kmo_identify_index(fn_reconstr, ifu_nr, FALSE);
01894                         KMO_TRY_CHECK_ERROR_STATE();
01895 
01896                         if (desc1.sub_desc[index-1].valid_data) {
01897                             KMO_TRY_EXIT_IF_NULL(
01898                                 cube_data[cube_counter_data] =
01899                                     kmclipm_imagelist_load(fn_reconstr, CPL_TYPE_FLOAT,
01900                                                            index));
01901                             if (edge_nan) {
01902                                 KMO_TRY_EXIT_IF_ERROR(
01903                                     kmo_edge_nan(cube_data[cube_counter_data], ifu_nr));
01904                             }
01905 
01906                             if (fast_mode) {
01907                                 KMO_TRY_EXIT_IF_NULL(
01908                                     tmpImg = cpl_imagelist_collapse_median_create(cube_data[cube_counter_data]));
01909                                 KMO_TRY_EXIT_IF_NULL(
01910                                     tmpCube = cpl_imagelist_new());
01911                                 KMO_TRY_EXIT_IF_ERROR(
01912                                     cpl_imagelist_set(tmpCube, tmpImg, 0));
01913                                 cpl_imagelist_delete(cube_data[cube_counter_data]);
01914                                 cube_data[cube_counter_data] = tmpCube;
01915                             }
01916 
01917                             KMO_TRY_EXIT_IF_NULL(
01918                                 header_data[cube_counter_data] =
01919                                     kmclipm_propertylist_load(fn_reconstr, index));
01920                             cpl_propertylist_update_string(header_data[cube_counter_data],
01921                                                     "ESO PRO FRNAME",
01922                                                     fn_reconstr);
01923                             cpl_propertylist_update_int(header_data[cube_counter_data],
01924                                                     "ESO PRO IFUNR",
01925                                                     index);
01926                             cube_counter_data++;
01927                         }
01928 
01929                         // load noise & subheader (if existing)
01930                         if (desc1.ex_noise) {
01931                             index = kmo_identify_index(fn_reconstr, ifu_nr, TRUE);
01932                             KMO_TRY_CHECK_ERROR_STATE();
01933                             if (desc1.sub_desc[index-1].valid_data) {
01934                                 KMO_TRY_EXIT_IF_NULL(
01935                                     cube_noise[cube_counter_noise] =
01936                                         kmclipm_imagelist_load(fn_reconstr, CPL_TYPE_FLOAT,
01937                                                                index));
01938 
01939                                 if (edge_nan) {
01940                                     KMO_TRY_EXIT_IF_ERROR(
01941                                         kmo_edge_nan(cube_noise[cube_counter_noise], ifu_nr));
01942                                 }
01943 
01944                                 if (fast_mode) {
01945                                     KMO_TRY_EXIT_IF_NULL(
01946                                         tmpImg = cpl_imagelist_collapse_median_create(cube_noise[cube_counter_noise]));
01947                                     KMO_TRY_EXIT_IF_NULL(
01948                                         tmpCube = cpl_imagelist_new());
01949                                     KMO_TRY_EXIT_IF_ERROR(
01950                                         cpl_imagelist_set(tmpCube, tmpImg, 0));
01951                                     cpl_imagelist_delete(cube_noise[cube_counter_noise]);
01952                                     cube_noise[cube_counter_noise] = tmpCube;
01953                                 }
01954                                 KMO_TRY_EXIT_IF_NULL(
01955                                     header_noise[cube_counter_noise] =
01956                                         kmclipm_propertylist_load(fn_reconstr, index));
01957                                 cube_counter_noise++;
01958                             }
01959                         }
01960                         cpl_error_reset();
01961                     } // end for ifu_nr
01962 
01963                     cpl_propertylist_delete(tmp_header); tmp_header = NULL;
01964                     tmp_frame = kmo_dfs_get_frame(frameset, NULL);
01965                     KMO_TRY_CHECK_ERROR_STATE();
01966                 } // end while-loop RECONSTRUCTED_CUBE frames
01967 
01968                 if (cube_counter_data > 1) {
01969                     if (cube_counter_data == cube_counter_noise) {
01970                         KMO_TRY_EXIT_IF_ERROR(
01971                             kmo_priv_combine(cube_data,
01972                                              cube_noise,
01973                                              header_data,
01974                                              header_noise,
01975                                              cube_counter_data,
01976                                              cube_counter_noise,
01977                                              mapping_mode,
01978                                              "",
01979                                              comb_method,
01980                                              smethod,
01981                                              fmethod,
01982                                              filename,
01983                                              cmethod,
01984                                              cpos_rej,
01985                                              cneg_rej,
01986                                              citer,
01987                                              cmin,
01988                                              cmax,
01989                                              extrapol_enum,
01990                                              flux,
01991                                              &combined_data,
01992                                              &combined_noise));
01993                     } else if (cube_counter_noise == 0) {
01994                         // if imethod == "CS"
01995                         KMO_TRY_EXIT_IF_ERROR(
01996                             kmo_priv_combine(cube_data,
01997                                              NULL,
01998                                              header_data,
01999                                              header_noise,
02000                                              cube_counter_data,
02001                                              cube_counter_noise,
02002                                              mapping_mode,
02003                                              "",
02004                                              comb_method,
02005                                              smethod,
02006                                              fmethod,
02007                                              filename,
02008                                              cmethod,
02009                                              cpos_rej,
02010                                              cneg_rej,
02011                                              citer,
02012                                              cmin,
02013                                              cmax,
02014                                              extrapol_enum,
02015                                              flux,
02016                                              &combined_data,
02017                                              &combined_noise));
02018                     } else {
02019                         KMO_TRY_ASSURE(1 == 0,
02020                                        CPL_ERROR_ILLEGAL_INPUT,
02021                                        "The number of cube-data and cube-noise "
02022                                        "isn't the same (%d vs. %d)!",
02023                                        cube_counter_data, cube_counter_noise);
02024                     }
02025                 } else {
02026                     cpl_msg_warning("", "There is only one reconstructed cube! "
02027                                         "Saving it as it is.");
02028                     KMO_TRY_EXIT_IF_NULL(
02029                         combined_data = cpl_imagelist_duplicate(cube_data[0]));
02030 
02031                     if (cube_noise[0] != NULL) {
02032                         KMO_TRY_EXIT_IF_NULL(
02033                             combined_noise = cpl_imagelist_duplicate(cube_noise[0]));
02034                     }
02035                 }
02036 
02037                 fn_out = COMBINED_CUBE;
02038                 KMO_TRY_EXIT_IF_NULL(
02039                     fn_suffix = cpl_sprintf("_%s", mapping_mode));
02040 
02041                 // save combined cube
02042                 KMO_TRY_EXIT_IF_NULL(
02043                     tmp_frame = kmo_dfs_get_frame(frameset, RECONSTRUCTED_CUBE));
02044                 KMO_TRY_EXIT_IF_ERROR(
02045                     kmo_dfs_save_main_header(frameset, fn_out, fn_suffix, tmp_frame,
02046                                              NULL, parlist, cpl_func));
02047 
02048                 KMO_TRY_EXIT_IF_ERROR(
02049                     kmo_dfs_save_cube(combined_data, fn_out, fn_suffix,
02050                                       header_data[0], 0./0.));
02051 
02052     //            if (combined_noise != NULL) {
02053                     if (header_noise[0] == NULL) {
02054                         KMO_TRY_EXIT_IF_NULL(
02055                             header_noise[0] =
02056                                  cpl_propertylist_duplicate(header_data[0]));
02057 
02058                         KMO_TRY_EXIT_IF_NULL(
02059                             tmp_str = cpl_propertylist_get_string(header_data[0],
02060                                                                   EXTNAME));
02061                         KMO_TRY_EXIT_IF_ERROR(
02062                             kmo_extname_extractor(tmp_str, &ft, &tmp_int, content));
02063                         KMO_TRY_EXIT_IF_NULL(
02064                             extname = kmo_extname_creator(ifu_frame, tmp_int,
02065                                                           EXT_NOISE));
02066                         KMO_TRY_EXIT_IF_ERROR(
02067                             kmclipm_update_property_string(header_noise[0],
02068                                                            EXTNAME, extname,
02069                                                            "FITS extension name"));
02070                         cpl_free(extname); extname = NULL;
02071                     }
02072                     KMO_TRY_EXIT_IF_ERROR(
02073                         kmo_dfs_save_cube(combined_noise, fn_out, fn_suffix,
02074                                           header_noise[0], 0./0.));
02075     //            }
02076 
02077                 for (int i = 0; i < nr_data_alloc; i++) {
02078                     cpl_imagelist_delete(cube_data[i]); cube_data[i] = NULL;
02079                     cpl_imagelist_delete(cube_noise[i]); cube_noise[i] = NULL;
02080                     cpl_propertylist_delete(header_data[i]); header_data[i] = NULL;
02081                     cpl_propertylist_delete(header_noise[i]); header_noise[i] = NULL;
02082                 }
02083                 cpl_free(cube_data);    cube_data = NULL;
02084                 cpl_free(cube_noise);   cube_noise = NULL;
02085                 cpl_free(header_data);  header_data = NULL;
02086                 cpl_free(header_noise); header_noise = NULL;
02087                 cpl_free(fn_suffix); fn_suffix = NULL;
02088                 cpl_imagelist_delete(combined_data); combined_data = NULL;
02089                 cpl_imagelist_delete(combined_noise); combined_noise = NULL;
02090             } // if mapping_mode
02091         } else {
02092             cpl_msg_info("", "NOT combining reconstructed objects (--no_combine is set)");
02093         } // if (!no_combine)
02094 
02095         cpl_msg_info("", "-------------------------------------------");
02096     }
02097     KMO_CATCH
02098     {
02099         KMO_CATCH_MSG();
02100         ret_val = -1;
02101     }
02102 
02103     if (cube_data != NULL) {
02104         for (int ifu_nr = 1; ifu_nr <= nr_data_alloc; ifu_nr++) {
02105             cpl_imagelist_delete(cube_data[ifu_nr-1]); cube_data[ifu_nr-1] = NULL;
02106         }
02107     }
02108     cpl_free(cube_data);    cube_data = NULL;
02109     if (cube_noise != NULL) {
02110         for (int ifu_nr = 1; ifu_nr <= nr_data_alloc; ifu_nr++) {
02111             cpl_imagelist_delete(cube_noise[ifu_nr-1]); cube_noise[ifu_nr-1] = NULL;
02112         }
02113     }
02114     cpl_free(cube_noise);   cube_noise = NULL;
02115     if (header_data != NULL) {
02116         for (int ifu_nr = 1; ifu_nr <= nr_data_alloc; ifu_nr++) {
02117             cpl_propertylist_delete(header_data[ifu_nr-1]); header_data[ifu_nr-1] = NULL;
02118         }
02119     }
02120     cpl_free(header_data);  header_data = NULL;
02121     if (header_noise != NULL) {
02122         for (int ifu_nr = 1; ifu_nr <= nr_data_alloc; ifu_nr++) {
02123             cpl_propertylist_delete(header_noise[ifu_nr-1]); header_noise[ifu_nr-1] = NULL;
02124         }
02125     }
02126     cpl_free(header_noise); header_noise = NULL;
02127 
02128 
02129     kmo_free_fits_desc(&desc1);
02130     kmo_free_fits_desc(&desc2);
02131     cpl_vector_delete(ifus); ifus = NULL;
02132     cpl_free(mapping_mode); mapping_mode = NULL;
02133     if (unused_ifus != NULL) {
02134         kmo_free_unused_ifus(unused_ifus); unused_ifus = NULL;
02135     }
02136     if (bounds != NULL) {
02137         cpl_free(bounds); bounds = NULL;
02138     }
02139     if (obj_sky_struct != NULL) {
02140         cpl_free(obj_sky_struct); obj_sky_struct = NULL;
02141     }
02142 
02143     // frees for the case of errors
02144     kmclipm_vector_delete(telluric_data); telluric_data = NULL;
02145     kmclipm_vector_delete(telluric_noise); telluric_noise = NULL;
02146     cpl_image_delete(illum_data); illum_data = NULL;
02147     cpl_image_delete(illum_noise); illum_noise = NULL;
02148     cpl_propertylist_delete(tmp_header); tmp_header = NULL;
02149     cpl_table_delete(band_table); band_table = NULL;
02150     cpl_propertylist_delete(main_header); main_header = NULL;
02151     if (lcal != NULL) {
02152         for (int i = 0; i < KMOS_NR_DETECTORS; i++) {
02153             cpl_image_delete(lcal[i]);
02154         }
02155     }
02156     cpl_free(lcal); lcal = NULL;
02157     cpl_free(fn_suffix); fn_suffix = NULL;
02158     cpl_free(suffix); suffix = NULL;
02159 
02160     if (all_obj != NULL) {
02161         for (int i = 0; i < nr_science_frames*KMOS_NR_IFUS; i++) {
02162             cpl_free(all_obj[i].name);
02163         }
02164     }
02165     cpl_free(all_obj); all_obj = NULL;
02166 
02167     return ret_val;
02168 }
02169