KMOS Pipeline Reference Manual  1.2.7
kmo_std_star.c
00001 /* $Id: kmo_std_star.c,v 1.79 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.79 $
00025  * $Name:  $
00026  */
00027 
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031 
00032 /*-----------------------------------------------------------------------------
00033  *                              Includes
00034  *----------------------------------------------------------------------------*/
00035 
00036 #include <math.h>
00037 #include <string.h>
00038 
00039 #include <cpl.h>
00040 #include "kmclipm_math.h"
00041 
00042 #include "kmo_constants.h"
00043 #include "kmo_cpl_extensions.h"
00044 #include "kmo_utils.h"
00045 #include "kmo_functions.h"
00046 #include "kmo_priv_std_star.h"
00047 #include "kmo_priv_fit_profile.h"
00048 #include "kmo_priv_extract_spec.h"
00049 #include "kmo_priv_functions.h"
00050 #include "kmo_dfs.h"
00051 #include "kmo_error.h"
00052 #include "kmo_debug.h"
00053 #include "kmo_priv_reconstruct.h"
00054 
00055 /*-----------------------------------------------------------------------------
00056  *              Lines (all vacuum)
00057  *
00058 # Line lists for use in telluric transmission correction for KMOS, etc.
00059 # based on OBA standard stars.
00060 #
00061 # 30/01/2013   NMFS
00062 #
00063 #
00064 # - H lines of the Paschen and Brackett series (perhaps also Pfund series
00065 #   at the very red edge of K band) will be most prominent for late-O to
00066 #   A types.
00067 #
00068 # - HeI lines in absorption are mostly for O types (with some dependence
00069 #   on luminosity class).
00070 # - HeII lines will only be relevant in the earliest O types
00071 # - HeI and HeII lines may also appear in emission.
00072 #
00073 # The note "weak - irrelevant?" indicates lines that tend to be much
00074 # weaker, and would only be discernable in R > 5000 spectra with very
00075 # high S/N ratio.  They may cause asymmetric wings for neighbouring
00076 # stronger features depending on the star/spectral type.
00077 # They are included here for completeness, but can probably be ignored
00078 # in the context of KMOS telluric calibration.
00079 #
00080 # It is important, however, to include the stronger HeI and HeII features,
00081 # experience with SINFONI shows they are frequently there (esp. in H band).
00082 #
00083 #
00084 # N.B.
00085 #  The H line list in this file is complete within the Iz - K coverage
00086 #  of KMOS (excluding the highest Pa, Br, abd Pf transitions, which
00087 #  become very weak).
00088 #  The He line for >= 1.0um is fairly complete (strongest common lines
00089 #  are included).
00090 #  HOWEVER: the He line list at < 1.0um, relevant for Iz band, is missing.
00091 #
00092 #
00093 # Useful references:
00094 #  Wallace et al. 2000, ApJ, 535, 325
00095 #  Wallace & Hinkle 1997,
00096 #  Meyer et al. 1998,
00097 #  Hanson et al. 2005, ApJS, 161, 154
00098 #
00099 # In the future: planned XShooter stellar library (PI S. Trager) will
00100 # provide a cross-check over the full Iz - K band, as well as allow the
00101 # identification of potentially missing He features in the range 0.8-1um.
00102 
00103  *-----------------------------------------------------------------------------*/
00104 const int         nr_lines_h     = 10;
00105 const double      lines_center_h[]      = {
00106                                     1.7001,     // HeI          // triplet
00107                                     // 1.52616,    // Br-19        // (weak - irrelevant?)
00108                                     1.53429,    // Br-18
00109                                     1.54400,    // Br-17
00110                                     1.55576,    // Br-16
00111                                     1.57018,    // Br-15
00112                                     1.58817,    // Br-14
00113                                     1.61105,    // Br-13
00114                                     1.64084,    // Br-12
00115                                     1.68077,    // Br-11
00116                                     1.73634    // Br-10
00117                                     // 1.6918,     // HeII     // weak
00118                                     // 1.81754,    // Br-epsilon   // (in band, but low transmission)
00119                                     // 1.87524     // Pa-alpha     // (out of H-band? useful for HK?)
00120                                    };
00121 const double      lines_width_h[]  = {
00122                                     0.025,    // HeI
00123                                     // 0.015,    // Br-19
00124                                     0.003,    // Br-18
00125                                     0.015,    // Br-17
00126                                     0.015,    // Br-16
00127                                     0.015,    // Br-15
00128                                     0.025,    // Br-14
00129                                     0.015,    // Br-13
00130                                     0.025,    // Br-12
00131                                     0.025,    // Br-11
00132                                     0.05    // Br-10
00133                                     // 0.015,    // HeII
00134                                     // 0.015,    // Br-epsilon
00135                                     // 0.015     // Pa-alpha
00136                                        };
00137 const int         nr_lines_k     = 2;
00138 const double      lines_center_k[]      = {
00139                                     // 1.94470,    // Br-delta                  // out of K-band
00140                                     // 2.0581,     // HeI          // singlet   // very faint, non detectable
00141                                     2.1120,     // HeI          // triplet
00142                                     //2.1132,     // HeI          // singlet
00143                                     // 2.1494,     // HeI        // (weak - irrelevant?)
00144                                     // 2.1607,     // HeI        // triplet (weak - irrelevant?)
00145                                     // 2.1617,     // HeI        // singlet (weak - irrelevant?)
00146                                     // 2.1641,     // HeI        // triplet (weak - irrelevant?)
00147                                     2.16569    // Br-gamma
00148                                     // 2.1815,     // HeI        // (weak - irrelevant?)
00149                                     // 2.1840,     // HeI        // (weak - irrelevant?)
00150 // wo ?!?                                    2.1885,     // HeII
00151                                     // 2.43087,    // Pf-20      // (weak - irrelevant?)
00152                                     // 2.44851,    // Pf-19      // (weak - irrelevant?)
00153                                     // 2.46949,    // Pf-18      // (weak - irrelevant?)
00154                                     // 2.49475     // Pf-17      // (weak - irrelevant?)  // out of band
00155                                    };
00156 const double      lines_width_k[]   = {
00157                                     // 0.015,    // Br-delta     // (out of K-band? useful for HK?)
00158   //                                  0.008,     // HeI          // singlet
00159                                     0.01,     // HeI          // triplet
00160                                     //0.0015,     // HeI          // singlet
00161                                     // 0.003,     // HeI        // (weak - irrelevant?)
00162                                     // 0.003,     // HeI        // triplet (weak - irrelevant?)
00163                                     // 0.003,     // HeI        // singlet (weak - irrelevant?)
00164                                     // 0.015,     // HeI        // triplet (weak - irrelevant?)
00165                                     0.015    // Br-gamma
00166                                     // 0.003,     // HeI        // (weak - irrelevant?)
00167                                     // 0.003,     // HeI        // (weak - irrelevant?)
00168                                     // 0.015,     // HeII
00169                                     // 0.015,    // Pf-20      // (weak - irrelevant?)
00170                                     // 0.015,    // Pf-19      // (weak - irrelevant?)
00171                                     // 0.015,    // Pf-18      // (weak - irrelevant?)
00172                                     // 0.015     // Pf-17      // (weak - irrelevant?)
00173                                        };
00174 const int         nr_lines_hk    = 12;
00175 const double      lines_center_hk[]     = {
00176                         // H
00177                                     1.7001,     // HeI          // triplet
00178 
00179                                     1.53429,    // Br-18
00180                                     1.54400,    // Br-17
00181                                     1.55576,    // Br-16
00182                                     1.57018,    // Br-15
00183                                     1.58817,    // Br-14
00184                                     1.61105,    // Br-13
00185                                     1.64084,    // Br-12
00186                                     1.68077,    // Br-11
00187                                     1.73634,    // Br-10
00188                         // K
00189                                     2.1120,     // HeI          // triplet
00190                                     2.16569     // Br-gamma
00191                                    };
00192 const double      lines_width_hk[]  = {
00193                         // H
00194                                         0.025,    // HeI
00195                                         0.003,    // Br-18
00196                                         0.015,    // Br-17
00197                                         0.015,    // Br-16
00198                                         0.015,    // Br-15
00199                                         0.025,    // Br-14
00200                                         0.015,    // Br-13
00201                                         0.025,    // Br-12
00202                                         0.025,    // Br-11
00203                                         0.05,     // Br-10
00204                         // K
00205                                         0.015,     // HeI          // triplet
00206                                         0.015    // Br-gamma
00207                                        };
00208 const int         nr_lines_iz    = 12;
00209 const double      lines_center_iz[]  = {
00210                                         0.84386,    // Pa-18
00211                                         0.84679,    // Pa-17
00212                                         0.85031,    // Pa-16
00213                                         0.85460,    // Pa-15
00214                                         0.85990,    // Pa-14
00215                                         0.86657,    // Pa-13
00216                                         0.87511,    // Pa-12
00217                                         0.88635,    // Pa-11
00218                                         0.90156,    // Pa-10
00219                                         0.92297,    // Pa-9
00220                                         0.95467,    // Pa-epsilon
00221                                         1.00501     // Pa-delta
00222                                        };
00223 const double      lines_width_iz[]  = {
00224                                          0.0008,     // Pa-18
00225                                         0.003225,    // Pa-17
00226                                         0.0039,     // Pa-16
00227                                         0.0048,     // Pa-15
00228                                         0.006,     // Pa-14
00229                                         0.0076,     // Pa-13
00230                                         0.001,     // Pa-12
00231                                         0.013,     // Pa-11
00232                                          0.01,     // Pa-10
00233                                          0.013,     // Pa-9
00234                                          0.02,     // Pa-epsilon
00235                                          0.025       // Pa-delta
00236                                        };
00237 const int         nr_lines_yj    = 7;
00238 const double      lines_center_yj[]     = {
00239                                     // 1.00501,    // Pa-delta     // (out of band?)
00240                                     1.08331,    // HeI
00241                                     1.09160,    // HeI
00242                                     1.09389,    // Pa-gamma
00243 
00244                                     1.19723,    // HeI
00245 
00246                                     1.28191,    // Pa-beta
00247                                     1.27882,    // HeI
00248                                     // 1.28495,    // HeI   // faint
00249                                     1.29720     // HeI
00250                                    };
00251 const double      lines_width_yj[]  = {
00252                                     // 0.015,    // Pa-delta     // (out of band?)
00253                                     .01,//0.005,    // HeI
00254                                     .01,//0.002,    // HeI
00255                                     0.02,    // Pa-gamma
00256 
00257                                     0.003,    // HeI
00258 
00259                                     0.02,    // Pa-beta
00260                                     0.0025,    // HeI
00261                                     // 0.0007,    // HeI
00262                                     0.002     // HeI
00263                                        };
00264 
00265 /*-----------------------------------------------------------------------------
00266  *                          Functions prototypes
00267  *----------------------------------------------------------------------------*/
00268 
00269 static int kmo_std_star_create(cpl_plugin *);
00270 static int kmo_std_star_exec(cpl_plugin *);
00271 static int kmo_std_star_destroy(cpl_plugin *);
00272 static int kmo_std_star(cpl_parameterlist *, cpl_frameset *);
00273 
00274 /*-----------------------------------------------------------------------------
00275  *                          Static variables
00276  *----------------------------------------------------------------------------*/
00277 
00278 static char kmo_std_star_description[] =
00279 "This recipe creates a telluric calibration frame and a PSF frame. It must be\n"
00280 "called after the kmo_illumination-recipe.\n"
00281 "Since there won’t be enough standard stars to observe for all IFUs in one ex-\n"
00282 "posure, one has to do several exposures in a way that there is at least one\n"
00283 "standard star and one sky exposure in each IFU. A internal data organiser will\n"
00284 "analyse the provided exposures and select the appropriate frames as follows:\n"
00285 "1. For each IFU the first standard star in the list of provided exposures is\n"
00286 "   taken. All subsequent standard star exposures for this IFU will be ignored\n"
00287 "2. A corresponding sky exposure will be chosen which will be as close in time\n"
00288 "   to the standard star exposure as possible.\n"
00289 "3. For any IFUs not containing a standard star and a sky exposure an empty\n"
00290 "   frame will be returned.\n"
00291 "\n"
00292 "NOISE_SPEC contains in any case the shot noise [sqrt(counts*gain)/gain]. If the\n"
00293 "exposures have been taken with template KMOS_spec_cal_stdstarscipatt, then an\n"
00294 "additional noise component is added in: All existing sky exposures for an IFU\n"
00295 "are subtracted pairwise, spectra are extracted and the std deviation is calculated.\n"
00296 "\n"
00297 "BASIC PARAMETERS:\n"
00298 "-----------------\n"
00299 "--startype\n"
00300 "If this parameter is specified, the stored star types of the observed obejcts \n"
00301 "in the FITS headers are overridden. This value applies to all objects exa-\n"
00302 "mined in the input frames. Examples would be “A3I”, “G3IV” or “K0I”. The first\n"
00303 "letter defines the star type, the second letter the spectral class and the last\n"
00304 "letters the luminosity class.\n"
00305 "\n"
00306 "--magnitude\n"
00307 "If this parameter is specified, the stored magnitudes in the FITS headers are \n"
00308 "overridden. For HK two magnitudes for each H and K have to be specified. All \n"
00309 "other gratings just use a single magnitude. If two values are provided, they \n"
00310 "have to be separated with a comma. \n"
00311 "\n"
00312 "--fmethod\n"
00313 "The type of function that should be fitted spatially to the collapsed image.\n"
00314 "This fit is used to create a mask to extract the spectrum of the object. Valid\n"
00315 "values are “gauss” and “moffat”.\n"
00316 "\n"
00317 "--imethod\n"
00318 "The interpolation method used for reconstruction. As default 'CS' is selected.\n"
00319 "Note that no error spectra will be generated for this interpolation method.\n"
00320 "Select a nearest neighbour method otherwise\n"
00321 "\n"
00322 "--range\n"
00323 "The spectral range [um] to combine when collapsing the reconstructed cubes.\n"
00324 "\n"
00325 "--save_cubes\n"
00326 "Set to TRUE if the intermediate reconstructed cubes (eventually divided by "
00327 "illumination correction) should be saved as well. Default is FALSE.\n"
00328 "\n"
00329 "--no_noise\n"
00330 "Applies only for data taken with template KMOS_spec_cal_stdstarscipatt:\n"
00331 "Skip lengthy calculation of noise-spectra on all sky exposures (no NOISE_SPEC\n"
00332 "will be produced).\n"
00333 "\n"
00334 "ADVANCED PARAMETERS\n"
00335 "-------------------\n"
00336 "--flux\n"
00337 "Specify if flux conservation should be applied.\n"
00338 "\n"
00339 "--neighborhoodRange\n"
00340 "Defines the range to search for neighbors during reconstruction\n"
00341 "\n"
00342 "--b_samples\n"
00343 "The number of samples in spectral direction for the reconstructed cube.\n"
00344 "Ideally this number should be greater than 2048, the detector size.\n"
00345 "\n"
00346 "--b_start\n"
00347 "--b_end\n"
00348 "Used to define manually the start and end wavelength for the reconstructed\n"
00349 "cube. By default the internally defined values are used.\n"
00350 "\n"
00351 "--cmethod\n"
00352 "Following methods of frame combination are available:\n"
00353 "   * 'ksigma' (Default)\n"
00354 "   An iterative sigma clipping. For each position all pixels in the spectrum\n"
00355 "   are examined. If they deviate significantly, they will be rejected according\n"
00356 "   to the conditions:\n"
00357 "       val > mean + stdev * cpos_rej\n"
00358 "   and\n"
00359 "       val < mean - stdev * cneg_rej\n"
00360 "   where --cpos_rej, --cneg_rej and --citer are the corresponding configuration\n"
00361 "   parameters. In the first iteration median and percentile level are used.\n"
00362 "\n"
00363 "   * 'median'\n"
00364 "   At each pixel position the median is calculated.\n"
00365 "\n"
00366 "   * 'average'\n"
00367 "   At each pixel position the average is calculated.\n"
00368 "\n"
00369 "   * 'sum'\n"
00370 "   At each pixel position the sum is calculated.\n"
00371 "\n"
00372 "   * 'min_max'\n"
00373 "   The specified number of minimum and maximum pixel values will be rejected.\n"
00374 "   --cmax and --cmin apply to this method.\n"
00375 "\n"
00376 "--cpos_rej\n"
00377 "--cneg_rej\n"
00378 "--citer\n"
00379 "see --cmethod='ksigma'\n"
00380 "\n"
00381 "--cmax\n"
00382 "--cmin\n"
00383 "see --cmethod='min_max'\n"
00384 "\n"
00385 "--xcal_interpolation\n"
00386 "If true interpolate the pixel position in the slitlet (xcal) using the two\n"
00387 "closest rotator angles in the calibration file. Otherwise take the values\n"
00388 "of the closest rotator angle\n"
00389 "\n"
00390 "--suppress_extension\n"
00391 "If set to TRUE, the arbitrary filename extensions are supressed. If multiple\n"
00392 "products with the same category are produced, they will be numered consecutively\n"
00393 "starting from 0.\n"
00394 "\n"
00395 "-------------------------------------------------------------------------------\n"
00396 "  Input files:                                                                 \n"
00397 "                                                                               \n"
00398 "   DO                      KMOS                                                \n"
00399 "   category                Type  Explanation                   Required #Frames\n"
00400 "   --------                ----- -----------                   -------- -------\n"
00401 "   STD                     RAW   Std. star & sky exposures         Y     >=1   \n"
00402 "   XCAL                    F2D   x calibration frame               Y      1    \n"
00403 "   YCAL                    F2D   y calibration frame               Y      1    \n"
00404 "   LCAL                    F2D   Wavelength calib. frame           Y      1    \n"
00405 "   MASTER_FLAT             F2D   Master flat frame                 Y      1    \n"
00406 "   WAVE_BAND               F2L   Table with start-/end-wavelengths Y      1    \n"
00407 "   ILLUM_CORR              F2I   Illumination correction           N     0,1   \n"
00408 "   SOLAR_SPEC              F1S   Solar spectrum                    N     0,1   \n"
00409 "                                 (only for G stars)                            \n"
00410 "   ATMOS_MODEL             F1S   Model atmospheric transmisson     N     0,1   \n"
00411 "                                 (only for OBAF stars in K band)               \n"
00412 "   SPEC_TYPE_LOOKUP        F2L   LUT  eff. stellar temperature     N     0,1   \n"
00413 "                                                                               \n"
00414 "  Output files:                                                                \n"
00415 "                                                                               \n"
00416 "   DO                      KMOS                                                \n"
00417 "   category                Type   Explanation                                  \n"
00418 "   --------                -----  -----------                                  \n"
00419 "   TELLURIC                F1I    The normalised telluric spectrum             \n"
00420 "                                  (including errors)                           \n"
00421 "   STAR_SPEC               F1I    The extracted star spectrum                  \n"
00422 "                                  (including errors)                           \n"
00423 "   STD_IMAGE               F2I    The standard star PSF images                 \n"
00424 "   STD_MASK                F2I    The generated mask used to extract the star  \n"
00425 "                                  spectrum                                     \n"
00426 "   NOISE_SPEC              F1I    The extracted noise spectrum                 \n"
00427 "-------------------------------------------------------------------------------\n"
00428 "\n";
00429 
00430 /*-----------------------------------------------------------------------------
00431  *                              Functions code
00432  *----------------------------------------------------------------------------*/
00433 
00450 int cpl_plugin_get_info(cpl_pluginlist *list)
00451 {
00452     cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe);
00453     cpl_plugin *plugin = &recipe->interface;
00454 
00455     cpl_plugin_init(plugin,
00456                         CPL_PLUGIN_API,
00457                         KMOS_BINARY_VERSION,
00458                         CPL_PLUGIN_TYPE_RECIPE,
00459                         "kmo_std_star",
00460                         "Create the telluric correction frame.",
00461                         kmo_std_star_description,
00462                         "Alex Agudo Berbel",
00463                         "kmos-spark@mpe.mpg.de",
00464                         kmos_get_license(),
00465                         kmo_std_star_create,
00466                         kmo_std_star_exec,
00467                         kmo_std_star_destroy);
00468 
00469     cpl_pluginlist_append(list, plugin);
00470 
00471     return 0;
00472 }
00473 
00481 static int kmo_std_star_create(cpl_plugin *plugin)
00482 {
00483     cpl_recipe *recipe;
00484     cpl_parameter *p;
00485 
00486     /* Check that the plugin is part of a valid recipe */
00487     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00488         recipe = (cpl_recipe *)plugin;
00489     else
00490         return -1;
00491 
00492     /* Create the parameters list in the cpl_recipe object */
00493     recipe->parameters = cpl_parameterlist_new();
00494 
00495     /* --startype */
00496     p = cpl_parameter_new_value("kmos.kmo_std_star.startype",
00497                                 CPL_TYPE_STRING,
00498                                 "The spectral type of the star (O, B, A, F, G)"
00499                                 " Format: G4V etc.",
00500                                 "kmos.kmo_std_star",
00501                                 "");
00502     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "startype");
00503     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00504     cpl_parameterlist_append(recipe->parameters, p);
00505 
00506     /* --imethod */
00507     p = cpl_parameter_new_value("kmos.kmo_std_star.imethod",
00508                                 CPL_TYPE_STRING,
00509                                 "Method to use for interpolation. "
00510                                 "[\"NN\" (nearest neighbour), "
00511                                 "\"lwNN\" (linear weighted nearest neighbor), "
00512                                 "\"swNN\" (square weighted nearest neighbor), "
00513                                 "\"MS\" (Modified Shepard's method), "
00514                                 "\"CS\" (Cubic spline)]",
00515                                 "kmos.kmo_std_star",
00516                                 "CS");
00517     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "imethod");
00518     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00519     cpl_parameterlist_append(recipe->parameters, p);
00520 
00521     /* --fmethod */
00522     p = cpl_parameter_new_value("kmos.kmo_std_star.fmethod",
00523                                 CPL_TYPE_STRING,
00524                                 "Either fit a 'gauss' or 'moffat' profile.",
00525                                 "kmos.kmo_std_star",
00526                                 "gauss");
00527     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "fmethod");
00528     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00529     cpl_parameterlist_append(recipe->parameters, p);
00530 
00531     /* --neighborhoodRange */
00532     p = cpl_parameter_new_value("kmos.kmo_std_star.neighborhoodRange",
00533                                 CPL_TYPE_DOUBLE,
00534                                 "Defines the range to search for neighbors "
00535                                 "in pixels",
00536                                 "kmos.kmo_std_star",
00537                                 1.001);
00538     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "neighborhoodRange");
00539     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00540     cpl_parameterlist_append(recipe->parameters, p);
00541 
00542     /* --magnitude */
00543     p = cpl_parameter_new_value("kmos.kmo_std_star.magnitude",
00544                                 CPL_TYPE_STRING,
00545                                 "The magnitude of the std star. For HK two "
00546                                 "values have to provided (eg. 12.1,13.2)",
00547                                 "kmos.kmo_std_star",
00548                                 "");
00549     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "magnitude");
00550     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00551     cpl_parameterlist_append(recipe->parameters, p);
00552 
00553     /* --flux */
00554     p = cpl_parameter_new_value("kmos.kmo_std_star.flux",
00555                                 CPL_TYPE_BOOL,
00556                                 "TRUE: Apply flux conservation. FALSE: otherwise",
00557                                 "kmos.kmo_std_star",
00558                                 TRUE);
00559     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "flux");
00560     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00561     cpl_parameterlist_append(recipe->parameters, p);
00562 
00563     /* --save_cubes */
00564     p = cpl_parameter_new_value("kmos.kmo_std_star.save_cubes",
00565                                 CPL_TYPE_BOOL,
00566                                 "TRUE: Save reconstructed cubes, FALSE: otherwise",
00567                                 "kmos.kmo_std_star",
00568                                 FALSE);
00569     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "save_cubes");
00570     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00571     cpl_parameterlist_append(recipe->parameters, p);
00572 
00573     /* --no_noise */
00574     p = cpl_parameter_new_value("kmos.kmo_std_star.no_noise",
00575                                 CPL_TYPE_BOOL,
00576                                 "Applies only for data taken with template KMOS_spec_cal_stdstarscipatt: "
00577                                 "FALSE:  Calculate noise-spectra on all sky exposures. "
00578                                 "TRUE: skip this step",
00579                                 "kmos.kmo_std_star",
00580                                 FALSE);
00581     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "no_noise");
00582     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00583     cpl_parameterlist_append(recipe->parameters, p);
00584 
00585     /* --xcal_interpolation */
00586     p = cpl_parameter_new_value("kmos.kmo_std_star.xcal_interpolation",
00587                                 CPL_TYPE_BOOL,
00588                                 "TRUE: Interpolate xcal between rotator angles. FALSE: otherwise",
00589                                 "kmos.kmo_std_star",
00590                                 TRUE);
00591     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "xcal_interpolation");
00592     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00593     cpl_parameterlist_append(recipe->parameters, p);
00594 
00595     /* --suppress_extension */
00596     p = cpl_parameter_new_value("kmos.kmo_std_star.suppress_extension",
00597                                 CPL_TYPE_BOOL,
00598                                 "Suppress arbitrary filename extension."
00599                                 "(TRUE (apply) or FALSE (don't apply)",
00600                                 "kmos.kmo_std_star",
00601                                 FALSE);
00602     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "suppress_extension");
00603     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00604     cpl_parameterlist_append(recipe->parameters, p);
00605 
00606     // add parameters for band-definition
00607     kmo_band_pars_create(recipe->parameters,
00608                          "kmos.kmo_std_star");
00609 
00610     // add parameters for combining
00611     return kmo_combine_pars_create(recipe->parameters,
00612                                    "kmos.kmo_std_star",
00613                                    DEF_REJ_METHOD,
00614                                    FALSE);
00615 }
00616 
00622 static int kmo_std_star_exec(cpl_plugin *plugin)
00623 {
00624     cpl_recipe  *recipe;
00625 
00626     /* Get the recipe out of the plugin */
00627     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00628         recipe = (cpl_recipe *)plugin;
00629     else return -1;
00630 
00631     return kmo_std_star(recipe->parameters, recipe->frames);
00632 }
00633 
00639 static int kmo_std_star_destroy(cpl_plugin *plugin)
00640 {
00641     cpl_recipe *recipe;
00642 
00643     /* Get the recipe out of the plugin */
00644     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00645         recipe = (cpl_recipe *)plugin;
00646     else return -1 ;
00647 
00648     cpl_parameterlist_delete(recipe->parameters);
00649     return 0 ;
00650 }
00651 
00666 static int kmo_std_star(cpl_parameterlist *parlist, cpl_frameset *frameset)
00667 {
00668     cpl_imagelist    **stored_data_cube      = NULL,
00669                      **stored_noise_cube     = NULL;
00670     cpl_image        **stored_psf_data       = NULL,
00671                      *illum_corr             = NULL,
00672                      **stored_mask           = NULL,
00673                      *lcal                   = NULL;
00674     const cpl_image  *tmp_img                = NULL;
00675     cpl_frame        *xcal_frame             = NULL,
00676                      *ycal_frame             = NULL,
00677                      *lcal_frame             = NULL,
00678                      *flat_frame             = NULL,
00679                      *illum_frame            = NULL,
00680                      *obj_frame              = NULL,
00681                      *sky_frame              = NULL,
00682                      *tmp_frame              = NULL;
00683     cpl_vector       *solar_spec             = NULL,
00684                      *atmos_model            = NULL,
00685                      **stored_telluric_data  = NULL,
00686                      **stored_telluric_noise = NULL,
00687                      **stored_starspec_data  = NULL,
00688                      **stored_starspec_noise = NULL,
00689                      *shot_noise             = NULL,
00690                      **stored_noisespec      = NULL,
00691                      *tmp_spec_data          = NULL,
00692                      *spec_qc                = NULL,
00693                      *tmp_spec_noise         = NULL,
00694                      *identified_slices      = NULL,
00695                      *tmp_vec                = NULL,
00696                      *lambda_x               = NULL;
00697     int              ret_val                 = 0,
00698                      nr_devices              = 0,
00699                      nr_exp                  = 0,
00700                      j                       = 0,
00701                      *bounds                 = NULL,
00702                      ifu_nr                  = 0,
00703                      citer                   = 0,
00704                      cmax                    = 0,
00705                      cmin                    = 0,
00706                      line_warning            = FALSE,
00707                      nr_std_stars            = 0,
00708                      print_warning_once      = TRUE,
00709                      flux                    = FALSE,
00710                      background              = FALSE,
00711                      band_method             = 0,
00712                      save_cubes              = FALSE,
00713                      no_noise                = FALSE,
00714                      has_magnitude           = TRUE,
00715                      xcal_interpolation      = FALSE,
00716                      suppress_extension      = FALSE,
00717                      nr_split_mag            = 0,
00718                      nr_sky_pairs            = 0,
00719                      i                       = 0,
00720                      ii                      = 0,
00721                      l                       = 0,
00722                      gx                      = 0,
00723                      gy                      = 0,
00724                      k                       = 0;
00725     const int        *punused_ifus           = NULL;
00726     objSkyStruct     *obj_sky_struct         = NULL;
00727     skySkyStruct     *sky_sky_struct         = NULL;
00728     double           *stored_qc_throughput   = NULL,
00729                      star_temperature        = 0.0,
00730                      neighborhoodRange       = 1.001,
00731                      cpos_rej                = 0.0,
00732                      cneg_rej                = 0.0,
00733                      zeropoint               = -1.0,
00734                      throughput_mean         = -1.0,
00735                      throughput_sdv          = -1.0,
00736                      std_trace               = -1.0,
00737                      counts1                 = 0.0,
00738                      counts2                 = 0.0,
00739                      magnitude1              = 0.0,
00740                      magnitude2              = 0.0,
00741                      gain                    = 0.0,
00742                      flux_scale_factor       = 0.0,
00743                      exptime                 = 0.,
00744                      cdelt3                  = 0.,
00745                      mean_data               = 0.,
00746                      mean_data2              = 0.,
00747                      *ptmp_spec_noise        = NULL,
00748                      *ppp                    = NULL,
00749                      crpix1                  = 0.,
00750                      crval1                  = 0.,
00751                      cdelt1                  = 0.,
00752                      tmp_data                = 0.,
00753                      tmp_noise               = 0.;
00754     const double     *ptmp_spec_data         = NULL;
00755     cpl_propertylist *main_header_tel                    = NULL,
00756                      *main_header_psf                    = NULL,
00757                      *sub_header_orig                    = NULL,
00758                      *tmp_sub_header                     = NULL,
00759                      *tmp_header                         = NULL,
00760                      **stored_sub_tel_data_headers       = NULL,
00761                      **stored_sub_tel_noise_headers      = NULL,
00762                      **stored_sub_cube_data_headers      = NULL,
00763                      **stored_sub_cube_noise_headers     = NULL,
00764                      **stored_sub_psf_headers            = NULL,
00765                      *pl_psf                             = NULL;
00766     cpl_table        *spec_type_LUT          = NULL,
00767                      *band_table             = NULL;;
00768     main_fits_desc   desc1,
00769                      desc2;
00770     char             *extname                = NULL,
00771                      *keyword                = NULL,
00772                      filename_telluric[256],
00773                      filename_starspec[256],
00774                      filename_psf[256],
00775                      filename_mask[256],
00776                      filename_cubes[256],
00777                      filename_noise[256],
00778                      *suffix                 = NULL,
00779                      *fn_suffix              = NULL,
00780                      spec_class[256],
00781                      lum_class[256],
00782                      star_type[2],
00783                      *tmp_band_method        = getenv("KMO_BAND_METHOD"),
00784                      **split_mag             = NULL,
00785                      *grat_id                = NULL,
00786                      *tplid                  = NULL;
00787     const char       *filter_id              = NULL,
00788                      *spec_type              = NULL,
00789                      *magnitude_txt          = NULL,
00790                      *imethod                = NULL,
00791                      *cmethod                = NULL,
00792                      *fmethod                = NULL,
00793                      *tmp_str                = NULL;
00794     gridDefinition   gd;
00795     cpl_array        **unused_ifus_before    = NULL,
00796                      **unused_ifus_after     = NULL;
00797     cpl_frameset     *frameset_std           = NULL;
00798 
00799     KMO_TRY
00800     {
00801         kmo_init_fits_desc(&desc1);
00802         kmo_init_fits_desc(&desc2);
00803 
00804         /* --- check input --- */
00805         KMO_TRY_ASSURE((parlist != NULL) &&
00806                        (frameset != NULL),
00807                        CPL_ERROR_NULL_INPUT,
00808                        "Not all input data is provided!");
00809 
00810         KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, STD) >= 1,
00811                        CPL_ERROR_ILLEGAL_INPUT,
00812                        "At least one STD frame is required!");
00813         if (cpl_frameset_count_tags(frameset, STD) == 1) {
00814             cpl_msg_warning("", "At least two STD frames should be provided "
00815                                 "in order to apply sky subtraction!");
00816         }
00817 
00818         KMO_TRY_ASSURE((cpl_frameset_count_tags(frameset, ILLUM_CORR) == 1) ||
00819                        (cpl_frameset_count_tags(frameset, ILLUM_CORR) == 0),
00820                        CPL_ERROR_FILE_NOT_FOUND,
00821                        "Exactly one ILLUM_CORR frame is required!");
00822         KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, XCAL) == 1,
00823                        CPL_ERROR_FILE_NOT_FOUND,
00824                        "Exactly one XCAL frame is required!");
00825         KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, YCAL) == 1,
00826                        CPL_ERROR_FILE_NOT_FOUND,
00827                        "Exactly one YCAL frame is required!");
00828         KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, LCAL) == 1,
00829                        CPL_ERROR_FILE_NOT_FOUND,
00830                        "Exactly one LCAL frame is required!");
00831         KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, MASTER_FLAT) == 1,
00832                        CPL_ERROR_FILE_NOT_FOUND,
00833                        "Exactly one MASTER_FLAT frame is required!");
00834         KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, WAVE_BAND) == 1,
00835                        CPL_ERROR_FILE_NOT_FOUND,
00836                        "Exactly one WAVE_BAND frame is required!");
00837         KMO_TRY_ASSURE(kmo_dfs_set_groups(frameset, "kmo_std_star") == 1,
00838                        CPL_ERROR_ILLEGAL_INPUT,
00839                        "Cannot identify RAW and CALIB frames!");
00840 
00841         /* --- get parameters --- */
00842         cpl_msg_info("", "--- Parameter setup for kmo_std_star ------");
00843 
00844         KMO_TRY_EXIT_IF_NULL(
00845             spec_type = kmo_dfs_get_parameter_string(parlist, "kmos.kmo_std_star.startype"));
00846         KMO_TRY_EXIT_IF_ERROR(
00847             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_std_star.startype"));
00848 
00849         KMO_TRY_EXIT_IF_NULL(
00850             imethod = kmo_dfs_get_parameter_string(parlist, "kmos.kmo_std_star.imethod"));
00851         KMO_TRY_ASSURE((strcmp(imethod, "NN") == 0) ||
00852                        (strcmp(imethod, "lwNN") == 0) ||
00853                        (strcmp(imethod, "swNN") == 0) ||
00854                        (strcmp(imethod, "MS") == 0) ||
00855                        (strcmp(imethod, "CS") == 0),
00856                        CPL_ERROR_ILLEGAL_INPUT,
00857                        "method must be either \"NN\", \"lwNN\", "
00858                        "\"swNN\", \"MS\" or \"CS\"!");
00859         KMO_TRY_EXIT_IF_ERROR(
00860             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_std_star.imethod"));
00861 
00862         KMO_TRY_EXIT_IF_NULL(
00863             fmethod = kmo_dfs_get_parameter_string(parlist, "kmos.kmo_std_star.fmethod"));
00864         KMO_TRY_ASSURE((strcmp(fmethod, "gauss") == 0) ||
00865                        (strcmp(fmethod, "moffat") == 0),
00866                        CPL_ERROR_ILLEGAL_INPUT,
00867                        "fmethod must be either 'gauss' or "
00868                        "'moffat' !");
00869         KMO_TRY_EXIT_IF_ERROR(
00870             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_std_star.method"));
00871 
00872         neighborhoodRange = kmo_dfs_get_parameter_double(parlist, "kmos.kmo_std_star.neighborhoodRange");
00873         KMO_TRY_CHECK_ERROR_STATE();
00874         KMO_TRY_ASSURE(neighborhoodRange > 0.0,
00875                        CPL_ERROR_ILLEGAL_INPUT,
00876                        "neighborhoodRange must be greater than 0.0");
00877         KMO_TRY_EXIT_IF_ERROR(
00878             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_std_star.neighborhoodRange"));
00879 
00880         magnitude_txt = kmo_dfs_get_parameter_string(parlist, "kmos.kmo_std_star.magnitude");
00881         KMO_TRY_CHECK_ERROR_STATE();
00882         KMO_TRY_EXIT_IF_ERROR(
00883             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_std_star.magnitude"));
00884 
00885         flux = kmo_dfs_get_parameter_bool(parlist, "kmos.kmo_std_star.flux");
00886         KMO_TRY_ASSURE((flux == FALSE) || (flux == TRUE),
00887                        CPL_ERROR_ILLEGAL_INPUT,
00888                        "flux must be either FALSE or TRUE!");
00889         KMO_TRY_EXIT_IF_ERROR(
00890             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_std_star.flux"));
00891 
00892         save_cubes = kmo_dfs_get_parameter_bool(parlist, "kmos.kmo_std_star.save_cubes");
00893         KMO_TRY_ASSURE((save_cubes == FALSE) || (save_cubes == TRUE),
00894                        CPL_ERROR_ILLEGAL_INPUT,
00895                        "save_cubes must be either FALSE or TRUE!");
00896         KMO_TRY_EXIT_IF_ERROR(
00897             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_std_star.save_cubes"));
00898 
00899         no_noise = kmo_dfs_get_parameter_bool(parlist, "kmos.kmo_std_star.no_noise");
00900         KMO_TRY_ASSURE((no_noise == FALSE) || (no_noise == TRUE),
00901                        CPL_ERROR_ILLEGAL_INPUT,
00902                        "no_noise must be either FALSE or TRUE!");
00903         KMO_TRY_EXIT_IF_ERROR(
00904             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_std_star.no_noise"));
00905 
00906         xcal_interpolation = kmo_dfs_get_parameter_bool(parlist, "kmos.kmo_std_star.xcal_interpolation");
00907         KMO_TRY_CHECK_ERROR_STATE();
00908         KMO_TRY_EXIT_IF_ERROR(
00909             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_std_star.xcal_interpolation"));
00910         KMO_TRY_ASSURE((xcal_interpolation == TRUE) ||
00911                        (xcal_interpolation == FALSE),
00912                        CPL_ERROR_ILLEGAL_INPUT,
00913                        "xcal_interpolation must be TRUE or FALSE!");
00914 
00915         suppress_extension = kmo_dfs_get_parameter_bool(parlist, "kmos.kmo_std_star.suppress_extension");
00916         KMO_TRY_CHECK_ERROR_STATE();
00917         KMO_TRY_EXIT_IF_ERROR(
00918             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_std_star.suppress_extension"));
00919 
00920         KMO_TRY_ASSURE((suppress_extension == TRUE) || (suppress_extension == FALSE),
00921                        CPL_ERROR_ILLEGAL_INPUT,
00922                        "suppress_extension must be TRUE or FALSE!");
00923 
00924         kmo_band_pars_load(parlist, "kmos.kmo_std_star");
00925 
00926         KMO_TRY_EXIT_IF_ERROR(
00927             kmo_combine_pars_load(parlist,
00928                                   "kmos.kmo_std_star",
00929                                   &cmethod,
00930                                   &cpos_rej,
00931                                   &cneg_rej,
00932                                   &citer,
00933                                   &cmin,
00934                                   &cmax,
00935                                   FALSE));
00936         cpl_msg_info("", "-------------------------------------------");
00937 
00938         //
00939         // Check if magnitude/frameset is valid and if throughput and zeropoint should be calculated
00940         //
00941 
00942         // Check if all STD frames have the same GRAT-ID
00943         // if not: don't calculate zeropoint and throughput
00944         KMO_TRY_EXIT_IF_NULL(
00945             frameset_std = cpl_frameset_new());
00946 
00947         KMO_TRY_EXIT_IF_NULL(
00948             tmp_frame = kmo_dfs_get_frame(frameset, STD));
00949         KMO_TRY_EXIT_IF_NULL(
00950             tmp_header = kmclipm_propertylist_load(cpl_frame_get_filename(tmp_frame), 0));
00951         KMO_TRY_EXIT_IF_NULL(
00952             grat_id = cpl_sprintf("%s", cpl_propertylist_get_string(tmp_header, "ESO INS GRAT1 ID")));
00953         KMO_TRY_EXIT_IF_NULL(
00954             tplid = cpl_sprintf("%s", cpl_propertylist_get_string(tmp_header, TPL_ID)));
00955         KMO_TRY_EXIT_IF_ERROR(
00956             cpl_frameset_insert(frameset_std, cpl_frame_duplicate(tmp_frame)));
00957         cpl_propertylist_delete(tmp_header); tmp_header = NULL;
00958         KMO_TRY_CHECK_ERROR_STATE();
00959 
00960         KMO_TRY_EXIT_IF_NULL(
00961             tmp_frame = kmo_dfs_get_frame(frameset, NULL));
00962         while (tmp_frame != NULL ) {
00963             KMO_TRY_EXIT_IF_NULL(
00964                 tmp_header = kmclipm_propertylist_load(cpl_frame_get_filename(tmp_frame), 0));
00965             if (strcmp(grat_id, cpl_propertylist_get_string(tmp_header, "ESO INS GRAT1 ID")) == 0) {
00966                 // same grating
00967                 KMO_TRY_EXIT_IF_ERROR(
00968                     cpl_frameset_insert(frameset_std, cpl_frame_duplicate(tmp_frame)));
00969             } else {
00970                 // there are STD frames with different gratings
00971                 if (has_magnitude) {
00972                     cpl_msg_warning(cpl_func, "The STD frames have different gratings,"
00973                                             "following QC parameters won't be "
00974                                             "calculated: QC ZEROPOINT, QC THROUGHPUT,"
00975                                             "QC THROUGHPUT MEAN and QC THROUGHPUT STD");
00976                 }
00977                 has_magnitude = FALSE;
00978             }
00979             cpl_propertylist_delete(tmp_header); tmp_header = NULL;
00980 
00981             tmp_frame = kmo_dfs_get_frame(frameset, NULL);
00982             KMO_TRY_CHECK_ERROR_STATE();
00983         }
00984         KMO_TRY_CHECK_ERROR_STATE();
00985 
00986         if (cpl_frameset_count_tags(frameset, ATMOS_MODEL) == 1) {
00987             // check if ATMOS_MODEL is the band as the STD frames
00988             KMO_TRY_EXIT_IF_NULL(
00989                 tmp_frame = kmo_dfs_get_frame(frameset, ATMOS_MODEL));
00990             KMO_TRY_EXIT_IF_NULL(
00991                 tmp_sub_header = kmclipm_propertylist_load( cpl_frame_get_filename(tmp_frame), 0));
00992             KMO_TRY_EXIT_IF_NULL(
00993                 tmp_str = cpl_propertylist_get_string(tmp_sub_header, FILT_ID));
00994             KMO_TRY_ASSURE(strcmp(grat_id, tmp_str) == 0,
00995                            CPL_ERROR_ILLEGAL_INPUT,
00996                            "ATMOS model must have primary "
00997                            "keyword '%s' equal '%s'!!!",
00998                            FILT_ID, grat_id);
00999             cpl_propertylist_delete(tmp_sub_header);
01000             tmp_sub_header = NULL;
01001         }
01002 
01003         if (has_magnitude) {
01004             // all STD frames have the same GRAT-ID
01005             // now check source of magnitude (user or keyword)
01006             KMO_TRY_EXIT_IF_NULL(
01007                 tmp_frame = kmo_dfs_get_frame(frameset, STD));
01008             KMO_TRY_EXIT_IF_NULL(
01009                 tmp_header = kmclipm_propertylist_load(cpl_frame_get_filename(tmp_frame), 0));
01010 
01011             if (strcmp(magnitude_txt, "") == 0) {
01012                 // no user defined magnitude
01013 
01014                 // check for magnitude-keyword
01015                 if ((cpl_propertylist_has(tmp_header, STDSTAR_MAG)) &&
01016                     (cpl_propertylist_get_type(tmp_header, STDSTAR_MAG) == CPL_TYPE_STRING))
01017                 {
01018                     KMO_TRY_EXIT_IF_NULL(
01019                         magnitude_txt = cpl_propertylist_get_string(tmp_header, STDSTAR_MAG));
01020                     KMO_TRY_EXIT_IF_NULL(
01021                         split_mag = kmo_strsplit(magnitude_txt, ",", &nr_split_mag));
01022 
01023                     // check if band and number of magnitudes matches
01024                     if ((nr_split_mag == 2) &&
01025                         (strcmp(grat_id, "HK") == 0))
01026                     {
01027                         magnitude1 = atof(split_mag[0]);
01028                         magnitude2 = atof(split_mag[1]);
01029                         cpl_msg_info("", "Magnitude in H: %g", magnitude1);
01030                         cpl_msg_info("", "Magnitude in K: %g", magnitude2);
01031                     } else if ((nr_split_mag >= 1) &&
01032                                ((strcmp(grat_id, "K") == 0) ||
01033                                 (strcmp(grat_id, "H") == 0) ||
01034                                 (strcmp(grat_id, "IZ") == 0) ||
01035                                 (strcmp(grat_id, "YJ") == 0)))
01036                     {
01037                         magnitude1 = atof(split_mag[0]);
01038                         cpl_msg_info("", "Magnitude in %s: %g", grat_id, magnitude1);
01039                     } else {
01040                         // keyword STDSTAR_MAG doesn't match filter
01041                         has_magnitude = FALSE;
01042                         cpl_msg_warning(cpl_func, "The keyword %s doesn't match to grating',"
01043                                                   "following QC parameters won't be "
01044                                                   "calculated: QC ZEROPOINT, QC THROUGHPUT,"
01045                                                   "QC THROUGHPUT MEAN and QC THROUGHPUT STD", STDSTAR_MAG);
01046                     }
01047                     kmo_strfreev(split_mag);
01048                 } else {
01049                     // keyword STDSTAR_MAG unavailable or wrong type
01050                     has_magnitude = FALSE;
01051                     cpl_msg_warning(cpl_func, "The keyword %s is not set or of wrong type,"
01052                                               "following QC parameters won't be "
01053                                               "calculated: QC ZEROPOINT, QC THROUGHPUT,"
01054                                               "QC THROUGHPUT MEAN and QC THROUGHPUT STD", STDSTAR_MAG);
01055                 }
01056             } else {
01057                 // magnitude is user specified
01058                 cpl_msg_info(cpl_func, "Magnitude has been specified by user. Any "
01059                                        "value in keyword %s will be ignored.", STDSTAR_MAG);
01060 
01061                 KMO_TRY_EXIT_IF_NULL(
01062                     split_mag = kmo_strsplit(magnitude_txt, ",", &nr_split_mag));
01063                 switch (nr_split_mag) {
01064                 case 1:
01065                     magnitude1 = atof(split_mag[0]);
01066                     cpl_msg_info("", "Magnitude in %s: %g", grat_id, magnitude1);
01067                     break;
01068                 case 2:
01069                     magnitude1 = atof(split_mag[0]);
01070                     magnitude2 = atof(split_mag[1]);
01071                     cpl_msg_info("", "Magnitude in H: %g", magnitude1);
01072                     cpl_msg_info("", "Magnitude in K: %g", magnitude2);
01073                     break;
01074                 default:
01075                     KMO_TRY_ASSURE(1 == 0,
01076                                    CPL_ERROR_ILLEGAL_INPUT,
01077                                    "Provided magnitude was in wrong format! "
01078                                    "Either a single float value or two separated by comma");
01079                 }
01080                 kmo_strfreev(split_mag);
01081             }
01082             cpl_propertylist_delete(tmp_header); tmp_header = NULL;
01083         } // if (has_magnitude)
01084         cpl_msg_info("", "-------------------------------------------");
01085         KMO_TRY_CHECK_ERROR_STATE();
01086 
01087         //
01088         // check for spectral type (--startype) (user or keyword)
01089         //
01090         if (strcmp(spec_type, "") == 0) {
01091             // no user defined startype
01092 
01093             KMO_TRY_EXIT_IF_NULL(
01094                 tmp_frame = kmo_dfs_get_frame(frameset, STD));
01095             KMO_TRY_EXIT_IF_NULL(
01096                 tmp_header = kmclipm_propertylist_load(cpl_frame_get_filename(tmp_frame), 0));
01097 
01098             // check for startype-keyword
01099             if ((cpl_propertylist_has(tmp_header, STDSTAR_TYPE)) &&
01100                 (cpl_propertylist_get_type(tmp_header, STDSTAR_TYPE) == CPL_TYPE_STRING))
01101             {
01102                 KMO_TRY_EXIT_IF_NULL(
01103                     spec_type = cpl_propertylist_get_string(tmp_header, STDSTAR_TYPE));
01104             } else {
01105                 // keyword STDSTAR_TYPE unavailable or wrong type
01106             }
01107         } else {
01108             // startype is user specified
01109             cpl_msg_info(cpl_func, "Type of star has been specified by user. Any "
01110                                    "value in keyword %s will be ignored.", STDSTAR_TYPE);
01111         }
01112         KMO_TRY_CHECK_ERROR_STATE();
01113 
01114         if (strlen(spec_type) > 0) {
01115             if (kmo_get_spec_type(spec_type, spec_class, lum_class) != CPL_ERROR_NONE) {
01116                 cpl_error_reset();
01117                 spec_class[0] = '\0';
01118                 lum_class[0] = '\0';
01119                 star_type[0] = '\0';
01120                 cpl_msg_warning("", "The keyword %s is not set or of wrong type nor was it provided by the user. "
01121                                     "Can't divide solar spectrum for G stars or fit a profile "
01122                                     "to atmospheric transmission for OBAF stars and can't "
01123                                     "divide blackbody for any star.", STDSTAR_TYPE);
01124                 cpl_msg_warning("", "%s = '%s' (should be something like e.g.'G2V' odr 'A9III')", STDSTAR_TYPE, spec_type);
01125             } else {
01126                 strncpy(star_type, spec_class, 1);
01127                 star_type[1] = '\0';
01128                 cpl_msg_info("", "Spectral class:   %s", spec_class);
01129                 cpl_msg_info("", "Luminosity class: %s", lum_class);
01130             }
01131         } else {
01132             spec_class[0] = '\0';
01133             lum_class[0] = '\0';
01134             star_type[0] = '\0';
01135             cpl_msg_warning("", "The keyword %s is not set nor was it provided by the user. "
01136                                 "Can't divide solar spectrum for G stars or fit a profile "
01137                                 "to atmospheric transmission for OBAF stars and can't "
01138                                 "divide blackbody for any star.", STDSTAR_TYPE);
01139         }
01140         cpl_propertylist_delete(tmp_header); tmp_header = NULL;
01141         cpl_msg_info("", "-------------------------------------------");
01142         KMO_TRY_CHECK_ERROR_STATE();
01143 
01144         // assure that filters, grating and rotation offsets match for
01145         // XCAL, YCAL, LCAL and for data frame to reconstruct (except DARK
01146         // frames)
01147         // check if filter_id and grating_id match for all detectors
01148         KMO_TRY_EXIT_IF_ERROR(
01149             kmo_check_frameset_setup(frameset, XCAL, FALSE, FALSE, TRUE));
01150         KMO_TRY_EXIT_IF_ERROR(
01151             kmo_check_frame_setup(frameset, XCAL, YCAL, TRUE, FALSE, TRUE));
01152         KMO_TRY_EXIT_IF_ERROR(
01153             kmo_check_frame_setup(frameset, XCAL, LCAL, TRUE, FALSE, TRUE));
01154         KMO_TRY_EXIT_IF_ERROR(
01155             kmo_check_frame_setup(frameset, XCAL, MASTER_FLAT, TRUE, FALSE, TRUE));
01156         KMO_TRY_EXIT_IF_ERROR(
01157             kmo_check_frame_setup(frameset, XCAL, STD, FALSE, FALSE, TRUE));
01158 
01159         if (cpl_frameset_count_tags(frameset, ILLUM_CORR) == 1) {
01160             KMO_TRY_EXIT_IF_ERROR(
01161                 kmo_check_frame_setup(frameset, XCAL, ILLUM_CORR, TRUE, FALSE, FALSE));
01162         }
01163 
01164         // check descriptors of all frames
01165         KMO_TRY_EXIT_IF_NULL(
01166             xcal_frame = kmo_dfs_get_frame(frameset, XCAL));
01167 
01168         desc1 = kmo_identify_fits_header(cpl_frame_get_filename(xcal_frame));
01169         KMO_TRY_CHECK_ERROR_STATE();
01170 
01171         KMO_TRY_ASSURE((desc1.nr_ext % 3 == 0) &&
01172                        (desc1.ex_badpix == FALSE) &&
01173                        (desc1.fits_type == f2d_fits) &&
01174                        (desc1.frame_type == detector_frame),
01175                        CPL_ERROR_ILLEGAL_INPUT,
01176                        "XCAL isn't in the correct format!!!");
01177 
01178         KMO_TRY_EXIT_IF_NULL(
01179             ycal_frame = kmo_dfs_get_frame(frameset, YCAL));
01180         desc2 = kmo_identify_fits_header(cpl_frame_get_filename(ycal_frame));
01181         KMO_TRY_CHECK_ERROR_STATE();
01182 
01183         KMO_TRY_ASSURE((desc1.nr_ext == desc2.nr_ext) &&
01184                        (desc1.ex_badpix == desc2.ex_badpix) &&
01185                        (desc1.fits_type == desc2.fits_type) &&
01186                        (desc1.frame_type == desc2.frame_type),
01187                        CPL_ERROR_ILLEGAL_INPUT,
01188                        "YCAL isn't in the correct format!!!");
01189         kmo_free_fits_desc(&desc2);
01190         kmo_init_fits_desc(&desc2);
01191 
01192         KMO_TRY_EXIT_IF_NULL(
01193             lcal_frame = kmo_dfs_get_frame(frameset, LCAL));
01194         desc2 = kmo_identify_fits_header(cpl_frame_get_filename(lcal_frame));
01195         KMO_TRY_CHECK_ERROR_STATE();
01196 
01197         KMO_TRY_ASSURE((desc1.nr_ext == desc2.nr_ext) &&
01198                        (desc1.ex_badpix == desc2.ex_badpix) &&
01199                        (desc1.fits_type == desc2.fits_type) &&
01200                        (desc1.frame_type == desc2.frame_type),
01201                        CPL_ERROR_ILLEGAL_INPUT,
01202                        "YCAL isn't in the correct format!!!");
01203         kmo_free_fits_desc(&desc2);
01204         kmo_init_fits_desc(&desc2);
01205 
01206         KMO_TRY_EXIT_IF_NULL(
01207             flat_frame = kmo_dfs_get_frame(frameset, MASTER_FLAT));
01208         desc2 = kmo_identify_fits_header(cpl_frame_get_filename(flat_frame));
01209         KMO_TRY_CHECK_ERROR_STATE();
01210 
01211         KMO_TRY_ASSURE((desc2.nr_ext % 6 == 0) &&
01212                        (desc1.ex_badpix == desc2.ex_badpix) &&
01213                        (desc1.fits_type == desc2.fits_type) &&
01214                        (desc1.frame_type == desc2.frame_type),
01215                        CPL_ERROR_ILLEGAL_INPUT,
01216                        "MASTER_FLAT isn't in the correct format!!!");
01217         kmo_free_fits_desc(&desc2);
01218         kmo_init_fits_desc(&desc2);
01219 
01220         if (cpl_frameset_count_tags(frameset, ILLUM_CORR) == 1) {
01221             KMO_TRY_EXIT_IF_NULL(
01222                 illum_frame = kmo_dfs_get_frame(frameset, ILLUM_CORR));
01223             desc2 = kmo_identify_fits_header(cpl_frame_get_filename(illum_frame));
01224             KMO_TRY_CHECK_ERROR_STATE();
01225             KMO_TRY_ASSURE(((desc2.nr_ext == 24) || (desc2.nr_ext == 48)) &&
01226                            (desc2.ex_badpix == FALSE) &&
01227                            (desc2.fits_type == f2i_fits) &&
01228                            (desc2.frame_type == ifu_frame),
01229                            CPL_ERROR_ILLEGAL_INPUT,
01230                            "ILLUM_CORR isn't in the correct format!!!");
01231             kmo_free_fits_desc(&desc2);
01232             kmo_init_fits_desc(&desc2);
01233         }
01234 
01235         if (cpl_frameset_count_tags(frameset, SPEC_TYPE_LOOKUP) == 1) {
01236             KMO_TRY_EXIT_IF_NULL(
01237                 tmp_frame = kmo_dfs_get_frame(frameset, SPEC_TYPE_LOOKUP));
01238             desc2 = kmo_identify_fits_header(cpl_frame_get_filename(tmp_frame));
01239             KMO_TRY_CHECK_ERROR_STATE();
01240             KMO_TRY_ASSURE((desc2.nr_ext == 1) &&
01241                            (desc2.ex_badpix == FALSE) &&
01242                            (desc2.fits_type == f2l_fits) &&
01243                            (desc2.frame_type == list_frame),
01244                            CPL_ERROR_ILLEGAL_INPUT,
01245                            "SPEC_TYPE_LOOKUP isn't in the correct format!!!");
01246             kmo_free_fits_desc(&desc2);
01247             kmo_init_fits_desc(&desc2);
01248         }
01249 
01250         if (cpl_frameset_count_tags(frameset, SOLAR_SPEC) == 1) {
01251             KMO_TRY_EXIT_IF_NULL(
01252                 tmp_frame = kmo_dfs_get_frame(frameset, SOLAR_SPEC));
01253             desc2 = kmo_identify_fits_header(cpl_frame_get_filename(tmp_frame));
01254             KMO_TRY_CHECK_ERROR_STATE();
01255             KMO_TRY_ASSURE((desc2.nr_ext == 1) &&
01256                            (desc2.ex_badpix == FALSE) &&
01257                            (desc2.fits_type == f1s_fits) &&
01258                            (desc2.frame_type == spectrum_frame),
01259                            CPL_ERROR_ILLEGAL_INPUT,
01260                            "SOLAR_SPEC isn't in the correct format!!!");
01261             kmo_free_fits_desc(&desc2);
01262             kmo_init_fits_desc(&desc2);
01263         }
01264 
01265         if (cpl_frameset_count_tags(frameset, ATMOS_MODEL) == 1) {
01266             KMO_TRY_EXIT_IF_NULL(
01267                 tmp_frame = kmo_dfs_get_frame(frameset, ATMOS_MODEL));
01268             desc2 = kmo_identify_fits_header(cpl_frame_get_filename(tmp_frame));
01269             KMO_TRY_CHECK_ERROR_STATE();
01270             KMO_TRY_ASSURE((desc2.nr_ext == 1) &&
01271                            (desc2.ex_badpix == FALSE) &&
01272                            (desc2.fits_type == f1s_fits) &&
01273                            (desc2.frame_type == spectrum_frame),
01274                            CPL_ERROR_ILLEGAL_INPUT,
01275                            "ATMOS_MODEL isn't in the correct format!!!");
01276             kmo_free_fits_desc(&desc2);
01277             kmo_init_fits_desc(&desc2);
01278         }
01279 
01280         KMO_TRY_EXIT_IF_NULL(
01281             tmp_frame = kmo_dfs_get_frame(frameset, STD));
01282         while (tmp_frame != NULL ) {
01283             desc2 = kmo_identify_fits_header(cpl_frame_get_filename(tmp_frame));
01284             KMO_TRY_CHECK_ERROR_STATE();
01285             KMO_TRY_ASSURE((desc2.nr_ext == 3) &&
01286                            (desc2.ex_badpix == FALSE) &&
01287                            (desc2.fits_type == raw_fits) &&
01288                            (desc2.frame_type == detector_frame),
01289                            CPL_ERROR_ILLEGAL_INPUT,
01290                            "STD isn't in the correct format!!!");
01291             nr_devices = desc2.nr_ext;
01292             kmo_free_fits_desc(&desc2);
01293             kmo_init_fits_desc(&desc2);
01294 
01295             tmp_frame = kmo_dfs_get_frame(frameset, NULL);
01296             KMO_TRY_CHECK_ERROR_STATE();
01297         }
01298         KMO_TRY_EXIT_IF_NULL(
01299             tmp_frame = kmo_dfs_get_frame(frameset, STD));
01300         KMO_TRY_EXIT_IF_NULL(
01301             suffix = kmo_dfs_get_suffix(tmp_frame, TRUE, FALSE));
01302 
01303         KMO_TRY_EXIT_IF_ERROR(
01304             kmo_check_frame_setup_md5_xycal(frameset));
01305         KMO_TRY_EXIT_IF_ERROR(
01306             kmo_check_frame_setup_md5(frameset));
01307 
01308         cpl_msg_info("", "Detected instrument setup:   %s", suffix+1);
01309         cpl_msg_info("", "(grating 1, 2 & 3)");
01310 
01311         // check which IFUs are active for all frames
01312         KMO_TRY_EXIT_IF_NULL(
01313             unused_ifus_before = kmo_get_unused_ifus(frameset, 0, 0));
01314 
01315         KMO_TRY_EXIT_IF_NULL(
01316             unused_ifus_after = kmo_duplicate_unused_ifus(unused_ifus_before));
01317 
01318         kmo_print_unused_ifus(unused_ifus_before, FALSE);
01319 
01320         /* --- load data --- */
01321 
01322         if ((cpl_frameset_count_tags(frameset, SPEC_TYPE_LOOKUP) == 1) &&
01323             ((strlen(spec_class) > 0) || (strlen(lum_class) > 0)))
01324         {
01325             // get star temperature out of SPEC_TYPE_LOOKUP table
01326             KMO_TRY_EXIT_IF_NULL(
01327                 spec_type_LUT = kmo_dfs_load_table(frameset, SPEC_TYPE_LOOKUP, 1, 0));
01328             star_temperature = kmo_get_temperature(spec_type_LUT, spec_class, lum_class);
01329             KMO_TRY_CHECK_ERROR_STATE();
01330         } else if (cpl_frameset_count_tags(frameset, SPEC_TYPE_LOOKUP) != 1) {
01331             cpl_msg_warning("","No SPEC_TYPE_LOOKUP was provided! Can't divide blackbody.");
01332         } else if ((strlen(spec_class) == 0) || (strlen(lum_class) == 0)) {
01333 //            cpl_msg_warning("","No startype was provided! Can't "
01334 //                            "divide blackbody.");
01335         }
01336 
01337         // allocate intermediate memory
01338         KMO_TRY_EXIT_IF_NULL(
01339             stored_telluric_data    = (cpl_vector**)cpl_calloc(nr_devices*KMOS_IFUS_PER_DETECTOR,
01340                                                                sizeof(cpl_vector*)));
01341         KMO_TRY_EXIT_IF_NULL(
01342             stored_telluric_noise   = (cpl_vector**)cpl_calloc(nr_devices*KMOS_IFUS_PER_DETECTOR,
01343                                                                sizeof(cpl_vector*)));
01344         KMO_TRY_EXIT_IF_NULL(
01345             stored_starspec_data    = (cpl_vector**)cpl_calloc(nr_devices*KMOS_IFUS_PER_DETECTOR,
01346                                                                sizeof(cpl_vector*)));
01347         KMO_TRY_EXIT_IF_NULL(
01348             stored_starspec_noise   = (cpl_vector**)cpl_calloc(nr_devices*KMOS_IFUS_PER_DETECTOR,
01349                                                                sizeof(cpl_vector*)));
01350         KMO_TRY_EXIT_IF_NULL(
01351             stored_psf_data         = (cpl_image**)cpl_calloc(nr_devices*KMOS_IFUS_PER_DETECTOR,
01352                                                               sizeof(cpl_image*)));
01353         KMO_TRY_EXIT_IF_NULL(
01354             stored_mask             = (cpl_image**)cpl_calloc(nr_devices*KMOS_IFUS_PER_DETECTOR,
01355                                                               sizeof(cpl_image*)));
01356         KMO_TRY_EXIT_IF_NULL(
01357             stored_data_cube        = (cpl_imagelist**)cpl_calloc(nr_devices*KMOS_IFUS_PER_DETECTOR,
01358                                                               sizeof(cpl_imagelist*)));
01359         KMO_TRY_EXIT_IF_NULL(
01360             stored_noise_cube       = (cpl_imagelist**)cpl_calloc(nr_devices*KMOS_IFUS_PER_DETECTOR,
01361                                                               sizeof(cpl_imagelist*)));
01362         KMO_TRY_EXIT_IF_NULL(
01363             stored_qc_throughput    = (double*)cpl_calloc(nr_devices*KMOS_IFUS_PER_DETECTOR,
01364                                                           sizeof(double)));
01365         KMO_TRY_EXIT_IF_NULL(
01366             stored_sub_psf_headers  = (cpl_propertylist**)cpl_calloc(nr_devices*KMOS_IFUS_PER_DETECTOR,
01367                                                                      sizeof(cpl_propertylist*)));
01368         KMO_TRY_EXIT_IF_NULL(
01369             stored_sub_tel_data_headers  = (cpl_propertylist**)cpl_calloc(nr_devices*KMOS_IFUS_PER_DETECTOR,
01370                                                                           sizeof(cpl_propertylist*)));
01371         KMO_TRY_EXIT_IF_NULL(
01372             stored_sub_tel_noise_headers = (cpl_propertylist**)cpl_calloc(nr_devices*KMOS_IFUS_PER_DETECTOR,
01373                                                                           sizeof(cpl_propertylist*)));
01374         if (save_cubes) {
01375             KMO_TRY_EXIT_IF_NULL(
01376                 stored_sub_cube_data_headers = (cpl_propertylist**)cpl_calloc(nr_devices*KMOS_IFUS_PER_DETECTOR,
01377                                                                              sizeof(cpl_propertylist*)));
01378             KMO_TRY_EXIT_IF_NULL(
01379                 stored_sub_cube_noise_headers = (cpl_propertylist**)cpl_calloc(nr_devices*KMOS_IFUS_PER_DETECTOR,
01380                                                                              sizeof(cpl_propertylist*)));
01381         }
01382 
01383         // get bounds
01384         KMO_TRY_EXIT_IF_NULL(
01385             tmp_header = kmo_dfs_load_primary_header(frameset, XCAL));
01386         KMO_TRY_EXIT_IF_NULL(
01387             bounds = kmclipm_extract_bounds(tmp_header));
01388         cpl_propertylist_delete(tmp_header); tmp_header = NULL;
01389 
01390         // setup grid definition, wavelength start and end points will be set
01391         // in the detector loop
01392         KMO_TRY_EXIT_IF_ERROR(
01393             kmclipm_setup_grid(&gd, imethod, neighborhoodRange, KMOS_PIX_RESOLUTION, 0.));
01394 
01395         // get valid STD frames with objects in it and associated sky exposures
01396         KMO_TRY_EXIT_IF_NULL(
01397             obj_sky_struct = kmo_create_objSkyStruct(frameset_std, STD, FALSE));
01398         kmo_print_objSkyStruct(obj_sky_struct);
01399 
01400         if (!no_noise && (strcmp(tplid, "KMOS_spec_cal_stdstarscipatt") == 0)) {
01401             KMO_TRY_EXIT_IF_NULL(
01402                 stored_noisespec = (cpl_vector**)cpl_calloc(nr_devices*KMOS_IFUS_PER_DETECTOR,
01403                                                                     sizeof(cpl_vector*)));
01404 
01405             // identify sky-sky-pairs for NOISE_SPEC calculation
01406             KMO_TRY_EXIT_IF_NULL(
01407                 sky_sky_struct = kmo_create_skySkyStruct(frameset_std));
01408         }
01409 
01410         // loop the object-sky pairs
01411         if (obj_sky_struct->size == 0) {
01412             cpl_msg_warning(cpl_func,"Not a single frame contains an object");
01413         } else {
01414             strcpy(filename_telluric, TELLURIC);
01415             strcpy(filename_starspec, STAR_SPEC);
01416             strcpy(filename_psf, STD_IMAGE);
01417             strcpy(filename_mask, STD_MASK);
01418             strcpy(filename_cubes, STD_CUBE);
01419             strcpy(filename_noise, NOISE_SPEC);
01420 
01421             obj_frame = obj_sky_struct->table[nr_exp].objFrame;
01422             KMO_TRY_EXIT_IF_NULL(
01423                 main_header_tel = kmclipm_propertylist_load(cpl_frame_get_filename(obj_frame), 0));
01424 
01425             exptime = cpl_propertylist_get_double(main_header_tel, EXPTIME);
01426             KMO_TRY_CHECK_ERROR_STATE();
01427 
01428             // load, process & store frames
01429 
01430             for (i = 1; i <= nr_devices; i++) {
01431                 // extract LCAL image close to ROTANGLE 0. assuming that the wavelength range
01432                 // doesn't differ too much with different ROTANGLEs.
01433                 print_cal_angle_msg_once = FALSE;
01434                 print_xcal_angle_msg_once = FALSE;
01435                 double rotangle_found;
01436                 KMO_TRY_EXIT_IF_NULL(
01437                     lcal = kmo_dfs_load_cal_image(frameset, LCAL, i, FALSE, 0., FALSE, NULL,
01438                             &rotangle_found, -1, 0, 0));
01439                 if (i==1) {
01440                     print_cal_angle_msg_once = TRUE;
01441                     print_xcal_angle_msg_once = TRUE;
01442                 }
01443                 if (tmp_band_method != NULL) {
01444                     band_method = atoi(tmp_band_method);
01445                 }
01446 
01447                 // get filter for this detector
01448                 // ESO INS FILTi ID
01449                 KMO_TRY_EXIT_IF_NULL(
01450                     keyword = cpl_sprintf("%s%d%s", IFU_FILTID_PREFIX, i, IFU_FILTID_POSTFIX));
01451                 filter_id = cpl_propertylist_get_string(main_header_tel, keyword);
01452                 cpl_free(keyword); keyword = NULL;
01453 
01454                 KMO_TRY_EXIT_IF_NULL(
01455                     band_table = kmo_dfs_load_table(frameset, WAVE_BAND, 1, 0));
01456                 KMO_TRY_EXIT_IF_ERROR(
01457                     kmclipm_setup_grid_band_lcal(&gd, lcal, filter_id,
01458                                                  band_method, band_table));
01459                 cpl_image_delete(lcal); lcal = NULL;
01460                 cpl_table_delete(band_table); band_table = NULL;
01461 
01462                 // load sub_header of original F2D image
01463                 KMO_TRY_EXIT_IF_NULL(
01464                     sub_header_orig = kmclipm_propertylist_load( cpl_frame_get_filename(obj_frame), i));
01465 
01466                 for (j = 0; j < KMOS_IFUS_PER_DETECTOR; j++) {
01467                     ifu_nr = (i-1)*KMOS_IFUS_PER_DETECTOR + j + 1;
01468                     // check if IFU is valid according to main header keywords &
01469                     // calibration files
01470                     // AND check if there is a sky frame available for this IFU
01471                     kmo_collapse_objSkyStruct(obj_sky_struct, ifu_nr,
01472                                               &obj_frame, &sky_frame);
01473 
01474                     KMO_TRY_EXIT_IF_NULL(
01475                         punused_ifus = cpl_array_get_data_int_const(unused_ifus_after[i-1]));
01476 
01477                     // Search for keyword ESO OCS ARMi NOTUSED
01478                     // If not present (CPL_ERROR_DATA_NOT_FOUND) we will eventually
01479                     // process standard star
01480                     KMO_TRY_EXIT_IF_NULL(
01481                         keyword = cpl_sprintf("%s%d%s", IFU_VALID_PREFIX, ifu_nr, IFU_VALID_POSTFIX));
01482                     tmp_str = cpl_propertylist_get_string(main_header_tel, keyword);
01483                     cpl_free(keyword); keyword = NULL;
01484 
01485                     if ((cpl_error_get_code() == CPL_ERROR_DATA_NOT_FOUND) &&
01486                         (bounds[2*(ifu_nr-1)] != -1) &&
01487                         (bounds[2*(ifu_nr-1)+1] != -1) &&
01488                         (sky_frame != NULL) &&
01489                         (punused_ifus[j] == 0))
01490                     {
01491                         cpl_error_reset();
01492                         // IFU is valid
01493 
01494                         if (sky_frame != NO_CORRESPONDING_SKYFRAME) {
01495                             cpl_msg_info("", "Processing standard star in IFU %d", ifu_nr);
01496                             cpl_msg_info("", "   (obj: %s, sky: %s)",
01497                                              cpl_frame_get_filename(obj_frame), cpl_frame_get_filename(sky_frame));
01498                         } else {
01499                             sky_frame = NULL;
01500                             cpl_msg_warning("", "Processing standard star in IFU %d", ifu_nr);
01501                             cpl_msg_warning("", "   (obj: %s, no corresponding sky frame)",
01502                                                 cpl_frame_get_filename(obj_frame));
01503                         }
01504 
01505                         nr_std_stars++;
01506 
01507                         char *ggg = cpl_sprintf("%s%d", PRO_STD, ifu_nr);
01508                         KMO_TRY_EXIT_IF_ERROR(
01509                             cpl_propertylist_update_int(main_header_tel, ggg, 1));
01510                         cpl_free(ggg); ggg = NULL;
01511 
01512                         // calculate WCS and make copies of sub_header
01513                         KMO_TRY_EXIT_IF_NULL(
01514                             tmp_sub_header = cpl_propertylist_duplicate(sub_header_orig));
01515                         KMO_TRY_EXIT_IF_ERROR(
01516                             kmo_calc_wcs_gd(main_header_tel, tmp_sub_header, ifu_nr, gd));
01517                         KMO_TRY_EXIT_IF_NULL(
01518                             stored_sub_tel_data_headers[ifu_nr-1] =
01519                                    cpl_propertylist_duplicate(tmp_sub_header));
01520                         KMO_TRY_EXIT_IF_NULL(
01521                             stored_sub_psf_headers[ifu_nr-1] =
01522                                    cpl_propertylist_duplicate(tmp_sub_header));
01523                         if (save_cubes) {
01524                             KMO_TRY_EXIT_IF_NULL(
01525                                 stored_sub_cube_data_headers[ifu_nr-1] =
01526                                        cpl_propertylist_duplicate(tmp_sub_header));
01527                         }
01528                         cpl_propertylist_delete(tmp_sub_header);
01529                         tmp_sub_header = NULL;
01530 
01531                         //
01532                         // adjust telluric-headers: copy CRPIX3 to CRPIX1,
01533                         //
01534                         cpl_propertylist_update_double(stored_sub_tel_data_headers[ifu_nr-1], CRVAL1,
01535                                 cpl_propertylist_get_double(stored_sub_tel_data_headers[ifu_nr-1], CRVAL3));
01536                         cpl_propertylist_erase(stored_sub_tel_data_headers[ifu_nr-1], CRVAL2);
01537                         cpl_propertylist_erase(stored_sub_tel_data_headers[ifu_nr-1], CRVAL3);
01538                         KMO_TRY_CHECK_ERROR_STATE();
01539 
01540                         // CRPIX
01541                         cpl_propertylist_update_double(stored_sub_tel_data_headers[ifu_nr-1], CRPIX1,
01542                                 cpl_propertylist_get_double(stored_sub_tel_data_headers[ifu_nr-1], CRPIX3));
01543                         cpl_propertylist_erase(stored_sub_tel_data_headers[ifu_nr-1], CRPIX2);
01544                         cpl_propertylist_erase(stored_sub_tel_data_headers[ifu_nr-1], CRPIX3);
01545                         KMO_TRY_CHECK_ERROR_STATE();
01546 
01547                         // CDELT
01548                         cdelt3 = cpl_propertylist_get_double(stored_sub_tel_data_headers[ifu_nr-1], CDELT3);
01549                         cpl_propertylist_update_double(stored_sub_tel_data_headers[ifu_nr-1], CDELT1,
01550                                 cdelt3);
01551                         cpl_propertylist_erase(stored_sub_tel_data_headers[ifu_nr-1], CDELT2);
01552                         cpl_propertylist_erase(stored_sub_tel_data_headers[ifu_nr-1], CDELT3);
01553                         KMO_TRY_CHECK_ERROR_STATE();
01554 
01555                         // CTYPE
01556                         cpl_propertylist_update_string(stored_sub_tel_data_headers[ifu_nr-1], CTYPE1,
01557                                 cpl_propertylist_get_string(stored_sub_tel_data_headers[ifu_nr-1], CTYPE3));
01558                         cpl_propertylist_erase(stored_sub_tel_data_headers[ifu_nr-1], CTYPE2);
01559                         cpl_propertylist_erase(stored_sub_tel_data_headers[ifu_nr-1], CTYPE3);
01560                         KMO_TRY_CHECK_ERROR_STATE();
01561 
01562                         // CUNIT
01563                         cpl_propertylist_update_string(stored_sub_tel_data_headers[ifu_nr-1], CUNIT1,
01564                         cpl_propertylist_get_string(stored_sub_tel_data_headers[ifu_nr-1], CUNIT3));
01565                         cpl_propertylist_erase(stored_sub_tel_data_headers[ifu_nr-1], CUNIT2);
01566                         cpl_propertylist_erase(stored_sub_tel_data_headers[ifu_nr-1], CUNIT3);
01567 
01568                         // CDx_x
01569                         cpl_propertylist_erase(stored_sub_tel_data_headers[ifu_nr-1], CD1_1);
01570                         cpl_propertylist_erase(stored_sub_tel_data_headers[ifu_nr-1], CD1_2);
01571                         cpl_propertylist_erase(stored_sub_tel_data_headers[ifu_nr-1], CD1_3);
01572                         cpl_propertylist_erase(stored_sub_tel_data_headers[ifu_nr-1], CD2_1);
01573                         cpl_propertylist_erase(stored_sub_tel_data_headers[ifu_nr-1], CD2_2);
01574                         cpl_propertylist_erase(stored_sub_tel_data_headers[ifu_nr-1], CD2_3);
01575                         cpl_propertylist_erase(stored_sub_tel_data_headers[ifu_nr-1], CD3_1);
01576                         cpl_propertylist_erase(stored_sub_tel_data_headers[ifu_nr-1], CD3_2);
01577                         cpl_propertylist_erase(stored_sub_tel_data_headers[ifu_nr-1], CD3_3);
01578                         KMO_TRY_CHECK_ERROR_STATE();
01579 
01580                         //
01581                         // adjust psf-headers: delete CRPIX3 etc.
01582                         //
01583                         cpl_propertylist_erase(stored_sub_psf_headers[ifu_nr-1], CRPIX3);
01584                         cpl_propertylist_erase(stored_sub_psf_headers[ifu_nr-1], CRPIX3);
01585                         cpl_propertylist_erase(stored_sub_psf_headers[ifu_nr-1], CDELT3);
01586                         cpl_propertylist_erase(stored_sub_psf_headers[ifu_nr-1], CRVAL3);
01587                         cpl_propertylist_erase(stored_sub_psf_headers[ifu_nr-1], CTYPE3);
01588                         cpl_propertylist_erase(stored_sub_psf_headers[ifu_nr-1], CUNIT3);
01589                         cpl_propertylist_erase(stored_sub_psf_headers[ifu_nr-1], CD1_3);
01590                         cpl_propertylist_erase(stored_sub_psf_headers[ifu_nr-1], CD2_3);
01591                         cpl_propertylist_erase(stored_sub_psf_headers[ifu_nr-1], CD3_1);
01592                         cpl_propertylist_erase(stored_sub_psf_headers[ifu_nr-1], CD3_2);
01593                         cpl_propertylist_erase(stored_sub_psf_headers[ifu_nr-1], CD3_3);
01594                         KMO_TRY_CHECK_ERROR_STATE();
01595 
01596                         KMO_TRY_EXIT_IF_ERROR(
01597                             kmo_reconstruct_sci(ifu_nr,
01598                                                 bounds[2*(ifu_nr-1)],
01599                                                 bounds[2*(ifu_nr-1)+1],
01600                                                 obj_frame,
01601                                                 STD,
01602                                                 sky_frame,
01603                                                 STD,
01604                                                 flat_frame,
01605                                                 xcal_frame,
01606                                                 ycal_frame,
01607                                                 lcal_frame,
01608                                                 NULL,
01609                                                 &gd,
01610                                                 &stored_data_cube[ifu_nr-1],
01611                                                 &stored_noise_cube[ifu_nr-1],
01612                                                 flux,
01613                                                 background,
01614                                                 xcal_interpolation));
01615 
01616                         // divide illumination correction from the data_cube
01617                         // (illumination noise will be very small versus
01618                         // noise_cube, so it is skipped here)
01619                         if (cpl_frameset_count_tags(frameset, ILLUM_CORR) == 1) {
01620                             KMO_TRY_EXIT_IF_NULL(
01621                                 illum_corr = kmo_dfs_load_image_frame(illum_frame, ifu_nr,
01622                                                                       FALSE, FALSE, NULL));
01623                             KMO_TRY_EXIT_IF_ERROR(
01624                                 cpl_imagelist_divide_image(stored_data_cube[ifu_nr-1], illum_corr));
01625                             cpl_image_delete(illum_corr); illum_corr = NULL;
01626                         }
01627 
01628                         // calculate QC_STD_TRACE
01629                         // (the distance of the PSF to the centre)
01630                         KMO_TRY_EXIT_IF_ERROR(
01631                             kmo_calculate_std_trace(stored_data_cube[ifu_nr-1], fmethod, &std_trace));
01632 
01633                         KMO_TRY_EXIT_IF_ERROR(
01634                             kmclipm_update_property_double(stored_sub_psf_headers[ifu_nr-1],
01635                                                            QC_STD_TRACE, std_trace,
01636                                                            "[pix] distance of PSF and centre of IFU"));
01637 
01638                         KMO_TRY_EXIT_IF_NULL(
01639                             identified_slices = cpl_vector_new(cpl_imagelist_get_size(stored_data_cube[ifu_nr-1])));
01640                         KMO_TRY_EXIT_IF_ERROR(
01641                             cpl_vector_fill(identified_slices, 1.0));
01642 
01643                         // collapse cube and get PSF image
01644                         KMO_TRY_EXIT_IF_ERROR(
01645                             kmclipm_make_image(stored_data_cube[ifu_nr-1], NULL,
01646                                                &stored_psf_data[ifu_nr-1], NULL,
01647                                                identified_slices,
01648                                                cmethod,
01649                                                cpos_rej, cneg_rej, citer,
01650                                                cmax, cmin));
01651                         cpl_vector_delete(identified_slices);
01652                         identified_slices= NULL;
01653 
01654                         // fit a 2D profile to get a mask and fwhm in x and y,
01655                         KMO_TRY_EXIT_IF_NULL(
01656                             tmp_vec = kmo_fit_profile_2D(stored_psf_data[ifu_nr-1],
01657                                                          NULL,
01658                                                          fmethod,
01659                                                          &stored_mask[ifu_nr-1],
01660                                                          &pl_psf));
01661 
01662                         // normalise mask to 1 and clip values below 0.5
01663                         cpl_image_divide_scalar(stored_mask[ifu_nr-1], cpl_image_get_max(stored_mask[ifu_nr-1]));
01664                         KMO_TRY_CHECK_ERROR_STATE();
01665 
01666                         int dummy=0;
01667                         for (gx = 1; gx <= cpl_image_get_size_x(stored_mask[ifu_nr-1]); gx++) {
01668                             for (gy = 1; gy <= cpl_image_get_size_y(stored_mask[ifu_nr-1]); gy++) {
01669                                 if (cpl_image_get(stored_mask[ifu_nr-1], gx, gy, &dummy) < 0.5) {
01670                                     cpl_image_set(stored_mask[ifu_nr-1], gx, gy, 0.);
01671                                 } else {
01672                                     cpl_image_set(stored_mask[ifu_nr-1], gx, gy, 1.);
01673                                 }
01674                             }
01675                         }
01676                         KMO_TRY_CHECK_ERROR_STATE();
01677 
01678                         // update subheader with fit parameters
01679                         KMO_TRY_EXIT_IF_ERROR(
01680                             cpl_propertylist_append(stored_sub_tel_data_headers[ifu_nr-1], pl_psf));
01681                         cpl_propertylist_delete(pl_psf); pl_psf = NULL;
01682 
01683                         // store QC_SPAT_RES (RMS of fwhm_x and fwhm_y)
01684                         double factor_fwhm = 2*sqrt(2*log(2));
01685                         double spat_res = pow(cpl_vector_get(tmp_vec, 4) * factor_fwhm, 2);
01686                         spat_res += pow(cpl_vector_get(tmp_vec, 5) * factor_fwhm, 2);
01687                         spat_res /= 2;
01688                         KMO_TRY_EXIT_IF_ERROR(
01689                             kmclipm_update_property_double(stored_sub_psf_headers[ifu_nr-1],
01690                                                            QC_SPAT_RES,
01691                                                            sqrt(spat_res)*KMOS_PIX_RESOLUTION,
01692                                                            "[arcsec] mean fwhm resolution of PSF"));
01693                         cpl_vector_delete(tmp_vec); tmp_vec = NULL;
01694                         
01695                         // extract spectrum in masked area and convert returned mean to sum
01696                         // (times mask aperture)
01697                         KMO_TRY_EXIT_IF_ERROR(
01698                             kmo_priv_extract_spec(stored_data_cube[ifu_nr-1],
01699                                                   stored_noise_cube[ifu_nr-1],
01700                                                   stored_mask[ifu_nr-1],
01701                                                   &tmp_spec_data,
01702                                                   &tmp_spec_noise));
01703                         KMO_TRY_CHECK_ERROR_STATE();
01704 
01705                         KMO_TRY_EXIT_IF_ERROR(
01706                             cpl_vector_multiply_scalar(tmp_spec_data, cpl_image_get_flux(stored_mask[ifu_nr-1])));
01707                         if (tmp_spec_noise != NULL) {
01708                             KMO_TRY_EXIT_IF_ERROR(
01709                                 cpl_vector_multiply_scalar(tmp_spec_noise, cpl_image_get_flux(stored_mask[ifu_nr-1])));
01710                         }
01711                         KMO_TRY_CHECK_ERROR_STATE();
01712 
01713                         // extract spectrum of whole area for QC THRUHPUT and QC ZEROPOINT and
01714                         // convert returned mean to sum (times 196, IFU area)
01715                         KMO_TRY_EXIT_IF_ERROR(
01716                             kmo_priv_extract_spec(stored_data_cube[ifu_nr-1],
01717                                                   stored_noise_cube[ifu_nr-1],
01718                                                   NULL,
01719                                                   &spec_qc,
01720                                                   &tmp_vec));
01721 
01722                         KMO_TRY_EXIT_IF_NULL(
01723                             tmp_img = cpl_imagelist_get(stored_data_cube[ifu_nr-1], 0));
01724                         int tmpx = cpl_image_get_size_x(tmp_img),
01725                             tmpy = cpl_image_get_size_x(tmp_img);
01726                         KMO_TRY_EXIT_IF_ERROR(
01727                             cpl_vector_multiply_scalar(spec_qc, tmpx*tmpy));
01728                         if (tmp_vec != NULL) {
01729                             KMO_TRY_EXIT_IF_ERROR(
01730                                 cpl_vector_multiply_scalar(tmp_vec, tmpx*tmpy));
01731                         }
01732 
01733                         // calculate shot noise
01734                         crpix1 = cpl_propertylist_get_double(stored_sub_tel_data_headers[ifu_nr-1], CRPIX1);
01735                         crval1 = cpl_propertylist_get_double(stored_sub_tel_data_headers[ifu_nr-1], CRVAL1);
01736                         cdelt1 = cpl_propertylist_get_double(stored_sub_tel_data_headers[ifu_nr-1], CDELT1);
01737                         gain = cpl_propertylist_get_double(stored_sub_tel_data_headers[ifu_nr-1], GAIN);
01738                         KMO_TRY_CHECK_ERROR_STATE();
01739 
01740                         // shot_noise = sqrt(tmp_spec_data*gain)/gain
01741                         // (set negative values and NaN's to zero before sqrt)
01742                         KMO_TRY_EXIT_IF_NULL(
01743                             shot_noise = cpl_vector_duplicate(tmp_spec_data));
01744                         KMO_TRY_EXIT_IF_ERROR(
01745                             cpl_vector_multiply_scalar(shot_noise, gain));
01746 
01747                         ppp = cpl_vector_get_data(shot_noise);
01748                         for (ii = 0; ii < cpl_vector_get_size(shot_noise); ii++) {
01749                             if ((ppp[ii] < 0.0) || kmclipm_is_nan_or_inf(ppp[ii])) {
01750                                 ppp[ii] = 0.0;
01751                             }
01752                         }
01753                         KMO_TRY_EXIT_IF_ERROR(
01754                             cpl_vector_sqrt(shot_noise));
01755                         KMO_TRY_EXIT_IF_ERROR(
01756                             cpl_vector_divide_scalar(shot_noise, gain));
01757 
01758                         // scale extracted spectrum to match the one calculated over the whole area
01759                         // (this is done in a band-specific range!)
01760                         KMO_TRY_EXIT_IF_ERROR(
01761                             kmo_calc_band_mean(stored_sub_tel_data_headers[ifu_nr-1],
01762                                                filter_id,
01763                                                tmp_spec_data,
01764                                                tmp_spec_noise,
01765                                                &mean_data,
01766                                                NULL));
01767 
01768                         KMO_TRY_EXIT_IF_ERROR(
01769                             kmo_calc_band_mean(stored_sub_tel_data_headers[ifu_nr-1],
01770                                                filter_id,
01771                                                spec_qc,
01772                                                tmp_vec,
01773                                                &mean_data2,
01774                                                NULL));
01775 
01776                         cpl_vector_delete(tmp_vec); tmp_vec = NULL;
01777 
01778                         flux_scale_factor = mean_data2/mean_data;
01779                         KMO_TRY_EXIT_IF_ERROR(
01780                             cpl_vector_multiply_scalar(shot_noise, flux_scale_factor));
01781                         KMO_TRY_EXIT_IF_ERROR(
01782                             cpl_vector_multiply_scalar(tmp_spec_data, flux_scale_factor));
01783                         if ((tmp_spec_noise != NULL) && (fabs(mean_data) > 1e-8)) {
01784                             KMO_TRY_EXIT_IF_ERROR(
01785                                 cpl_vector_multiply_scalar(tmp_spec_noise, flux_scale_factor));
01786                         }
01787 
01788                         // store to save to disk later on
01789                         stored_starspec_data[ifu_nr-1] = cpl_vector_duplicate(tmp_spec_data);
01790                         if (tmp_spec_noise != NULL) {
01791                             stored_starspec_noise[ifu_nr-1] = cpl_vector_duplicate(tmp_spec_noise);
01792                         }
01793                         KMO_TRY_CHECK_ERROR_STATE();
01794 
01795                         //
01796                         // calculate noise spectra
01797                         //
01798                         if (!no_noise && (strcmp(tplid, "KMOS_spec_cal_stdstarscipatt") == 0)) {
01799                             nr_sky_pairs = sky_sky_struct[ifu_nr-1].nrSkyPairs;
01800                             if (nr_sky_pairs > 2) {
01801                                 cpl_msg_info("", "   Calculating noise-spectra on sky exposures for IFU %d", ifu_nr);
01802                                 int             ll                     = 0;
01803                                 double          **pvec_array            = NULL,
01804                                                 *ptmp_vec               = NULL,
01805                                                 *pstored_noisespec      = NULL;
01806                                 cpl_vector      **vec_array             = NULL;
01807                                 cpl_imagelist   *tmp_cube               = NULL;
01808 
01809                                 KMO_TRY_EXIT_IF_NULL(
01810                                     vec_array = cpl_calloc(nr_sky_pairs, sizeof(cpl_vector*)));
01811                                 KMO_TRY_EXIT_IF_NULL(
01812                                     pvec_array = cpl_calloc(nr_sky_pairs, sizeof(double*)));
01813                                 // reconstruct all sky-Pairs, extract spectra using a mask and store temporarily
01814                                 for (ii = 0; ii < nr_sky_pairs; ii++) {
01815                                     // reconstruct (sky1-sky2)/flatfield
01816                                     KMO_TRY_EXIT_IF_ERROR(
01817                                         kmo_reconstruct_sci(ifu_nr,
01818                                                             bounds[2*(ifu_nr-1)],
01819                                                             bounds[2*(ifu_nr-1)+1],
01820                                                             sky_sky_struct[ifu_nr-1].skyPairs[ii].skyFrame1,
01821                                                             STD,
01822                                                             sky_sky_struct[ifu_nr-1].skyPairs[ii].skyFrame2,
01823                                                             STD,
01824                                                             flat_frame,
01825                                                             xcal_frame,
01826                                                             ycal_frame,
01827                                                             lcal_frame,
01828                                                             NULL,
01829                                                             &gd,
01830                                                             &tmp_cube,
01831                                                             NULL,
01832                                                             FALSE,
01833                                                             FALSE,
01834                                                             xcal_interpolation));
01835 
01836                                     // extract spectrum in masked area and convert mean to sum
01837                                     // (times mask aperture)
01838                                     KMO_TRY_EXIT_IF_ERROR(
01839                                         kmo_priv_extract_spec(tmp_cube,
01840                                                               NULL,
01841                                                               stored_mask[ifu_nr-1],
01842                                                               &(vec_array[ii]),
01843                                                               NULL));
01844                                     KMO_TRY_EXIT_IF_ERROR(
01845                                        cpl_vector_multiply_scalar(vec_array[ii], cpl_image_get_flux(stored_mask[ifu_nr-1])));
01846 
01847                                    // again: scale calculated noise spectrum to match the one calculated over the whole area
01848                                    // (this is done in a band-specific range!)
01849                                    KMO_TRY_EXIT_IF_ERROR(
01850                                        cpl_vector_multiply_scalar(vec_array[ii], flux_scale_factor));
01851 
01852                                     KMO_TRY_EXIT_IF_NULL(
01853                                         pvec_array[ii] = cpl_vector_get_data(vec_array[ii]));
01854 
01855                                     cpl_imagelist_delete(tmp_cube); tmp_cube = NULL;
01856                                 }
01857                                 KMO_TRY_CHECK_ERROR_STATE();
01858 
01859                                 // now calculate stddev on every wavelength of all temporary
01860                                 // extracted spectra
01861                                 KMO_TRY_EXIT_IF_NULL(
01862                                     stored_noisespec[ifu_nr-1] = cpl_vector_new(gd.l.dim));
01863                                 KMO_TRY_EXIT_IF_NULL(
01864                                     pstored_noisespec = cpl_vector_get_data(stored_noisespec[ifu_nr-1]));
01865                                 KMO_TRY_EXIT_IF_NULL(
01866                                     tmp_vec = cpl_vector_new(nr_sky_pairs));
01867                                 KMO_TRY_EXIT_IF_NULL(
01868                                     ptmp_vec = cpl_vector_get_data(tmp_vec));
01869                                 for (ll = 0; ll < gd.l.dim; ll++) {
01870                                     for (ii = 0; ii < nr_sky_pairs; ii++) {
01871                                         ptmp_vec[ii] = pvec_array[ii][ll];
01872                                     }
01873 
01874                                     pstored_noisespec[ll] = cpl_vector_get_stdev(tmp_vec);
01875                                 }
01876                                 KMO_TRY_CHECK_ERROR_STATE();
01877 
01878                                 // free temporary data
01879                                 for (ii = 0; ii < nr_sky_pairs; ii++) {
01880                                     cpl_vector_delete(vec_array[ii]); vec_array[ii] = NULL;
01881                                 }
01882                                 cpl_free(vec_array); vec_array = NULL;
01883                                 cpl_free(pvec_array); pvec_array = NULL;
01884                                 cpl_vector_delete(tmp_vec); tmp_vec = NULL;
01885                                 
01886                                 // apply shot_noise (total noise = sqrt (shot_noise^2 + sky_noise^2) )
01887                                 // and set negative values and NaN's to zero
01888                                 KMO_TRY_EXIT_IF_ERROR(
01889                                     cpl_vector_power(stored_noisespec[ifu_nr-1], 2.));
01890                                 KMO_TRY_EXIT_IF_ERROR(
01891                                     cpl_vector_power(shot_noise, 2.));
01892                                 KMO_TRY_EXIT_IF_ERROR(
01893                                     cpl_vector_add(stored_noisespec[ifu_nr-1], shot_noise));
01894                                 ppp = cpl_vector_get_data(stored_noisespec[ifu_nr-1]);
01895                                 for (ii = 0; ii < cpl_vector_get_size(stored_noisespec[ifu_nr-1]); ii++) {
01896                                     if ((ppp[ii] < 0.0) || kmclipm_is_nan_or_inf(ppp[ii])) {
01897                                         ppp[ii] = 0.0;
01898                                     }
01899                                 }
01900                                 KMO_TRY_EXIT_IF_ERROR(
01901                                     cpl_vector_sqrt(stored_noisespec[ifu_nr-1]));
01902                                 cpl_vector_delete(shot_noise); shot_noise = NULL;
01903                             } else {
01904                                 cpl_msg_warning("", "   Not calculating noise-spectra because there are less than "
01905                                                        "2 sky-sky pairs present (skies must be subsequent in time)!"
01906                                                        " Just storing shot-noise.");
01907                                 stored_noisespec[ifu_nr-1] = shot_noise;
01908                             } // end if (nr_sky_pairs > 0)
01909                         } else {
01910                             stored_noisespec[ifu_nr-1] = shot_noise;
01911                         } // end if (!no_noise & ...)
01912                         KMO_TRY_CHECK_ERROR_STATE();
01913 
01914                         //
01915                         // spectrum correction
01916                         //
01917 
01918                         // calculate abscissa of output spectrum
01919                         KMO_TRY_EXIT_IF_NULL(
01920                             lambda_x = kmo_create_lambda_vec(gd.l.dim, 1,
01921                                                             gd.l.start,
01922                                                             gd.l.delta));
01923 
01924                         if ((strcmp(star_type, "O") == 0) ||
01925                             (strcmp(star_type, "B") == 0) ||
01926                             (strcmp(star_type, "A") == 0) ||
01927                             (strcmp(star_type, "F") == 0))
01928                         {
01929                             // we have a OBAF star
01930 
01931                             // if ATMOS_MODEL is present, lines will be removed
01932                             if (cpl_frameset_count_tags(frameset, ATMOS_MODEL) == 1) {
01933                                 // interpolate ATMOS_MODEL to same scale as data
01934                                 KMO_TRY_EXIT_IF_NULL(
01935                                     tmp_frame = kmo_dfs_get_frame(frameset, ATMOS_MODEL));
01936 
01937                                 KMO_TRY_EXIT_IF_NULL(
01938                                     atmos_model = kmo_interpolate_vector_wcs(tmp_frame, lambda_x));
01939 cpl_vector *tmp_spec_data_orig = NULL;
01940 int plot_it = 0;
01941 if (plot_it) {
01942     // store original spectrum
01943     KMO_TRY_EXIT_IF_NULL(
01944         tmp_spec_data_orig = cpl_vector_duplicate(tmp_spec_data));
01945 }
01946                                 // remove band-specific lines
01947                                 if (strcmp(filter_id, "H") == 0) {
01948                                     for (l = 0; l < nr_lines_h; l++) {
01949                                         KMO_TRY_EXIT_IF_ERROR(
01950                                             kmo_remove_line(tmp_spec_data, lambda_x, atmos_model, lines_center_h[l], lines_width_h[l]));
01951                                     }
01952                                 } else if (strcmp(filter_id, "HK") == 0) {
01953                                     for (l = 0; l < nr_lines_hk; l++) {
01954                                         KMO_TRY_EXIT_IF_ERROR(
01955                                             kmo_remove_line(tmp_spec_data, lambda_x, atmos_model, lines_center_hk[l], lines_width_hk[l]));
01956                                     }
01957                                 } else if (strcmp(filter_id, "K") == 0) {
01958                                     for (l = 0; l < nr_lines_k; l++) {
01959                                         KMO_TRY_EXIT_IF_ERROR(
01960                                             kmo_remove_line(tmp_spec_data, lambda_x, atmos_model, lines_center_k[l], lines_width_k[l]));
01961                                     }
01962                                 } else if (strcmp(filter_id, "IZ") == 0) {
01963                                     for (l = 0; l < nr_lines_iz; l++) {
01964                                         KMO_TRY_EXIT_IF_ERROR(
01965                                             kmo_remove_line(tmp_spec_data, lambda_x, atmos_model, lines_center_iz[l], lines_width_iz[l]));
01966                                     }
01967                                 } else if (strcmp(filter_id, "YJ") == 0) {
01968                                     for (l = 0; l < nr_lines_yj; l++) {
01969                                         KMO_TRY_EXIT_IF_ERROR(
01970                                             kmo_remove_line(tmp_spec_data, lambda_x, atmos_model, lines_center_yj[l], lines_width_yj[l]));
01971                                     }
01972                                 }
01973 if (plot_it) {
01974     cpl_vector *tmp_spec_data_atmo = NULL;
01975     cpl_vector *tmp_spec_data_new = NULL;
01976     KMO_TRY_EXIT_IF_NULL(
01977         tmp_spec_data_atmo = cpl_vector_duplicate(tmp_spec_data_orig));
01978     KMO_TRY_EXIT_IF_NULL(
01979         tmp_spec_data_new = cpl_vector_duplicate(tmp_spec_data));
01980     KMO_TRY_EXIT_IF_ERROR(
01981         cpl_vector_divide(tmp_spec_data_atmo, atmos_model));
01982 
01983     char *sss = cpl_sprintf("atmo_div_%s.fits", filter_id);
01984     if (i == 1) {
01985         cpl_vector_save(tmp_spec_data_atmo, sss, CPL_BPP_IEEE_DOUBLE, stored_sub_tel_data_headers[ifu_nr-1], CPL_IO_CREATE);
01986     } else {
01987         cpl_vector_save(tmp_spec_data_atmo, sss, CPL_BPP_IEEE_DOUBLE, stored_sub_tel_data_headers[ifu_nr-1], CPL_IO_EXTEND);
01988     }
01989 
01990     cpl_vector *med_vec = cpl_vector_duplicate(tmp_spec_data_orig);
01991     double  median = cpl_vector_get_median(med_vec);
01992     cpl_vector_delete(med_vec);
01993     int ii = 0;
01994     for (ii = 0; ii < cpl_vector_get_size(tmp_spec_data_orig); ii++) {
01995         if (cpl_vector_get(tmp_spec_data_orig, ii) < median/8)
01996             cpl_vector_set(tmp_spec_data_orig, ii, 0);
01997         if (cpl_vector_get(tmp_spec_data_atmo, ii) < median/8)
01998             cpl_vector_set(tmp_spec_data_atmo, ii, 0);
01999         if (cpl_vector_get(tmp_spec_data_new, ii) < median/8)
02000             cpl_vector_set(tmp_spec_data_new, ii, 0);
02001 
02002         if (cpl_vector_get(tmp_spec_data_orig, ii) > 3*median)
02003             cpl_vector_set(tmp_spec_data_orig, ii, 3*median);
02004         if (cpl_vector_get(tmp_spec_data_atmo, ii) > 3*median)
02005             cpl_vector_set(tmp_spec_data_atmo, ii, 3*median);
02006         if (cpl_vector_get(tmp_spec_data_new, ii) > 3*median)
02007             cpl_vector_set(tmp_spec_data_new, ii, 3*median);
02008     }
02009 
02010     double *pspec_dup = cpl_vector_get_data(tmp_spec_data_atmo);
02011     for (ii = 0; ii < cpl_vector_get_size(tmp_spec_data_atmo); ii++) {
02012         if (kmclipm_is_nan_or_inf(pspec_dup[ii])) {
02013             pspec_dup[ii] = 0.;
02014         }
02015     }
02016 
02017     cpl_bivector *plots[3];
02018     plots[0] = cpl_bivector_wrap_vectors((cpl_vector*)lambda_x, tmp_spec_data_orig);
02019     plots[1] = cpl_bivector_wrap_vectors((cpl_vector*)lambda_x, tmp_spec_data_atmo);
02020     plots[2] = cpl_bivector_wrap_vectors((cpl_vector*)lambda_x, tmp_spec_data_new);
02021     char *options[3] = {"w l t 'original'",
02022                         "w l t 'atmo divided'",
02023                         "w l t 'lines removed'"};
02024     sss = cpl_sprintf("set title '%s-band line removal (DET #%d)';", filter_id, i);
02025     cpl_plot_bivectors(sss,
02026                        (const char**)options, "", (const cpl_bivector**)plots, 3);
02027 //    cpl_plot_bivectors("set title 'Spectrum with lines removed'; set xrange [2.14:2.19];",
02028 //                       (const char**)options, "", (const cpl_bivector**)plots, 2);
02029     cpl_bivector_unwrap_vectors(plots[0]);
02030     cpl_bivector_unwrap_vectors(plots[1]);
02031     cpl_bivector_unwrap_vectors(plots[2]);
02032     cpl_free(sss); sss = NULL;
02033     cpl_vector_delete(tmp_spec_data_orig); tmp_spec_data_orig = NULL;
02034     cpl_vector_delete(tmp_spec_data_atmo); tmp_spec_data_atmo = NULL;
02035     cpl_vector_delete(tmp_spec_data_new); tmp_spec_data_new = NULL;
02036 }
02037                                 cpl_vector_delete(atmos_model); atmos_model = NULL;
02038                             } else {
02039                                 if (line_warning == FALSE) {
02040                                     cpl_msg_warning("", "No atmospheric model (ATMOS_MODEL) provided! "
02041                                                         "Won't remove any lines.");
02042                                     line_warning = TRUE;
02043                                 }
02044                             }
02045                         } else if (strcmp(star_type, "G") == 0) {
02046                             // we have a G star
02047                             if (cpl_frameset_count_tags(frameset, SOLAR_SPEC) == 1) {
02048                                 // interpolate SOLAR_SPEC to same scale as data
02049                                 // and divide it
02050                                 KMO_TRY_EXIT_IF_NULL(
02051                                     tmp_frame = kmo_dfs_get_frame(frameset, SOLAR_SPEC));
02052 
02053                                 // check if SOLAR_SPEC is the filter_id-one
02054                                 KMO_TRY_EXIT_IF_NULL(
02055                                     tmp_sub_header = kmclipm_propertylist_load(cpl_frame_get_filename(tmp_frame), 0));
02056                                 KMO_TRY_EXIT_IF_NULL(
02057                                     tmp_str = cpl_propertylist_get_string(tmp_sub_header, FILT_ID));
02058                                 KMO_TRY_ASSURE(strcmp(filter_id, tmp_str) == 0,
02059                                                CPL_ERROR_ILLEGAL_INPUT,
02060                                                "SOLAR_SPEC model must have primary "
02061                                                "keyword '%s' equal '%s'!!!",
02062                                                FILT_ID, filter_id);
02063                                 cpl_propertylist_delete(tmp_sub_header); tmp_sub_header = NULL;
02064 
02065                                 KMO_TRY_EXIT_IF_NULL(
02066                                     solar_spec = kmo_interpolate_vector_wcs(tmp_frame, lambda_x));
02067 
02068                                 // values are set to zero if solar_spec isn't
02069                                 // overlapping wavelength range of star apectrum
02070                                 // completely
02071                                 KMO_TRY_EXIT_IF_ERROR(
02072                                     cpl_vector_divide(tmp_spec_data, solar_spec));
02073                                 cpl_vector_delete(solar_spec); solar_spec = NULL;
02074                             } else {
02075                                 if (print_warning_once == TRUE) {
02076                                     cpl_msg_warning("","No solar spectrum (SOLAR_SPEC) provided! "
02077                                                        "Can't divide it from extracted "
02078                                                        "standard star spectrum!");
02079                                     print_warning_once = FALSE;
02080                                 }
02081                             }
02082                         } else {
02083 //                            cpl_msg_warning("","No startype was provided! Can't"
02084 //                                            " divide solar spectrum for G stars "
02085 //                                            "or fit a profile to atmospheric "
02086 //                                            "transmission for OBAF stars.");
02087                         }
02088 
02089                         if (star_temperature > 0.0) {
02090                             // divide blackbody from tmp_spec_data
02091                             KMO_TRY_EXIT_IF_ERROR(
02092                                 kmo_divide_blackbody(tmp_spec_data, lambda_x, star_temperature));
02093                         }
02094 
02095                         cpl_vector_delete(lambda_x); lambda_x = NULL;
02096 
02097                         // normalise telluric and its noise
02098                         // mean is taken in lambda defined range
02099                         KMO_TRY_EXIT_IF_ERROR(
02100                             kmo_calc_band_mean(stored_sub_tel_data_headers[ifu_nr-1],
02101                                                filter_id,
02102                                                tmp_spec_data,
02103                                                tmp_spec_noise,
02104                                                &mean_data,
02105                                                NULL));
02106 
02107                         KMO_TRY_EXIT_IF_ERROR(
02108                             cpl_vector_divide_scalar(tmp_spec_data, mean_data));
02109 
02110                         if (tmp_spec_noise != NULL) {
02111                             // scale noise with the same factor as data
02112                             KMO_TRY_EXIT_IF_ERROR(
02113                                 cpl_vector_divide_scalar(tmp_spec_noise, mean_data));
02114 
02115                             // set noise spectrum also to zero when solar_spec is too short
02116                             KMO_TRY_EXIT_IF_NULL(
02117                                 ptmp_spec_data = cpl_vector_get_data_const(tmp_spec_data));
02118                             KMO_TRY_EXIT_IF_NULL(
02119                                 ptmp_spec_noise = cpl_vector_get_data(tmp_spec_noise));
02120                             for (k = 0; k < cpl_vector_get_size(tmp_spec_data); k++) {
02121                                 if (ptmp_spec_data[k] == 0.0) {
02122                                     ptmp_spec_noise[k] = 0.0;
02123                                 }
02124                             }
02125                         }
02126                         KMO_TRY_CHECK_ERROR_STATE();
02127 
02128                         // store telluric & error spectrum
02129                         stored_telluric_data[ifu_nr-1] = tmp_spec_data;
02130                         stored_telluric_noise[ifu_nr-1] = tmp_spec_noise;
02131 
02132                         // if magnitude is provided
02133                         // calculate zeropoint and throughput
02134                         if (has_magnitude) {
02135                             // calculate QC THROUGHPUT
02136                             KMO_TRY_EXIT_IF_ERROR(
02137                                 kmo_calc_counts(spec_qc, filter_id,
02138                                                 crpix1, crval1, cdelt1,
02139                                                 &counts1, &counts2));
02140                             KMO_TRY_CHECK_ERROR_STATE();
02141 
02142                             counts1 /= exptime;
02143                             counts2 /= exptime;
02144 
02145                             stored_qc_throughput[ifu_nr-1] = kmo_calc_throughput(magnitude1, magnitude2,
02146                                                                                  counts1, counts2, gain, filter_id);
02147                             KMO_TRY_CHECK_ERROR_STATE();
02148 
02149                             if (kmclipm_is_nan_or_inf(stored_qc_throughput[ifu_nr-1])) {
02150                                 stored_qc_throughput[ifu_nr-1] = -1;
02151                             }
02152                             KMO_TRY_EXIT_IF_ERROR(
02153                                 kmclipm_update_property_double(stored_sub_tel_data_headers[ifu_nr-1],
02154                                                                QC_THROUGHPUT,
02155                                                                stored_qc_throughput[ifu_nr-1],
02156                                                                "[] IFU throughput"));
02157 
02158                             // calculate QC ZEROPOINT
02159                             zeropoint = kmo_calc_zeropoint(magnitude1, magnitude2, counts1, counts2, cdelt3, filter_id);
02160                             if (kmclipm_is_nan_or_inf(zeropoint)) {
02161                                 zeropoint = -1;
02162                             }
02163                             KMO_TRY_CHECK_ERROR_STATE();
02164 
02165                             KMO_TRY_EXIT_IF_ERROR(
02166                                 kmclipm_update_property_double(stored_sub_tel_data_headers[ifu_nr-1],
02167                                                                QC_ZEROPOINT,
02168                                                                zeropoint,
02169                                                                "[mag] IFU zeropoint"));
02170                         }
02171                         cpl_vector_delete(spec_qc); spec_qc = NULL;
02172                     } else {
02173                         cpl_error_reset();
02174                         // IFU is invalid
02175                         KMO_TRY_EXIT_IF_NULL(
02176                             stored_sub_tel_data_headers[ifu_nr-1] =
02177                                 cpl_propertylist_duplicate(sub_header_orig));
02178                         KMO_TRY_EXIT_IF_NULL(
02179                             stored_sub_tel_noise_headers[ifu_nr-1] =
02180                                 cpl_propertylist_duplicate(sub_header_orig));
02181                         KMO_TRY_EXIT_IF_NULL(
02182                             stored_sub_psf_headers[ifu_nr-1] =
02183                                 cpl_propertylist_duplicate(sub_header_orig));
02184                         if (save_cubes) {
02185                             KMO_TRY_EXIT_IF_NULL(
02186                                 stored_sub_cube_data_headers[ifu_nr-1] =
02187                                     cpl_propertylist_duplicate(sub_header_orig));
02188                             KMO_TRY_EXIT_IF_NULL(
02189                                 stored_sub_cube_noise_headers[ifu_nr-1] =
02190                                     cpl_propertylist_duplicate(sub_header_orig));
02191                         }
02192                     }
02193 
02194                     // create EXTNAME keyword as DATA
02195                     KMO_TRY_EXIT_IF_NULL(
02196                         extname = kmo_extname_creator(ifu_frame, ifu_nr, EXT_DATA));
02197                     KMO_TRY_EXIT_IF_ERROR(
02198                         kmclipm_update_property_string(stored_sub_tel_data_headers[ifu_nr-1],
02199                                                        EXTNAME, extname, "FITS extension name"));
02200                     KMO_TRY_EXIT_IF_ERROR(
02201                         kmclipm_update_property_string(stored_sub_psf_headers[ifu_nr-1],
02202                                                        EXTNAME, extname, "FITS extension name"));
02203                     if (save_cubes) {
02204                         KMO_TRY_EXIT_IF_ERROR(
02205                             kmclipm_update_property_string(stored_sub_cube_data_headers[ifu_nr-1],
02206                                                            EXTNAME, extname, "FITS extension name"));
02207                     }
02208                     cpl_free(extname); extname = NULL;
02209 
02210                     // create EXTNAME keyword as NOISE
02211                     if (stored_sub_tel_noise_headers[ifu_nr-1] == NULL) {
02212                         KMO_TRY_EXIT_IF_NULL(
02213                             stored_sub_tel_noise_headers[ifu_nr-1] =
02214                                     cpl_propertylist_duplicate(
02215                                             stored_sub_tel_data_headers[ifu_nr-1]));
02216                     }
02217                     KMO_TRY_EXIT_IF_NULL(
02218                         extname = kmo_extname_creator(ifu_frame, ifu_nr, EXT_NOISE));
02219                     KMO_TRY_EXIT_IF_ERROR(
02220                         kmclipm_update_property_string(stored_sub_tel_noise_headers[ifu_nr-1],
02221                                                        EXTNAME, extname, "FITS extension name"));
02222                     if (save_cubes) {
02223                         if (stored_sub_cube_noise_headers[ifu_nr-1] == NULL) {
02224                             KMO_TRY_EXIT_IF_NULL(
02225                                 stored_sub_cube_noise_headers[ifu_nr-1] =
02226                                         cpl_propertylist_duplicate(
02227                                                 stored_sub_cube_data_headers[ifu_nr-1]));
02228                         }
02229 
02230                         KMO_TRY_EXIT_IF_ERROR(
02231                             kmclipm_update_property_string(stored_sub_cube_noise_headers[ifu_nr-1],
02232                                                            EXTNAME, extname, "FITS extension name"));
02233                     }
02234                     cpl_free(extname); extname = NULL;
02235                 } // for j ifus (load, process & store)
02236                 cpl_propertylist_delete(sub_header_orig); sub_header_orig = NULL;
02237             } // for i detectors (load, process & store)
02238             KMO_TRY_CHECK_ERROR_STATE();
02239 
02240             // write QC parameter: nr of std stars
02241             KMO_TRY_EXIT_IF_ERROR(
02242                 kmclipm_update_property_int(main_header_tel, QC_NR_STD_STARS,
02243                                         nr_std_stars, "[] Nr. of std stars"));
02244 
02245             // update which IFUs are not used
02246             kmo_print_unused_ifus(unused_ifus_after, TRUE);
02247 
02248             KMO_TRY_EXIT_IF_ERROR(
02249                 kmo_set_unused_ifus(unused_ifus_after, main_header_tel, "kmo_std_star"));
02250 
02251             KMO_TRY_EXIT_IF_NULL(
02252                 main_header_psf = cpl_propertylist_duplicate(main_header_tel));
02253 
02254             if (has_magnitude) {
02255                 // calculate QC THROUGHPUT MEAN and QC THROUGHPUT SDV
02256                 // and update main header
02257                 KMO_TRY_EXIT_IF_ERROR(
02258                     kmo_calc_mean_throughput(stored_qc_throughput,
02259                                              nr_devices * KMOS_IFUS_PER_DETECTOR,
02260                                              &throughput_mean,
02261                                              &throughput_sdv));
02262                 KMO_TRY_EXIT_IF_ERROR(
02263                     kmclipm_update_property_double(main_header_tel, QC_THROUGHPUT_MEAN,
02264                                                    throughput_mean, "[] mean throughput for all detectors"));
02265                 KMO_TRY_EXIT_IF_ERROR(
02266                     kmclipm_update_property_double(main_header_tel, QC_THROUGHPUT_SDV,
02267                                                    throughput_sdv, "[] stdev throughput for all detectors"));
02268             }
02269             KMO_TRY_CHECK_ERROR_STATE();
02270 
02271             //
02272             // save output data
02273             //
02274             if (!suppress_extension) {
02275                 KMO_TRY_EXIT_IF_NULL(
02276                     fn_suffix = cpl_sprintf("%s", suffix));
02277             } else {
02278                 KMO_TRY_EXIT_IF_NULL(
02279                     fn_suffix = cpl_sprintf("%s", ""));
02280             }
02281 
02282             // save primary extension
02283             KMO_TRY_EXIT_IF_ERROR(
02284                 kmo_dfs_save_main_header(frameset, filename_telluric, fn_suffix,
02285                                          obj_frame, main_header_tel, parlist,
02286                                          cpl_func));
02287             KMO_TRY_EXIT_IF_ERROR(
02288                 kmo_dfs_save_main_header(frameset, filename_starspec, fn_suffix,
02289                                          obj_frame, main_header_tel, parlist,
02290                                          cpl_func));
02291             KMO_TRY_EXIT_IF_ERROR(
02292                 kmo_dfs_save_main_header(frameset, filename_mask, fn_suffix,
02293                                          obj_frame, main_header_psf, parlist,
02294                                          cpl_func));
02295             KMO_TRY_EXIT_IF_ERROR(
02296                 kmo_dfs_save_main_header(frameset, filename_psf, fn_suffix,
02297                                          obj_frame, main_header_psf, parlist,
02298                                          cpl_func));
02299             if (!no_noise && (strcmp(tplid, "KMOS_spec_cal_stdstarscipatt") == 0)) {
02300                 KMO_TRY_EXIT_IF_ERROR(
02301                     kmo_dfs_save_main_header(frameset, filename_noise, fn_suffix,
02302                                              obj_frame, main_header_tel, parlist,
02303                                              cpl_func));
02304             }
02305             if (save_cubes) {
02306                 KMO_TRY_EXIT_IF_ERROR(
02307                     kmo_dfs_save_main_header(frameset, filename_cubes, fn_suffix,
02308                                              obj_frame, main_header_psf, parlist,
02309                                              cpl_func));
02310             }
02311 
02312             // save stored frames
02313             for (i = 1; i <= nr_devices; i++) {
02314                 for (j = 0; j < KMOS_IFUS_PER_DETECTOR; j++) {
02315                     ifu_nr = (i-1)*KMOS_IFUS_PER_DETECTOR + j + 1;
02316 
02317                     // save telluric-vector
02318 kmclipm_vector *ddd = NULL;
02319 if (stored_telluric_data[ifu_nr-1] != NULL)
02320 ddd = kmclipm_vector_create(cpl_vector_duplicate(stored_telluric_data[ifu_nr-1]));
02321                     KMO_TRY_EXIT_IF_ERROR(
02322                         kmo_dfs_save_vector(ddd, filename_telluric, fn_suffix,
02323                                             stored_sub_tel_data_headers[ifu_nr-1],
02324                                             0./0.));
02325 kmclipm_vector_delete(ddd); ddd = NULL;
02326 
02327 if (stored_telluric_noise[ifu_nr-1] != NULL)
02328 ddd = kmclipm_vector_create(cpl_vector_duplicate(stored_telluric_noise[ifu_nr-1]));
02329                     KMO_TRY_EXIT_IF_ERROR(
02330                         kmo_dfs_save_vector(ddd, filename_telluric, fn_suffix,
02331                                             stored_sub_tel_noise_headers[ifu_nr-1],
02332                                             0./0.));
02333 kmclipm_vector_delete(ddd); ddd = NULL;
02334 
02335                     // save star_spec-vector
02336 if (stored_starspec_data[ifu_nr-1] != NULL)
02337 ddd = kmclipm_vector_create(cpl_vector_duplicate(stored_starspec_data[ifu_nr-1]));
02338                     KMO_TRY_EXIT_IF_ERROR(
02339                         kmo_dfs_save_vector(ddd, filename_starspec, fn_suffix,
02340                                             stored_sub_tel_data_headers[ifu_nr-1],
02341                                             0./0.));
02342 kmclipm_vector_delete(ddd); ddd = NULL;
02343 
02344 if (stored_starspec_noise[ifu_nr-1] != NULL)
02345 ddd = kmclipm_vector_create(cpl_vector_duplicate(stored_starspec_noise[ifu_nr-1]));
02346                     KMO_TRY_EXIT_IF_ERROR(
02347                         kmo_dfs_save_vector(ddd, filename_starspec, fn_suffix,
02348                                             stored_sub_tel_noise_headers[ifu_nr-1],
02349                                             0./0.));
02350 kmclipm_vector_delete(ddd); ddd = NULL;
02351 
02352                     // save psf-image
02353                     KMO_TRY_EXIT_IF_ERROR(
02354                         kmo_dfs_save_image(stored_psf_data[ifu_nr-1],
02355                                            filename_psf, fn_suffix,
02356                                            stored_sub_psf_headers[ifu_nr-1],
02357                                            0./0.));
02358 
02359                     // save mask-image
02360                     KMO_TRY_EXIT_IF_ERROR(
02361                         kmo_dfs_save_image(stored_mask[ifu_nr-1],
02362                                            filename_mask, fn_suffix,
02363                                            stored_sub_psf_headers[ifu_nr-1],
02364                                            0./0.));
02365 
02366                     // save noise_spec-vector
02367                     if (!no_noise &&
02368                         (strcmp(tplid, "KMOS_spec_cal_stdstarscipatt") == 0) &&
02369                         (stored_noisespec != NULL) &&
02370                         (stored_noisespec[ifu_nr-1] != NULL) &&
02371                         (stored_starspec_data[ifu_nr-1] != NULL))
02372                     {
02373                         // calculate QC SNR
02374                         KMO_TRY_EXIT_IF_ERROR(
02375                             kmo_calc_band_mean(stored_sub_tel_data_headers[ifu_nr-1],
02376                                                filter_id,
02377                                                stored_starspec_data[ifu_nr-1], NULL,
02378                                                &tmp_data, NULL));
02379                         KMO_TRY_EXIT_IF_ERROR(
02380                             kmo_calc_band_mean(stored_sub_tel_data_headers[ifu_nr-1],
02381                                                filter_id,
02382                                                stored_noisespec[ifu_nr-1], NULL,
02383                                                &tmp_noise, NULL));
02384                         KMO_TRY_EXIT_IF_ERROR(
02385                             kmclipm_update_property_double(stored_sub_tel_data_headers[ifu_nr-1], QC_SNR,
02386                                                            tmp_data/tmp_noise, "[] SNR"));
02387                     }
02388 
02389                     if (!no_noise && (strcmp(tplid, "KMOS_spec_cal_stdstarscipatt") == 0)) {
02390 if ((stored_noisespec != NULL) && (stored_noisespec[ifu_nr-1] != NULL))
02391 ddd = kmclipm_vector_create(cpl_vector_duplicate(stored_noisespec[ifu_nr-1]));
02392                     KMO_TRY_EXIT_IF_ERROR(
02393                         kmo_dfs_save_vector(ddd, filename_noise, fn_suffix,
02394                                             stored_sub_tel_data_headers[ifu_nr-1],
02395                                             0./0.));
02396 kmclipm_vector_delete(ddd); ddd = NULL;
02397                     }
02398 
02399                     // save reonstructed cubes
02400                     if (save_cubes) {
02401                         KMO_TRY_EXIT_IF_ERROR(
02402                             kmo_dfs_save_cube(stored_data_cube[ifu_nr-1],
02403                                               filename_cubes, fn_suffix,
02404                                               stored_sub_cube_data_headers[ifu_nr-1],
02405                                               0./0.));
02406                         KMO_TRY_EXIT_IF_ERROR(
02407                             kmo_dfs_save_cube(stored_noise_cube[ifu_nr-1],
02408                                               filename_cubes, fn_suffix,
02409                                               stored_sub_cube_noise_headers[ifu_nr-1],
02410                                               0./0.));
02411                     }
02412                 } // for j ifus (save stored)
02413             } // for i detectors (save stored)
02414             KMO_TRY_CHECK_ERROR_STATE();
02415         } // if (frameCnt == 0)
02416     }
02417     KMO_CATCH
02418     {
02419         KMO_CATCH_MSG();
02420         ret_val = -1;
02421     }
02422 
02423     kmo_delete_objSkyStruct(obj_sky_struct);
02424     kmo_free_fits_desc(&desc1);
02425     kmo_free_fits_desc(&desc2);
02426     kmo_free_unused_ifus(unused_ifus_before); unused_ifus_before = NULL;
02427     kmo_free_unused_ifus(unused_ifus_after); unused_ifus_after = NULL;
02428     cpl_free(bounds); bounds = NULL;
02429     cpl_propertylist_delete(main_header_tel); main_header_tel = NULL;
02430     cpl_propertylist_delete(main_header_psf); main_header_psf = NULL;
02431     cpl_vector_delete(atmos_model); atmos_model = NULL;
02432     cpl_vector_delete(solar_spec); solar_spec = NULL;
02433     cpl_table_delete(spec_type_LUT); spec_type_LUT = NULL;
02434     cpl_vector_delete(identified_slices); identified_slices = NULL;
02435     cpl_propertylist_delete(sub_header_orig); sub_header_orig = NULL;
02436     for (i = 0; i < nr_devices * KMOS_IFUS_PER_DETECTOR; i++) {
02437         cpl_vector_delete(stored_telluric_data[i]); stored_telluric_data[i] = NULL;
02438         cpl_vector_delete(stored_telluric_noise[i]); stored_telluric_noise[i] = NULL;
02439         cpl_vector_delete(stored_starspec_data[i]); stored_starspec_data[i] = NULL;
02440         cpl_vector_delete(stored_starspec_noise[i]); stored_starspec_noise[i] = NULL;
02441         cpl_image_delete(stored_psf_data[i]); stored_psf_data[i] = NULL;
02442         if ((stored_noisespec != NULL) && (stored_noisespec[i] != NULL)) {
02443             cpl_vector_delete(stored_noisespec[i]); stored_noisespec[i] = NULL;
02444         }
02445         cpl_propertylist_delete(stored_sub_tel_data_headers[i]); stored_sub_tel_data_headers[i] = NULL;
02446         cpl_propertylist_delete(stored_sub_tel_noise_headers[i]); stored_sub_tel_noise_headers[i] = NULL;
02447         if (save_cubes) {
02448             cpl_propertylist_delete(stored_sub_cube_data_headers[i]); stored_sub_cube_data_headers[i] = NULL;
02449             cpl_propertylist_delete(stored_sub_cube_noise_headers[i]); stored_sub_cube_noise_headers[i] = NULL;
02450         }
02451         cpl_propertylist_delete(stored_sub_psf_headers[i]); stored_sub_psf_headers[i] = NULL;
02452         cpl_image_delete(stored_mask[i]); stored_mask[i] = NULL;
02453         cpl_imagelist_delete(stored_data_cube[i]); stored_data_cube[i] = NULL;
02454         cpl_imagelist_delete(stored_noise_cube[i]); stored_noise_cube[i] = NULL;
02455     }
02456     cpl_free(stored_telluric_data); stored_telluric_data = NULL;
02457     cpl_free(stored_telluric_noise); stored_telluric_noise = NULL;
02458     cpl_free(stored_starspec_data); stored_starspec_data = NULL;
02459     if (stored_noisespec != NULL) {
02460         cpl_free(stored_noisespec); stored_noisespec = NULL;
02461     }
02462     kmo_delete_skySkyStruct(sky_sky_struct); sky_sky_struct = NULL;
02463     cpl_free(stored_starspec_noise); stored_starspec_noise = NULL;
02464     cpl_free(stored_psf_data); stored_psf_data = NULL;
02465     cpl_free(stored_sub_tel_data_headers); stored_sub_tel_data_headers = NULL;
02466     cpl_free(stored_sub_tel_noise_headers); stored_sub_tel_noise_headers = NULL;
02467     if (save_cubes) {
02468         cpl_free(stored_sub_cube_data_headers); stored_sub_cube_data_headers = NULL;
02469         cpl_free(stored_sub_cube_noise_headers); stored_sub_cube_noise_headers = NULL;
02470     }
02471     cpl_free(stored_sub_psf_headers); stored_sub_psf_headers = NULL;
02472     cpl_free(stored_qc_throughput); stored_qc_throughput = NULL;
02473     cpl_free(suffix); suffix = NULL;
02474     cpl_free(fn_suffix); fn_suffix = NULL;
02475     cpl_free(stored_mask); stored_mask = NULL;
02476     cpl_free(stored_data_cube); stored_data_cube = NULL;
02477     cpl_free(stored_noise_cube); stored_noise_cube = NULL;
02478     cpl_free(grat_id); grat_id = NULL;
02479     cpl_frameset_delete(frameset_std); frameset_std = NULL;
02480     cpl_free(extname); extname = NULL;
02481     cpl_free(tplid); tplid = NULL;
02482 
02483     return ret_val;
02484 }
02485