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