KMOS Pipeline Reference Manual  1.1.4
kmo_std_star.c
00001 /* $Id: kmo_std_star.c,v 1.62 2013/05/21 15:40:37 erw Exp $
00002  *
00003  * This file is part of the KMOS Pipeline
00004  * Copyright (C) 2002,2003 European Southern Observatory
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  */
00020 
00021 /*
00022  * $Author: erw $
00023  * $Date: 2013/05/21 15:40:37 $
00024  * $Revision: 1.62 $
00025  * $Name: HEAD $
00026  */
00027 
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031 
00032 /*-----------------------------------------------------------------------------
00033  *                              Includes
00034  *----------------------------------------------------------------------------*/
00035 
00036 #include <math.h>
00037 #include <string.h>
00038 
00039 #include <cpl.h>
00040 #include "kmclipm_math.h"
00041 
00042 #include "kmo_constants.h"
00043 #include "kmo_cpl_extensions.h"
00044 #include "kmo_utils.h"
00045 #include "kmo_functions.h"
00046 #include "kmo_priv_std_star.h"
00047 #include "kmo_priv_fit_profile.h"
00048 #include "kmo_priv_extract_spec.h"
00049 #include "kmo_priv_functions.h"
00050 #include "kmo_dfs.h"
00051 #include "kmo_error.h"
00052 #include "kmo_debug.h"
00053 #include "kmo_priv_reconstruct.h"
00054 
00055 /*-----------------------------------------------------------------------------
00056  *                          Functions prototypes
00057  *----------------------------------------------------------------------------*/
00058 
00059 static int kmo_std_star_create(cpl_plugin *);
00060 static int kmo_std_star_exec(cpl_plugin *);
00061 static int kmo_std_star_destroy(cpl_plugin *);
00062 static int kmo_std_star(cpl_parameterlist *, cpl_frameset *);
00063 
00064 /*-----------------------------------------------------------------------------
00065  *                          Static variables
00066  *----------------------------------------------------------------------------*/
00067 
00068 static char kmo_std_star_description[] =
00069 "This recipe creates a telluric calibration frame and a PSF frame. It must be\n"
00070 "called after the kmo_illumination-recipe.\n"
00071 "Since there won’t be enough standard stars to observe for all IFUs in one ex-\n"
00072 "posure, one has to do several exposures in a way that there is at least one\n"
00073 "standard star and one sky exposure in each IFU. A internal data organiser will\n"
00074 "analyse the provided exposures and select the appropriate frames as follows:\n"
00075 "1. For each IFU the first standard star in the list of provided exposures is\n"
00076 "   taken. All subsequent standard star exposures for this IFU will be ignored\n"
00077 "2. A corresponding sky exposure will be chosen which will be as close in time\n"
00078 "   to the standard star exposure as possible.\n"
00079 "3. For any IFUs not containing a standard star and a sky exposure an empty\n"
00080 "   frame will be returned.\n"
00081 "\n"
00082 "BASIC PARAMETERS:\n"
00083 "-----------------\n"
00084 "--startype\n"
00085 "The star type of the observed object . This value applies to all objects exa-\n"
00086 "mined in the input frames. Examples would be “A3I”, “G3IV” or “K0I”. The first\n"
00087 "letter defines the star type, the second letter the spectral class and the last\n"
00088 "letters the luminosity class.\n"
00089 "\n"
00090 "--magnitude\n"
00091 "The magnitude of the observed object..\n"
00092 "\n"
00093 "--fmethod\n"
00094 "The type of function that should be fitted spatially to the collapsed image.\n"
00095 "This fit is used to create a mask to extract the spectrum of the object. Valid\n"
00096 "values are “gauss” and “moffat”.\n"
00097 "\n"
00098 "--imethod\n"
00099 "The interpolation method used for reconstruction. As default 'CS' is selected.\n"
00100 "Note that no error spectra will be generated for this interpolation method.\n"
00101 "Select a nearest neighbour method otherwise\n"
00102 "\n"
00103 "--range\n"
00104 "The spectral range [um] to combine when collapsing the reconstructed cubes.\n"
00105 "\n"
00106 "--save-cubes\n"
00107 "Set to TRUE if the intermediate reconstructed cubes (eventually divided by "
00108 "illumination correction) should be saved as well. Default is FALSE.\n"
00109 "\n"
00110 "ADVANCED PARAMETERS\n"
00111 "-------------------\n"
00112 "--flux\n"
00113 "Specify if flux conservation should be applied.\n"
00114 "\n"
00115 "--neighborhoodRange\n"
00116 "Defines the range to search for neighbors during reconstruction\n"
00117 "\n"
00118 "--b_samples\n"
00119 "The number of samples in spectral direction for the reconstructed cube.\n"
00120 "Ideally this number should be greater than 2048, the detector size.\n"
00121 "\n"
00122 "--b_start\n"
00123 "--b_end\n"
00124 "Used to define manually the start and end wavelength for the reconstructed\n"
00125 "cube. By default the internally defined values are used.\n"
00126 "\n"
00127 "--cmethod\n"
00128 "Following methods of frame combination are available:\n"
00129 "   * 'ksigma' (Default)\n"
00130 "   An iterative sigma clipping. For each position all pixels in the spectrum\n"
00131 "   are examined. If they deviate significantly, they will be rejected according\n"
00132 "   to the conditions:\n"
00133 "       val > mean + stdev * cpos_rej\n"
00134 "   and\n"
00135 "       val < mean - stdev * cneg_rej\n"
00136 "   where --cpos_rej, --cneg_rej and --citer are the corresponding configuration\n"
00137 "   parameters. In the first iteration median and percentile level are used.\n"
00138 "\n"
00139 "   * 'median'\n"
00140 "   At each pixel position the median is calculated.\n"
00141 "\n"
00142 "   * 'average'\n"
00143 "   At each pixel position the average is calculated.\n"
00144 "\n"
00145 "   * 'sum'\n"
00146 "   At each pixel position the sum is calculated.\n"
00147 "\n"
00148 "   * 'min_max'\n"
00149 "   The specified number of minimum and maximum pixel values will be rejected.\n"
00150 "   --cmax and --cmin apply to this method.\n"
00151 "\n"
00152 "--cpos_rej\n"
00153 "--cneg_rej\n"
00154 "--citer\n"
00155 "see --cmethod='ksigma'\n"
00156 "\n"
00157 "--cmax\n"
00158 "--cmin\n"
00159 "see --cmethod='min_max'\n"
00160 "\n"
00161 "--xcal_interpolation\n"
00162 "If true interpolate the pixel position in the slitlet (xcal) using the two\n"
00163 "closest rotator angles in the calibration file. Otherwise take the values\n"
00164 "of the closest rotator angle\n"
00165 "\n"
00166 "-------------------------------------------------------------------------------\n"
00167 "  Input files:\n"
00168 "\n"
00169 "   DO                      KMOS                                                \n"
00170 "   category                Type  Explanation                   Required #Frames\n"
00171 "   --------                ----- -----------                   -------- -------\n"
00172 "   STD                     RAW   Std. star & sky exposures         Y     >=1   \n"
00173 "   XCAL                    F2D   x calibration frame               Y      1    \n"
00174 "   YCAL                    F2D   y calibration frame               Y      1    \n"
00175 "   LCAL                    F2D   Wavelength calib. frame           Y      1    \n"
00176 "   MASTER_FLAT             F2D   Master flat frame                 Y      1    \n"
00177 "   WAVE_BAND               F2L   Table with start-/end-wavelengths Y      1    \n"
00178 "   ILLUM_CORR              F2I   Illumination correction           N     0,1   \n"
00179 "   SOLAR_SPEC              F1S   Solar spectrum                    N     0,1   \n"
00180 "                                 (only for G stars)                            \n"
00181 "   ATMOS_MODEL             F1S   Model atmospheric transmisson     N     0,1   \n"
00182 "                                 (only for OBAF stars in K band)               \n"
00183 "   SPEC_TYPE_LOOKUP        F2L   LUT  eff. stellar temperature     N     0,1   \n"
00184 "\n"
00185 "  Output files:\n"
00186 "\n"
00187 "   DO                      KMOS\n"
00188 "   category                Type   Explanation\n"
00189 "   --------                -----  -----------\n"
00190 "   TELLURIC                F1I    normalised telluric spectrum   \n"
00191 "                                  (including errors)             \n"
00192 "   STD_IMAGE               F2I    Standard star PSF images       \n"
00193 "-------------------------------------------------------------------------------\n"
00194 "\n";
00195 
00196 /*-----------------------------------------------------------------------------
00197  *                              Functions code
00198  *----------------------------------------------------------------------------*/
00199 
00216 int cpl_plugin_get_info(cpl_pluginlist *list)
00217 {
00218     cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe);
00219     cpl_plugin *plugin = &recipe->interface;
00220 
00221     cpl_plugin_init(plugin,
00222                         CPL_PLUGIN_API,
00223                         KMOS_BINARY_VERSION,
00224                         CPL_PLUGIN_TYPE_RECIPE,
00225                         "kmo_std_star",
00226                         "Create the telluric correction frame.",
00227                         kmo_std_star_description,
00228                         "Alex Agudo Berbel",
00229                         "kmos-spark@mpe.mpg.de",
00230                         kmos_get_license(),
00231                         kmo_std_star_create,
00232                         kmo_std_star_exec,
00233                         kmo_std_star_destroy);
00234 
00235     cpl_pluginlist_append(list, plugin);
00236 
00237     return 0;
00238 }
00239 
00247 static int kmo_std_star_create(cpl_plugin *plugin)
00248 {
00249     cpl_recipe *recipe;
00250     cpl_parameter *p;
00251 
00252     /* Check that the plugin is part of a valid recipe */
00253     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00254         recipe = (cpl_recipe *)plugin;
00255     else
00256         return -1;
00257 
00258     /* Create the parameters list in the cpl_recipe object */
00259     recipe->parameters = cpl_parameterlist_new();
00260 
00261     /* Fill the parameters list */
00262     p = cpl_parameter_new_value("kmos.kmo_std_star.startype",
00263                                 CPL_TYPE_STRING,
00264                                 "The spectral type of the star (O, B, A, F, G)"
00265                                 " Format: G4V etc.",
00266                                 "kmos.kmo_std_star",
00267                                 "");
00268     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "startype");
00269     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00270     cpl_parameterlist_append(recipe->parameters, p);
00271 
00272     /* --imethod */
00273     p = cpl_parameter_new_value("kmos.kmo_std_star.imethod",
00274                                 CPL_TYPE_STRING,
00275                                 "Method to use for interpolation. "
00276                                 "[\"NN\" (nearest neighbour), "
00277                                 "\"lwNN\" (linear weighted nearest neighbor), "
00278                                 "\"swNN\" (square weighted nearest neighbor), "
00279                                 "\"MS\" (Modified Shepard's method), "
00280                                 "\"CS\" (Cubic spline)]",
00281                                 "kmos.kmo_std_star",
00282                                 "CS");
00283     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "imethod");
00284     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00285     cpl_parameterlist_append(recipe->parameters, p);
00286 
00287     /* --fmethod */
00288     p = cpl_parameter_new_value("kmos.kmo_std_star.fmethod",
00289                                 CPL_TYPE_STRING,
00290                                 "Either fit a 'gauss' or 'moffat' profile.",
00291                                 "kmos.kmo_std_star",
00292                                 "gauss");
00293     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "fmethod");
00294     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00295     cpl_parameterlist_append(recipe->parameters, p);
00296 
00297     /* --neighborhoodRange */
00298     p = cpl_parameter_new_value("kmos.kmo_std_star.neighborhoodRange",
00299                                 CPL_TYPE_DOUBLE,
00300                                 "Defines the range to search for neighbors "
00301                                 "in pixels",
00302                                 "kmos.kmo_std_star",
00303                                 1.001);
00304     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "neighborhoodRange");
00305     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00306     cpl_parameterlist_append(recipe->parameters, p);
00307 
00308     /* --magnitude */
00309     p = cpl_parameter_new_value("kmos.kmo_std_star.magnitude",
00310                                 CPL_TYPE_STRING,
00311                                 "The magnitude of the std star. For HK two "
00312                                 "values have to provided (eg. 12.1,13.2)",
00313                                 "kmos.kmo_std_star",
00314                                 "");
00315     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "magnitude");
00316     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00317     cpl_parameterlist_append(recipe->parameters, p);
00318 
00319     /* --flux */
00320     p = cpl_parameter_new_value("kmos.kmo_std_star.flux",
00321                                 CPL_TYPE_BOOL,
00322                                 "TRUE: Apply flux conservation. FALSE: otherwise",
00323                                 "kmos.kmo_std_star",
00324                                 TRUE);
00325     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "flux");
00326     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00327     cpl_parameterlist_append(recipe->parameters, p);
00328 
00329     /* --save-cubes */
00330     p = cpl_parameter_new_value("kmos.kmo_std_star.save-cubes",
00331                                 CPL_TYPE_BOOL,
00332                                 "TRUE: Save reconstructed cubes, FALSE: otherwise",
00333                                 "kmos.kmo_std_star",
00334                                 FALSE);
00335     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "save-cubes");
00336     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00337     cpl_parameterlist_append(recipe->parameters, p);
00338 
00339     /* --xcal_interpolation */
00340     p = cpl_parameter_new_value("kmos.kmo_std_star.xcal_interpolation",
00341                                 CPL_TYPE_BOOL,
00342                                 "TRUE: Interpolate xcal between rotator angles. FALSE: otherwise",
00343                                 "kmos.kmo_std_star",
00344                                 TRUE);
00345     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "xcal_interpolation");
00346     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00347     cpl_parameterlist_append(recipe->parameters, p);
00348 
00349     // add parameters for band-definition
00350     kmo_band_pars_create(recipe->parameters,
00351                          "kmos.kmo_std_star");
00352 
00353     // add parameters for combining
00354     return kmo_combine_pars_create(recipe->parameters,
00355                                    "kmos.kmo_std_star",
00356                                    DEF_REJ_METHOD,
00357                                    FALSE);
00358 }
00359 
00365 static int kmo_std_star_exec(cpl_plugin *plugin)
00366 {
00367     cpl_recipe  *recipe;
00368 
00369     /* Get the recipe out of the plugin */
00370     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00371         recipe = (cpl_recipe *)plugin;
00372     else return -1;
00373 
00374     return kmo_std_star(recipe->parameters, recipe->frames);
00375 }
00376 
00382 static int kmo_std_star_destroy(cpl_plugin *plugin)
00383 {
00384     cpl_recipe *recipe;
00385 
00386     /* Get the recipe out of the plugin */
00387     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00388         recipe = (cpl_recipe *)plugin;
00389     else return -1 ;
00390 
00391     cpl_parameterlist_delete(recipe->parameters);
00392     return 0 ;
00393 }
00394 
00409 static int kmo_std_star(cpl_parameterlist *parlist, cpl_frameset *frameset)
00410 {
00411     cpl_imagelist    **stored_data_cube     = NULL,
00412                      **stored_noise_cube    = NULL;
00413 
00414     cpl_image        **stored_psf_data      = NULL,
00415                      *illum_corr            = NULL,
00416                      **stored_mask          = NULL,
00417                      *lcal                  = NULL;
00418 
00419     cpl_frame        *xcal_frame            = NULL,
00420                      *ycal_frame            = NULL,
00421                      *lcal_frame            = NULL,
00422                      *flat_frame            = NULL,
00423                      *illum_frame           = NULL,
00424                      *obj_frame             = NULL,
00425                      *sky_frame             = NULL,
00426                      *tmp_frame             = NULL;
00427 
00428     cpl_vector       *solar_spec             = NULL,
00429                      *atmos_model            = NULL,
00430                      **stored_telluric_data  = NULL,
00431                      **stored_telluric_noise = NULL,
00432                      **stored_starspec_data  = NULL,
00433                      **stored_starspec_noise = NULL,
00434                      *tmp_spec_data          = NULL,
00435                      *spec_qc     = NULL,
00436                      *tmp_spec_noise         = NULL,
00437                      *identified_slices      = NULL,
00438                      *tmp_vec                = NULL,
00439                      *lambda_x               = NULL;
00440 
00441     int              ret_val                = 0,
00442                      nr_devices             = 0,
00443                      nr_exp                 = 0,
00444                      i                      = 0,
00445                      j                      = 0,
00446                      frameCnt               = 0,
00447                      *bounds                = NULL,
00448                      ifu_nr                 = 0,
00449                      citer                  = 0,
00450                      cmax                   = 0,
00451                      cmin                   = 0,
00452                      line_warning           = FALSE,
00453                      nr_std_stars           = 0,
00454                      print_warning_once     = TRUE,
00455                      flux                   = FALSE,
00456                      background             = FALSE,
00457                      band_method            = 0,
00458                      save_cubes             = FALSE,
00459                      has_magnitude          = TRUE,
00460                      xcal_interpolation     = FALSE,
00461                      nr_split_mag           = 0;
00462 
00463     const int        *punused_ifus          = NULL;
00464 
00465     objSkyFrameTableStruct *obj_sky_struct  = NULL;
00466 
00467     double           *stored_qc_throughput  = NULL,
00468                      star_temperature       = 0.0,
00469                      neighborhoodRange      = 1.001,
00470                      cpos_rej               = 0.0,
00471                      cneg_rej               = 0.0,
00472                      zeropoint              = -1.0,
00473                      throughput_mean        = -1.0,
00474                      throughput_sdv         = -1.0,
00475                      std_trace              = -1.0,
00476                      counts1                = 0.0,
00477                      counts2                = 0.0,
00478                      magnitude1             = 0.0,
00479                      magnitude2             = 0.0,
00480                      exptime                = 0.,
00481                      cdelt3                 = 0.,
00482                      mean_data              = 0.,
00483                      mean_noise             = 0.,
00484                      *ptmp_spec_noise       = NULL,
00485                      crpix1                 = 0.,
00486                      crval1                 = 0.,
00487                      cdelt1                 = 0.;
00488 
00489     const double     *ptmp_spec_data        = NULL;
00490 
00491     cpl_propertylist *main_header_tel                    = NULL,
00492                      *main_header_psf                    = NULL,
00493                      *sub_header_orig                    = NULL,
00494                      *tmp_sub_header                     = NULL,
00495                      *tmp_header                         = NULL,
00496                      **stored_sub_tel_data_headers       = NULL,
00497                      **stored_sub_tel_noise_headers      = NULL,
00498                      **stored_sub_cube_data_headers      = NULL,
00499                      **stored_sub_cube_noise_headers     = NULL,
00500                      **stored_sub_psf_headers            = NULL,
00501                      *pl_psf                             = NULL;
00502 
00503     cpl_table        *spec_type_LUT         = NULL,
00504                      *band_table            = NULL;;
00505 
00506     main_fits_desc   desc1,
00507                      desc2;
00508 
00509     char             *extname               = NULL,
00510                      *keyword               = NULL,
00511                      filename_telluric[256],
00512                      filename_starspec[256],
00513                      filename_psf[256],
00514                      filename_mask[256],
00515                      filename_cubes[256],
00516                      *suffix                = NULL,
00517                      spec_class[256],
00518                      lum_class[256],
00519                      star_type[2],
00520                      *tmp_band_method       = getenv("KMO_BAND_METHOD"),
00521                      **split_mag            = NULL,
00522                      *grat_id               = NULL;
00523 
00524     const char       *filter_id             = NULL,
00525                      *spec_type             = NULL,
00526                      *magnitude_txt         = NULL,
00527                      *imethod               = NULL,
00528                      *cmethod               = NULL,
00529                      *fmethod               = NULL,
00530                      *tmp_str               = NULL;
00531 
00532     gridDefinition   gd;
00533 
00534     cpl_array        **unused_ifus_before   = NULL,
00535                      **unused_ifus_after    = NULL;
00536     cpl_frameset     *frameset_std          = NULL;
00537 
00538     KMO_TRY
00539     {
00540         kmo_init_fits_desc(&desc1);
00541         kmo_init_fits_desc(&desc2);
00542 
00543         /* --- check input --- */
00544         KMO_TRY_ASSURE((parlist != NULL) &&
00545                        (frameset != NULL),
00546                        CPL_ERROR_NULL_INPUT,
00547                        "Not all input data is provided!");
00548 
00549         KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, STD) >= 1,
00550                        CPL_ERROR_ILLEGAL_INPUT,
00551                        "At least one STD frame is required!");
00552         if (cpl_frameset_count_tags(frameset, STD) == 1) {
00553             cpl_msg_warning("", "At least two STD frames should be provided "
00554                                 "in order to apply sky subtraction!");
00555         }
00556 
00557         KMO_TRY_ASSURE((cpl_frameset_count_tags(frameset, ILLUM_CORR) == 1) ||
00558                        (cpl_frameset_count_tags(frameset, ILLUM_CORR) == 0),
00559                        CPL_ERROR_FILE_NOT_FOUND,
00560                        "Exactly one ILLUM_CORR frame is required!");
00561         KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, XCAL) == 1,
00562                        CPL_ERROR_FILE_NOT_FOUND,
00563                        "Exactly one XCAL frame is required!");
00564         KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, YCAL) == 1,
00565                        CPL_ERROR_FILE_NOT_FOUND,
00566                        "Exactly one YCAL frame is required!");
00567         KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, LCAL) == 1,
00568                        CPL_ERROR_FILE_NOT_FOUND,
00569                        "Exactly one LCAL frame is required!");
00570         KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, MASTER_FLAT) == 1,
00571                        CPL_ERROR_FILE_NOT_FOUND,
00572                        "Exactly one MASTER_FLAT frame is required!");
00573         KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, WAVE_BAND) == 1,
00574                        CPL_ERROR_FILE_NOT_FOUND,
00575                        "Exactly one WAVE_BAND frame is required!");
00576         KMO_TRY_ASSURE(kmo_dfs_set_groups(frameset, "kmo_std_star") == 1,
00577                        CPL_ERROR_ILLEGAL_INPUT,
00578                        "Cannot identify RAW and CALIB frames!");
00579 
00580         /* --- get parameters --- */
00581         cpl_msg_info("", "--- Parameter setup for kmo_std_star ------");
00582 
00583         KMO_TRY_EXIT_IF_NULL(
00584             spec_type = kmo_dfs_get_parameter_string(parlist,
00585                                                      "kmos.kmo_std_star.startype"));
00586         KMO_TRY_EXIT_IF_ERROR(
00587             kmo_dfs_print_parameter_help(parlist,
00588                                          "kmos.kmo_std_star.startype"));
00589 
00590         KMO_TRY_EXIT_IF_NULL(
00591             imethod = kmo_dfs_get_parameter_string(parlist,
00592                                                    "kmos.kmo_std_star.imethod"));
00593         KMO_TRY_ASSURE((strcmp(imethod, "NN") == 0) ||
00594                        (strcmp(imethod, "lwNN") == 0) ||
00595                        (strcmp(imethod, "swNN") == 0) ||
00596                        (strcmp(imethod, "MS") == 0) ||
00597                        (strcmp(imethod, "CS") == 0),
00598                        CPL_ERROR_ILLEGAL_INPUT,
00599                        "method must be either \"NN\", \"lwNN\", "
00600                        "\"swNN\", \"MS\" or \"CS\"!");
00601         KMO_TRY_EXIT_IF_ERROR(
00602             kmo_dfs_print_parameter_help(parlist,
00603                                          "kmos.kmo_std_star.imethod"));
00604 
00605         KMO_TRY_EXIT_IF_NULL(
00606             fmethod = kmo_dfs_get_parameter_string(parlist,
00607                                                    "kmos.kmo_std_star.fmethod"));
00608         KMO_TRY_ASSURE((strcmp(fmethod, "gauss") == 0) ||
00609                        (strcmp(fmethod, "moffat") == 0),
00610                        CPL_ERROR_ILLEGAL_INPUT,
00611                        "fmethod must be either 'gauss' or "
00612                        "'moffat' !");
00613         KMO_TRY_EXIT_IF_ERROR(
00614             kmo_dfs_print_parameter_help(parlist,
00615                                         "kmos.kmo_std_star.method"));
00616 
00617         neighborhoodRange = kmo_dfs_get_parameter_double(parlist,
00618                                                          "kmos.kmo_std_star.neighborhoodRange");
00619         KMO_TRY_CHECK_ERROR_STATE();
00620         KMO_TRY_ASSURE(neighborhoodRange > 0.0,
00621                        CPL_ERROR_ILLEGAL_INPUT,
00622                        "neighborhoodRange must be greater than 0.0");
00623         KMO_TRY_EXIT_IF_ERROR(
00624             kmo_dfs_print_parameter_help(parlist,
00625                                          "kmos.kmo_std_star.neighborhoodRange"));
00626 
00627         magnitude_txt = kmo_dfs_get_parameter_string(parlist,
00628                                                      "kmos.kmo_std_star.magnitude");
00629         KMO_TRY_CHECK_ERROR_STATE();
00630         KMO_TRY_EXIT_IF_ERROR(
00631             kmo_dfs_print_parameter_help(parlist,
00632                                          "kmos.kmo_std_star.magnitude"));
00633 
00634         flux = kmo_dfs_get_parameter_bool(parlist,
00635                                           "kmos.kmo_std_star.flux");
00636         KMO_TRY_ASSURE((flux == FALSE) || (flux == TRUE),
00637                        CPL_ERROR_ILLEGAL_INPUT,
00638                        "flux must be either FALSE or TRUE!");
00639         KMO_TRY_EXIT_IF_ERROR(
00640             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_std_star.flux"));
00641 
00642         save_cubes = kmo_dfs_get_parameter_bool(parlist,
00643                                           "kmos.kmo_std_star.save-cubes");
00644         KMO_TRY_ASSURE((save_cubes == FALSE) || (save_cubes == TRUE),
00645                        CPL_ERROR_ILLEGAL_INPUT,
00646                        "save_cubes must be either FALSE or TRUE!");
00647         KMO_TRY_EXIT_IF_ERROR(
00648             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_std_star.save-cubes"));
00649 
00650         xcal_interpolation = kmo_dfs_get_parameter_bool(parlist,
00651                                            "kmos.kmo_std_star.xcal_interpolation");
00652         KMO_TRY_CHECK_ERROR_STATE();
00653         KMO_TRY_EXIT_IF_ERROR(
00654             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_std_star.xcal_interpolation"));
00655         KMO_TRY_ASSURE((xcal_interpolation == TRUE) ||
00656                        (xcal_interpolation == FALSE),
00657                        CPL_ERROR_ILLEGAL_INPUT,
00658                        "xcal_interpolation must be TRUE or FALSE!");
00659 
00660         kmo_band_pars_load(parlist, "kmos.kmo_std_star");
00661 
00662         KMO_TRY_EXIT_IF_ERROR(
00663             kmo_combine_pars_load(parlist,
00664                                   "kmos.kmo_std_star",
00665                                   &cmethod,
00666                                   &cpos_rej,
00667                                   &cneg_rej,
00668                                   &citer,
00669                                   &cmin,
00670                                   &cmax,
00671                                   FALSE));
00672         cpl_msg_info("", "-------------------------------------------");
00673 
00674         //
00675         // Check if magnitude/frameset is valid and if throughput and zeropoint should be calculated
00676         //
00677 
00678         // Check if all STD frames have the same GRAT-ID
00679         // if not: don't calculate zeropoint and throughput
00680         KMO_TRY_EXIT_IF_NULL(
00681             frameset_std = cpl_frameset_new());
00682 
00683         KMO_TRY_EXIT_IF_NULL(
00684             tmp_frame = kmo_dfs_get_frame(frameset, STD));
00685         KMO_TRY_EXIT_IF_NULL(
00686             tmp_header = kmclipm_propertylist_load(cpl_frame_get_filename(tmp_frame), 0));
00687         KMO_TRY_EXIT_IF_NULL(
00688             grat_id = cpl_sprintf("%s", cpl_propertylist_get_string(tmp_header, "ESO INS GRAT1 ID")));
00689         KMO_TRY_EXIT_IF_ERROR(
00690             cpl_frameset_insert(frameset_std, cpl_frame_duplicate(tmp_frame)));
00691         cpl_propertylist_delete(tmp_header); tmp_header = NULL;
00692 KMO_TRY_CHECK_ERROR_STATE();
00693         KMO_TRY_EXIT_IF_NULL(
00694             tmp_frame = kmo_dfs_get_frame(frameset, NULL));
00695         while (tmp_frame != NULL ) {
00696             KMO_TRY_EXIT_IF_NULL(
00697                 tmp_header = kmclipm_propertylist_load(cpl_frame_get_filename(tmp_frame), 0));
00698             if (strcmp(grat_id, cpl_propertylist_get_string(tmp_header, "ESO INS GRAT1 ID")) == 0) {
00699                 // same grating
00700                 KMO_TRY_EXIT_IF_ERROR(
00701                     cpl_frameset_insert(frameset_std, cpl_frame_duplicate(tmp_frame)));
00702             } else {
00703                 // there are STD frames with different gratings
00704                 if (has_magnitude) {
00705                     cpl_msg_warning(cpl_func, "The STD frames have different gratings,"
00706                                             "following QC parameters won't be "
00707                                             "calculated: QC ZEROPOINT, QC THROUGHPUT,"
00708                                             "QC THROUGHPUT MEAN and QC THROUGHPUT STD");
00709                 }
00710                 has_magnitude = FALSE;
00711             }
00712             cpl_propertylist_delete(tmp_header); tmp_header = NULL;
00713 
00714             tmp_frame = kmo_dfs_get_frame(frameset, NULL);
00715             KMO_TRY_CHECK_ERROR_STATE();
00716         }
00717         KMO_TRY_CHECK_ERROR_STATE();
00718 
00719         if (cpl_frameset_count_tags(frameset, ATMOS_MODEL) == 1) {
00720             // check if ATMOS_MODEL is the band as the STD frames
00721             KMO_TRY_EXIT_IF_NULL(
00722                 tmp_frame = kmo_dfs_get_frame(frameset, ATMOS_MODEL));
00723             KMO_TRY_EXIT_IF_NULL(
00724                 tmp_sub_header = kmclipm_propertylist_load( cpl_frame_get_filename(tmp_frame), 0));
00725             KMO_TRY_EXIT_IF_NULL(
00726                 tmp_str = cpl_propertylist_get_string(tmp_sub_header, FILT_ID));
00727             KMO_TRY_ASSURE(strcmp(grat_id, tmp_str) == 0,
00728                            CPL_ERROR_ILLEGAL_INPUT,
00729                            "ATMOS model must have primary "
00730                            "keyword '%s' equal '%s'!!!",
00731                            FILT_ID, grat_id);
00732             cpl_propertylist_delete(tmp_sub_header);
00733             tmp_sub_header = NULL;
00734         }
00735 
00736         if (has_magnitude) {
00737             // all STD frames have the same GRAT-ID
00738             // now check source of magnitude (user or keyword)
00739             KMO_TRY_EXIT_IF_NULL(
00740                 tmp_frame = kmo_dfs_get_frame(frameset, STD));
00741             KMO_TRY_EXIT_IF_NULL(
00742                 tmp_header = kmclipm_propertylist_load(cpl_frame_get_filename(tmp_frame), 0));
00743 
00744             if (strcmp(magnitude_txt, "") == 0) {
00745                 // no user defined magnitude
00746 
00747                 // check for magnitude-keyword
00748                 if ((cpl_propertylist_has(tmp_header, STDSTAR_MAG)) &&
00749                     (cpl_propertylist_get_type(tmp_header, STDSTAR_MAG) == CPL_TYPE_STRING))
00750                 {
00751                     KMO_TRY_EXIT_IF_NULL(
00752                         magnitude_txt = cpl_propertylist_get_string(tmp_header, STDSTAR_MAG));
00753                     KMO_TRY_EXIT_IF_NULL(
00754                         split_mag = kmo_strsplit(magnitude_txt, ",", &nr_split_mag));
00755 
00756                     // check if band and number of magnitudes matches
00757                     if ((nr_split_mag == 2) &&
00758                         (strcmp(grat_id, "HK") == 0))
00759                     {
00760                         magnitude1 = atof(split_mag[0]);
00761                         magnitude2 = atof(split_mag[1]);
00762                         cpl_msg_info("", "Magnitude in H: %g", magnitude1);
00763                         cpl_msg_info("", "Magnitude in K: %g", magnitude2);
00764                     } else if ((nr_split_mag >= 1) &&
00765                                ((strcmp(grat_id, "K") == 0) ||
00766                                 (strcmp(grat_id, "H") == 0) ||
00767                                 (strcmp(grat_id, "IZ") == 0) ||
00768                                 (strcmp(grat_id, "YJ") == 0)))
00769                     {
00770                         magnitude1 = atof(split_mag[0]);
00771                         cpl_msg_info("", "Magnitude in %s: %g", grat_id, magnitude1);
00772                     } else {
00773                         // keyword STDSTAR_MAG doesn't match filter
00774                         has_magnitude = FALSE;
00775                         cpl_msg_warning(cpl_func, "The keyword %s doesn't match to grating',"
00776                                                   "following QC parameters won't be "
00777                                                   "calculated: QC ZEROPOINT, QC THROUGHPUT,"
00778                                                   "QC THROUGHPUT MEAN and QC THROUGHPUT STD", STDSTAR_MAG);
00779                     }
00780                     kmo_strfreev(split_mag);
00781                 } else {
00782                     // keyword STDSTAR_MAG unavailable or wrong type
00783                     has_magnitude = FALSE;
00784                     cpl_msg_warning(cpl_func, "The keyword %s is not set or of wrong type,"
00785                                               "following QC parameters won't be "
00786                                               "calculated: QC ZEROPOINT, QC THROUGHPUT,"
00787                                               "QC THROUGHPUT MEAN and QC THROUGHPUT STD", STDSTAR_MAG);
00788                 }
00789             } else {
00790                 // magnitude is user specified
00791                 cpl_msg_info(cpl_func, "Magnitude has been specified by user. Any "
00792                                        "value in keyword %s will be ignored.", STDSTAR_MAG);
00793 
00794                 KMO_TRY_EXIT_IF_NULL(
00795                     split_mag = kmo_strsplit(magnitude_txt, ",", &nr_split_mag));
00796                 switch (nr_split_mag) {
00797                 case 1:
00798                     magnitude1 = atof(split_mag[0]);
00799                     cpl_msg_info("", "Magnitude in %s: %g", grat_id, magnitude1);
00800                     break;
00801                 case 2:
00802                     magnitude1 = atof(split_mag[0]);
00803                     magnitude2 = atof(split_mag[1]);
00804                     cpl_msg_info("", "Magnitude in H: %g", magnitude1);
00805                     cpl_msg_info("", "Magnitude in K: %g", magnitude2);
00806                     break;
00807                 default:
00808                     KMO_TRY_ASSURE(1 == 0,
00809                                    CPL_ERROR_ILLEGAL_INPUT,
00810                                    "Provided magnitude was in wrong format! "
00811                                    "Either a single float value or two separated by comma");
00812                 }
00813                 kmo_strfreev(split_mag);
00814             }
00815             cpl_propertylist_delete(tmp_header); tmp_header = NULL;
00816         } // if (has_magnitude)
00817         cpl_msg_info("", "-------------------------------------------");
00818         KMO_TRY_CHECK_ERROR_STATE();
00819 
00820         //
00821         // check for spectral type (--startype) (user or keyword)
00822         //
00823         if (strcmp(spec_type, "") == 0) {
00824             // no user defined startype
00825 
00826             KMO_TRY_EXIT_IF_NULL(
00827                 tmp_frame = kmo_dfs_get_frame(frameset, STD));
00828             KMO_TRY_EXIT_IF_NULL(
00829                 tmp_header = kmclipm_propertylist_load(cpl_frame_get_filename(tmp_frame), 0));
00830 
00831             // check for startype-keyword
00832             if ((cpl_propertylist_has(tmp_header, STDSTAR_TYPE)) &&
00833                 (cpl_propertylist_get_type(tmp_header, STDSTAR_TYPE) == CPL_TYPE_STRING))
00834             {
00835                 KMO_TRY_EXIT_IF_NULL(
00836                     spec_type = cpl_propertylist_get_string(tmp_header, STDSTAR_TYPE));
00837             } else {
00838                 // keyword STDSTAR_TYPE unavailable or wrong type
00839             }
00840         } else {
00841             // startype is user specified
00842             cpl_msg_info(cpl_func, "Type of star has been specified by user. Any "
00843                                    "value in keyword %s will be ignored.", STDSTAR_TYPE);
00844         }
00845         KMO_TRY_CHECK_ERROR_STATE();
00846 
00847         if (strlen(spec_type) > 0) {
00848             if (kmo_get_spec_type(spec_type, spec_class, lum_class) != CPL_ERROR_NONE) {
00849                 cpl_error_reset();
00850                 spec_class[0] = '\0';
00851                 lum_class[0] = '\0';
00852                 star_type[0] = '\0';
00853                 cpl_msg_warning("", "The keyword %s is not set or of wrong type nor was it provided by the user. "
00854                                     "Can't divide solar spectrum for G stars or fit a profile "
00855                                     "to atmospheric transmission for OBAF stars and can't "
00856                                     "divide blackbody for any star.", STDSTAR_TYPE);
00857                 cpl_msg_warning("", "%s = '%s' (should be something like e.g.'G2V' odr 'A9III')", STDSTAR_TYPE, spec_type);
00858             } else {
00859                 strncpy(star_type, spec_class, 1);
00860                 star_type[1] = '\0';
00861                 cpl_msg_info("", "Spectral class:   %s", spec_class);
00862                 cpl_msg_info("", "Luminosity class: %s", lum_class);
00863             }
00864         } else {
00865             spec_class[0] = '\0';
00866             lum_class[0] = '\0';
00867             star_type[0] = '\0';
00868             cpl_msg_warning("", "The keyword %s is not set nor was it provided by the user. "
00869                                 "Can't divide solar spectrum for G stars or fit a profile "
00870                                 "to atmospheric transmission for OBAF stars and can't "
00871                                 "divide blackbody for any star.", STDSTAR_TYPE);
00872         }
00873         cpl_propertylist_delete(tmp_header); tmp_header = NULL;
00874         cpl_msg_info("", "-------------------------------------------");
00875         KMO_TRY_CHECK_ERROR_STATE();
00876 
00877         // assure that filters, grating and rotation offsets match for
00878         // XCAL, YCAL, LCAL and for data frame to reconstruct (except DARK
00879         // frames)
00880         // check if filter_id and grating_id match for all detectors
00881         KMO_TRY_EXIT_IF_ERROR(
00882             kmo_check_frameset_setup(frameset, XCAL, FALSE, FALSE, TRUE));
00883         KMO_TRY_EXIT_IF_ERROR(
00884             kmo_check_frame_setup(frameset, XCAL, YCAL, TRUE, FALSE, TRUE));
00885         KMO_TRY_EXIT_IF_ERROR(
00886             kmo_check_frame_setup(frameset, XCAL, LCAL, TRUE, FALSE, TRUE));
00887         KMO_TRY_EXIT_IF_ERROR(
00888             kmo_check_frame_setup(frameset, XCAL, MASTER_FLAT, TRUE, FALSE, TRUE));
00889         KMO_TRY_EXIT_IF_ERROR(
00890             kmo_check_frame_setup(frameset, XCAL, STD, FALSE, FALSE, TRUE));
00891 //        KMO_TRY_EXIT_IF_ERROR(
00892 //            kmo_check_cal_frames_rotangle(frameset, XCAL, YCAL));
00893 //        KMO_TRY_EXIT_IF_ERROR(
00894 //            kmo_check_cal_frames_rotangle(frameset, XCAL, LCAL));
00895 
00896         if (cpl_frameset_count_tags(frameset, ILLUM_CORR) == 1) {
00897             KMO_TRY_EXIT_IF_ERROR(
00898                 kmo_check_frame_setup(frameset, XCAL, ILLUM_CORR, TRUE, FALSE, FALSE));
00899         }
00900 
00901         // check descriptors of all frames
00902         KMO_TRY_EXIT_IF_NULL(
00903             xcal_frame = kmo_dfs_get_frame(frameset, XCAL));
00904 
00905         desc1 = kmo_identify_fits_header(cpl_frame_get_filename(xcal_frame));
00906         KMO_TRY_CHECK_ERROR_STATE();
00907 
00908         KMO_TRY_ASSURE((desc1.nr_ext % 3 == 0) &&
00909                        (desc1.ex_badpix == FALSE) &&
00910                        (desc1.fits_type == f2d_fits) &&
00911                        (desc1.frame_type == detector_frame),
00912                        CPL_ERROR_ILLEGAL_INPUT,
00913                        "XCAL isn't in the correct format!!!");
00914 
00915         KMO_TRY_EXIT_IF_NULL(
00916             ycal_frame = kmo_dfs_get_frame(frameset, YCAL));
00917         desc2 = kmo_identify_fits_header(cpl_frame_get_filename(ycal_frame));
00918         KMO_TRY_CHECK_ERROR_STATE();
00919 
00920         KMO_TRY_ASSURE((desc1.nr_ext == desc2.nr_ext) &&
00921                        (desc1.ex_badpix == desc2.ex_badpix) &&
00922                        (desc1.fits_type == desc2.fits_type) &&
00923                        (desc1.frame_type == desc2.frame_type),
00924                        CPL_ERROR_ILLEGAL_INPUT,
00925                        "YCAL isn't in the correct format!!!");
00926         kmo_free_fits_desc(&desc2);
00927         kmo_init_fits_desc(&desc2);
00928 
00929         KMO_TRY_EXIT_IF_NULL(
00930             lcal_frame = kmo_dfs_get_frame(frameset, LCAL));
00931         desc2 = kmo_identify_fits_header(cpl_frame_get_filename(lcal_frame));
00932         KMO_TRY_CHECK_ERROR_STATE();
00933 
00934         KMO_TRY_ASSURE((desc1.nr_ext == desc2.nr_ext) &&
00935                        (desc1.ex_badpix == desc2.ex_badpix) &&
00936                        (desc1.fits_type == desc2.fits_type) &&
00937                        (desc1.frame_type == desc2.frame_type),
00938                        CPL_ERROR_ILLEGAL_INPUT,
00939                        "YCAL isn't in the correct format!!!");
00940         kmo_free_fits_desc(&desc2);
00941         kmo_init_fits_desc(&desc2);
00942 
00943         KMO_TRY_EXIT_IF_NULL(
00944             flat_frame = kmo_dfs_get_frame(frameset, MASTER_FLAT));
00945         desc2 = kmo_identify_fits_header(cpl_frame_get_filename(flat_frame));
00946         KMO_TRY_CHECK_ERROR_STATE();
00947 
00948         KMO_TRY_ASSURE((desc2.nr_ext % 6 == 0) &&
00949                        (desc1.ex_badpix == desc2.ex_badpix) &&
00950                        (desc1.fits_type == desc2.fits_type) &&
00951                        (desc1.frame_type == desc2.frame_type),
00952                        CPL_ERROR_ILLEGAL_INPUT,
00953                        "MASTER_FLAT isn't in the correct format!!!");
00954         kmo_free_fits_desc(&desc2);
00955         kmo_init_fits_desc(&desc2);
00956 
00957         if (cpl_frameset_count_tags(frameset, ILLUM_CORR) == 1) {
00958             KMO_TRY_EXIT_IF_NULL(
00959                 illum_frame = kmo_dfs_get_frame(frameset, ILLUM_CORR));
00960             desc2 = kmo_identify_fits_header(cpl_frame_get_filename(illum_frame));
00961             KMO_TRY_CHECK_ERROR_STATE();
00962             KMO_TRY_ASSURE(((desc2.nr_ext == 24) || (desc2.nr_ext == 48)) &&
00963                            (desc2.ex_badpix == FALSE) &&
00964                            (desc2.fits_type == f2i_fits) &&
00965                            (desc2.frame_type == ifu_frame),
00966                            CPL_ERROR_ILLEGAL_INPUT,
00967                            "ILLUM_CORR isn't in the correct format!!!");
00968             kmo_free_fits_desc(&desc2);
00969             kmo_init_fits_desc(&desc2);
00970         }
00971 
00972         if (cpl_frameset_count_tags(frameset, SPEC_TYPE_LOOKUP) == 1) {
00973             KMO_TRY_EXIT_IF_NULL(
00974                 tmp_frame = kmo_dfs_get_frame(frameset, SPEC_TYPE_LOOKUP));
00975             desc2 = kmo_identify_fits_header(cpl_frame_get_filename(tmp_frame));
00976             KMO_TRY_CHECK_ERROR_STATE();
00977             KMO_TRY_ASSURE((desc2.nr_ext == 1) &&
00978                            (desc2.ex_badpix == FALSE) &&
00979                            (desc2.fits_type == f2l_fits) &&
00980                            (desc2.frame_type == list_frame),
00981                            CPL_ERROR_ILLEGAL_INPUT,
00982                            "SPEC_TYPE_LOOKUP isn't in the correct format!!!");
00983             kmo_free_fits_desc(&desc2);
00984             kmo_init_fits_desc(&desc2);
00985         }
00986 
00987         if (cpl_frameset_count_tags(frameset, SOLAR_SPEC) == 1) {
00988             KMO_TRY_EXIT_IF_NULL(
00989                 tmp_frame = kmo_dfs_get_frame(frameset, SOLAR_SPEC));
00990             desc2 = kmo_identify_fits_header(cpl_frame_get_filename(tmp_frame));
00991             KMO_TRY_CHECK_ERROR_STATE();
00992             KMO_TRY_ASSURE((desc2.nr_ext == 1) &&
00993                            (desc2.ex_badpix == FALSE) &&
00994                            (desc2.fits_type == f1s_fits) &&
00995                            (desc2.frame_type == spectrum_frame),
00996                            CPL_ERROR_ILLEGAL_INPUT,
00997                            "SOLAR_SPEC isn't in the correct format!!!");
00998             kmo_free_fits_desc(&desc2);
00999             kmo_init_fits_desc(&desc2);
01000         }
01001 
01002         if (cpl_frameset_count_tags(frameset, ATMOS_MODEL) == 1) {
01003             KMO_TRY_EXIT_IF_NULL(
01004                 tmp_frame = kmo_dfs_get_frame(frameset, ATMOS_MODEL));
01005             desc2 = kmo_identify_fits_header(cpl_frame_get_filename(tmp_frame));
01006             KMO_TRY_CHECK_ERROR_STATE();
01007             KMO_TRY_ASSURE((desc2.nr_ext == 1) &&
01008                            (desc2.ex_badpix == FALSE) &&
01009                            (desc2.fits_type == f1s_fits) &&
01010                            (desc2.frame_type == spectrum_frame),
01011                            CPL_ERROR_ILLEGAL_INPUT,
01012                            "ATMOS_MODEL isn't in the correct format!!!");
01013             kmo_free_fits_desc(&desc2);
01014             kmo_init_fits_desc(&desc2);
01015         }
01016 
01017         KMO_TRY_EXIT_IF_NULL(
01018             tmp_frame = kmo_dfs_get_frame(frameset, STD));
01019         while (tmp_frame != NULL ) {
01020             desc2 = kmo_identify_fits_header(cpl_frame_get_filename(tmp_frame));
01021             KMO_TRY_CHECK_ERROR_STATE();
01022             KMO_TRY_ASSURE((desc2.nr_ext == 3) &&
01023                            (desc2.ex_badpix == FALSE) &&
01024                            (desc2.fits_type == raw_fits) &&
01025                            (desc2.frame_type == detector_frame),
01026                            CPL_ERROR_ILLEGAL_INPUT,
01027                            "STD isn't in the correct format!!!");
01028             nr_devices = desc2.nr_ext;
01029             kmo_free_fits_desc(&desc2);
01030             kmo_init_fits_desc(&desc2);
01031 
01032             tmp_frame = kmo_dfs_get_frame(frameset, NULL);
01033             KMO_TRY_CHECK_ERROR_STATE();
01034         }
01035         KMO_TRY_EXIT_IF_NULL(
01036             tmp_frame = kmo_dfs_get_frame(frameset, STD));
01037         KMO_TRY_EXIT_IF_NULL(
01038             suffix = kmo_dfs_get_suffix(tmp_frame, TRUE, FALSE));
01039 
01040         KMO_TRY_EXIT_IF_ERROR(
01041             kmo_check_frame_setup_md5_xycal(frameset));
01042         KMO_TRY_EXIT_IF_ERROR(
01043             kmo_check_frame_setup_md5(frameset));
01044 
01045         cpl_msg_info("", "Detected instrument setup:   %s", suffix+1);
01046         cpl_msg_info("", "(grating 1, 2 & 3, rotation angle)");
01047 
01048         // check which IFUs are active for all frames
01049         KMO_TRY_EXIT_IF_NULL(
01050             unused_ifus_before = kmo_get_unused_ifus(frameset, 0, 0));
01051 
01052         KMO_TRY_EXIT_IF_NULL(
01053             unused_ifus_after = kmo_duplicate_unused_ifus(unused_ifus_before));
01054 
01055         kmo_print_unused_ifus(unused_ifus_before, FALSE);
01056 
01057         /* --- load data --- */
01058 
01059         if ((cpl_frameset_count_tags(frameset, SPEC_TYPE_LOOKUP) == 1) &&
01060             ((strlen(spec_class) > 0) || (strlen(lum_class) > 0)))
01061         {
01062             // get star temperature out of SPEC_TYPE_LOOKUP table
01063             KMO_TRY_EXIT_IF_NULL(
01064                 spec_type_LUT = kmo_dfs_load_table(frameset, SPEC_TYPE_LOOKUP, 1, 0));
01065             star_temperature = kmo_get_temperature(spec_type_LUT, spec_class, lum_class);
01066             KMO_TRY_CHECK_ERROR_STATE();
01067         } else if (cpl_frameset_count_tags(frameset, SPEC_TYPE_LOOKUP) != 1) {
01068             cpl_msg_warning("","No SPEC_TYPE_LOOKUP was provided! Can't divide blackbody.");
01069         } else if ((strlen(spec_class) == 0) || (strlen(lum_class) == 0)) {
01070 //            cpl_msg_warning("","No startype was provided! Can't "
01071 //                            "divide blackbody.");
01072         }
01073 
01074         // allocate intermediate memory
01075         KMO_TRY_EXIT_IF_NULL(
01076             stored_telluric_data    = (cpl_vector**)cpl_calloc(nr_devices*KMOS_IFUS_PER_DETECTOR,
01077                                                                sizeof(cpl_vector*)));
01078         KMO_TRY_EXIT_IF_NULL(
01079             stored_telluric_noise   = (cpl_vector**)cpl_calloc(nr_devices*KMOS_IFUS_PER_DETECTOR,
01080                                                                sizeof(cpl_vector*)));
01081         KMO_TRY_EXIT_IF_NULL(
01082             stored_starspec_data    = (cpl_vector**)cpl_calloc(nr_devices*KMOS_IFUS_PER_DETECTOR,
01083                                                                sizeof(cpl_vector*)));
01084         KMO_TRY_EXIT_IF_NULL(
01085             stored_starspec_noise   = (cpl_vector**)cpl_calloc(nr_devices*KMOS_IFUS_PER_DETECTOR,
01086                                                                sizeof(cpl_vector*)));
01087         KMO_TRY_EXIT_IF_NULL(
01088             stored_psf_data         = (cpl_image**)cpl_calloc(nr_devices*KMOS_IFUS_PER_DETECTOR,
01089                                                               sizeof(cpl_image*)));
01090         KMO_TRY_EXIT_IF_NULL(
01091             stored_mask             = (cpl_image**)cpl_calloc(nr_devices*KMOS_IFUS_PER_DETECTOR,
01092                                                               sizeof(cpl_image*)));
01093         KMO_TRY_EXIT_IF_NULL(
01094             stored_data_cube        = (cpl_imagelist**)cpl_calloc(nr_devices*KMOS_IFUS_PER_DETECTOR,
01095                                                               sizeof(cpl_imagelist*)));
01096         KMO_TRY_EXIT_IF_NULL(
01097             stored_noise_cube       = (cpl_imagelist**)cpl_calloc(nr_devices*KMOS_IFUS_PER_DETECTOR,
01098                                                               sizeof(cpl_imagelist*)));
01099         KMO_TRY_EXIT_IF_NULL(
01100             stored_qc_throughput    = (double*)cpl_calloc(nr_devices*KMOS_IFUS_PER_DETECTOR,
01101                                                           sizeof(double)));
01102         KMO_TRY_EXIT_IF_NULL(
01103             stored_sub_psf_headers  = (cpl_propertylist**)cpl_calloc(nr_devices*KMOS_IFUS_PER_DETECTOR,
01104                                                                      sizeof(cpl_propertylist*)));
01105         KMO_TRY_EXIT_IF_NULL(
01106             stored_sub_tel_data_headers = (cpl_propertylist**)cpl_calloc(nr_devices*KMOS_IFUS_PER_DETECTOR,
01107                                                                          sizeof(cpl_propertylist*)));
01108         KMO_TRY_EXIT_IF_NULL(
01109             stored_sub_tel_noise_headers = (cpl_propertylist**)cpl_calloc(nr_devices*KMOS_IFUS_PER_DETECTOR,
01110                                                                          sizeof(cpl_propertylist*)));
01111 
01112         if (save_cubes) {
01113             KMO_TRY_EXIT_IF_NULL(
01114                 stored_sub_cube_data_headers = (cpl_propertylist**)cpl_calloc(nr_devices*KMOS_IFUS_PER_DETECTOR,
01115                                                                              sizeof(cpl_propertylist*)));
01116             KMO_TRY_EXIT_IF_NULL(
01117                 stored_sub_cube_noise_headers = (cpl_propertylist**)cpl_calloc(nr_devices*KMOS_IFUS_PER_DETECTOR,
01118                                                                              sizeof(cpl_propertylist*)));
01119         }
01120 
01121         // get bounds
01122         KMO_TRY_EXIT_IF_NULL(
01123             tmp_header = kmclipm_propertylist_load(cpl_frame_get_filename(xcal_frame), 0));
01124         KMO_TRY_EXIT_IF_NULL(
01125             bounds = kmclipm_extract_bounds(tmp_header));
01126         cpl_propertylist_delete(tmp_header); tmp_header = NULL;
01127 
01128         // setup grid definition, wavelength start and end points will be set
01129         // in the detector loop
01130         KMO_TRY_EXIT_IF_ERROR(
01131             kmclipm_setup_grid(&gd, imethod, neighborhoodRange, KMOS_PIX_RESOLUTION));
01132 
01133         // get valid STD frames with objects in it and associated sky exposures
01134         KMO_TRY_EXIT_IF_NULL(
01135             obj_sky_struct = kmo_get_obj_sky_frame_table(frameset_std, &frameCnt, STD, FALSE));
01136 
01137         // loop the object-sky pairs
01138         if (frameCnt == 0) {
01139             cpl_msg_warning(cpl_func,"Not a single frame contains an object");
01140         } else {
01141             strcpy(filename_telluric, TELLURIC);
01142             strcpy(filename_starspec, STAR_SPEC);
01143             strcpy(filename_psf, STD_IMAGE);
01144             strcpy(filename_mask, STD_MASK);
01145             strcpy(filename_cubes, STD_CUBE);
01146 
01147             obj_frame = obj_sky_struct[nr_exp].objectFrame;
01148             KMO_TRY_EXIT_IF_NULL(
01149                 main_header_tel = kmclipm_propertylist_load(cpl_frame_get_filename(obj_frame), 0));
01150 
01151             exptime = cpl_propertylist_get_double(main_header_tel, EXPTIME);
01152             KMO_TRY_CHECK_ERROR_STATE();
01153 
01154             // load, process & store frames
01155 
01156             for (i = 1; i <= nr_devices; i++) {
01157                 // extract LCAL image close to ROTANGLE 0. assuming that the wavelength range
01158                 // doesn't differ too much with different ROTANGLEs.
01159                 double rotangle_found;
01160                 KMO_TRY_EXIT_IF_NULL(
01161                     lcal = kmo_dfs_load_cal_image(frameset, LCAL, i, FALSE, 0., FALSE, NULL,
01162                             &rotangle_found, -1, 0, 0));
01163 
01164                 if (tmp_band_method != NULL) {
01165                     band_method = atoi(tmp_band_method);
01166                 }
01167 
01168                 // get filter for this detector
01169                 // ESO INS FILTi ID
01170                 KMO_TRY_EXIT_IF_NULL(
01171                     keyword = cpl_sprintf("%s%d%s", IFU_FILTID_PREFIX, i, IFU_FILTID_POSTFIX));
01172                 filter_id = cpl_propertylist_get_string(main_header_tel, keyword);
01173                 cpl_free(keyword); keyword = NULL;
01174 
01175                 KMO_TRY_EXIT_IF_NULL(
01176                     band_table = kmo_dfs_load_table(frameset, WAVE_BAND, 1, 0));
01177                 KMO_TRY_EXIT_IF_ERROR(
01178                     kmclipm_setup_grid_band_lcal(&gd, lcal, filter_id,
01179                                                  band_method, band_table));
01180                 cpl_image_delete(lcal); lcal = NULL;
01181                 cpl_table_delete(band_table); band_table = NULL;
01182 
01183                 // load sub_header of original F2D image
01184                 KMO_TRY_EXIT_IF_NULL(
01185                     sub_header_orig = kmclipm_propertylist_load( cpl_frame_get_filename(obj_frame), i));
01186 
01187                 for (j = 0; j < KMOS_IFUS_PER_DETECTOR; j++) {
01188                     ifu_nr = (i-1)*KMOS_IFUS_PER_DETECTOR + j + 1;
01189                     // check if IFU is valid according to main header keywords &
01190                     // calibration files
01191                     // AND check if there is a sky frame available for this IFU
01192 
01193                     kmo_collapse_object_sky_frame_table(frameCnt, obj_sky_struct, ifu_nr,
01194                                                         &obj_frame, &sky_frame);
01195 
01196                     KMO_TRY_EXIT_IF_NULL(
01197                         punused_ifus = cpl_array_get_data_int_const(unused_ifus_after[i-1]));
01198 
01199                     // Search for keyword ESO OCS ARMi NOTUSED
01200                     // If not present (CPL_ERROR_DATA_NOT_FOUND) we will eventually
01201                     // process standard star
01202                     KMO_TRY_EXIT_IF_NULL(
01203                         keyword = cpl_sprintf("%s%d%s", IFU_VALID_PREFIX, ifu_nr, IFU_VALID_POSTFIX));
01204                     tmp_str = cpl_propertylist_get_string(main_header_tel, keyword);
01205                     cpl_free(keyword); keyword = NULL;
01206 
01207                     if ((cpl_error_get_code() == CPL_ERROR_DATA_NOT_FOUND) &&
01208                         (bounds[2*(ifu_nr-1)] != -1) &&
01209                         (bounds[2*(ifu_nr-1)+1] != -1) &&
01210                         (sky_frame != NULL) &&
01211                         (punused_ifus[j] == 0))
01212                     {
01213                         cpl_error_reset();
01214                         // IFU is valid
01215 
01216                         if (sky_frame != NO_CORRESPONDING_SKYFRAME) {
01217                             cpl_msg_info("","Processing standard star in IFU %d\n"
01218                                          "(std. star in file: %s,\n"
01219                                          " sky in file:       %s)", ifu_nr,
01220                                          cpl_frame_get_filename(obj_frame),
01221                                          cpl_frame_get_filename(sky_frame));
01222                         } else {
01223                             sky_frame = NULL;
01224                             cpl_msg_warning("","Processing standard star in IFU %d\n"
01225                                          "(std. star in file: %s, no corresponding sky frame",
01226                                          ifu_nr, cpl_frame_get_filename(obj_frame));
01227                         }
01228 
01229                         nr_std_stars++;
01230 
01231                         // calculate WCS and make copies of sub_header
01232                         KMO_TRY_EXIT_IF_NULL(
01233                             tmp_sub_header = cpl_propertylist_duplicate(sub_header_orig));
01234                         KMO_TRY_EXIT_IF_ERROR(
01235                             kmo_calc_wcs_gd(main_header_tel, tmp_sub_header, ifu_nr, gd));
01236                         KMO_TRY_EXIT_IF_NULL(
01237                             stored_sub_tel_data_headers[ifu_nr-1] =
01238                                    cpl_propertylist_duplicate(tmp_sub_header));
01239                         KMO_TRY_EXIT_IF_NULL(
01240                             stored_sub_psf_headers[ifu_nr-1] =
01241                                    cpl_propertylist_duplicate(tmp_sub_header));
01242                         if (save_cubes) {
01243                             KMO_TRY_EXIT_IF_NULL(
01244                                 stored_sub_cube_data_headers[ifu_nr-1] =
01245                                        cpl_propertylist_duplicate(tmp_sub_header));
01246                         }
01247                         cpl_propertylist_delete(tmp_sub_header);
01248                         tmp_sub_header = NULL;
01249 
01250                         //
01251                         // adjust telluric-headers: copy CRPIX3 to CRPIX1,
01252                         //
01253                         cpl_propertylist_update_double(stored_sub_tel_data_headers[ifu_nr-1], CRVAL1,
01254                                 cpl_propertylist_get_double(stored_sub_tel_data_headers[ifu_nr-1], CRVAL3));
01255                         cpl_propertylist_erase(stored_sub_tel_data_headers[ifu_nr-1], CRVAL2);
01256                         cpl_propertylist_erase(stored_sub_tel_data_headers[ifu_nr-1], CRVAL3);
01257                         KMO_TRY_CHECK_ERROR_STATE();
01258 
01259                         // CRPIX
01260                         cpl_propertylist_update_double(stored_sub_tel_data_headers[ifu_nr-1], CRPIX1,
01261                                 cpl_propertylist_get_double(stored_sub_tel_data_headers[ifu_nr-1], CRPIX3));
01262                         cpl_propertylist_erase(stored_sub_tel_data_headers[ifu_nr-1], CRPIX2);
01263                         cpl_propertylist_erase(stored_sub_tel_data_headers[ifu_nr-1], CRPIX3);
01264                         KMO_TRY_CHECK_ERROR_STATE();
01265 
01266                         // CDELT
01267                         cdelt3 = cpl_propertylist_get_double(stored_sub_tel_data_headers[ifu_nr-1], CDELT3);
01268                         cpl_propertylist_update_double(stored_sub_tel_data_headers[ifu_nr-1], CDELT1,
01269                                 cdelt3);
01270                         cpl_propertylist_erase(stored_sub_tel_data_headers[ifu_nr-1], CDELT2);
01271                         cpl_propertylist_erase(stored_sub_tel_data_headers[ifu_nr-1], CDELT3);
01272                         KMO_TRY_CHECK_ERROR_STATE();
01273 
01274                         // CTYPE
01275                         cpl_propertylist_update_string(stored_sub_tel_data_headers[ifu_nr-1], CTYPE1,
01276                                 cpl_propertylist_get_string(stored_sub_tel_data_headers[ifu_nr-1], CTYPE3));
01277                         cpl_propertylist_erase(stored_sub_tel_data_headers[ifu_nr-1], CTYPE2);
01278                         cpl_propertylist_erase(stored_sub_tel_data_headers[ifu_nr-1], CTYPE3);
01279                         KMO_TRY_CHECK_ERROR_STATE();
01280 
01281                         // CUNIT
01282                         cpl_propertylist_update_string(stored_sub_tel_data_headers[ifu_nr-1], CUNIT1,
01283                                 cpl_propertylist_get_string(stored_sub_tel_data_headers[ifu_nr-1], CUNIT3));
01284                         cpl_propertylist_erase(stored_sub_tel_data_headers[ifu_nr-1], CUNIT2);
01285                         cpl_propertylist_erase(stored_sub_tel_data_headers[ifu_nr-1], CUNIT3);
01286 
01287                         // CDx_x
01288                         cpl_propertylist_erase(stored_sub_tel_data_headers[ifu_nr-1], CD1_1);
01289                         cpl_propertylist_erase(stored_sub_tel_data_headers[ifu_nr-1], CD1_2);
01290                         cpl_propertylist_erase(stored_sub_tel_data_headers[ifu_nr-1], CD1_3);
01291                         cpl_propertylist_erase(stored_sub_tel_data_headers[ifu_nr-1], CD2_1);
01292                         cpl_propertylist_erase(stored_sub_tel_data_headers[ifu_nr-1], CD2_2);
01293                         cpl_propertylist_erase(stored_sub_tel_data_headers[ifu_nr-1], CD2_3);
01294                         cpl_propertylist_erase(stored_sub_tel_data_headers[ifu_nr-1], CD3_1);
01295                         cpl_propertylist_erase(stored_sub_tel_data_headers[ifu_nr-1], CD3_2);
01296                         cpl_propertylist_erase(stored_sub_tel_data_headers[ifu_nr-1], CD3_3);
01297                         KMO_TRY_CHECK_ERROR_STATE();
01298 
01299                         //
01300                         // adjust psf-headers: delete CRPIX3 etc.
01301                         //
01302                         cpl_propertylist_erase(stored_sub_psf_headers[ifu_nr-1], CRPIX3);
01303                         cpl_propertylist_erase(stored_sub_psf_headers[ifu_nr-1], CRPIX3);
01304                         cpl_propertylist_erase(stored_sub_psf_headers[ifu_nr-1], CDELT3);
01305                         cpl_propertylist_erase(stored_sub_psf_headers[ifu_nr-1], CRVAL3);
01306                         cpl_propertylist_erase(stored_sub_psf_headers[ifu_nr-1], CTYPE3);
01307                         cpl_propertylist_erase(stored_sub_psf_headers[ifu_nr-1], CUNIT3);
01308                         cpl_propertylist_erase(stored_sub_psf_headers[ifu_nr-1], CD1_3);
01309                         cpl_propertylist_erase(stored_sub_psf_headers[ifu_nr-1], CD2_3);
01310                         cpl_propertylist_erase(stored_sub_psf_headers[ifu_nr-1], CD3_1);
01311                         cpl_propertylist_erase(stored_sub_psf_headers[ifu_nr-1], CD3_2);
01312                         cpl_propertylist_erase(stored_sub_psf_headers[ifu_nr-1], CD3_3);
01313                         KMO_TRY_CHECK_ERROR_STATE();
01314 
01315                         KMO_TRY_EXIT_IF_ERROR(
01316                             kmo_reconstruct_sci(ifu_nr,
01317                                                 bounds[2*(ifu_nr-1)],
01318                                                 bounds[2*(ifu_nr-1)+1],
01319                                                 obj_frame,
01320                                                 STD,
01321                                                 sky_frame,
01322                                                 STD,
01323                                                 flat_frame,
01324                                                 xcal_frame,
01325                                                 ycal_frame,
01326                                                 lcal_frame,
01327                                                 NULL,
01328                                                 &gd,
01329                                                 &stored_data_cube[ifu_nr-1],
01330                                                 &stored_noise_cube[ifu_nr-1],
01331                                                 flux,
01332                                                 background,
01333                                                 xcal_interpolation));
01334 
01335                         // divide illumination correction from the data_cube
01336                         // (illumination noise will be very small versus
01337                         // noise_cube, so it is skipped here)
01338                         if (cpl_frameset_count_tags(frameset, ILLUM_CORR) == 1) {
01339                             KMO_TRY_EXIT_IF_NULL(
01340                                 illum_corr = kmo_dfs_load_image_frame(illum_frame, ifu_nr,
01341                                                                       FALSE, FALSE, NULL));
01342                             KMO_TRY_EXIT_IF_ERROR(
01343                                 cpl_imagelist_divide_image(stored_data_cube[ifu_nr-1], illum_corr));
01344                             cpl_image_delete(illum_corr); illum_corr = NULL;
01345                         }
01346 cpl_imagelist_save(stored_data_cube[ifu_nr-1], "cube.fits", CPL_BPP_IEEE_FLOAT, NULL, CPL_IO_CREATE);
01347                         // calculate QC_STD_TRACE
01348                         // (the distance of the PSF to the centre)
01349                         KMO_TRY_EXIT_IF_ERROR(
01350                             kmo_calculate_std_trace(stored_data_cube[ifu_nr-1], fmethod, &std_trace));
01351 
01352                         KMO_TRY_EXIT_IF_ERROR(
01353                             kmclipm_update_property_double(stored_sub_psf_headers[ifu_nr-1],
01354                                                            QC_STD_TRACE, std_trace,
01355                                                            "[pix] distance of PSF and centre of IFU"));
01356 
01357                         KMO_TRY_EXIT_IF_NULL(
01358                             identified_slices = cpl_vector_new(cpl_imagelist_get_size(stored_data_cube[ifu_nr-1])));
01359                         KMO_TRY_EXIT_IF_ERROR(
01360                             cpl_vector_fill(identified_slices, 1.0));
01361 
01362                         // collapse cube and get PSF image
01363                         KMO_TRY_EXIT_IF_ERROR(
01364                             kmclipm_make_image(stored_data_cube[ifu_nr-1], NULL,
01365                                                &stored_psf_data[ifu_nr-1], NULL,
01366                                                identified_slices,
01367                                                cmethod,
01368                                                cpos_rej, cneg_rej, citer,
01369                                                cmax, cmin));
01370                         cpl_vector_delete(identified_slices);
01371                         identified_slices= NULL;
01372 
01373                         // fit a 2D profile to get a mask and fwhm in x and y,
01374                         KMO_TRY_EXIT_IF_NULL(
01375                             tmp_vec = kmo_fit_profile_2D(stored_psf_data[ifu_nr-1],
01376                                                          NULL,
01377                                                          fmethod,
01378                                                          &stored_mask[ifu_nr-1],
01379                                                          &pl_psf));
01380 
01381                         // normalise mask to 1 and clip values below 0.5
01382                         cpl_image_divide_scalar(stored_mask[ifu_nr-1], cpl_image_get_max(stored_mask[ifu_nr-1]));
01383                         KMO_TRY_CHECK_ERROR_STATE();
01384 
01385                         int dummy=0;
01386                         for (int gx = 1; gx <= cpl_image_get_size_x(stored_mask[ifu_nr-1]); gx++) {
01387                             for (int gy = 1; gy <= cpl_image_get_size_y(stored_mask[ifu_nr-1]); gy++) {
01388                                 if (cpl_image_get(stored_mask[ifu_nr-1], gx, gy, &dummy) < 0.5) {
01389                                     cpl_image_set(stored_mask[ifu_nr-1], gx, gy, 0.);
01390                                 } else {
01391                                     cpl_image_set(stored_mask[ifu_nr-1], gx, gy, 1.);
01392                                 }
01393                             }
01394                         }
01395                         KMO_TRY_CHECK_ERROR_STATE();
01396 
01397                         // update subheader with fit parameters
01398                         KMO_TRY_EXIT_IF_ERROR(
01399                             cpl_propertylist_append(stored_sub_tel_data_headers[ifu_nr-1], pl_psf));
01400                         cpl_propertylist_delete(pl_psf); pl_psf = NULL;
01401 
01402                         // store QC_SPAT_RES (RMS of fwhm_x and fwhm_y)
01403                         double factor_fwhm = 2*sqrt(2*log(2));
01404                         double spat_res = pow(cpl_vector_get(tmp_vec, 4) * factor_fwhm, 2);
01405                         spat_res += pow(cpl_vector_get(tmp_vec, 5) * factor_fwhm, 2);
01406                         spat_res /= 2;
01407                         KMO_TRY_EXIT_IF_ERROR(
01408                             kmclipm_update_property_double(stored_sub_psf_headers[ifu_nr-1],
01409                                                            QC_SPAT_RES,
01410                                                            sqrt(spat_res)*KMOS_PIX_RESOLUTION,
01411                                                            "[arcsec] mean fwhm resolution of PSF"));
01412                         cpl_vector_delete(tmp_vec); tmp_vec = NULL;
01413 
01414                         // extract spectrum in masked area
01415                         KMO_TRY_EXIT_IF_ERROR(
01416                             kmo_priv_extract_spec(stored_data_cube[ifu_nr-1],
01417                                                   stored_noise_cube[ifu_nr-1],
01418                                                   stored_mask[ifu_nr-1],
01419                                                   &tmp_spec_data,
01420                                                   &tmp_spec_noise));
01421 
01422                         // store to save to disk later on
01423                         stored_starspec_data[ifu_nr-1] = cpl_vector_duplicate(tmp_spec_data);
01424                         if (tmp_spec_noise != NULL) {
01425                             stored_starspec_noise[ifu_nr-1] = cpl_vector_duplicate(tmp_spec_noise);
01426                         }
01427                         KMO_TRY_CHECK_ERROR_STATE();
01428 
01429                         // if magnitude is provided
01430                         // calculate zeropoint and throughput
01431                         if (has_magnitude) {
01432                             // extract spectrum of whole are for QC THRUHput and ZEROPOINT
01433                             KMO_TRY_EXIT_IF_ERROR(
01434                                 kmo_priv_extract_spec(stored_data_cube[ifu_nr-1],
01435                                                       NULL,
01436                                                       NULL,
01437                                                       &spec_qc,
01438                                                       NULL));
01439 
01440                             // multiply spectrum with area of IFU (196) to get the sum
01441                             const cpl_image *tmp_img = cpl_imagelist_get(stored_data_cube[ifu_nr-1], 0);
01442                             int tmpx = cpl_image_get_size_x(tmp_img),
01443                                 tmpy = cpl_image_get_size_x(tmp_img);
01444                             cpl_vector_multiply_scalar(spec_qc, tmpx*tmpy);
01445                         }
01446 
01447                         // calculate abscissa of output spectrum
01448                         KMO_TRY_EXIT_IF_NULL(
01449                             lambda_x = kmo_create_lambda_vec(gd.l.dim, 1,
01450                                                             gd.l.start,
01451                                                             gd.l.delta));
01452                         //
01453                         // spectrum correction
01454                         //
01455                         if ((strcmp(star_type, "O") == 0) ||
01456                             (strcmp(star_type, "B") == 0) ||
01457                             (strcmp(star_type, "A") == 0) ||
01458                             (strcmp(star_type, "F") == 0))
01459                         {
01460                             // we have a OBAF star
01461 
01462                             // if ATMOS_MODEL is present, lines will be removed
01463                             if (cpl_frameset_count_tags(frameset, ATMOS_MODEL) == 1) {
01464                                 // interpolate ATMOS_MODEL to same scale as data
01465                                 KMO_TRY_EXIT_IF_NULL(
01466                                     tmp_frame = kmo_dfs_get_frame(frameset, ATMOS_MODEL));
01467 
01468                                 KMO_TRY_EXIT_IF_NULL(
01469                                     atmos_model = kmo_interpolate_vector_wcs(tmp_frame, lambda_x));
01470 cpl_vector *tmp_spec_data_orig = NULL;
01471 int plot_it = 0;
01472 if (plot_it) {
01473     // store original spectrum
01474     KMO_TRY_EXIT_IF_NULL(
01475         tmp_spec_data_orig = cpl_vector_duplicate(tmp_spec_data));
01476 }
01477                                 // remove band-specific lines
01478                                 if (strcmp(filter_id, "H") == 0) {
01479                                     for (int l = 0; l < nr_lines_h; l++) {
01480                                         KMO_TRY_EXIT_IF_ERROR(
01481                                             kmo_remove_line(tmp_spec_data, lambda_x, atmos_model, lines_center_h[l], lines_width_h[l]));
01482                                     }
01483                                 } else if (strcmp(filter_id, "HK") == 0) {
01484                                     for (int l = 0; l < nr_lines_hk; l++) {
01485                                         KMO_TRY_EXIT_IF_ERROR(
01486                                             kmo_remove_line(tmp_spec_data, lambda_x, atmos_model, lines_center_hk[l], lines_width_hk[l]));
01487                                     }
01488                                 } else if (strcmp(filter_id, "K") == 0) {
01489                                     for (int l = 0; l < nr_lines_k; l++) {
01490                                         KMO_TRY_EXIT_IF_ERROR(
01491                                             kmo_remove_line(tmp_spec_data, lambda_x, atmos_model, lines_center_k[l], lines_width_k[l]));
01492                                     }
01493                                 } else if (strcmp(filter_id, "IZ") == 0) {
01494                                     for (int l = 0; l < nr_lines_iz; l++) {
01495                                         KMO_TRY_EXIT_IF_ERROR(
01496                                             kmo_remove_line(tmp_spec_data, lambda_x, atmos_model, lines_center_iz[l], lines_width_iz[l]));
01497                                     }
01498                                 } else if (strcmp(filter_id, "YJ") == 0) {
01499                                     for (int l = 0; l < nr_lines_yj; l++) {
01500                                         KMO_TRY_EXIT_IF_ERROR(
01501                                             kmo_remove_line(tmp_spec_data, lambda_x, atmos_model, lines_center_yj[l], lines_width_yj[l]));
01502                                     }
01503                                 }
01504 if (plot_it) {
01505     cpl_vector *tmp_spec_data_atmo = NULL;
01506     cpl_vector *tmp_spec_data_new = NULL;
01507     KMO_TRY_EXIT_IF_NULL(
01508         tmp_spec_data_atmo = cpl_vector_duplicate(tmp_spec_data_orig));
01509     KMO_TRY_EXIT_IF_NULL(
01510         tmp_spec_data_new = cpl_vector_duplicate(tmp_spec_data));
01511     KMO_TRY_EXIT_IF_ERROR(
01512         cpl_vector_divide(tmp_spec_data_atmo, atmos_model));
01513 
01514     char *sss = cpl_sprintf("atmo_div_%s.fits", filter_id);
01515     if (i == 1) {
01516         cpl_vector_save(tmp_spec_data_atmo, sss, CPL_BPP_IEEE_DOUBLE, stored_sub_tel_data_headers[ifu_nr-1], CPL_IO_CREATE);
01517     } else {
01518         cpl_vector_save(tmp_spec_data_atmo, sss, CPL_BPP_IEEE_DOUBLE, stored_sub_tel_data_headers[ifu_nr-1], CPL_IO_EXTEND);
01519     }
01520 
01521     cpl_vector *med_vec = cpl_vector_duplicate(tmp_spec_data_orig);
01522     double  median = cpl_vector_get_median(med_vec);
01523     cpl_vector_delete(med_vec);
01524     for (int i = 0; i < cpl_vector_get_size(tmp_spec_data_orig); i++) {
01525         if (cpl_vector_get(tmp_spec_data_orig, i) < median/8)
01526             cpl_vector_set(tmp_spec_data_orig, i, 0);
01527         if (cpl_vector_get(tmp_spec_data_atmo, i) < median/8)
01528             cpl_vector_set(tmp_spec_data_atmo, i, 0);
01529         if (cpl_vector_get(tmp_spec_data_new, i) < median/8)
01530             cpl_vector_set(tmp_spec_data_new, i, 0);
01531 
01532         if (cpl_vector_get(tmp_spec_data_orig, i) > 3*median)
01533             cpl_vector_set(tmp_spec_data_orig, i, 3*median);
01534         if (cpl_vector_get(tmp_spec_data_atmo, i) > 3*median)
01535             cpl_vector_set(tmp_spec_data_atmo, i, 3*median);
01536         if (cpl_vector_get(tmp_spec_data_new, i) > 3*median)
01537             cpl_vector_set(tmp_spec_data_new, i, 3*median);
01538     }
01539 
01540     double *pspec_dup = cpl_vector_get_data(tmp_spec_data_atmo);
01541     for (int i = 0; i < cpl_vector_get_size(tmp_spec_data_atmo); i++) {
01542         if (kmclipm_is_nan_or_inf(pspec_dup[i])) {
01543             pspec_dup[i] = 0.;
01544         }
01545     }
01546 
01547     cpl_bivector *plots[3];
01548     plots[0] = cpl_bivector_wrap_vectors((cpl_vector*)lambda_x, tmp_spec_data_orig);
01549     plots[1] = cpl_bivector_wrap_vectors((cpl_vector*)lambda_x, tmp_spec_data_atmo);
01550     plots[2] = cpl_bivector_wrap_vectors((cpl_vector*)lambda_x, tmp_spec_data_new);
01551     char *options[3] = {"w l t 'original'",
01552                         "w l t 'atmo divided'",
01553                         "w l t 'lines removed'"};
01554     sss = cpl_sprintf("set title '%s-band line removal (DET #%d)';", filter_id, i);
01555     cpl_plot_bivectors(sss,
01556                        (const char**)options, "", (const cpl_bivector**)plots, 3);
01557 //    cpl_plot_bivectors("set title 'Spectrum with lines removed'; set xrange [2.14:2.19];",
01558 //                       (const char**)options, "", (const cpl_bivector**)plots, 2);
01559     cpl_bivector_unwrap_vectors(plots[0]);
01560     cpl_bivector_unwrap_vectors(plots[1]);
01561     cpl_bivector_unwrap_vectors(plots[2]);
01562     cpl_free(sss); sss = NULL;
01563     cpl_vector_delete(tmp_spec_data_orig); tmp_spec_data_orig = NULL;
01564     cpl_vector_delete(tmp_spec_data_atmo); tmp_spec_data_atmo = NULL;
01565     cpl_vector_delete(tmp_spec_data_new); tmp_spec_data_new = NULL;
01566 }
01567                                 cpl_vector_delete(atmos_model); atmos_model = NULL;
01568                             } else {
01569                                 if (line_warning == FALSE) {
01570                                     cpl_msg_warning("", "No atmospheric model (ATMOS_MODEL) provided! "
01571                                                         "Won't remove any lines.");
01572                                     line_warning = TRUE;
01573                                 }
01574                             }
01575                         } else if (strcmp(star_type, "G") == 0) {
01576                             // we have a G star
01577                             if (cpl_frameset_count_tags(frameset, SOLAR_SPEC) == 1) {
01578                                 // interpolate SOLAR_SPEC to same scale as data
01579                                 // and divide it
01580                                 KMO_TRY_EXIT_IF_NULL(
01581                                     tmp_frame = kmo_dfs_get_frame(frameset, SOLAR_SPEC));
01582 
01583                                 // check if SOLAR_SPEC is the filter_id-one
01584                                 KMO_TRY_EXIT_IF_NULL(
01585                                     tmp_sub_header = kmclipm_propertylist_load(cpl_frame_get_filename(tmp_frame), 0));
01586                                 KMO_TRY_EXIT_IF_NULL(
01587                                     tmp_str = cpl_propertylist_get_string(tmp_sub_header, FILT_ID));
01588                                 KMO_TRY_ASSURE(strcmp(filter_id, tmp_str) == 0,
01589                                                CPL_ERROR_ILLEGAL_INPUT,
01590                                                "SOLAR_SPEC model must have primary "
01591                                                "keyword '%s' equal '%s'!!!",
01592                                                FILT_ID, filter_id);
01593                                 cpl_propertylist_delete(tmp_sub_header); tmp_sub_header = NULL;
01594 
01595                                 KMO_TRY_EXIT_IF_NULL(
01596                                     solar_spec = kmo_interpolate_vector_wcs(tmp_frame, lambda_x));
01597 
01598                                 // values are set to zero if solar_spec isn't
01599                                 // overlapping wavelength range of star apectrum
01600                                 // completely
01601                                 KMO_TRY_EXIT_IF_ERROR(
01602                                     cpl_vector_divide(tmp_spec_data, solar_spec));
01603                                 cpl_vector_delete(solar_spec); solar_spec = NULL;
01604                             } else {
01605                                 if (print_warning_once == TRUE) {
01606                                     cpl_msg_warning("","No solar spectrum (SOLAR_SPEC) provided! "
01607                                                        "Can't divide it from extracted "
01608                                                        "standard star spectrum!");
01609                                     print_warning_once = FALSE;
01610                                 }
01611                             }
01612                         } else {
01613 //                            cpl_msg_warning("","No startype was provided! Can't"
01614 //                                            " divide solar spectrum for G stars "
01615 //                                            "or fit a profile to atmospheric "
01616 //                                            "transmission for OBAF stars.");
01617                         }
01618 
01619                         if (star_temperature > 0.0) {
01620                             // divide blackbody from tmp_spec_data
01621                             KMO_TRY_EXIT_IF_ERROR(
01622                                 kmo_divide_blackbody(tmp_spec_data, lambda_x, star_temperature));
01623                         }
01624 
01625                         cpl_vector_delete(lambda_x); lambda_x = NULL;
01626 
01627                         // normalise telluric and its noise
01628                         // mean is taken in lambda defined range
01629                         KMO_TRY_EXIT_IF_ERROR(
01630                             kmo_calc_band_mean(stored_sub_tel_data_headers[ifu_nr-1],
01631                                                filter_id,
01632                                                tmp_spec_data,
01633                                                tmp_spec_noise,
01634                                                &mean_data,
01635                                                &mean_noise));
01636 
01637                         KMO_TRY_EXIT_IF_ERROR(
01638                             cpl_vector_divide_scalar(tmp_spec_data, mean_data));
01639 
01640                         if (tmp_spec_noise != NULL) {
01641                             KMO_TRY_EXIT_IF_ERROR(
01642                                 cpl_vector_divide_scalar(tmp_spec_noise, mean_noise));
01643 
01644                             // set noise spectrum also to zero when solar_spec is too short
01645                             KMO_TRY_EXIT_IF_NULL(
01646                                 ptmp_spec_data = cpl_vector_get_data_const(tmp_spec_data));
01647                             KMO_TRY_EXIT_IF_NULL(
01648                                 ptmp_spec_noise = cpl_vector_get_data(tmp_spec_noise));
01649                             for (int i = 0; i < cpl_vector_get_size(tmp_spec_data); i++) {
01650                                 if (ptmp_spec_data[i] == 0.0) {
01651                                     ptmp_spec_noise[i] = 0.0;
01652                                 }
01653                             }
01654                         }
01655                         KMO_TRY_CHECK_ERROR_STATE();
01656 
01657                         // store telluric & error spectrum
01658                         stored_telluric_data[ifu_nr-1] = tmp_spec_data;
01659                         stored_telluric_noise[ifu_nr-1] = tmp_spec_noise;
01660 
01661                         // if magnitude is provided
01662                         // calculate zeropoint and throughput
01663                         if (has_magnitude) {
01664                             // calculate QC THROUGHPUT
01665                             crpix1 = cpl_propertylist_get_double(stored_sub_tel_data_headers[ifu_nr-1], CRPIX1);
01666                             crval1 = cpl_propertylist_get_double(stored_sub_tel_data_headers[ifu_nr-1], CRVAL1);
01667                             cdelt1 = cpl_propertylist_get_double(stored_sub_tel_data_headers[ifu_nr-1], CDELT1);
01668                             KMO_TRY_CHECK_ERROR_STATE();
01669 
01670                             KMO_TRY_EXIT_IF_ERROR(
01671                                 kmo_calc_counts(spec_qc, filter_id,
01672                                                 crpix1, crval1, cdelt1,
01673                                                 &counts1, &counts2));
01674                             KMO_TRY_CHECK_ERROR_STATE();
01675 
01676                             counts1 /= exptime;
01677                             counts2 /= exptime;
01678 
01679                             stored_qc_throughput[ifu_nr-1] =
01680                                 kmo_calc_throughput(magnitude1, magnitude2, counts1, counts2,
01681                                                     cpl_propertylist_get_double(stored_sub_tel_data_headers[ifu_nr-1], GAIN),
01682                                                     filter_id);
01683                             KMO_TRY_CHECK_ERROR_STATE();
01684 
01685                             if (kmclipm_is_nan_or_inf(stored_qc_throughput[ifu_nr-1])) {
01686                                 stored_qc_throughput[ifu_nr-1] = -1;
01687                             }
01688                             KMO_TRY_EXIT_IF_ERROR(
01689                                 kmclipm_update_property_double(stored_sub_tel_data_headers[ifu_nr-1],
01690                                                                QC_THROUGHPUT,
01691                                                                stored_qc_throughput[ifu_nr-1],
01692                                                                "[] IFU throughput"));
01693 
01694                             // calculate QC ZEROPOINT
01695                             zeropoint = kmo_calc_zeropoint(magnitude1, magnitude2, counts1, counts2, cdelt3, filter_id);
01696                             if (kmclipm_is_nan_or_inf(zeropoint)) {
01697                                 zeropoint = -1;
01698                             }
01699                             KMO_TRY_CHECK_ERROR_STATE();
01700 
01701                             KMO_TRY_EXIT_IF_ERROR(
01702                                 kmclipm_update_property_double(stored_sub_tel_data_headers[ifu_nr-1],
01703                                                                QC_ZEROPOINT,
01704                                                                zeropoint,
01705                                                                "[mag] IFU zeropoint"));
01706                         }
01707                         cpl_vector_delete(spec_qc);spec_qc = NULL;
01708                     } else {
01709                         cpl_error_reset();
01710                         // IFU is invalid
01711                         KMO_TRY_EXIT_IF_NULL(
01712                             stored_sub_tel_data_headers[ifu_nr-1] =
01713                                 cpl_propertylist_duplicate(sub_header_orig));
01714                         KMO_TRY_EXIT_IF_NULL(
01715                             stored_sub_tel_noise_headers[ifu_nr-1] =
01716                                 cpl_propertylist_duplicate(sub_header_orig));
01717                         KMO_TRY_EXIT_IF_NULL(
01718                             stored_sub_psf_headers[ifu_nr-1] =
01719                                 cpl_propertylist_duplicate(sub_header_orig));
01720                         if (save_cubes) {
01721                             KMO_TRY_EXIT_IF_NULL(
01722                                 stored_sub_cube_data_headers[ifu_nr-1] =
01723                                     cpl_propertylist_duplicate(sub_header_orig));
01724                             KMO_TRY_EXIT_IF_NULL(
01725                                 stored_sub_cube_noise_headers[ifu_nr-1] =
01726                                     cpl_propertylist_duplicate(sub_header_orig));
01727                         }
01728                     }
01729 
01730                     // create EXTNAME keyword as DATA
01731                     KMO_TRY_EXIT_IF_NULL(
01732                         extname = kmo_extname_creator(ifu_frame, ifu_nr, EXT_DATA));
01733                     KMO_TRY_EXIT_IF_ERROR(
01734                         kmclipm_update_property_string(stored_sub_tel_data_headers[ifu_nr-1],
01735                                                        EXTNAME, extname, "FITS extension name"));
01736                     KMO_TRY_EXIT_IF_ERROR(
01737                         kmclipm_update_property_string(stored_sub_psf_headers[ifu_nr-1],
01738                                                        EXTNAME, extname, "FITS extension name"));
01739                     if (save_cubes) {
01740                         KMO_TRY_EXIT_IF_ERROR(
01741                             kmclipm_update_property_string(stored_sub_cube_data_headers[ifu_nr-1],
01742                                                            EXTNAME, extname, "FITS extension name"));
01743                     }
01744                     cpl_free(extname); extname = NULL;
01745 
01746                     // create EXTNAME keyword as NOISE
01747                     if (stored_sub_tel_noise_headers[ifu_nr-1] == NULL) {
01748                         KMO_TRY_EXIT_IF_NULL(
01749                             stored_sub_tel_noise_headers[ifu_nr-1] =
01750                                     cpl_propertylist_duplicate(
01751                                             stored_sub_tel_data_headers[ifu_nr-1]));
01752                     }
01753                     KMO_TRY_EXIT_IF_NULL(
01754                         extname = kmo_extname_creator(ifu_frame, ifu_nr, EXT_NOISE));
01755                     KMO_TRY_EXIT_IF_ERROR(
01756                         kmclipm_update_property_string(stored_sub_tel_noise_headers[ifu_nr-1],
01757                                                        EXTNAME, extname, "FITS extension name"));
01758                     if (save_cubes) {
01759                         KMO_TRY_EXIT_IF_NULL(
01760                             stored_sub_cube_noise_headers[ifu_nr-1] =
01761                                     cpl_propertylist_duplicate(
01762                                             stored_sub_cube_data_headers[ifu_nr-1]));
01763                         KMO_TRY_EXIT_IF_ERROR(
01764                             kmclipm_update_property_string(stored_sub_cube_noise_headers[ifu_nr-1],
01765                                                            EXTNAME, extname, "FITS extension name"));
01766                     }
01767                     cpl_free(extname); extname = NULL;
01768                 } // for j ifus (load, process & store)
01769                 cpl_propertylist_delete(sub_header_orig); sub_header_orig = NULL;
01770             } // for i detectors (load, process & store)
01771             KMO_TRY_CHECK_ERROR_STATE();
01772 
01773             // write QC parameter: nr of std stars
01774             KMO_TRY_EXIT_IF_ERROR(
01775                 kmclipm_update_property_int(main_header_tel, QC_NR_STD_STARS,
01776                                         nr_std_stars, "[] Nr. of std stars"));
01777 
01778             // update which IFUs are not used
01779             kmo_print_unused_ifus(unused_ifus_after, TRUE);
01780 
01781             KMO_TRY_EXIT_IF_ERROR(
01782                 kmo_set_unused_ifus(unused_ifus_after, main_header_tel, "kmo_std_star"));
01783 
01784             KMO_TRY_EXIT_IF_NULL(
01785                 main_header_psf = cpl_propertylist_duplicate(main_header_tel));
01786 
01787             if (has_magnitude) {
01788                 // calculate QC THROUGHPUT MEAN and QC THROUGHPUT SDV
01789                 // and update main header
01790                 KMO_TRY_EXIT_IF_ERROR(
01791                     kmo_calc_mean_throughput(stored_qc_throughput,
01792                                              nr_devices * KMOS_IFUS_PER_DETECTOR,
01793                                              &throughput_mean,
01794                                              &throughput_sdv));
01795                 KMO_TRY_EXIT_IF_ERROR(
01796                     kmclipm_update_property_double(main_header_tel, QC_THROUGHPUT_MEAN,
01797                                                    throughput_mean, "[] mean throughput for all detectors"));
01798                 KMO_TRY_EXIT_IF_ERROR(
01799                     kmclipm_update_property_double(main_header_tel, QC_THROUGHPUT_SDV,
01800                                                    throughput_sdv, "[] stdev throughput for all detectors"));
01801             }
01802             KMO_TRY_CHECK_ERROR_STATE();
01803 
01804             //
01805             // save output data
01806             //
01807 
01808             // save primary extension
01809             cpl_msg_info("","Saving STD exposure No. %d", nr_exp+1);
01810             KMO_TRY_EXIT_IF_ERROR(
01811                 kmo_dfs_save_main_header(frameset, filename_telluric, suffix,
01812                                          obj_frame, main_header_tel, parlist,
01813                                          cpl_func));
01814             KMO_TRY_EXIT_IF_ERROR(
01815                 kmo_dfs_save_main_header(frameset, filename_starspec, suffix,
01816                                          obj_frame, main_header_tel, parlist,
01817                                          cpl_func));
01818             KMO_TRY_EXIT_IF_ERROR(
01819                 kmo_dfs_save_main_header(frameset, filename_mask, suffix,
01820                                          obj_frame, main_header_psf, parlist,
01821                                          cpl_func));
01822             KMO_TRY_EXIT_IF_ERROR(
01823                 kmo_dfs_save_main_header(frameset, filename_psf, suffix,
01824                                          obj_frame, main_header_psf, parlist,
01825                                          cpl_func));
01826             if (save_cubes) {
01827                 KMO_TRY_EXIT_IF_ERROR(
01828                     kmo_dfs_save_main_header(frameset, filename_cubes, suffix,
01829                                              obj_frame, main_header_psf, parlist,
01830                                              cpl_func));
01831             }
01832 
01833             // save stored frames
01834             for (i = 1; i <= nr_devices; i++) {
01835                 for (j = 0; j < KMOS_IFUS_PER_DETECTOR; j++) {
01836                     ifu_nr = (i-1)*KMOS_IFUS_PER_DETECTOR + j + 1;
01837 
01838                     // save telluric-vector
01839 kmclipm_vector *ddd = NULL;
01840 if (stored_telluric_data[ifu_nr-1] != NULL)
01841 ddd = kmclipm_vector_create(cpl_vector_duplicate(stored_telluric_data[ifu_nr-1]));
01842                     KMO_TRY_EXIT_IF_ERROR(
01843                         kmo_dfs_save_vector(ddd, filename_telluric, suffix,
01844                                             stored_sub_tel_data_headers[ifu_nr-1],
01845                                             0./0.));
01846 kmclipm_vector_delete(ddd); ddd =NULL;
01847 
01848 if (stored_telluric_noise[ifu_nr-1] != NULL)
01849 ddd = kmclipm_vector_create(cpl_vector_duplicate(stored_telluric_noise[ifu_nr-1]));
01850                     KMO_TRY_EXIT_IF_ERROR(
01851                         kmo_dfs_save_vector(ddd, filename_telluric, suffix,
01852                                             stored_sub_tel_noise_headers[ifu_nr-1],
01853                                             0./0.));
01854 kmclipm_vector_delete(ddd); ddd =NULL;
01855 
01856                     // save star_spec-vector
01857 if (stored_starspec_data[ifu_nr-1] != NULL)
01858 ddd = kmclipm_vector_create(cpl_vector_duplicate(stored_starspec_data[ifu_nr-1]));
01859                     KMO_TRY_EXIT_IF_ERROR(
01860                         kmo_dfs_save_vector(ddd, filename_starspec, suffix,
01861                                             stored_sub_tel_data_headers[ifu_nr-1],
01862                                             0./0.));
01863 kmclipm_vector_delete(ddd); ddd =NULL;
01864 
01865 if (stored_starspec_noise[ifu_nr-1] != NULL)
01866 ddd = kmclipm_vector_create(cpl_vector_duplicate(stored_starspec_noise[ifu_nr-1]));
01867                     KMO_TRY_EXIT_IF_ERROR(
01868                         kmo_dfs_save_vector(ddd, filename_starspec, suffix,
01869                                             stored_sub_tel_noise_headers[ifu_nr-1],
01870                                             0./0.));
01871 kmclipm_vector_delete(ddd); ddd =NULL;
01872 
01873                     // save psf-image
01874                     KMO_TRY_EXIT_IF_ERROR(
01875                         kmo_dfs_save_image(stored_psf_data[ifu_nr-1],
01876                                            filename_psf, suffix,
01877                                            stored_sub_psf_headers[ifu_nr-1],
01878                                            0./0.));
01879 
01880                     // save mask-image
01881                     KMO_TRY_EXIT_IF_ERROR(
01882                         kmo_dfs_save_image(stored_mask[ifu_nr-1],
01883                                            filename_mask, suffix,
01884                                            stored_sub_psf_headers[ifu_nr-1],
01885                                            0./0.));
01886                     // save reonstructed cubes
01887                     if (save_cubes) {
01888                         KMO_TRY_EXIT_IF_ERROR(
01889                             kmo_dfs_save_cube(stored_data_cube[ifu_nr-1],
01890                                               filename_cubes, suffix,
01891                                               stored_sub_cube_data_headers[ifu_nr-1],
01892                                               0./0.));
01893                         KMO_TRY_EXIT_IF_ERROR(
01894                             kmo_dfs_save_cube(stored_noise_cube[ifu_nr-1],
01895                                               filename_cubes, suffix,
01896                                               stored_sub_cube_noise_headers[ifu_nr-1],
01897                                               0./0.));
01898                     }
01899                 } // for j ifus (save stored)
01900             } // for i detectors (save stored)
01901             KMO_TRY_CHECK_ERROR_STATE();
01902         } // if (frameCnt == 0)
01903     }
01904     KMO_CATCH
01905     {
01906         KMO_CATCH_MSG();
01907         ret_val = -1;
01908     }
01909 
01910     cpl_free(obj_sky_struct); obj_sky_struct = NULL;
01911     kmo_free_fits_desc(&desc1);
01912     kmo_free_fits_desc(&desc2);
01913     kmo_free_unused_ifus(unused_ifus_before); unused_ifus_before = NULL;
01914     kmo_free_unused_ifus(unused_ifus_after); unused_ifus_after = NULL;
01915     cpl_free(bounds); bounds = NULL;
01916     cpl_propertylist_delete(main_header_tel); main_header_tel = NULL;
01917     cpl_propertylist_delete(main_header_psf); main_header_psf = NULL;
01918     cpl_vector_delete(atmos_model); atmos_model = NULL;
01919     cpl_vector_delete(solar_spec); solar_spec = NULL;
01920     cpl_table_delete(spec_type_LUT); spec_type_LUT = NULL;
01921     cpl_vector_delete(identified_slices); identified_slices = NULL;
01922     cpl_propertylist_delete(sub_header_orig); sub_header_orig = NULL;
01923     for (i = 0; i < nr_devices * KMOS_IFUS_PER_DETECTOR; i++) {
01924         cpl_vector_delete(stored_telluric_data[i]); stored_telluric_data[i] = NULL;
01925         cpl_vector_delete(stored_telluric_noise[i]); stored_telluric_noise[i] = NULL;
01926         cpl_vector_delete(stored_starspec_data[i]); stored_starspec_data[i] = NULL;
01927         cpl_vector_delete(stored_starspec_noise[i]); stored_starspec_noise[i] = NULL;
01928         cpl_image_delete(stored_psf_data[i]); stored_psf_data[i] = NULL;
01929         cpl_propertylist_delete(stored_sub_tel_data_headers[i]); stored_sub_tel_data_headers[i] = NULL;
01930         cpl_propertylist_delete(stored_sub_tel_noise_headers[i]); stored_sub_tel_noise_headers[i] = NULL;
01931         if (save_cubes) {
01932             cpl_propertylist_delete(stored_sub_cube_data_headers[i]); stored_sub_cube_data_headers[i] = NULL;
01933             cpl_propertylist_delete(stored_sub_cube_noise_headers[i]); stored_sub_cube_noise_headers[i] = NULL;
01934         }
01935         cpl_propertylist_delete(stored_sub_psf_headers[i]); stored_sub_psf_headers[i] = NULL;
01936         cpl_image_delete(stored_mask[i]); stored_mask[i] = NULL;
01937         cpl_imagelist_delete(stored_data_cube[i]); stored_data_cube[i] = NULL;
01938         cpl_imagelist_delete(stored_noise_cube[i]); stored_noise_cube[i] = NULL;
01939     }
01940     cpl_free(stored_telluric_data); stored_telluric_data = NULL;
01941     cpl_free(stored_telluric_noise); stored_telluric_noise = NULL;
01942     cpl_free(stored_starspec_data); stored_starspec_data = NULL;
01943     cpl_free(stored_starspec_noise); stored_starspec_noise = NULL;
01944     cpl_free(stored_psf_data); stored_psf_data = NULL;
01945     cpl_free(stored_sub_tel_data_headers); stored_sub_tel_data_headers = NULL;
01946     cpl_free(stored_sub_tel_noise_headers); stored_sub_tel_noise_headers = NULL;
01947     if (save_cubes) {
01948         cpl_free(stored_sub_cube_data_headers); stored_sub_cube_data_headers = NULL;
01949         cpl_free(stored_sub_cube_noise_headers); stored_sub_cube_noise_headers = NULL;
01950     }
01951     cpl_free(stored_sub_psf_headers); stored_sub_psf_headers = NULL;
01952     cpl_free(stored_qc_throughput); stored_qc_throughput = NULL;
01953     cpl_free(suffix); suffix = NULL;
01954     cpl_free(stored_mask); stored_mask = NULL;
01955     cpl_free(stored_data_cube); stored_data_cube = NULL;
01956     cpl_free(stored_noise_cube); stored_noise_cube = NULL;
01957     cpl_free(grat_id); grat_id = NULL;
01958     cpl_frameset_delete(frameset_std); frameset_std = NULL;
01959 
01960     return ret_val;
01961 }
01962