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