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