KMOS Pipeline Reference Manual  1.2.6
kmo_multi_reconstruct.c
00001 /* $Id: kmo_multi_reconstruct.c,v 1.55 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.55 $
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_cpl_extensions.h"
00045 #include "kmo_priv_lcorr.h"
00046 #include "kmo_utils.h"
00047 #include "kmo_error.h"
00048 #include "kmo_dfs.h"
00049 #include "kmo_functions.h"
00050 #include "kmo_priv_arithmetic.h"
00051 #include "kmo_priv_combine.h"
00052 #include "kmo_priv_functions.h"
00053 #include "kmo_priv_reconstruct.h"
00054 #include "kmo_priv_multi_reconstruct.h"
00055 
00056 /*-----------------------------------------------------------------------------
00057  *              Types
00058  *-----------------------------------------------------------------------------*/
00059 
00060 /*-----------------------------------------------------------------------------
00061  *                          Functions prototypes
00062  *----------------------------------------------------------------------------*/
00063 
00064 static int kmo_multi_reconstruct_create(cpl_plugin *);
00065 static int kmo_multi_reconstruct_exec(cpl_plugin *);
00066 static int kmo_multi_reconstruct_destroy(cpl_plugin *);
00067 static int kmo_multi_reconstruct(cpl_parameterlist *, cpl_frameset *);
00068 
00069 /*-----------------------------------------------------------------------------
00070  *                          Static variables
00071  *----------------------------------------------------------------------------*/
00072 
00073 static char kmo_multi_reconstruct_description[] =
00074 "Ideally at least two data frames have to be provided since we need for each IFU\n"
00075 "pointing to an object as well a sky frame for the same IFU.\n"
00076 "If an OH spectrum is given in the SOF file the lambda axis will be corrected\n"
00077 "using the OH lines as reference.\n"
00078 "All IFUs with the same object name will be reconstructed and combined in one step\n"
00079 "Telluric correction is only supported if the objects have been observed with\n"
00080 "the same IFU on all exposures (dithering).\n"
00081 "The number of created files depends on the number of objects of different name.\n"
00082 "If the user just wants to combine a certain object, the parameters --name or\n"
00083 "--ifus can be used.\n"
00084 "\n"
00085 "Exposures taken with the templates KMOS_spec_obs_mapping8 and\n"
00086 "KMOS_spec_obs_mapping24 can't be processed with this recipe! Use kmo_sci_red\n"
00087 "instead.\n"
00088 "\n"
00089 "BASIC PARAMETERS:\n"
00090 "-----------------\n"
00091 "--imethod\n"
00092 "The interpolation method used for reconstruction.\n"
00093 "\n"
00094 "--name\n"
00095 "--ifus\n"
00096 "Since an object can be present only once per exposure and since it can be\n"
00097 "located in different IFUs for the existing exposures, there are two modes to\n"
00098 "identify the objects:\n"
00099 "   * Combine by object names (default)\n"
00100 "   In this case the object name must be provided via the --name parameter. The\n"
00101 "   object name will be searched for in all primary headers of all provided\n"
00102 "   frames in the keyword ESO OCS ARMx NAME.\n"
00103 "\n"
00104 "   * Combine by index (advanced)\n"
00105 "   In this case the --ifus parameter must be provided. The parameter must have\n"
00106 "   the same number of entries as frames are provided, e.g. \"3;1;24\" for 3\n"
00107 "   exposures. The index doesn't reference the extension in the frame but the\n"
00108 "   real index of the IFU as defined in the EXTNAME keyword.\n"
00109 "   (e.g. 'IFU.3.DATA')\n"
00110 "\n"
00111 "ADVANCED PARAMETERS\n"
00112 "-------------------\n"
00113 "--flux\n"
00114 "Specify if flux conservation should be applied.\n"
00115 "\n"
00116 "--background\n"
00117 "Specify if background removal should be applied.\n"
00118 "\n"
00119 "--suppress_extension\n"
00120 "If set to TRUE, the arbitrary filename extensions are supressed. If multiple\n"
00121 "products with the same category are produced, they will be numered consecutively\n"
00122 "starting from 0.\n"
00123 "\n"
00124 "  Advanced reconstruction parameters\n"
00125 "  ----------------------------------\n"
00126 "--neighborhoodRange\n"
00127 "Defines the range to search for neighbors during reconstruction\n"
00128 "\n"
00129 "--b_samples\n"
00130 "The number of samples in spectral direction for the reconstructed cube.\n"
00131 "Ideally this number should be greater than 2048, the detector size.\n"
00132 "\n"
00133 "--b_start\n"
00134 "--b_end\n"
00135 "Used to define manually the start and end wavelength for the reconstructed\n"
00136 "cube. By default the internally defined values are used.\n"
00137 "\n"
00138 "--pix_scale\n"
00139 "Change the pixel scale [arcsec]. Default of 0.2\" results into cubes of\n"
00140 "14x14pix, a scale of 0.1\" results into cubes of 28x28pix, etc.\n"
00141 "\n"
00142 "--no_subtract\n"
00143 "If set to TRUE, the found objects and references won't be sky subtracted. \n"
00144 "Additionally all IFUs will be reconstructed, even the ones containing skies. \n"
00145 "This option sets the parameter no_combine to TRUE automatically.\n"
00146 "\n"
00147 "--xcal_interpolation\n"
00148 "If true interpolate the pixel position in the slitlet (xcal) using the two\n"
00149 "closest rotator angles in the calibration file. Otherwise take the values\n"
00150 "of the closest rotator angle\n"
00151 "\n"
00152 "  Advanced combining parameters\n"
00153 "  ----------------------------------\n"
00154 "--method\n"
00155 "There are following sources to get the shift parameters from:\n"
00156 "   * 'header' (default)\n"
00157 "   The shifts are calculated according to the WCS information stored in the\n"
00158 "   header of every IFU. The output frame will get larger, except the object is\n"
00159 "   at the exact same position for all exposures. The size of the exposures can\n"
00160 "   differ, but the orientation must be the same for all exposures.\n"
00161 "\n"
00162 "   * 'none'\n"
00163 "   The cubes are directly recombined, not shifting at all. The ouput frame\n"
00164 "   will have the same dimensions as the input cubes.\n"
00165 "   If the size differs a warning will be emitted and the cubes will be aligned\n"
00166 "   to the lower left corner. If the orientation differs a warning will be\n"
00167 "   emitted, but the cubes are combined anyway.\n"
00168 "\n"
00169 "   * 'center'\n"
00170 "   The shifts are calculated using a centering algorithm. The cube will be\n"
00171 "   collapsed and a 2D profile will be fitted to it to identify the centre.\n"
00172 "   With the parameter --fmethod the function to fit can be provided. The size\n"
00173 "   of the exposures can differ, but the orientation must be the same for all\n"
00174 "   exposures.\n"
00175 "\n"
00176 "   * 'user'\n"
00177 "   Read the shifts from a user specified file. The path of the file must be\n"
00178 "   provided using the --filename parameter. For every exposure (except the\n"
00179 "   first one) two shift values are expected per line, they have to be separa-\n"
00180 "   ted with simple spaces. The values indicate pixel shifts and are referenced\n"
00181 "   to the first frame. The 1st value is the shift in x-direction to the left,\n"
00182 "   the 2nd the shift in y-direction upwards. The size of the exposures can\n"
00183 "   differ, but the orientation must be the same for all exposures.\n"
00184 "\n"
00185 "--fmethod\n"
00186 "see --method='center'\n"
00187 "The type of function that should be fitted spatially to the collapsed image.\n"
00188 "This fit is used to create a mask to extract the spectrum of the object. Valid\n"
00189 "values are 'gauss' and 'moffat'.\n"
00190 "\n"
00191 "--filename\n"
00192 "see --method='user'\n"
00193 "\n"
00194 "--cmethod\n"
00195 "Following methods of frame combination are available:\n"
00196 "   * 'ksigma' (Default)\n"
00197 "   An iterative sigma clipping. For each position all pixels in the spectrum\n"
00198 "   are examined. If they deviate significantly, they will be rejected according\n"
00199 "   to the conditions:\n"
00200 "       val > mean + stdev * cpos_rej\n"
00201 "   and\n"
00202 "       val < mean - stdev * cneg_rej\n"
00203 "   where --cpos_rej, --cneg_rej and --citer are the corresponding configuration\n"
00204 "   parameters. In the first iteration median and percentile level are used.\n"
00205 "\n"
00206 "   * 'median'\n"
00207 "   At each pixel position the median is calculated.\n"
00208 "\n"
00209 "   * 'average'\n"
00210 "   At each pixel position the average is calculated.\n"
00211 "\n"
00212 "   * 'sum'\n"
00213 "   At each pixel position the sum is calculated.\n"
00214 "\n"
00215 "   * 'min_max'\n"
00216 "   The specified number of minimum and maximum pixel values will be rejected.\n"
00217 "   --cmax and --cmin apply to this method.\n"
00218 "\n"
00219 "--cpos_rej\n"
00220 "--cneg_rej\n"
00221 "--citer\n"
00222 "see --cmethod='ksigma'\n"
00223 "\n"
00224 "--cmax\n"
00225 "--cmin\n"
00226 "see --cmethod='min_max'\n"
00227 "\n"
00228 "------------------------------------------------------------------------------\n"
00229 "  Input files:\n"
00230 "\n"
00231 "   DO                    KMOS                                                  \n"
00232 "   category              Type   Explanation                   Required #Frames\n"
00233 "   --------              -----  -----------                   -------- -------\n"
00234 "   SCIENCE               RAW    The science frames                Y      >=1  \n"
00235 "   XCAL                  F2D    x calibration frame               Y       1   \n"
00236 "   YCAL                  F2D    y calibration frame               Y       1   \n"
00237 "   LCAL                  F2D    Wavelength calib. frame           Y       1   \n"
00238 "   MASTER_FLAT           F2D    Master flat                       Y      0,1  \n"
00239 "   WAVE_BAND             F2L    Table with start-/end-wavelengths Y       1   \n"
00240 "   TELLURIC              F1I    normalised telluric spectrum      N      0,1  \n"
00241 "   OH_SPEC               F1S    Vector holding OH lines           N      0,1  \n"
00242 "\n"
00243 "  Output files:\n"
00244 "\n"
00245 "   DO                    KMOS\n"
00246 "   category              Type   Explanation\n"
00247 "   --------              -----  -----------\n"
00248 "   CUBE_MULTI            F3I    Combined cubes with noise\n"
00249 "------------------------------------------------------------------------------\n"
00250 "\n";
00251 
00252 /*-----------------------------------------------------------------------------
00253  *                              Functions code
00254  *----------------------------------------------------------------------------*/
00255 
00273 int cpl_plugin_get_info(cpl_pluginlist *list)
00274 {
00275     cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe);
00276     cpl_plugin *plugin = &recipe->interface;
00277 
00278     cpl_plugin_init(plugin,
00279                         CPL_PLUGIN_API,
00280                         KMOS_BINARY_VERSION,
00281                         CPL_PLUGIN_TYPE_RECIPE,
00282                         "kmo_multi_reconstruct",
00283                         "Reconstruct and combine obj/sky-pairs in one step.",
00284                         kmo_multi_reconstruct_description,
00285                         "Alex Agudo Berbel",
00286                         "kmos-spark@mpe.mpg.de",
00287                         kmos_get_license(),
00288                         kmo_multi_reconstruct_create,
00289                         kmo_multi_reconstruct_exec,
00290                         kmo_multi_reconstruct_destroy);
00291 
00292     cpl_pluginlist_append(list, plugin);
00293 
00294     return 0;
00295 }
00296 
00304 static int kmo_multi_reconstruct_create(cpl_plugin *plugin)
00305 {
00306     cpl_recipe *recipe;
00307     cpl_parameter *p;
00308 
00309     /* Check that the plugin is part of a valid recipe */
00310     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00311         recipe = (cpl_recipe *)plugin;
00312     else
00313         return -1;
00314 
00315     /* Create the parameters list in the cpl_recipe object */
00316     recipe->parameters = cpl_parameterlist_new();
00317 
00318     /* --imethod (interpolation method) */
00319     p = cpl_parameter_new_value("kmos.kmo_multi_reconstruct.imethod",
00320                                 CPL_TYPE_STRING,
00321                                 "Method to use for interpolation during reconstruction. "
00322                                 "[\"NN\" (nearest neighbour), "
00323                                 "\"lwNN\" (linear weighted nearest neighbor), "
00324                                 "\"swNN\" (square weighted nearest neighbor), "
00325                                 "\"MS\" (Modified Shepard's method)",
00326                                 "kmos.kmo_multi_reconstruct",
00327                                 "MS");
00328     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "imethod");
00329     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00330     cpl_parameterlist_append(recipe->parameters, p);
00331 
00332     /* --method  (shift method) */
00333     p = cpl_parameter_new_value("kmos.kmo_multi_reconstruct.method",
00334                                 CPL_TYPE_STRING,
00335                                 "The shifting method:   "
00336                                 "'none': no shifting, combined directly, "
00337                                 "'header': shift according to WCS (default), "
00338                                 "'center': centering algorithm, "
00339                                 "'user': read shifts from file",
00340                                 "kmos.kmo_multi_reconstruct",
00341                                 "header");
00342     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "method");
00343     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00344     cpl_parameterlist_append(recipe->parameters, p);
00345 
00346     /* --fmethod */
00347     p = cpl_parameter_new_value("kmos.kmo_multi_reconstruct.fmethod",
00348                                 CPL_TYPE_STRING,
00349                                 "The fitting method (applies only when "
00350                                 "method='center'):   "
00351                                 "'gauss': fit a gauss function to collapsed "
00352                                 "image (default), "
00353                                 "'moffat': fit a moffat function to collapsed"
00354                                 " image",
00355                                 "kmos.kmo_multi_reconstruct",
00356                                 "gauss");
00357     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "fmethod");
00358     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00359     cpl_parameterlist_append(recipe->parameters, p);
00360 
00361     /* --name */
00362     p = cpl_parameter_new_value("kmos.kmo_multi_reconstruct.name",
00363                                 CPL_TYPE_STRING,
00364                                 "Name of the object to combine.",
00365                                 "kmos.kmo_multi_reconstruct",
00366                                 "");
00367     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "name");
00368     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00369     cpl_parameterlist_append(recipe->parameters, p);
00370 
00371     /* --ifus */
00372     p = cpl_parameter_new_value("kmos.kmo_multi_reconstruct.ifus",
00373                                 CPL_TYPE_STRING,
00374                                 "The indices of the IFUs to combine. "
00375                                 "\"ifu1;ifu2;...\"",
00376                                 "kmos.kmo_multi_reconstruct",
00377                                 "");
00378     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "ifus");
00379     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00380     cpl_parameterlist_append(recipe->parameters, p);
00381 
00382     /* --pix_scale */
00383     p = cpl_parameter_new_value("kmos.kmo_multi_reconstruct.pix_scale",
00384                                 CPL_TYPE_DOUBLE,
00385                                 "Change the pixel scale [arcsec]. "
00386                                 "Default of 0.2\" results into cubes of 14x14pix, "
00387                                 "a scale of 0.1\" results into cubes of 28x28pix, "
00388                                 "etc.",
00389                                 "kmos.kmo_multi_reconstruct",
00390                                 KMOS_PIX_RESOLUTION);
00391     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "pix_scale");
00392     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00393     cpl_parameterlist_append(recipe->parameters, p);
00394 
00395     /* --suppress_extension */
00396     p = cpl_parameter_new_value("kmos.kmo_multi_reconstruct.suppress_extension",
00397                                 CPL_TYPE_BOOL,
00398                                 "Suppress arbitrary filename extension."
00399                                 "(TRUE (apply) or FALSE (don't apply)",
00400                                 "kmos.kmo_multi_reconstruct",
00401                                 FALSE);
00402     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "suppress_extension");
00403     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00404     cpl_parameterlist_append(recipe->parameters, p);
00405 
00406     /* --neighborhoodRange */
00407     p = cpl_parameter_new_value("kmos.kmo_multi_reconstruct.neighborhoodRange",
00408                                 CPL_TYPE_DOUBLE,
00409                                 "Defines the range to search for neighbors "
00410                                 "in pixels",
00411                                 "kmos.kmo_multi_reconstruct",
00412                                 1.001);
00413     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "neighborhoodRange");
00414     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00415     cpl_parameterlist_append(recipe->parameters, p);
00416 
00417     /* --filename */
00418     p = cpl_parameter_new_value("kmos.kmo_multi_reconstruct.filename",
00419                                 CPL_TYPE_STRING,
00420                                 "The path to the file with the shift vectors."
00421                                 "(Applies only to method='user')",
00422                                 "kmos.kmo_multi_reconstruct",
00423                                 "");
00424     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "filename");
00425     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00426     cpl_parameterlist_append(recipe->parameters, p);
00427 
00428     /* --flux */
00429     p = cpl_parameter_new_value("kmos.kmo_multi_reconstruct.flux",
00430                                 CPL_TYPE_BOOL,
00431                                 "TRUE: Apply flux conservation. FALSE: otherwise",
00432                                 "kmos.kmo_multi_reconstruct",
00433                                 FALSE);
00434     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "flux");
00435     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00436     cpl_parameterlist_append(recipe->parameters, p);
00437 
00438     /* --background */
00439     p = cpl_parameter_new_value("kmos.kmo_multi_reconstruct.background",
00440                                 CPL_TYPE_BOOL,
00441                                 "TRUE: Apply background removal. FALSE: otherwise",
00442                                 "kmos.kmo_multi_reconstruct",
00443                                 FALSE);
00444     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "background");
00445     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00446     cpl_parameterlist_append(recipe->parameters, p);
00447 
00448     /* --xcal_interpolation */
00449     p = cpl_parameter_new_value("kmos.kmo_multi_reconstruct.xcal_interpolation",
00450                                 CPL_TYPE_BOOL,
00451                                 "TRUE: Interpolate xcal between rotator angles. FALSE: otherwise",
00452                                 "kmos.kmo_multi_reconstruct",
00453                                 TRUE);
00454     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "xcal_interpolation");
00455     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00456     cpl_parameterlist_append(recipe->parameters, p);
00457 
00458     /* --no_subtract */
00459     p = cpl_parameter_new_value("kmos.kmo_multi_reconstruct.no_subtract",
00460                                 CPL_TYPE_BOOL,
00461                                 "Don't sky subtract object and references."
00462                                 "(TRUE (apply) or "
00463                                 "FALSE (don't apply)",
00464                                 "kmos.kmo_multi_reconstruct",
00465                                 FALSE);
00466     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "no_subtract");
00467     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00468     cpl_parameterlist_append(recipe->parameters, p);
00469 
00470     /* --dev_cal */
00471     p = cpl_parameter_new_value("kmos.kmo_multi_reconstruct.dev_cal",
00472                                 CPL_TYPE_BOOL,
00473                                 "Development only: If calibration data is to be "
00474                                 "reconstructed the ALPHA/DELTA keywords are "
00475                                 "missing. Setting this parameter to TRUE prevents "
00476                                 "according data check",
00477                                 "kmos.kmo_multi_reconstruct",
00478                                 FALSE);
00479     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "dev_cal");
00480     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00481     cpl_parameterlist_append(recipe->parameters, p);
00482 
00483     // add parameters for band-definition
00484     kmo_band_pars_create(recipe->parameters,
00485                          "kmos.kmo_multi_reconstruct");
00486 
00487     return kmo_combine_pars_create(recipe->parameters,
00488                                    "kmos.kmo_multi_reconstruct",
00489                                    DEF_REJ_METHOD,
00490                                    FALSE);
00491 }
00492 
00498 static int kmo_multi_reconstruct_exec(cpl_plugin *plugin)
00499 {
00500     cpl_recipe  *recipe;
00501 
00502     /* Get the recipe out of the plugin */
00503     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00504         recipe = (cpl_recipe *)plugin;
00505     else return -1 ;
00506 
00507     return kmo_multi_reconstruct(recipe->parameters, recipe->frames);
00508 }
00509 
00515 static int kmo_multi_reconstruct_destroy(cpl_plugin *plugin)
00516 {
00517     cpl_recipe *recipe;
00518 
00519     /* Get the recipe out of the plugin */
00520     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00521         recipe = (cpl_recipe *)plugin;
00522     else return -1 ;
00523 
00524     cpl_parameterlist_delete(recipe->parameters);
00525     return 0 ;
00526 }
00527 
00542 static int kmo_multi_reconstruct(cpl_parameterlist *parlist, cpl_frameset *frameset)
00543 {
00544     int                     ret_val                     = 0,
00545                             nr_science_frames           = 0,
00546                             has_illum_corr              = 0,
00547                             has_master_flat             = 0,
00548                             has_telluric                = 0,
00549                             *bounds                     = NULL,
00550                             citer                       = 0,
00551                             cmin                        = 0,
00552                             cmax                        = 0,
00553                             flux                        = FALSE,
00554                             background                  = FALSE,
00555                             no_subtract                 = FALSE,
00556                             xcal_interpolation          = FALSE,
00557                             suppress_extension          = FALSE,
00558                             dev_cal                     = 0,
00559                             cnt                         = 0,
00560                             arm_index                   = 0,
00561                             suppress_index              = 0,
00562                             xdim                        = 0,
00563                             ydim                        = 0,
00564                             iy                          = 0,
00565                             ix                          = 0,
00566                             ifu_nr                      = 0,
00567                             nr_frames                   = 0;
00568     double                  xmin                        = DBL_MAX,
00569                             xmax                        = -DBL_MAX,
00570                             ymin                        = DBL_MAX,
00571                             ymax                        = -DBL_MAX,
00572                             gxshift                     = 0.,
00573                             gyshift                     = 0.,
00574                             gxdim                       = 0.,
00575                             gydim                       = 0.,
00576                             neighborhoodRange           = 1.001,
00577                             cpos_rej                    = 0.0,
00578                             cneg_rej                    = 0.0,
00579                             pix_scale                   = 0.0,
00580                             *xshifts                    = NULL,
00581                             *yshifts                    = NULL;
00582     char                    *suffix                     = NULL,
00583                             *mapping_mode               = NULL,
00584                             *fn_cube                    = NULL,
00585                             *fn_suffix                  = NULL,
00586                             *filter_id                  = NULL,
00587                             *extname                    = NULL;
00588     const char              *imethod                    = NULL,
00589                             *ifus_txt                   = NULL,
00590                             *name                       = NULL,
00591                             *tmp_str                    = NULL,
00592                             *filename                   = NULL,
00593                             *comb_method                = NULL,
00594                             *cmethod                    = NULL,
00595                             *fmethod                    = NULL,
00596                             *filter_keyword             = "ESO INS FILT1 ID";
00597     cpl_array               **unused_ifus_before        = NULL,
00598                             **unused_ifus_after         = NULL;
00599     cpl_frame               *xcal_frame                 = NULL,
00600                             *ycal_frame                 = NULL,
00601                             *lcal_frame                 = NULL,
00602                             *flat_frame                 = NULL,
00603                             *illum_frame                = NULL,
00604                             *telluric_frame             = NULL,
00605                             *science_frame              = NULL,
00606                             *ref_spectrum_frame         = NULL;
00607     cpl_propertylist        *tmp_header                 = NULL,
00608                             *ref_sub_header             = NULL,
00609                             *science_frame_header       = NULL,
00610                             **sub_headers               = NULL;
00611     cpl_vector              *ifus                       = NULL;
00612     cpl_table               *band_table                 = NULL;
00613 
00614     cpl_polynomial          **lcorr_coeffs              = NULL;
00615     cpl_imagelist           *cube_combined_data         = NULL,
00616                             *cube_combined_noise        = NULL,
00617                             **pre_data_cube_list        = NULL;
00618     kmclipm_vector          *telluric_data              = NULL,
00619                             *telluric_noise             = NULL;
00620     main_fits_desc          desc1,
00621                             desc2,
00622                             desc_telluric;
00623     gridDefinition          gd,
00624                             gd_14x14;
00625     armNameStruct           *arm_name_struct            = NULL;
00626 
00627     KMO_TRY
00628     {
00629 
00630         kmo_init_fits_desc(&desc1);
00631         kmo_init_fits_desc(&desc2);
00632         kmo_init_fits_desc(&desc_telluric);
00633 
00634         //
00635         // check frameset
00636         //
00637         KMO_TRY_ASSURE((parlist != NULL) &&
00638                        (frameset != NULL),
00639                        CPL_ERROR_NULL_INPUT,
00640                        "Not all input data is provided!");
00641 
00642         nr_science_frames = cpl_frameset_count_tags(frameset, SCIENCE);
00643         KMO_TRY_ASSURE(nr_science_frames >= 1,
00644                        CPL_ERROR_ILLEGAL_INPUT,
00645                        "At least one SCIENCE frame is required!");
00646         if (nr_science_frames == 1) {
00647             cpl_msg_warning("", "At least two SCIENCE frames should be provided "
00648                                 "in order to apply sky subtraction!");
00649             cpl_msg_warning("", "All IFUs will be reconstructed regardless if "
00650                                 "they contain object, reference or sky!");
00651         }
00652 
00653         KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, XCAL) == 1,
00654                        CPL_ERROR_FILE_NOT_FOUND,
00655                        "Exactly one XCAL frame is required!");
00656 
00657         KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, YCAL) == 1,
00658                        CPL_ERROR_FILE_NOT_FOUND,
00659                        "Exactly one YCAL frame is required!");
00660 
00661         KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, LCAL) == 1,
00662                        CPL_ERROR_FILE_NOT_FOUND,
00663                        "Exactly one LCAL frame is required!");
00664 
00665         has_master_flat = cpl_frameset_count_tags(frameset, MASTER_FLAT);
00666         KMO_TRY_ASSURE((has_master_flat == 0) || (has_master_flat == 1),
00667                        CPL_ERROR_FILE_NOT_FOUND,
00668                        "At most one MASTER_FLAT frame can be provided!");
00669 
00670         KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, WAVE_BAND) == 1,
00671                        CPL_ERROR_FILE_NOT_FOUND,
00672                        "Exactly one WAVE_BAND frame is required!");
00673 
00674         has_illum_corr = cpl_frameset_count_tags(frameset, ILLUM_CORR);
00675         KMO_TRY_ASSURE((has_illum_corr == 0) || (has_illum_corr == 1),
00676                        CPL_ERROR_FILE_NOT_FOUND,
00677                        "At most one ILLUM_CORR frame can be provided!");
00678 
00679         has_telluric = cpl_frameset_count_tags(frameset, TELLURIC);
00680         KMO_TRY_ASSURE((has_telluric == 0) || (has_telluric == 1),
00681                        CPL_ERROR_FILE_NOT_FOUND,
00682                        "At most one TELLURIC frame can be provided!");
00683 
00684         KMO_TRY_ASSURE(kmo_dfs_set_groups(frameset, "kmo_multi_reconstruct") == 1,
00685                        CPL_ERROR_ILLEGAL_INPUT,
00686                        "Cannot identify RAW and CALIB frames!");
00687 
00688         KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, OH_SPEC) == 0 ||
00689                        cpl_frameset_count_tags(frameset, OH_SPEC) == 1,
00690                        CPL_ERROR_ILLEGAL_INPUT,
00691                        "Only a single reference spectrum can be provided!");
00692         //
00693         // get parameters
00694         //
00695         cpl_msg_info("", "--- Parameter setup for kmo_multi_reconstruct ------");
00696 
00697         flux = kmo_dfs_get_parameter_bool(parlist, "kmos.kmo_multi_reconstruct.flux");
00698         KMO_TRY_ASSURE((flux == 0) ||
00699                        (flux == 1),
00700                        CPL_ERROR_ILLEGAL_INPUT,
00701                        "flux must be either FALSE or TRUE! %d", flux);
00702         KMO_TRY_EXIT_IF_ERROR(
00703             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_multi_reconstruct.flux"));
00704 
00705         background = kmo_dfs_get_parameter_bool(parlist, "kmos.kmo_multi_reconstruct.background");
00706         KMO_TRY_ASSURE((background == 0) ||
00707                        (background == 1),
00708                        CPL_ERROR_ILLEGAL_INPUT,
00709                        "background must be either FALSE or TRUE! %d", background);
00710         KMO_TRY_EXIT_IF_ERROR(
00711             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_multi_reconstruct.background"));
00712 
00713         KMO_TRY_EXIT_IF_NULL(
00714             imethod = kmo_dfs_get_parameter_string(parlist, "kmos.kmo_multi_reconstruct.imethod"));
00715         KMO_TRY_ASSURE((strcmp(imethod, "NN") == 0) ||
00716                        (strcmp(imethod, "lwNN") == 0) ||
00717                        (strcmp(imethod, "swNN") == 0) ||
00718                        (strcmp(imethod, "MS") == 0),
00719                        CPL_ERROR_ILLEGAL_INPUT,
00720                        "imethod must be either \"NN\", \"lwNN\", "
00721                        "\"swNN\" or \"MS\"!");
00722         KMO_TRY_EXIT_IF_ERROR(
00723             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_multi_reconstruct.imethod"));
00724 
00725         neighborhoodRange = kmo_dfs_get_parameter_double(parlist, "kmos.kmo_multi_reconstruct.neighborhoodRange");
00726         KMO_TRY_CHECK_ERROR_STATE();
00727         KMO_TRY_ASSURE(neighborhoodRange > 0.0,
00728                        CPL_ERROR_ILLEGAL_INPUT,
00729                        "neighborhoodRange must be greater than 0.0");
00730         KMO_TRY_EXIT_IF_ERROR(
00731             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_multi_reconstruct.neighborhoodRange"));
00732 
00733         KMO_TRY_EXIT_IF_NULL(
00734             comb_method = kmo_dfs_get_parameter_string(parlist, "kmos.kmo_multi_reconstruct.method"));
00735         KMO_TRY_EXIT_IF_NULL(
00736             fmethod = kmo_dfs_get_parameter_string(parlist, "kmos.kmo_multi_reconstruct.fmethod"));
00737         KMO_TRY_ASSURE((strcmp(comb_method, "none") == 0) ||
00738                        (strcmp(comb_method, "header") == 0) ||
00739                        (strcmp(comb_method, "center") == 0) ||
00740                        (strcmp(comb_method, "user") == 0),
00741                        CPL_ERROR_ILLEGAL_INPUT,
00742                        "Following shift methods are available : 'none', "
00743                        "'header', 'center' or 'user'");
00744 
00745         if (strcmp(comb_method, "user") == 0) {
00746             filename = kmo_dfs_get_parameter_string(parlist, "kmos.kmo_multi_reconstruct.filename");
00747             KMO_TRY_CHECK_ERROR_STATE();
00748             KMO_TRY_ASSURE(strcmp(filename, "") != 0,
00749                            CPL_ERROR_ILLEGAL_INPUT,
00750                            "path of file with shift information must be "
00751                            "provided!");
00752             KMO_TRY_EXIT_IF_ERROR(
00753                 kmo_dfs_print_parameter_help(parlist, "kmos.kmo_multi_reconstruct.filename"));
00754         }
00755 
00756         KMO_TRY_EXIT_IF_ERROR(
00757             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_multi_reconstruct.method"));
00758         ifus_txt = kmo_dfs_get_parameter_string(parlist,
00759                                                   "kmos.kmo_multi_reconstruct.ifus");
00760         KMO_TRY_CHECK_ERROR_STATE();
00761         name = kmo_dfs_get_parameter_string(parlist, "kmos.kmo_multi_reconstruct.name");
00762         KMO_TRY_CHECK_ERROR_STATE();
00763 
00764         if (strcmp(ifus_txt, "") != 0) {
00765             KMO_TRY_ASSURE(strcmp(name, "") == 0,
00766                            CPL_ERROR_ILLEGAL_INPUT,
00767                            "name parameter must be NULL if IFU indices are "
00768                            "provided!");
00769 
00770             KMO_TRY_EXIT_IF_NULL(
00771                 ifus = kmo_identify_values(ifus_txt));
00772 
00773             KMO_TRY_ASSURE(cpl_vector_get_size(ifus) == nr_science_frames,
00774                            CPL_ERROR_ILLEGAL_INPUT,
00775                            "ifus parameter must have the same number of values "
00776                            "than frames provided (for frames just containing "
00777                            "skies insert 0)) (%lld=%d)",
00778                            cpl_vector_get_size(ifus), nr_science_frames);
00779         }
00780 
00781         if (strcmp(name, "") != 0) {
00782             KMO_TRY_ASSURE(strcmp(ifus_txt, "") == 0,
00783                            CPL_ERROR_ILLEGAL_INPUT,
00784                            "ifus parameter must be NULL if name is provided!");
00785         }
00786 
00787         KMO_TRY_EXIT_IF_ERROR(
00788             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_multi_reconstruct.ifus"));
00789         KMO_TRY_EXIT_IF_ERROR(
00790             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_multi_reconstruct.name"));
00791 
00792         kmo_band_pars_load(parlist, "kmos.kmo_multi_reconstruct");
00793 
00794         no_subtract = kmo_dfs_get_parameter_bool(parlist, "kmos.kmo_multi_reconstruct.no_subtract");
00795         KMO_TRY_CHECK_ERROR_STATE();
00796         KMO_TRY_ASSURE((no_subtract == TRUE) || (no_subtract == FALSE),
00797                        CPL_ERROR_ILLEGAL_INPUT,
00798                        "no_subtract must be TRUE or FALSE!");
00799         KMO_TRY_EXIT_IF_ERROR(
00800             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_multi_reconstruct.no_subtract"));
00801 
00802         pix_scale = kmo_dfs_get_parameter_double(parlist, "kmos.kmo_multi_reconstruct.pix_scale");
00803         KMO_TRY_CHECK_ERROR_STATE();
00804         KMO_TRY_ASSURE((pix_scale >= 0.01) &&
00805                        (pix_scale <= 0.4),
00806                        CPL_ERROR_ILLEGAL_INPUT,
00807                        "pix_scale must be between 0.01 and 0.4 (results in cubes "
00808                        "with 7x7 to 280x280 pixels)!");
00809         KMO_TRY_EXIT_IF_ERROR(
00810            kmo_dfs_print_parameter_help(parlist, "kmos.kmo_multi_reconstruct.pix_scale"));
00811 
00812         xcal_interpolation = kmo_dfs_get_parameter_bool(parlist, "kmos.kmo_multi_reconstruct.xcal_interpolation");
00813         KMO_TRY_CHECK_ERROR_STATE();
00814         KMO_TRY_ASSURE((xcal_interpolation == TRUE) ||
00815                        (xcal_interpolation == FALSE),
00816                        CPL_ERROR_ILLEGAL_INPUT,
00817                        "xcal_interpolation must be TRUE or FALSE!");
00818         KMO_TRY_EXIT_IF_ERROR(
00819             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_multi_reconstruct.xcal_interpolation"));
00820 
00821         suppress_extension = kmo_dfs_get_parameter_bool(parlist, "kmos.kmo_multi_reconstruct.suppress_extension");
00822         KMO_TRY_CHECK_ERROR_STATE();
00823         KMO_TRY_ASSURE((suppress_extension == TRUE) || (suppress_extension == FALSE),
00824                        CPL_ERROR_ILLEGAL_INPUT,
00825                        "suppress_extension must be TRUE or FALSE!");
00826         KMO_TRY_EXIT_IF_ERROR(
00827             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_multi_reconstruct.suppress_extension"));
00828 
00829         dev_cal = kmo_dfs_get_parameter_bool(parlist, "kmos.kmo_multi_reconstruct.dev_cal");
00830         KMO_TRY_CHECK_ERROR_STATE();
00831         KMO_TRY_ASSURE((dev_cal == TRUE) || (dev_cal == FALSE),
00832                        CPL_ERROR_ILLEGAL_INPUT,
00833                        "dev_cal must be TRUE or FALSE!");
00834         KMO_TRY_EXIT_IF_ERROR(
00835             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_multi_reconstruct.dev_cal"));
00836 
00837         KMO_TRY_EXIT_IF_ERROR(
00838             kmo_combine_pars_load(parlist,
00839                                   "kmos.kmo_multi_reconstruct",
00840                                   &cmethod,
00841                                   &cpos_rej,
00842                                   &cneg_rej,
00843                                   &citer,
00844                                   &cmin,
00845                                   &cmax,
00846                                   FALSE));
00847 
00848         cpl_msg_info("", "-------------------------------------------");
00849 
00850         //
00851         // assure that filters, grating and rotation offsets match for
00852         // XCAL, YCAL, LCAL and for data frame to reconstruct (except DARK
00853         // frames)
00854         //
00855 
00856         // check if filter_id and grating_id match for all detectors
00857         KMO_TRY_EXIT_IF_ERROR(
00858             kmo_check_frameset_setup(frameset, SCIENCE, TRUE, FALSE, TRUE));
00859         KMO_TRY_EXIT_IF_ERROR(
00860             kmo_check_frame_setup(frameset, SCIENCE, YCAL, TRUE, FALSE, TRUE));
00861         KMO_TRY_EXIT_IF_ERROR(
00862             kmo_check_frame_setup(frameset, XCAL, YCAL, TRUE, FALSE, TRUE));
00863         KMO_TRY_EXIT_IF_ERROR(
00864             kmo_check_frame_setup(frameset, XCAL, LCAL, TRUE, FALSE, TRUE));
00865         if (has_master_flat) {
00866             KMO_TRY_EXIT_IF_ERROR(
00867                 kmo_check_frame_setup(frameset, XCAL, MASTER_FLAT, TRUE, FALSE, TRUE));
00868         }
00869         if (has_telluric) {
00870             KMO_TRY_EXIT_IF_ERROR(
00871                 kmo_check_frame_setup(frameset, XCAL, TELLURIC,
00872                                            TRUE, FALSE, TRUE));
00873         }
00874 
00875         // check descriptors of all frames
00876         KMO_TRY_EXIT_IF_NULL(
00877             xcal_frame = kmo_dfs_get_frame(frameset, XCAL));
00878 
00879         desc1 = kmo_identify_fits_header(cpl_frame_get_filename(xcal_frame));
00880         KMO_TRY_CHECK_ERROR_STATE();
00881 
00882         KMO_TRY_ASSURE((desc1.nr_ext % KMOS_NR_DETECTORS == 0) &&
00883                        (desc1.ex_badpix == FALSE) &&
00884                        (desc1.fits_type == f2d_fits) &&
00885                        (desc1.frame_type == detector_frame),
00886                        CPL_ERROR_ILLEGAL_INPUT,
00887                        "XCAL isn't in the correct format!!!");
00888 
00889         KMO_TRY_EXIT_IF_NULL(
00890             ycal_frame = kmo_dfs_get_frame(frameset, YCAL));
00891         desc2 = kmo_identify_fits_header(cpl_frame_get_filename(ycal_frame));
00892         KMO_TRY_CHECK_ERROR_STATE();
00893 
00894         KMO_TRY_ASSURE((desc1.nr_ext == desc2.nr_ext) &&
00895                        (desc1.ex_badpix == desc2.ex_badpix) &&
00896                        (desc1.fits_type == desc2.fits_type) &&
00897                        (desc1.frame_type == desc2.frame_type),
00898                        CPL_ERROR_ILLEGAL_INPUT,
00899                        "YCAL isn't in the correct format!!!");
00900         kmo_free_fits_desc(&desc2);
00901         kmo_init_fits_desc(&desc2);
00902 
00903         KMO_TRY_EXIT_IF_NULL(
00904             lcal_frame = kmo_dfs_get_frame(frameset, LCAL));
00905         desc2 = kmo_identify_fits_header(cpl_frame_get_filename(lcal_frame));
00906         KMO_TRY_CHECK_ERROR_STATE();
00907 
00908         KMO_TRY_ASSURE((desc2.nr_ext % KMOS_NR_DETECTORS == 0) &&
00909                        (desc1.ex_badpix == desc2.ex_badpix) &&
00910                        (desc1.fits_type == desc2.fits_type) &&
00911                        (desc1.frame_type == desc2.frame_type),
00912                        CPL_ERROR_ILLEGAL_INPUT,
00913                        "LCAL isn't in the correct format!!!");
00914         kmo_free_fits_desc(&desc2);
00915         kmo_init_fits_desc(&desc2);
00916 
00917         if (has_master_flat) {
00918             KMO_TRY_EXIT_IF_NULL(
00919                 flat_frame = kmo_dfs_get_frame(frameset, MASTER_FLAT));
00920             desc2 = kmo_identify_fits_header(cpl_frame_get_filename(flat_frame));
00921             KMO_TRY_CHECK_ERROR_STATE();
00922 
00923             KMO_TRY_ASSURE((desc2.nr_ext % (2*KMOS_NR_DETECTORS) == 0) &&
00924                            (desc1.ex_badpix == desc2.ex_badpix) &&
00925                            (desc1.fits_type == desc2.fits_type) &&
00926                            (desc1.frame_type == desc2.frame_type),
00927                            CPL_ERROR_ILLEGAL_INPUT,
00928                            "MASTER_FLAT isn't in the correct format!!!");
00929             kmo_free_fits_desc(&desc2);
00930             kmo_init_fits_desc(&desc2);
00931         }
00932 
00933         if (has_illum_corr) {
00934             KMO_TRY_EXIT_IF_NULL(
00935                 illum_frame = kmo_dfs_get_frame(frameset, ILLUM_CORR));
00936             desc2 = kmo_identify_fits_header(
00937                         cpl_frame_get_filename(illum_frame));
00938             KMO_TRY_CHECK_ERROR_STATE();
00939             KMO_TRY_ASSURE(((desc2.nr_ext == 24) || (desc2.nr_ext == 48)) &&
00940                            (desc2.ex_badpix == FALSE) &&
00941                            (desc2.fits_type == f2i_fits) &&
00942                            (desc2.frame_type == ifu_frame),
00943                            CPL_ERROR_ILLEGAL_INPUT,
00944                            "ILLUM_CORR isn't in the correct format!!!");
00945             kmo_free_fits_desc(&desc2);
00946             kmo_init_fits_desc(&desc2);
00947         }
00948 
00949         if (has_telluric) {
00950             KMO_TRY_EXIT_IF_NULL(
00951                 telluric_frame = kmo_dfs_get_frame(frameset, TELLURIC));
00952             desc_telluric = kmo_identify_fits_header(
00953                         cpl_frame_get_filename(telluric_frame));
00954             KMO_TRY_CHECK_ERROR_STATE();
00955             KMO_TRY_ASSURE(((desc_telluric.nr_ext == 24) || (desc_telluric.nr_ext == 48)) &&
00956                            (desc_telluric.ex_badpix == FALSE) &&
00957                            (desc_telluric.fits_type == f1i_fits) &&
00958                            (desc_telluric.frame_type == ifu_frame),
00959                            CPL_ERROR_ILLEGAL_INPUT,
00960                            "TELLURIC isn't in the correct format!!!");
00961         }
00962 
00963         KMO_TRY_EXIT_IF_NULL(
00964             science_frame = kmo_dfs_get_frame(frameset, SCIENCE));
00965         while (science_frame != NULL ) {
00966             desc2 = kmo_identify_fits_header(cpl_frame_get_filename(science_frame));
00967             KMO_TRY_CHECK_ERROR_STATE();
00968             KMO_TRY_ASSURE((desc2.nr_ext == 3) &&
00969                            (desc2.ex_badpix == FALSE) &&
00970                            (desc2.fits_type == raw_fits) &&
00971                            (desc2.frame_type == detector_frame),
00972                            CPL_ERROR_ILLEGAL_INPUT,
00973                            "SCIENCE isn't in the correct format!!!");
00974             kmo_free_fits_desc(&desc2);
00975             kmo_init_fits_desc(&desc2);
00976 
00977             if (mapping_mode == NULL) {
00978                 KMO_TRY_EXIT_IF_NULL(
00979                     tmp_header =
00980                           kmclipm_propertylist_load(
00981                                          cpl_frame_get_filename(science_frame), 0));
00982                 if (cpl_propertylist_has(tmp_header, TPL_ID)) {
00983                     KMO_TRY_EXIT_IF_NULL(
00984                         tmp_str = cpl_propertylist_get_string(tmp_header,
00985                                                               TPL_ID));
00986                     if (strcmp(tmp_str, MAPPING8) == 0)
00987                     {
00988                         mapping_mode = cpl_sprintf("%s", "mapping8");
00989                     }
00990                     if (strcmp(tmp_str, MAPPING24) == 0)
00991                     {
00992                         mapping_mode = cpl_sprintf("%s", "mapping24");
00993                     }
00994                 }
00995 
00996                 // when mapping-mode should be supported, remove this if-statement...
00997                 if (mapping_mode != NULL) {
00998                     cpl_msg_error("", "*******************************************************");
00999                     cpl_msg_error("", "*******************************************************");
01000                     cpl_msg_error("", "***                                                 ***");
01001                     cpl_msg_error("", "*** The provided SCIENCE frames have been produced  ***");
01002                     cpl_msg_error("", "*** with template %s           ***", tmp_str);
01003                     cpl_msg_error("", "***                                                 ***");
01004                     cpl_msg_error("", "*** kmo_multi_reconstruct doesn't support yet this  ***");
01005                     cpl_msg_error("", "*** observation mode. Please use recipe kmo_sci_red ***");
01006                     cpl_msg_error("", "*** instead!                                        ***");
01007                     cpl_msg_error("", "***                                                 ***");
01008                     cpl_msg_error("", "*******************************************************");
01009                     cpl_msg_error("", "*******************************************************");
01010                     KMO_TRY_ASSURE(1==0,
01011                                    CPL_ERROR_ILLEGAL_INPUT,
01012                                    " ");
01013                 }
01014 
01015                 cpl_propertylist_delete(tmp_header); tmp_header = NULL;
01016             }
01017 
01018             science_frame = kmo_dfs_get_frame(frameset, NULL);
01019             KMO_TRY_CHECK_ERROR_STATE();
01020         }
01021 
01022         if ((mapping_mode != NULL) && ((ifus != NULL) || (strcmp(name, "") != 0))) {
01023             cpl_msg_warning("","The SCIENCE frames have been taken in one of the "
01024                                "mapping modes AND specific IFUs have been "
01025                                "specified! --> Only processing these!");
01026         }
01027 
01028         KMO_TRY_EXIT_IF_NULL(
01029             suffix = kmo_dfs_get_suffix(xcal_frame, TRUE, FALSE));
01030 
01031         KMO_TRY_EXIT_IF_ERROR(
01032             kmo_check_frame_setup_md5_xycal(frameset));
01033         KMO_TRY_EXIT_IF_ERROR(
01034             kmo_check_frame_setup_md5(frameset));
01035         KMO_TRY_EXIT_IF_ERROR(
01036             kmo_check_frame_setup_sampling(frameset));
01037 
01038         cpl_msg_info("", "Detected instrument setup:   %s", suffix+1);
01039         cpl_msg_info("", "(grating 1, 2 & 3)");
01040         cpl_msg_info("", "-------------------------------------------");
01041         cpl_free(suffix); suffix = NULL;
01042 
01043         if (cpl_frameset_count_tags(frameset, OH_SPEC) != 0) {
01044             int         is_all_obs          = TRUE,
01045                         has_all_origfile    = TRUE;
01046             cpl_frame   *tmp_frame          = NULL;
01047 
01048             KMO_TRY_EXIT_IF_NULL(
01049                 tmp_frame = kmo_dfs_get_frame(frameset, SCIENCE));
01050             while (tmp_frame != NULL ) {
01051                 KMO_TRY_EXIT_IF_NULL(
01052                     tmp_header = kmclipm_propertylist_load(cpl_frame_get_filename(tmp_frame), 0));
01053 
01054                 if (cpl_propertylist_has(tmp_header, ORIGFILE)) {
01055                     KMO_TRY_EXIT_IF_NULL(
01056                         tmp_str = cpl_propertylist_get_string(tmp_header, ORIGFILE));
01057                     if (strstr(tmp_str, "OBS") == NULL) {
01058                         is_all_obs = FALSE;
01059                     }
01060                 } else {
01061                     has_all_origfile = FALSE;
01062                 }
01063                 cpl_propertylist_delete(tmp_header); tmp_header = NULL;
01064                 tmp_frame = kmo_dfs_get_frame(frameset, NULL);
01065                 KMO_TRY_CHECK_ERROR_STATE();
01066             }
01067 
01068             if (has_all_origfile) {
01069                 if (is_all_obs) {
01070                     // we are reconstructing an OBS-frame, allow OH_SPEC correction
01071                     KMO_TRY_EXIT_IF_NULL(
01072                         ref_spectrum_frame = kmo_dfs_get_frame(frameset, OH_SPEC));
01073                 } else {
01074                     cpl_msg_warning("", "Supplied OH_SPEC is ignored since a calibration "
01075                                         "frame is being used as SCIENCE frame.");
01076                 }
01077             } else {
01078                 cpl_msg_warning("", "The supplied SCIENCE frames are all assumed to be "
01079                                     "science frames. If any of them is a calibration frame, "
01080                                     "omit OH_SPEC from sof-file");
01081                 KMO_TRY_EXIT_IF_NULL(
01082                     ref_spectrum_frame = kmo_dfs_get_frame(frameset, OH_SPEC));
01083             }
01084         }
01085 
01086         //
01087         // check which IFUs are active for all frames
01088         //
01089         KMO_TRY_EXIT_IF_NULL(
01090             unused_ifus_before = kmo_get_unused_ifus(frameset, 1, 1));
01091 
01092         KMO_TRY_EXIT_IF_NULL(
01093             unused_ifus_after = kmo_duplicate_unused_ifus(unused_ifus_before));
01094 
01095         kmo_print_unused_ifus(unused_ifus_before, FALSE);
01096 
01097         //
01098         // get bounds, setup grid, setup arm_name-struct
01099         //
01100 
01101         // get left and right bounds of IFUs
01102         KMO_TRY_EXIT_IF_NULL(
01103             tmp_header = kmo_dfs_load_primary_header(frameset, XCAL));
01104         KMO_TRY_EXIT_IF_NULL(
01105             bounds = kmclipm_extract_bounds(tmp_header));
01106         cpl_propertylist_delete(tmp_header); tmp_header = NULL;
01107 
01108         // setup grid definition, wavelength start and end points will be set
01109         // in the detector loop
01110         KMO_TRY_EXIT_IF_ERROR(
01111             kmclipm_setup_grid(&gd, imethod, neighborhoodRange, pix_scale, 0.));
01112         KMO_TRY_EXIT_IF_ERROR(
01113             kmclipm_setup_grid(&gd_14x14, imethod, neighborhoodRange, pix_scale, 0.));
01114 
01115         KMO_TRY_EXIT_IF_NULL(
01116             band_table = kmo_dfs_load_table(frameset, WAVE_BAND, 1, 0));
01117         KMO_TRY_EXIT_IF_NULL(
01118             tmp_header = kmo_dfs_load_primary_header(frameset, LCAL));
01119         KMO_TRY_EXIT_IF_NULL(
01120             filter_id = cpl_sprintf("%s", cpl_propertylist_get_string(tmp_header, filter_keyword)));
01121         KMO_TRY_EXIT_IF_ERROR(
01122             kmclipm_setup_grid_band_lcal(&gd, NULL, filter_id, 0, band_table));
01123         KMO_TRY_EXIT_IF_ERROR(
01124             kmclipm_setup_grid_band_lcal(&gd_14x14, NULL, filter_id, 0, band_table));
01125         cpl_propertylist_delete(tmp_header); tmp_header = NULL;
01126         cpl_table_delete(band_table); band_table = NULL;
01127 
01128         //
01129         // get valid object names to process, either one object name across
01130         // several SCIENCE frames, or all object names
01131         //
01132         KMO_TRY_EXIT_IF_NULL(
01133             arm_name_struct = kmo_create_armNameStruct(frameset,
01134                                                        SCIENCE,
01135                                                        ifus,
01136                                                        name,
01137                                                        unused_ifus_after,
01138                                                        bounds,
01139                                                        mapping_mode,
01140                                                        no_subtract));
01141         cpl_free(bounds); bounds = NULL;
01142 
01143         kmo_print_armNameStruct(frameset, arm_name_struct);
01144 
01145         //
01146         // check availability of tellurics for the different IFUs used
01147         //
01148         if (has_telluric && (mapping_mode != NULL)) {
01149             // in mapping-mode check if for all IFUs there is either no telluric at all
01150             // or the same number of tellurics than object names
01151             int telluric_ok = TRUE;
01152             for (cnt = 0; cnt < arm_name_struct->nrNames; cnt++) {
01153                 if (!((arm_name_struct->telluricCnt[cnt] == arm_name_struct->namesCnt[cnt]) ||
01154                     (arm_name_struct->telluricCnt[cnt] == 0)))
01155                 {
01156                     telluric_ok = FALSE;
01157                     break;
01158                 }
01159             }
01160             if (!telluric_ok) {
01161                 KMO_TRY_ASSURE(1==0,
01162                                CPL_ERROR_UNSUPPORTED_MODE,
01163                                "Mosaics need a TELLURIC frame with at least a telluric correction per detector available! "
01164                                "Omit the TELLURIC from your sof-file or choose another TELLURIC!");
01165             }
01166         }
01167 
01168         //
01169         // loop over all object names
01170         //   (for mapping template only once,)
01171         //   (when ifus or name is set as well only once)
01172         //
01173         for (arm_index = 0; arm_index < arm_name_struct->nrNames; arm_index++) {
01174 
01175             nr_frames = arm_name_struct->namesCnt[arm_index];
01176 
01177             KMO_TRY_EXIT_IF_NULL(
01178                 sub_headers = kmo_mr_get_headers(arm_name_struct,
01179                                                  arm_index+1,
01180                                                  frameset,
01181                                                  gd_14x14));
01182 
01183             if ((strcmp(comb_method, "center") == 0) ||
01184                 (ref_spectrum_frame != NULL))
01185             {
01186                 //
01187                 // reconstruct preliminary cubes
01188                 //
01189                 KMO_TRY_EXIT_IF_NULL(
01190                     pre_data_cube_list = kmo_mr_create_datacubes(arm_name_struct,
01191                                                                  arm_index+1,
01192                                                                  frameset,
01193                                                                  gd_14x14,
01194                                                                  xcal_interpolation));
01195                 //
01196                 // calculate lambda-correction coefficients
01197                 //
01198                 if (ref_spectrum_frame != NULL) {
01199                     KMO_TRY_EXIT_IF_NULL(
01200                         lcorr_coeffs = cpl_calloc(nr_frames, sizeof(cpl_polynomial*)));
01201 
01202                     cnt = 0;
01203                     for (iy = 0; iy < arm_name_struct->size; iy++) {
01204                         for (ix = 0; ix < KMOS_NR_IFUS; ix++) {
01205                             ifu_nr = ix + 1;
01206                             if (arm_name_struct->name_ids[ix+iy*KMOS_NR_IFUS] == arm_index+1) {
01207                                 KMO_TRY_EXIT_IF_NULL(
01208                                     lcorr_coeffs[cnt] = kmo_lcorr_get(pre_data_cube_list[cnt],
01209                                                                       sub_headers[cnt],
01210                                                                       ref_spectrum_frame,
01211                                                                       gd_14x14,
01212                                                                       filter_id,
01213                                                                       ifu_nr));
01214                                 cnt++;
01215                             }
01216                         }
01217                     }
01218                 } // end if (lcorr)
01219             } // end if (center, lcorr)
01220 
01221             //
01222             // calculate offsets
01223             //
01224             KMO_TRY_EXIT_IF_ERROR(
01225                 kmo_mr_get_offsets(arm_name_struct,
01226                                    arm_index+1,
01227                                    comb_method,
01228                                    imethod,
01229                                    filename,
01230                                    frameset,
01231                                    pre_data_cube_list,
01232                                    sub_headers,
01233                                    fmethod,
01234                                    cmethod,
01235                                    cpos_rej,
01236                                    cneg_rej,
01237                                    citer,
01238                                    cmin,
01239                                    cmax,
01240                                    dev_cal,
01241                                    mapping_mode,
01242                                    &xshifts,
01243                                    &yshifts));
01244 
01245             KMO_TRY_EXIT_IF_NULL(
01246                 ref_sub_header = cpl_propertylist_duplicate(sub_headers[0]));
01247 
01248             for (cnt = 0; cnt < nr_frames; cnt++) {
01249                 cpl_propertylist_delete(sub_headers[cnt]); sub_headers[cnt] = NULL;
01250             }
01251             cpl_free(sub_headers); sub_headers = NULL;
01252 
01253             if (pre_data_cube_list != NULL) {
01254                 for (cnt = 0; cnt < nr_frames; cnt++) {
01255                     cpl_imagelist_delete(pre_data_cube_list[cnt]);
01256                 }
01257                 cpl_free(pre_data_cube_list); pre_data_cube_list = NULL;
01258             }
01259 
01260             //
01261             // set spatial part of the grid
01262             //
01263             for (cnt = 0; cnt < nr_frames; cnt++) {
01264                 if (xmin > xshifts[cnt]) {
01265                     xmin = xshifts[cnt];
01266                 }
01267                 if (xmax < xshifts[cnt]) {
01268                     xmax = xshifts[cnt];
01269                 }
01270                 if (ymin > yshifts[cnt]) {
01271                     ymin = yshifts[cnt];
01272                 }
01273                 if (ymax < yshifts[cnt]) {
01274                     ymax = yshifts[cnt];
01275                 }
01276             }
01277 
01278             if (xmax > 0.0001) {
01279                 gxshift = -rint(xmax);      //(int)xmax;   // gxshift = - ceil(xmax);
01280             } else {
01281                 gxshift = 0.;
01282             }
01283             if (ymin < -0.0001) {
01284                 gyshift = rint(ymin);   //(int)ymin;    // gyshift = floor(ymin);
01285             } else {
01286                 gyshift = 0.;
01287             }
01288             if (xmin < -0.0001) {
01289                 gxdim = - floor(xmin);
01290             } else {
01291                 gxdim = 0.;
01292             }
01293             if (ymax > 0.0001) {
01294                 gydim = ceil(ymax);
01295             } else {
01296                 gydim = 0.;
01297             }
01298 
01299             xdim = (int)(gxdim - gxshift + .5);
01300             ydim = (int)(gydim - gyshift + .5);
01301             gd.x.start += gxshift * pix_scale*1000;
01302             gd.y.start += gyshift * pix_scale*1000;
01303             gd.x.dim += xdim;
01304             gd.y.dim += ydim;
01305 
01306 //            cpl_msg_set_level(CPL_MSG_DEBUG);
01307 //            cpl_msg_debug(cpl_func,"x: %f < %f,   y: %f < %f",
01308 //                              xmin,xmax,ymin,ymax);
01309 //            cpl_msg_debug(cpl_func,"gxshift: %f gxdim: %f xdim: %d,   gyshift: %f gydim: %f ydim: %d",
01310 //                              gxshift, gxdim, xdim, gyshift, gydim, ydim);
01311 //            cpl_msg_debug(cpl_func,"gd: start          delta            dim");
01312 //            cpl_msg_debug(cpl_func," x: %f      %f      %d", gd.x.start, gd.x.delta, gd.x.dim);
01313 //            cpl_msg_debug(cpl_func," y: %f      %f      %d", gd.y.start, gd.y.delta, gd.y.dim);
01314 //            cpl_msg_debug(cpl_func," l: %f      %f      %d", gd.l.start, gd.l.delta, gd.l.dim);
01315 //            cpl_msg_set_level(CPL_MSG_INFO);
01316 
01317             //
01318             // reconstruct multiple detector images
01319             //
01320             KMO_TRY_EXIT_IF_ERROR(
01321                 kmo_mr_reconstruct(frameset,
01322                                    arm_name_struct,
01323                                    arm_index+1,
01324                                    xshifts,
01325                                    yshifts,
01326                                    gd,
01327                                    gd_14x14,
01328                                    pix_scale,
01329                                    xcal_interpolation,
01330                                    lcorr_coeffs,
01331                                    &cube_combined_data,
01332                                    &cube_combined_noise,
01333                                    no_subtract,
01334                                    flux,
01335                                    background));
01336 
01337             if (lcorr_coeffs != NULL) {
01338                 for (cnt = 0; cnt < nr_frames; cnt++) {
01339                     cpl_polynomial_delete(lcorr_coeffs[cnt]); lcorr_coeffs[cnt] = NULL;
01340                 }
01341                 cpl_free(lcorr_coeffs); lcorr_coeffs = NULL;
01342             }
01343 
01344             //
01345             // identify ifu_nr of current object name in first SCIENCE frame
01346             // containing this object name (e.g. first frame could contain skies only)
01347             //
01348             ifu_nr = -1;
01349             science_frame = NULL;
01350             for (iy = 0; iy < arm_name_struct->size; iy++) {
01351                 for (ix = 0; ix < KMOS_NR_IFUS; ix++) {
01352                     if (arm_name_struct->name_ids[ix+iy*KMOS_NR_IFUS] == arm_index+1) {
01353                         if (ifu_nr == -1) {
01354                             KMO_TRY_EXIT_IF_NULL(
01355                                 science_frame = arm_name_struct->obj_sky_struct->table[iy].objFrame);
01356 
01357                             ifu_nr = ix + 1;
01358                             break;
01359                         }
01360                     }
01361                 }
01362                 if (ifu_nr != -1) { break; }
01363             }
01364 
01365             //
01366             // divide cube by telluric correction
01367             //
01368             if (has_telluric &&
01369                 (arm_name_struct->sameTelluric[arm_index] > 0))
01370             {
01371                 telluric_data = kmo_tweak_load_telluric(frameset, ifu_nr, FALSE, no_subtract);
01372                 KMO_TRY_CHECK_ERROR_STATE();
01373                 if (telluric_data != NULL) {
01374                     int index = kmo_identify_index_desc(desc_telluric, ifu_nr, TRUE);
01375                     KMO_TRY_CHECK_ERROR_STATE();
01376                     if (desc_telluric.sub_desc[index-1].valid_data == TRUE) {
01377                         // load noise if present
01378                         telluric_noise = kmo_tweak_load_telluric(frameset, ifu_nr, TRUE, no_subtract);
01379                         KMO_TRY_CHECK_ERROR_STATE();
01380                     } else {
01381                         if (print_warning_once_tweak_std_noise && (cube_combined_noise != NULL)) {
01382                             cpl_msg_warning("","************************************************************");
01383                             cpl_msg_warning("","* Noise cubes were calculated, but won't be divided by     *");
01384                             cpl_msg_warning("","* telluric error since it is missing.                      *");
01385                             cpl_msg_warning("","* In order to get a telluric with errors, execute          *");
01386                             cpl_msg_warning("","* kmo_std_star with one of the nearest neighbour methods   *");
01387                             cpl_msg_warning("","* (set --imethod to NN, lwNN or swNN)                      *");
01388                             cpl_msg_warning("","************************************************************");
01389                             print_warning_once_tweak_std_noise = FALSE;
01390                         }
01391                     }
01392 
01393                     KMO_TRY_EXIT_IF_ERROR(
01394                         kmo_arithmetic_3D_1D(
01395                                 cube_combined_data, telluric_data,
01396                                 cube_combined_noise, telluric_noise, "/"));
01397                 }
01398                 kmclipm_vector_delete(telluric_data); telluric_data = NULL;
01399                 kmclipm_vector_delete(telluric_noise); telluric_noise = NULL;
01400             }
01401 
01402             //
01403             // saving
01404             //
01405             fn_cube = CUBE_MULTI;
01406             if (!suppress_extension) {
01407                 char tmp_suffix[1024];
01408                 tmp_suffix[0] = '\0';
01409 
01410                 if (arm_name_struct->telluricCnt[arm_index] == nr_frames) {
01411                     strcat(tmp_suffix, "_telluric");
01412                 }
01413                 if (has_illum_corr) {
01414                     strcat(tmp_suffix, "_illum");
01415                 }
01416 //                if (sky_tweak) {
01417 //                    strcat(tmp_suffix, "_skytweak");
01418 //                }
01419 
01420                 if (strlen(tmp_suffix) > 0) {
01421                     KMO_TRY_EXIT_IF_NULL(
01422                         fn_suffix = cpl_sprintf("_%s_%s", arm_name_struct->names[arm_index], tmp_suffix));
01423                 } else {
01424                     KMO_TRY_EXIT_IF_NULL(
01425                         fn_suffix = cpl_sprintf("_%s", arm_name_struct->names[arm_index]));
01426                 }
01427             } else {
01428                 KMO_TRY_EXIT_IF_NULL(
01429                     fn_suffix = cpl_sprintf("_%d", suppress_index++));
01430             }
01431 
01432             //
01433             // calculate WCS
01434             //
01435             KMO_TRY_EXIT_IF_NULL(
01436                 science_frame_header = kmclipm_propertylist_load(cpl_frame_get_filename(science_frame), 0));
01437 
01438             KMO_TRY_EXIT_IF_ERROR(
01439                 kmo_calc_wcs_gd(science_frame_header, ref_sub_header, ifu_nr, gd));
01440 
01441             cpl_propertylist_delete(science_frame_header); science_frame_header = NULL;
01442 
01443             //
01444             // save product
01445             //
01446             KMO_TRY_EXIT_IF_ERROR(
01447                 kmo_dfs_save_main_header(frameset, fn_cube, fn_suffix,
01448                                          science_frame, NULL, parlist, cpl_func));
01449 
01450             KMO_TRY_EXIT_IF_NULL(
01451                 extname = cpl_sprintf("%s.DATA", arm_name_struct->names[arm_index]));
01452             KMO_TRY_EXIT_IF_ERROR(
01453                 kmclipm_update_property_string(ref_sub_header,
01454                                                EXTNAME,
01455                                                extname,
01456                                                "FITS extension name"));
01457             cpl_free(extname); extname = NULL;
01458 
01459             KMO_TRY_EXIT_IF_ERROR(
01460                 kmo_dfs_save_cube(cube_combined_data, fn_cube, fn_suffix,
01461                                   ref_sub_header, 0./0.));
01462 
01463             if (cube_combined_noise != NULL) {
01464                 KMO_TRY_EXIT_IF_NULL(
01465                     extname = cpl_sprintf("%s.NOISE", arm_name_struct->names[arm_index]));
01466                 KMO_TRY_EXIT_IF_ERROR(
01467                     kmclipm_update_property_string(ref_sub_header,
01468                                                    EXTNAME,
01469                                                    extname,
01470                                                    "FITS extension name"));
01471                 cpl_free(extname); extname = NULL;
01472 
01473                 KMO_TRY_EXIT_IF_ERROR(
01474                     kmo_dfs_save_cube(cube_combined_noise, fn_cube, fn_suffix,
01475                                       ref_sub_header, 0./0.));
01476             }
01477 
01478             cpl_imagelist_delete(cube_combined_data); cube_combined_data = NULL;
01479             cpl_imagelist_delete(cube_combined_noise); cube_combined_noise = NULL;
01480             cpl_propertylist_delete(ref_sub_header); ref_sub_header = NULL;
01481             cpl_free(fn_suffix); fn_suffix = NULL;
01482             cpl_free(xshifts); xshifts = NULL;
01483             cpl_free(yshifts); yshifts = NULL;
01484         }  // for (arm_index = nrNames)
01485 
01486         kmo_print_unused_ifus(unused_ifus_after, TRUE);
01487     }
01488     KMO_CATCH
01489     {
01490         KMO_CATCH_MSG();
01491         ret_val = -1;
01492     }
01493 
01494     kmo_free_fits_desc(&desc1);
01495     kmo_free_fits_desc(&desc2);
01496     kmo_free_fits_desc(&desc_telluric);
01497     cpl_vector_delete(ifus); ifus = NULL;
01498     cpl_free(mapping_mode); mapping_mode = NULL;
01499     if (unused_ifus_before != NULL) {
01500         kmo_free_unused_ifus(unused_ifus_before); unused_ifus_before = NULL;
01501     }
01502     if (unused_ifus_after != NULL) {
01503         kmo_free_unused_ifus(unused_ifus_after); unused_ifus_after = NULL;
01504     }
01505     if (bounds != NULL) {
01506         cpl_free(bounds); bounds = NULL;
01507     }
01508 
01509     kmo_delete_armNameStruct(arm_name_struct);
01510 
01511     // frees for the case of errors
01512     kmclipm_vector_delete(telluric_data); telluric_data = NULL;
01513     kmclipm_vector_delete(telluric_noise); telluric_noise = NULL;
01514     cpl_propertylist_delete(tmp_header); tmp_header = NULL;
01515     cpl_table_delete(band_table); band_table = NULL;
01516     cpl_free(suffix); suffix = NULL;
01517     cpl_free(fn_suffix); fn_suffix = NULL;
01518     cpl_free(filter_id); filter_id = NULL;
01519 
01520     return ret_val;
01521 }
01522