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