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