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