KMOS Pipeline Reference Manual  1.0.8
kmo_std_star.c
00001 /* $Id: kmo_std_star.c,v 1.42 2013/02/04 22:20:50 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/02/04 22:20:50 $
00024  * $Revision: 1.42 $
00025  * $Name: kmosp_v1_0_8__20130220 $
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                      *tmp_spec_data_copy     = 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_psf_headers            = NULL,
00482                      *pl_psf                             = NULL;
00483 
00484     cpl_property     *p                     = 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         cpl_msg_info("", "Detected instrument setup:   %s", suffix+1);
00983         cpl_msg_info("", "(grating 1, 2 & 3, rotation angle)");
00984 
00985         // check which IFUs are active for all frames
00986         KMO_TRY_EXIT_IF_NULL(
00987             unused_ifus_before = kmo_get_unused_ifus(frameset, 0, 0));
00988 
00989         KMO_TRY_EXIT_IF_NULL(
00990             unused_ifus_after = kmo_duplicate_unused_ifus(unused_ifus_before));
00991 
00992         kmo_print_unused_ifus(unused_ifus_before, FALSE);
00993 
00994         /* --- load data --- */
00995 
00996         if ((cpl_frameset_count_tags(frameset, SPEC_TYPE_LOOKUP) == 1) &&
00997             ((strlen(spec_class) > 0) || (strlen(lum_class) > 0)))
00998         {
00999             // get star temperature out of SPEC_TYPE_LOOKUP table
01000             KMO_TRY_EXIT_IF_NULL(
01001                 spec_type_LUT = kmo_dfs_load_table(frameset, SPEC_TYPE_LOOKUP, 1, 0));
01002             star_temperature = kmo_get_temperature(spec_type_LUT, spec_class, lum_class);
01003             KMO_TRY_CHECK_ERROR_STATE();
01004         } else if (cpl_frameset_count_tags(frameset, SPEC_TYPE_LOOKUP) != 1) {
01005             cpl_msg_warning("","No SPEC_TYPE_LOOKUP was provided! Can't divide blackbody.");
01006         } else if ((strlen(spec_class) == 0) || (strlen(lum_class) == 0)) {
01007 //            cpl_msg_warning("","No startype was provided! Can't "
01008 //                            "divide blackbody.");
01009         }
01010 
01011         // allocate intermediate memory
01012         KMO_TRY_EXIT_IF_NULL(
01013             stored_telluric_data    = (cpl_vector**)cpl_calloc(nr_devices*KMOS_IFUS_PER_DETECTOR,
01014                                                                sizeof(cpl_vector*)));
01015         KMO_TRY_EXIT_IF_NULL(
01016             stored_telluric_noise   = (cpl_vector**)cpl_calloc(nr_devices*KMOS_IFUS_PER_DETECTOR,
01017                                                                sizeof(cpl_vector*)));
01018         KMO_TRY_EXIT_IF_NULL(
01019             stored_starspec_data    = (cpl_vector**)cpl_calloc(nr_devices*KMOS_IFUS_PER_DETECTOR,
01020                                                                sizeof(cpl_vector*)));
01021         KMO_TRY_EXIT_IF_NULL(
01022             stored_starspec_noise   = (cpl_vector**)cpl_calloc(nr_devices*KMOS_IFUS_PER_DETECTOR,
01023                                                                sizeof(cpl_vector*)));
01024         KMO_TRY_EXIT_IF_NULL(
01025             stored_psf_data         = (cpl_image**)cpl_calloc(nr_devices*KMOS_IFUS_PER_DETECTOR,
01026                                                               sizeof(cpl_image*)));
01027         KMO_TRY_EXIT_IF_NULL(
01028             stored_mask             = (cpl_image**)cpl_calloc(nr_devices*KMOS_IFUS_PER_DETECTOR,
01029                                                               sizeof(cpl_image*)));
01030         KMO_TRY_EXIT_IF_NULL(
01031             stored_data_cube        = (cpl_imagelist**)cpl_calloc(nr_devices*KMOS_IFUS_PER_DETECTOR,
01032                                                               sizeof(cpl_imagelist*)));
01033         KMO_TRY_EXIT_IF_NULL(
01034             stored_noise_cube       = (cpl_imagelist**)cpl_calloc(nr_devices*KMOS_IFUS_PER_DETECTOR,
01035                                                               sizeof(cpl_imagelist*)));
01036         KMO_TRY_EXIT_IF_NULL(
01037             stored_qc_throughput    = (double*)cpl_calloc(nr_devices*KMOS_IFUS_PER_DETECTOR,
01038                                                           sizeof(double)));
01039         KMO_TRY_EXIT_IF_NULL(
01040             stored_sub_psf_headers  = (cpl_propertylist**)cpl_calloc(nr_devices*KMOS_IFUS_PER_DETECTOR,
01041                                                                      sizeof(cpl_propertylist*)));
01042         KMO_TRY_EXIT_IF_NULL(
01043             stored_sub_tel_data_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_noise_headers = (cpl_propertylist**)cpl_calloc(nr_devices*KMOS_IFUS_PER_DETECTOR,
01047                                                                          sizeof(cpl_propertylist*)));
01048 
01049         // get bounds
01050         KMO_TRY_EXIT_IF_NULL(
01051             tmp_header = kmclipm_propertylist_load(cpl_frame_get_filename(xcal_frame), 0));
01052         KMO_TRY_EXIT_IF_NULL(
01053             bounds = kmclipm_extract_bounds(tmp_header));
01054         cpl_propertylist_delete(tmp_header); tmp_header = NULL;
01055 
01056         // setup grid definition, wavelength start and end points will be set
01057         // in the detector loop
01058         KMO_TRY_EXIT_IF_ERROR(
01059             kmclipm_setup_grid(&gd, imethod, neighborhoodRange));
01060 
01061         // get valid STD frames with objects in it and associated sky exposures
01062         KMO_TRY_EXIT_IF_NULL(
01063             obj_sky_struct = kmo_get_obj_sky_frame_table(frameset_std, &frameCnt, STD));
01064 
01065         // loop the object-sky pairs
01066         if (frameCnt == 0) {
01067             cpl_msg_warning(cpl_func,"Not a single frame contains an object");
01068         } else {
01069             strcpy(filename_telluric, TELLURIC);
01070             strcpy(filename_starspec, STAR_SPEC);
01071             strcpy(filename_psf, STD_IMAGE);
01072             strcpy(filename_mask, STD_MASK);
01073             strcpy(filename_cubes, STD_CUBE);
01074 
01075             obj_frame = obj_sky_struct[nr_exp].objectFrame;
01076             KMO_TRY_EXIT_IF_NULL(
01077                 main_header_tel = kmclipm_propertylist_load(cpl_frame_get_filename(obj_frame), 0));
01078 
01079             exptime = cpl_propertylist_get_double(main_header_tel, EXPTIME);
01080             KMO_TRY_CHECK_ERROR_STATE();
01081 
01082             // load, process & store frames
01083 
01084             for (i = 1; i <= nr_devices; i++) {
01085                 // extract LCAL image close to ROTANGLE 0. assuming that the wavelength range
01086                 // doesn't differ too much with different ROTANGLEs.
01087                 double rotangle_found;
01088                 KMO_TRY_EXIT_IF_NULL(
01089                     lcal = kmo_dfs_load_cal_image(frameset, LCAL, i, FALSE, 0., FALSE, NULL,
01090                             &rotangle_found));
01091 
01092                 if (tmp_band_method != NULL) {
01093                     band_method = atoi(tmp_band_method);
01094                 }
01095 
01096                 // get filter for this detector
01097                 // ESO INS FILTi ID
01098                 KMO_TRY_EXIT_IF_NULL(
01099                     keyword = cpl_sprintf("%s%d%s", IFU_FILTID_PREFIX, i, IFU_FILTID_POSTFIX));
01100                 filter_id = cpl_propertylist_get_string(main_header_tel, keyword);
01101                 cpl_free(keyword); keyword = NULL;
01102 
01103                 KMO_TRY_EXIT_IF_NULL(
01104                     band_table = kmo_dfs_load_table(frameset, WAVE_BAND, 1, 0));
01105                 KMO_TRY_EXIT_IF_ERROR(
01106                     kmclipm_setup_grid_band_lcal(&gd, lcal, filter_id,
01107                                                  band_method, band_table));
01108                 cpl_image_delete(lcal); lcal = NULL;
01109                 cpl_table_delete(band_table); band_table = NULL;
01110 
01111                 // load sub_header of original F2D image
01112                 KMO_TRY_EXIT_IF_NULL(
01113                     sub_header_orig = kmclipm_propertylist_load( cpl_frame_get_filename(obj_frame), i));
01114 
01115                 for (j = 0; j < KMOS_IFUS_PER_DETECTOR; j++) {
01116                     ifu_nr = (i-1)*KMOS_IFUS_PER_DETECTOR + j + 1;
01117                     // check if IFU is valid according to main header keywords &
01118                     // calibration files
01119                     // AND check if there is a sky frame available for this IFU
01120 
01121                     kmo_collapse_object_sky_frame_table(frameCnt, obj_sky_struct, ifu_nr,
01122                                                         &obj_frame, &sky_frame);
01123 
01124                     KMO_TRY_EXIT_IF_NULL(
01125                         punused_ifus = cpl_array_get_data_int_const(unused_ifus_after[i-1]));
01126 
01127                     // Search for keyword ESO OCS ARMi NOTUSED
01128                     // If not present (CPL_ERROR_DATA_NOT_FOUND) we will eventually
01129                     // process standard star
01130                     KMO_TRY_EXIT_IF_NULL(
01131                         keyword = cpl_sprintf("%s%d%s", IFU_VALID_PREFIX, ifu_nr, IFU_VALID_POSTFIX));
01132                     tmp_str = cpl_propertylist_get_string(main_header_tel, keyword);
01133                     cpl_free(keyword); keyword = NULL;
01134 
01135                     if ((cpl_error_get_code() == CPL_ERROR_DATA_NOT_FOUND) &&
01136                         (bounds[2*(ifu_nr-1)] != -1) &&
01137                         (bounds[2*(ifu_nr-1)+1] != -1) &&
01138                         (sky_frame != NULL) &&
01139                         (punused_ifus[j] == 0))
01140                     {
01141                         cpl_error_reset();
01142                         // IFU is valid
01143 
01144                         if (sky_frame != NO_CORRESPONDING_SKYFRAME) {
01145                             cpl_msg_info("","Processing standard star in IFU %d\n"
01146                                          "(std. star in file: %s,\n"
01147                                          " sky in file:       %s)", ifu_nr,
01148                                          cpl_frame_get_filename(obj_frame),
01149                                          cpl_frame_get_filename(sky_frame));
01150                         } else {
01151                             sky_frame = NULL;
01152                             cpl_msg_warning("","Processing standard star in IFU %d\n"
01153                                          "(std. star in file: %s, no corresponding sky frame",
01154                                          ifu_nr, cpl_frame_get_filename(obj_frame));
01155                         }
01156 
01157                         nr_std_stars++;
01158 
01159                         // calculate WCS and make copies of sub_header
01160                         KMO_TRY_EXIT_IF_NULL(
01161                             tmp_sub_header = cpl_propertylist_duplicate(sub_header_orig));
01162                         KMO_TRY_EXIT_IF_ERROR(
01163                             kmo_calc_wcs(main_header_tel, tmp_sub_header,
01164                                          ifu_nr, gd.l.start, gd.l.delta));
01165                         KMO_TRY_EXIT_IF_NULL(
01166                             stored_sub_tel_data_headers[ifu_nr-1] =
01167                                    cpl_propertylist_duplicate(tmp_sub_header));
01168                         KMO_TRY_EXIT_IF_NULL(
01169                             stored_sub_psf_headers[ifu_nr-1] =
01170                                    cpl_propertylist_duplicate(tmp_sub_header));
01171                         cpl_propertylist_delete(tmp_sub_header);
01172                         tmp_sub_header = NULL;
01173 
01174                         // for telluric-headers copy CRPIX3 to CRPIX1,
01175                         // delete CRPIX3 etc.
01176                         // CRVAL
01177                         cpl_propertylist_erase(stored_sub_tel_data_headers[ifu_nr-1], CRVAL1);
01178                         cpl_propertylist_erase(stored_sub_tel_data_headers[ifu_nr-1], CRVAL2);
01179                         KMO_TRY_CHECK_ERROR_STATE();
01180                         KMO_TRY_EXIT_IF_NULL(
01181                             p = cpl_propertylist_get_property(stored_sub_tel_data_headers[ifu_nr-1], CRVAL3));
01182                         KMO_TRY_EXIT_IF_ERROR(
01183                             cpl_property_set_name (p, CRVAL1));
01184 
01185                         // CRPIX
01186                         cpl_propertylist_erase(stored_sub_tel_data_headers[ifu_nr-1], CRPIX1);
01187                         cpl_propertylist_erase(stored_sub_tel_data_headers[ifu_nr-1], CRPIX2);
01188                         KMO_TRY_CHECK_ERROR_STATE();
01189                         KMO_TRY_EXIT_IF_NULL(
01190                             p = cpl_propertylist_get_property(stored_sub_tel_data_headers[ifu_nr-1], CRPIX3));
01191                         KMO_TRY_EXIT_IF_ERROR(
01192                             cpl_property_set_name (p, CRPIX1));
01193 
01194                         // CDELT
01195                         cpl_propertylist_erase(stored_sub_tel_data_headers[ifu_nr-1], CDELT1);
01196                         cpl_propertylist_erase(stored_sub_tel_data_headers[ifu_nr-1], CDELT2);
01197                         KMO_TRY_CHECK_ERROR_STATE();
01198                         KMO_TRY_EXIT_IF_NULL(
01199                             p = cpl_propertylist_get_property(stored_sub_tel_data_headers[ifu_nr-1], CDELT3));
01200 
01201                         cdelt3 = cpl_property_get_double(p);
01202                         KMO_TRY_CHECK_ERROR_STATE();
01203 
01204                         KMO_TRY_EXIT_IF_ERROR(
01205                             cpl_property_set_name (p, CDELT1));
01206 
01207                         // CTYPE
01208                         cpl_propertylist_erase(stored_sub_tel_data_headers[ifu_nr-1], CTYPE1);
01209                         cpl_propertylist_erase(stored_sub_tel_data_headers[ifu_nr-1], CTYPE2);
01210                         KMO_TRY_CHECK_ERROR_STATE();
01211                         KMO_TRY_EXIT_IF_NULL(
01212                             p = cpl_propertylist_get_property(stored_sub_tel_data_headers[ifu_nr-1], CTYPE3));
01213                         KMO_TRY_EXIT_IF_ERROR(
01214                             cpl_property_set_name (p, CTYPE1));
01215 
01216                         // CDx_x
01217                         cpl_propertylist_erase(stored_sub_tel_data_headers[ifu_nr-1], CD1_1);
01218                         cpl_propertylist_erase(stored_sub_tel_data_headers[ifu_nr-1], CD1_2);
01219                         cpl_propertylist_erase(stored_sub_tel_data_headers[ifu_nr-1], CD1_3);
01220                         cpl_propertylist_erase(stored_sub_tel_data_headers[ifu_nr-1], CD2_1);
01221                         cpl_propertylist_erase(stored_sub_tel_data_headers[ifu_nr-1], CD2_2);
01222                         cpl_propertylist_erase(stored_sub_tel_data_headers[ifu_nr-1], CD2_3);
01223                         cpl_propertylist_erase(stored_sub_tel_data_headers[ifu_nr-1], CD3_1);
01224                         cpl_propertylist_erase(stored_sub_tel_data_headers[ifu_nr-1], CD3_2);
01225                         cpl_propertylist_erase(stored_sub_tel_data_headers[ifu_nr-1], CD3_3);
01226                         KMO_TRY_CHECK_ERROR_STATE();
01227 
01228                         // for psf-headers: delete CRPIX3 etc.
01229                         cpl_propertylist_erase(stored_sub_psf_headers[ifu_nr-1], CRPIX3);
01230                         cpl_propertylist_erase(stored_sub_psf_headers[ifu_nr-1], CRPIX3);
01231                         cpl_propertylist_erase(stored_sub_psf_headers[ifu_nr-1], CDELT3);
01232                         cpl_propertylist_erase(stored_sub_psf_headers[ifu_nr-1], CRVAL3);
01233                         cpl_propertylist_erase(stored_sub_psf_headers[ifu_nr-1], CTYPE3);
01234                         KMO_TRY_CHECK_ERROR_STATE();
01235 
01236                         KMO_TRY_EXIT_IF_ERROR(
01237                             kmo_reconstruct_sci(ifu_nr,
01238                                                 bounds[2*(ifu_nr-1)],
01239                                                 bounds[2*(ifu_nr-1)+1],
01240                                                 obj_frame,
01241                                                 STD,
01242                                                 sky_frame,
01243                                                 STD,
01244                                                 flat_frame,
01245                                                 xcal_frame,
01246                                                 ycal_frame,
01247                                                 lcal_frame,
01248                                                 &gd,
01249                                                 &stored_data_cube[ifu_nr-1],
01250                                                 &stored_noise_cube[ifu_nr-1],
01251                                                 flux));
01252 
01253                         // divide illumination correction from the data_cube
01254                         // (illumination noise will be very small versus
01255                         // noise_cube, so it is skipped here)
01256                         if (cpl_frameset_count_tags(frameset, ILLUM_CORR) == 1) {
01257                             KMO_TRY_EXIT_IF_NULL(
01258                                 illum_corr = kmo_dfs_load_image_frame(illum_frame, ifu_nr,
01259                                                                       FALSE, FALSE, NULL));
01260                             KMO_TRY_EXIT_IF_ERROR(
01261                                 cpl_imagelist_divide_image(stored_data_cube[ifu_nr-1], illum_corr));
01262                             cpl_image_delete(illum_corr); illum_corr = NULL;
01263                         }
01264 
01265                         // calculate QC_STD_TRACE
01266                         // (the distance of the PSF to the centre)
01267                         KMO_TRY_EXIT_IF_ERROR(
01268                             kmo_calculate_std_trace(stored_data_cube[ifu_nr-1], fmethod, &std_trace));
01269 
01270                         KMO_TRY_EXIT_IF_ERROR(
01271                             kmclipm_update_property_double(stored_sub_psf_headers[ifu_nr-1],
01272                                                            QC_STD_TRACE, std_trace,
01273                                                            "[pix] distance of PSF and centre of IFU"));
01274 
01275                         KMO_TRY_EXIT_IF_NULL(
01276                             identified_slices = cpl_vector_new(cpl_imagelist_get_size(stored_data_cube[ifu_nr-1])));
01277                         KMO_TRY_EXIT_IF_ERROR(
01278                             cpl_vector_fill(identified_slices, 1.0));
01279 
01280                         // collapse cube and get PSF image
01281                         KMO_TRY_EXIT_IF_ERROR(
01282                             kmclipm_make_image(stored_data_cube[ifu_nr-1], NULL,
01283                                                &stored_psf_data[ifu_nr-1], NULL,
01284                                                identified_slices,
01285                                                cmethod,
01286                                                cpos_rej, cneg_rej, citer,
01287                                                cmax, cmin));
01288                         cpl_vector_delete(identified_slices);
01289                         identified_slices= NULL;
01290 
01291                         // fit a 2D profile to get a mask and fwhm in x and y,
01292                         KMO_TRY_EXIT_IF_NULL(
01293                             tmp_vec = kmo_fit_profile_2D(stored_psf_data[ifu_nr-1],
01294                                                          NULL,
01295                                                          fmethod,
01296                                                          &stored_mask[ifu_nr-1],
01297                                                          &pl_psf));
01298 
01299                         // normalise mask to 1 and clip values below 0.5
01300                         cpl_image_divide_scalar(stored_mask[ifu_nr-1], cpl_image_get_max(stored_mask[ifu_nr-1]));
01301                         KMO_TRY_CHECK_ERROR_STATE();
01302 
01303                         int dummy=0;
01304                         for (int gx = 1; gx <= cpl_image_get_size_x(stored_mask[ifu_nr-1]); gx++) {
01305                             for (int gy = 1; gy <= cpl_image_get_size_y(stored_mask[ifu_nr-1]); gy++) {
01306                                 if (cpl_image_get(stored_mask[ifu_nr-1], gx, gy, &dummy) < 0.5) {
01307                                     cpl_image_set(stored_mask[ifu_nr-1], gx, gy, 0.);
01308                                 } else {
01309                                     cpl_image_set(stored_mask[ifu_nr-1], gx, gy, 1.);
01310                                 }
01311                             }
01312                         }
01313                         KMO_TRY_CHECK_ERROR_STATE();
01314 
01315                         // update subheader with fit parameters
01316                         KMO_TRY_EXIT_IF_ERROR(
01317                             cpl_propertylist_append(stored_sub_tel_data_headers[ifu_nr-1], pl_psf));
01318                         cpl_propertylist_delete(pl_psf); pl_psf = NULL;
01319 
01320                         // store QC_SPAT_RES (RMS of fwhm_x and fwhm_y)
01321                         double factor_fwhm = 2*sqrt(2*log(2));
01322                         double spat_res = pow(cpl_vector_get(tmp_vec, 4) * factor_fwhm, 2);
01323                         spat_res += pow(cpl_vector_get(tmp_vec, 5) * factor_fwhm, 2);
01324                         spat_res /= 2;
01325                         KMO_TRY_EXIT_IF_ERROR(
01326                             kmclipm_update_property_double(stored_sub_psf_headers[ifu_nr-1],
01327                                                            QC_SPAT_RES,
01328                                                            sqrt(spat_res)*KMOS_PIX_RESOLUTION,
01329                                                            "[arcsec] mean fwhm resolution of PSF"));
01330                         cpl_vector_delete(tmp_vec); tmp_vec = NULL;
01331 
01332                         // extract spectrum in masked area
01333                         KMO_TRY_EXIT_IF_ERROR(
01334                             kmo_priv_extract_spec(stored_data_cube[ifu_nr-1],
01335                                                   stored_noise_cube[ifu_nr-1],
01336                                                   stored_mask[ifu_nr-1],
01337                                                   &tmp_spec_data,
01338                                                   &tmp_spec_noise));
01339 
01340                         // store to save to disk later on
01341                         stored_starspec_data[ifu_nr-1] = cpl_vector_duplicate(tmp_spec_data);
01342                         if (tmp_spec_noise != NULL) {
01343                             stored_starspec_noise[ifu_nr-1] = cpl_vector_duplicate(tmp_spec_noise);
01344                         }
01345                         KMO_TRY_CHECK_ERROR_STATE();
01346 
01347                         // create duplicate of tmp_spec_data for
01348                         // QC calculation below
01349                         KMO_TRY_EXIT_IF_NULL(
01350                             tmp_spec_data_copy = cpl_vector_duplicate(tmp_spec_data));
01351 
01352                         // calculate abscissa of output spectrum
01353                         KMO_TRY_EXIT_IF_NULL(
01354                             solar_x = kmo_create_lambda_vec(gd.l.dim, 1,
01355                                                             gd.l.start,
01356                                                             gd.l.delta));
01357 
01358                         //
01359                         // spectrum correction
01360                         //
01361                         if ((strcmp(star_type, "O") == 0) ||
01362                             (strcmp(star_type, "B") == 0) ||
01363                             (strcmp(star_type, "A") == 0) ||
01364                             (strcmp(star_type, "F") == 0))
01365                         {
01366                             // we have a OBAF star
01367                             if (strcmp(filter_id, "K") == 0) {
01368                                 if (cpl_frameset_count_tags(frameset, ATMOS_MODEL) == 1) {
01369                                     // interpolate ATMOS_MODEL to same scale
01370                                     // as data
01371                                     KMO_TRY_EXIT_IF_NULL(
01372                                         tmp_frame = kmo_dfs_get_frame(frameset, ATMOS_MODEL));
01373 
01374                                     // check if ATMOS_MODEL is the K one
01375                                     KMO_TRY_EXIT_IF_NULL(
01376                                         tmp_sub_header =
01377                                             kmclipm_propertylist_load( cpl_frame_get_filename(tmp_frame), 0));
01378                                     KMO_TRY_EXIT_IF_NULL(
01379                                         tmp_str = cpl_propertylist_get_string(tmp_sub_header, FILT_ID));
01380                                     KMO_TRY_ASSURE(strcmp("K", tmp_str) == 0,
01381                                                    CPL_ERROR_ILLEGAL_INPUT,
01382                                                    "ATMOS model must have primary "
01383                                                    "keyword '%s' equal 'K'!!!",
01384                                                    FILT_ID);
01385                                     cpl_propertylist_delete(tmp_sub_header);
01386                                     tmp_sub_header = NULL;
01387 
01388                                     KMO_TRY_EXIT_IF_NULL(
01389                                         atmos_model = kmo_interpolate_vector_wcs(tmp_frame, solar_x));
01390 
01391                                     KMO_TRY_EXIT_IF_ERROR(
01392                                              kmo_remove_brg_line(tmp_spec_data, solar_x, atmos_model));
01393 
01394                                     cpl_vector_delete(atmos_model);atmos_model = NULL;
01395                                 } else {
01396                                     cpl_msg_warning("", "No atmospheric model (ATMOS_MODEL) provided! "
01397                                                         "Can't remove Br-gamma-line.");
01398                                 }
01399                             } else {
01400                                 if (k_band_warning == FALSE) {
01401                                     if (cpl_frameset_count_tags(frameset, ATMOS_MODEL) == 1) {
01402                                         cpl_msg_warning("", "The atmospheric model is ignored for all "
01403                                                             "bands except K band (i.e. the Br-gamma "
01404                                                             "line won't be removed')");
01405                                         k_band_warning = TRUE;
01406                                     }
01407                                 }
01408                             }
01409                         } else if (strcmp(star_type, "G") == 0) {
01410                             // we have a G star
01411                             if (cpl_frameset_count_tags(frameset, SOLAR_SPEC) == 1) {
01412                                 // interpolate SOLAR_SPEC to same scale as data
01413                                 // and divide it
01414                                 KMO_TRY_EXIT_IF_NULL(
01415                                     tmp_frame = kmo_dfs_get_frame(frameset, SOLAR_SPEC));
01416 
01417                                 // check if SOLAR_SPEC is the filter_id-one
01418                                 KMO_TRY_EXIT_IF_NULL(
01419                                     tmp_sub_header = kmclipm_propertylist_load(cpl_frame_get_filename(tmp_frame), 0));
01420                                 KMO_TRY_EXIT_IF_NULL(
01421                                     tmp_str = cpl_propertylist_get_string(tmp_sub_header, FILT_ID));
01422                                 KMO_TRY_ASSURE(strcmp(filter_id, tmp_str) == 0,
01423                                                CPL_ERROR_ILLEGAL_INPUT,
01424                                                "SOLAR_SPEC model must have primary "
01425                                                "keyword '%s' equal '%s'!!!",
01426                                                FILT_ID, filter_id);
01427                                 cpl_propertylist_delete(tmp_sub_header); tmp_sub_header = NULL;
01428 
01429                                 KMO_TRY_EXIT_IF_NULL(
01430                                     solar_spec = kmo_interpolate_vector_wcs(tmp_frame, solar_x));
01431 
01432                                 // values are set to zero if solar_spec isn't
01433                                 // overlapping wavelength range of star apectrum
01434                                 // completely
01435                                 KMO_TRY_EXIT_IF_ERROR(
01436                                     cpl_vector_divide(tmp_spec_data, solar_spec));
01437                                 cpl_vector_delete(solar_spec); solar_spec = NULL;
01438                             } else {
01439                                 if (print_warning_once == TRUE) {
01440                                     cpl_msg_warning("","No solar spectrum (SOLAR_SPEC) provided! "
01441                                                        "Can't divide it from extracted "
01442                                                        "standard star spectrum!");
01443                                     print_warning_once = FALSE;
01444                                 }
01445                             }
01446                         } else {
01447 //                            cpl_msg_warning("","No startype was provided! Can't"
01448 //                                            " divide solar spectrum for G stars "
01449 //                                            "or fit a profile to atmospheric "
01450 //                                            "transmission for OBAF stars.");
01451                         }
01452 
01453                         if (star_temperature > 0.0) {
01454                             // divide blackbody from tmp_spec_data
01455                             KMO_TRY_EXIT_IF_ERROR(
01456                                 kmo_divide_blackbody(tmp_spec_data, solar_x, star_temperature));
01457                         }
01458 
01459                         cpl_vector_delete(solar_x); solar_x = NULL;
01460 
01461                         // normalise telluric and its noise
01462                         // mean is taken in lambda defined range
01463                         KMO_TRY_EXIT_IF_ERROR(
01464                             kmo_calc_band_mean(stored_sub_tel_data_headers[ifu_nr-1],
01465                                                filter_id,
01466                                                tmp_spec_data,
01467                                                tmp_spec_noise,
01468                                                &mean_data,
01469                                                &mean_noise));
01470 
01471                         KMO_TRY_EXIT_IF_ERROR(
01472                             cpl_vector_divide_scalar(tmp_spec_data, mean_data));
01473 
01474                         if (tmp_spec_noise != NULL) {
01475                             KMO_TRY_EXIT_IF_ERROR(
01476                                 cpl_vector_divide_scalar(tmp_spec_noise, mean_noise));
01477 
01478                             // set noise spectrum also to zero when solar_spec is too short
01479                             KMO_TRY_EXIT_IF_NULL(
01480                                 ptmp_spec_data = cpl_vector_get_data_const(tmp_spec_data));
01481                             KMO_TRY_EXIT_IF_NULL(
01482                                 ptmp_spec_noise = cpl_vector_get_data(tmp_spec_noise));
01483                             for (int i = 0; i < cpl_vector_get_size(tmp_spec_data); i++) {
01484                                 if (ptmp_spec_data[i] == 0.0) {
01485                                     ptmp_spec_noise[i] = 0.0;
01486                                 }
01487                             }
01488                         }
01489                         KMO_TRY_CHECK_ERROR_STATE();
01490 
01491                         // store telluric & error spectrum
01492                         stored_telluric_data[ifu_nr-1] = tmp_spec_data;
01493                         stored_telluric_noise[ifu_nr-1] = tmp_spec_noise;
01494 
01495                         // if magnitude is provided
01496                         // calculate zeropoint and throughput
01497                         if (has_magnitude) {
01498                             // correct for capped mask (by 0.5)
01499                             KMO_TRY_EXIT_IF_ERROR(
01500                                 cpl_vector_multiply_scalar(tmp_spec_data_copy, 2));
01501 
01502                             // calculate QC THROUGHPUT
01503                             crpix1 = cpl_propertylist_get_double(stored_sub_tel_data_headers[ifu_nr-1], CRPIX1);
01504                             crval1 = cpl_propertylist_get_double(stored_sub_tel_data_headers[ifu_nr-1], CRVAL1);
01505                             cdelt1 = cpl_propertylist_get_double(stored_sub_tel_data_headers[ifu_nr-1], CDELT1);
01506                             KMO_TRY_CHECK_ERROR_STATE();
01507 
01508                             KMO_TRY_EXIT_IF_ERROR(
01509                                 kmo_calc_counts(tmp_spec_data_copy, filter_id,
01510                                                 crpix1, crval1, cdelt1,
01511                                                 &counts1, &counts2));
01512                             KMO_TRY_CHECK_ERROR_STATE();
01513 
01514                             counts1 /= exptime;
01515                             counts2 /= exptime;
01516 
01517                             stored_qc_throughput[ifu_nr-1] =
01518                                 kmo_calc_throughput(magnitude1, magnitude2, counts1, counts2,
01519                                                     cpl_propertylist_get_double(stored_sub_tel_data_headers[ifu_nr-1], GAIN),
01520                                                     filter_id);
01521                             KMO_TRY_CHECK_ERROR_STATE();
01522 
01523                             if (kmclipm_is_nan_or_inf(stored_qc_throughput[ifu_nr-1])) {
01524                                 stored_qc_throughput[ifu_nr-1] = -1;
01525                             }
01526                             KMO_TRY_EXIT_IF_ERROR(
01527                                 kmclipm_update_property_double(stored_sub_tel_data_headers[ifu_nr-1],
01528                                                                QC_THROUGHPUT,
01529                                                                stored_qc_throughput[ifu_nr-1],
01530                                                                "[] IFU throughput"));
01531 
01532                             // calculate QC ZEROPOINT
01533                             zeropoint = kmo_calc_zeropoint(magnitude1, magnitude2, counts1, counts2, cdelt3, filter_id);
01534                             if (kmclipm_is_nan_or_inf(zeropoint)) {
01535                                 zeropoint = -1;
01536                             }
01537                             KMO_TRY_CHECK_ERROR_STATE();
01538 
01539                             KMO_TRY_EXIT_IF_ERROR(
01540                                 kmclipm_update_property_double(stored_sub_tel_data_headers[ifu_nr-1],
01541                                                                QC_ZEROPOINT,
01542                                                                zeropoint,
01543                                                                "[mag] IFU zeropoint"));
01544                         }
01545                         cpl_vector_delete(tmp_spec_data_copy);tmp_spec_data_copy = NULL;
01546                     } else {
01547                         cpl_error_reset();
01548                         // IFU is invalid
01549                         KMO_TRY_EXIT_IF_NULL(
01550                             stored_sub_tel_data_headers[ifu_nr-1] =
01551                                 cpl_propertylist_duplicate(sub_header_orig));
01552                         KMO_TRY_EXIT_IF_NULL(
01553                             stored_sub_psf_headers[ifu_nr-1] =
01554                                 cpl_propertylist_duplicate(sub_header_orig));
01555                     }
01556 
01557                     // create EXTNAME keyword as DATA
01558                     KMO_TRY_EXIT_IF_NULL(
01559                         extname = kmo_extname_creator(ifu_frame, ifu_nr, EXT_DATA));
01560                     KMO_TRY_EXIT_IF_ERROR(
01561                         kmclipm_update_property_string(stored_sub_tel_data_headers[ifu_nr-1],
01562                                                        EXTNAME,
01563                                                        extname,
01564                                                        "FITS extension name"));
01565                     KMO_TRY_EXIT_IF_ERROR(
01566                         kmclipm_update_property_string(stored_sub_psf_headers[ifu_nr-1],
01567                                                        EXTNAME,
01568                                                        extname,
01569                                                        "FITS extension name"));
01570                     cpl_free(extname); extname = NULL;
01571 
01572                     // create EXTNAME keyword as NOISE
01573                     KMO_TRY_EXIT_IF_NULL(
01574                         stored_sub_tel_noise_headers[ifu_nr-1] =
01575                                 cpl_propertylist_duplicate(
01576                                         stored_sub_tel_data_headers[ifu_nr-1]));
01577 
01578                     KMO_TRY_EXIT_IF_NULL(
01579                         extname = kmo_extname_creator(ifu_frame, ifu_nr, EXT_NOISE));
01580                     KMO_TRY_EXIT_IF_ERROR(
01581                         kmclipm_update_property_string(stored_sub_tel_noise_headers[ifu_nr-1],
01582                                                        EXTNAME,
01583                                                        extname,
01584                                                        "FITS extension name"));
01585                     cpl_free(extname); extname = NULL;
01586                 } // for j ifus (load, process & store)
01587                 cpl_propertylist_delete(sub_header_orig); sub_header_orig = NULL;
01588             } // for i detectors (load, process & store)
01589             KMO_TRY_CHECK_ERROR_STATE();
01590 
01591             // write QC parameter: nr of std stars
01592             KMO_TRY_EXIT_IF_ERROR(
01593                 kmclipm_update_property_int(main_header_tel, QC_NR_STD_STARS,
01594                                         nr_std_stars, "[] Nr. of std stars"));
01595 
01596             // update which IFUs are not used
01597             kmo_print_unused_ifus(unused_ifus_after, TRUE);
01598 
01599             KMO_TRY_EXIT_IF_ERROR(
01600                 kmo_set_unused_ifus(unused_ifus_after, main_header_tel, "kmo_std_star"));
01601 
01602             KMO_TRY_EXIT_IF_NULL(
01603                 main_header_psf = cpl_propertylist_duplicate(main_header_tel));
01604 
01605             if (has_magnitude) {
01606                 // calculate QC THROUGHPUT MEAN and QC THROUGHPUT SDV
01607                 // and update main header
01608                 KMO_TRY_EXIT_IF_ERROR(
01609                     kmo_calc_mean_throughput(stored_qc_throughput,
01610                                              nr_devices * KMOS_IFUS_PER_DETECTOR,
01611                                              &throughput_mean,
01612                                              &throughput_sdv));
01613                 KMO_TRY_EXIT_IF_ERROR(
01614                     kmclipm_update_property_double(main_header_tel,
01615                                                    QC_THROUGHPUT_MEAN,
01616                                                    throughput_mean,
01617                                                    "[] mean throughput for all detectors"));
01618                 KMO_TRY_EXIT_IF_ERROR(
01619                     kmclipm_update_property_double(main_header_tel,
01620                                                    QC_THROUGHPUT_SDV,
01621                                                    throughput_sdv,
01622                                                    "[] stdev throughput for all detectors"));
01623             }
01624             KMO_TRY_CHECK_ERROR_STATE();
01625 
01626             //
01627             // save output data
01628             //
01629 
01630             // save primary extension
01631             cpl_msg_info("","Saving STD exposure No. %d", nr_exp+1);
01632             KMO_TRY_EXIT_IF_ERROR(
01633                 kmo_dfs_save_main_header(frameset, filename_telluric, suffix,
01634                                          obj_frame, main_header_tel, parlist,
01635                                          cpl_func));
01636             KMO_TRY_EXIT_IF_ERROR(
01637                 kmo_dfs_save_main_header(frameset, filename_starspec, suffix,
01638                                          obj_frame, main_header_tel, parlist,
01639                                          cpl_func));
01640             KMO_TRY_EXIT_IF_ERROR(
01641                 kmo_dfs_save_main_header(frameset, filename_mask, suffix,
01642                                          obj_frame, main_header_psf, parlist,
01643                                          cpl_func));
01644             KMO_TRY_EXIT_IF_ERROR(
01645                 kmo_dfs_save_main_header(frameset, filename_psf, suffix,
01646                                          obj_frame, main_header_psf, parlist,
01647                                          cpl_func));
01648             if (save_cubes) {
01649                 KMO_TRY_EXIT_IF_ERROR(
01650                     kmo_dfs_save_main_header(frameset, filename_cubes, suffix,
01651                                              obj_frame, main_header_psf, parlist,
01652                                              cpl_func));
01653             }
01654 
01655             // save stored frames
01656             for (i = 1; i <= nr_devices; i++) {
01657                 for (j = 0; j < KMOS_IFUS_PER_DETECTOR; j++) {
01658                     ifu_nr = (i-1)*KMOS_IFUS_PER_DETECTOR + j + 1;
01659 
01660                     // save telluric-vector
01661 kmclipm_vector *ddd = NULL;
01662 if (stored_telluric_data[ifu_nr-1] != NULL)
01663 ddd = kmclipm_vector_create(cpl_vector_duplicate(stored_telluric_data[ifu_nr-1]));
01664                     KMO_TRY_EXIT_IF_ERROR(
01665                         kmo_dfs_save_vector(ddd, filename_telluric, suffix,
01666                                             stored_sub_tel_data_headers[ifu_nr-1],
01667                                             0./0.));
01668 kmclipm_vector_delete(ddd); ddd =NULL;
01669 
01670 if (stored_telluric_noise[ifu_nr-1] != NULL)
01671 ddd = kmclipm_vector_create(cpl_vector_duplicate(stored_telluric_noise[ifu_nr-1]));
01672                     KMO_TRY_EXIT_IF_ERROR(
01673                         kmo_dfs_save_vector(ddd, filename_telluric, suffix,
01674                                             stored_sub_tel_noise_headers[ifu_nr-1],
01675                                             0./0.));
01676 kmclipm_vector_delete(ddd); ddd =NULL;
01677 
01678                     // save star_spec-vector
01679 if (stored_starspec_data[ifu_nr-1] != NULL)
01680 ddd = kmclipm_vector_create(cpl_vector_duplicate(stored_starspec_data[ifu_nr-1]));
01681                     KMO_TRY_EXIT_IF_ERROR(
01682                         kmo_dfs_save_vector(ddd, filename_starspec, suffix,
01683                                             stored_sub_tel_data_headers[ifu_nr-1],
01684                                             0./0.));
01685 kmclipm_vector_delete(ddd); ddd =NULL;
01686 
01687 if (stored_starspec_noise[ifu_nr-1] != NULL)
01688 ddd = kmclipm_vector_create(cpl_vector_duplicate(stored_starspec_noise[ifu_nr-1]));
01689                     KMO_TRY_EXIT_IF_ERROR(
01690                         kmo_dfs_save_vector(ddd, filename_starspec, suffix,
01691                                             stored_sub_tel_noise_headers[ifu_nr-1],
01692                                             0./0.));
01693 kmclipm_vector_delete(ddd); ddd =NULL;
01694 
01695                     // save psf-image
01696                     KMO_TRY_EXIT_IF_ERROR(
01697                         kmo_dfs_save_image(stored_psf_data[ifu_nr-1],
01698                                            filename_psf, suffix,
01699                                            stored_sub_psf_headers[ifu_nr-1],
01700                                            0./0.));
01701 
01702                     // save mask-image
01703                     KMO_TRY_EXIT_IF_ERROR(
01704                         kmo_dfs_save_image(stored_mask[ifu_nr-1],
01705                                            filename_mask, suffix,
01706                                            stored_sub_psf_headers[ifu_nr-1],
01707                                            0./0.));
01708                     // save reonstructed cubes
01709                     if (save_cubes) {
01710                         KMO_TRY_EXIT_IF_ERROR(
01711                             kmo_dfs_save_cube(stored_data_cube[ifu_nr-1],
01712                                               filename_cubes, suffix,
01713                                               stored_sub_psf_headers[ifu_nr-1],
01714                                               0./0.));
01715                         KMO_TRY_EXIT_IF_ERROR(
01716                             kmo_dfs_save_cube(stored_noise_cube[ifu_nr-1],
01717                                               filename_cubes, suffix,
01718                                               stored_sub_psf_headers[ifu_nr-1],
01719                                               0./0.));
01720                     }
01721                 } // for j ifus (save stored)
01722             } // for i detectors (save stored)
01723             KMO_TRY_CHECK_ERROR_STATE();
01724 
01725 //            // prepare for next STD input frame
01726 //            cpl_propertylist_delete(main_header_tel); main_header_tel = NULL;
01727 //            cpl_propertylist_delete(main_header_psf); main_header_psf = NULL;
01728 //            for (i = 0; i < nr_devices * KMOS_IFUS_PER_DETECTOR; i++) {
01729 //                cpl_vector_delete(stored_telluric_data[i]); stored_telluric_data[i] = NULL;
01730 //                cpl_vector_delete(stored_telluric_noise[i]); stored_telluric_noise[i] = NULL;
01731 //                cpl_vector_delete(stored_starspec_data[i]); stored_starspec_data[i] = NULL;
01732 //                cpl_vector_delete(stored_starspec_noise[i]); stored_starspec_noise[i] = NULL;
01733 //                cpl_image_delete(stored_psf_data[i]); stored_psf_data[i] = NULL;
01734 //                cpl_propertylist_delete(stored_sub_tel_data_headers[i]); stored_sub_tel_data_headers[i] = NULL;
01735 //                cpl_propertylist_delete(stored_sub_tel_noise_headers[i]); stored_sub_tel_noise_headers[i] = NULL;
01736 //                cpl_propertylist_delete(stored_sub_psf_headers[i]); stored_sub_psf_headers[i] = NULL;
01737 //                cpl_image_delete(stored_mask[i]); stored_mask[i] = NULL;
01738 //                cpl_imagelist_delete(stored_data_cube[i]); stored_data_cube[i] = NULL;
01739 //                cpl_imagelist_delete(stored_noise_cube[i]); stored_noise_cube[i] = NULL;
01740 //            }
01741         } // if (frameCnt == 0)
01742     }
01743     KMO_CATCH
01744     {
01745         KMO_CATCH_MSG();
01746         ret_val = -1;
01747     }
01748 
01749     cpl_free(obj_sky_struct); obj_sky_struct = NULL;
01750     kmo_free_fits_desc(&desc1);
01751     kmo_free_fits_desc(&desc2);
01752     kmo_free_unused_ifus(unused_ifus_before); unused_ifus_before = NULL;
01753     kmo_free_unused_ifus(unused_ifus_after); unused_ifus_after = NULL;
01754     cpl_free(bounds); bounds = NULL;
01755     cpl_propertylist_delete(main_header_tel); main_header_tel = NULL;
01756     cpl_propertylist_delete(main_header_psf); main_header_psf = NULL;
01757     cpl_vector_delete(atmos_model); atmos_model = NULL;
01758     cpl_vector_delete(solar_spec); solar_spec = NULL;
01759     cpl_table_delete(spec_type_LUT); spec_type_LUT = NULL;
01760     cpl_vector_delete(identified_slices); identified_slices = NULL;
01761     cpl_propertylist_delete(sub_header_orig); sub_header_orig = NULL;
01762     for (i = 0; i < nr_devices * KMOS_IFUS_PER_DETECTOR; i++) {
01763         cpl_vector_delete(stored_telluric_data[i]); stored_telluric_data[i] = NULL;
01764         cpl_vector_delete(stored_telluric_noise[i]); stored_telluric_noise[i] = NULL;
01765         cpl_vector_delete(stored_starspec_data[i]); stored_starspec_data[i] = NULL;
01766         cpl_vector_delete(stored_starspec_noise[i]); stored_starspec_noise[i] = NULL;
01767         cpl_image_delete(stored_psf_data[i]); stored_psf_data[i] = NULL;
01768         cpl_propertylist_delete(stored_sub_tel_data_headers[i]); stored_sub_tel_data_headers[i] = NULL;
01769         cpl_propertylist_delete(stored_sub_tel_noise_headers[i]); stored_sub_tel_noise_headers[i] = NULL;
01770         cpl_propertylist_delete(stored_sub_psf_headers[i]); stored_sub_psf_headers[i] = NULL;
01771         cpl_image_delete(stored_mask[i]); stored_mask[i] = NULL;
01772         cpl_imagelist_delete(stored_data_cube[i]); stored_data_cube[i] = NULL;
01773         cpl_imagelist_delete(stored_noise_cube[i]); stored_noise_cube[i] = NULL;
01774     }
01775     cpl_free(stored_telluric_data); stored_telluric_data = NULL;
01776     cpl_free(stored_telluric_noise); stored_telluric_noise = NULL;
01777     cpl_free(stored_starspec_data); stored_starspec_data = NULL;
01778     cpl_free(stored_starspec_noise); stored_starspec_noise = NULL;
01779     cpl_free(stored_psf_data); stored_psf_data = NULL;
01780     cpl_free(stored_sub_tel_data_headers); stored_sub_tel_data_headers = NULL;
01781     cpl_free(stored_sub_tel_noise_headers); stored_sub_tel_noise_headers = NULL;
01782     cpl_free(stored_sub_psf_headers); stored_sub_psf_headers = NULL;
01783     cpl_free(stored_qc_throughput); stored_qc_throughput = NULL;
01784     cpl_free(suffix); suffix = NULL;
01785     cpl_free(stored_mask); stored_mask = NULL;
01786     cpl_free(stored_data_cube); stored_data_cube = NULL;
01787     cpl_free(stored_noise_cube); stored_noise_cube = NULL;
01788     cpl_free(grat_id); grat_id = NULL;
01789     cpl_frameset_delete(frameset_std); frameset_std = NULL;
01790 
01791     return ret_val;
01792 }
01793