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