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