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