KMOS Pipeline Reference Manual  1.3.16
kmos_std_star.c
00001 /* 
00002  * This file is part of the KMOS Pipeline
00003  * Copyright (C) 2002,2003 European Southern Observatory
00004  *
00005  * This program is free software; you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License as published by
00007  * the Free Software Foundation; either version 2 of the License, or
00008  * (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program; if not, write to the Free Software
00017  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018  */
00019 
00020 #ifdef HAVE_CONFIG_H
00021 #include <config.h>
00022 #endif
00023 
00024 /*-----------------------------------------------------------------------------
00025  *                              Includes
00026  *----------------------------------------------------------------------------*/
00027 
00028 #include <math.h>
00029 #include <string.h>
00030 
00031 #include <cpl.h>
00032 
00033 #include "kmclipm_math.h"
00034 
00035 #include "kmo_constants.h"
00036 #include "kmo_cpl_extensions.h"
00037 #include "kmo_utils.h"
00038 #include "kmo_functions.h"
00039 #include "kmo_priv_std_star.h"
00040 #include "kmo_priv_fit_profile.h"
00041 #include "kmo_priv_extract_spec.h"
00042 #include "kmo_priv_functions.h"
00043 #include "kmo_dfs.h"
00044 #include "kmo_error.h"
00045 #include "kmo_debug.h"
00046 #include "kmo_priv_reconstruct.h"
00047 
00048 const int       nr_lines_h = 10;
00049 const double    lines_center_h[] = {
00050     1.7001,     // HeI          // triplet
00051     1.53429,    // Br-18
00052     1.54400,    // Br-17
00053     1.55576,    // Br-16
00054     1.57018,    // Br-15
00055     1.58817,    // Br-14
00056     1.61105,    // Br-13
00057     1.64084,    // Br-12
00058     1.68077,    // Br-11
00059     1.73634     // Br-10
00060 };
00061 const double    lines_width_h[] = {
00062     0.025,      // HeI
00063     0.003,      // Br-18
00064     0.015,      // Br-17
00065     0.015,      // Br-16
00066     0.015,      // Br-15
00067     0.025,      // Br-14
00068     0.015,      // Br-13
00069     0.025,      // Br-12
00070     0.025,      // Br-11
00071     0.05        // Br-10
00072 };
00073 const int       nr_lines_k = 2;
00074 const double    lines_center_k[] = {
00075     2.1120,     // HeI          // triplet
00076     2.16569     // Br-gamma
00077 };
00078 const double lines_width_k[] = {
00079     0.01,       // HeI          // triplet
00080     0.015       // Br-gamma
00081 };
00082 const int       nr_lines_hk = 12;
00083 const double    lines_center_hk[] = {
00084     1.7001,     // HeI          // triplet
00085     1.53429,    // Br-18
00086     1.54400,    // Br-17
00087     1.55576,    // Br-16
00088     1.57018,    // Br-15
00089     1.58817,    // Br-14
00090     1.61105,    // Br-13
00091     1.64084,    // Br-12
00092     1.68077,    // Br-11
00093     1.73634,    // Br-10
00094     2.1120,     // HeI          // triplet
00095     2.16569     // Br-gamma
00096 };
00097 const double lines_width_hk[] = {
00098     0.025,      // HeI
00099     0.003,      // Br-18
00100     0.015,      // Br-17
00101     0.015,      // Br-16
00102     0.015,      // Br-15
00103     0.025,      // Br-14
00104     0.015,      // Br-13
00105     0.025,      // Br-12
00106     0.025,      // Br-11
00107     0.05,       // Br-10
00108     0.015,      // HeI          // triplet
00109     0.015       // Br-gamma
00110 };
00111 const int       nr_lines_iz = 12;
00112 const double    lines_center_iz[] = {
00113     0.84386,    // Pa-18
00114     0.84679,    // Pa-17
00115     0.85031,    // Pa-16
00116     0.85460,    // Pa-15
00117     0.85990,    // Pa-14
00118     0.86657,    // Pa-13
00119     0.87511,    // Pa-12
00120     0.88635,    // Pa-11
00121     0.90156,    // Pa-10
00122     0.92297,    // Pa-9
00123     0.95467,    // Pa-epsilon
00124     1.00501     // Pa-delta
00125 };
00126 const double    lines_width_iz[] = {
00127     0.0008,     // Pa-18
00128     0.003225,   // Pa-17
00129     0.0039,     // Pa-16
00130     0.0048,     // Pa-15
00131     0.006,      // Pa-14
00132     0.0076,     // Pa-13
00133     0.001,      // Pa-12
00134     0.013,      // Pa-11
00135     0.01,       // Pa-10
00136     0.013,      // Pa-9
00137     0.02,       // Pa-epsilon
00138     0.025       // Pa-delta
00139 };
00140 const int       nr_lines_yj = 7;
00141 const double    lines_center_yj[] = {
00142     1.08331,    // HeI
00143     1.09160,    // HeI
00144     1.09389,    // Pa-gamma
00145     1.19723,    // HeI
00146     1.28191,    // Pa-beta
00147     1.27882,    // HeI
00148     1.29720     // HeI
00149 };
00150 const double    lines_width_yj[] = {
00151     .01,        //0.005,    // HeI
00152     .01,        //0.002,    // HeI
00153     0.02,       // Pa-gamma
00154     0.003,      // HeI
00155     0.02,       // Pa-beta
00156     0.0025,     // HeI
00157     0.002       // HeI
00158 };
00159 
00160 /*-----------------------------------------------------------------------------
00161  *                          Functions prototypes
00162  *----------------------------------------------------------------------------*/
00163 
00164 static int kmos_std_star_compute_ifu(
00165         cpl_propertylist    *   sub_header_orig,
00166         cpl_frame           *   obj_frame,
00167         cpl_frame           *   sky_frame,
00168         cpl_frame           *   flat_frame,
00169         cpl_frame           *   xcal_frame,
00170         cpl_frame           *   ycal_frame,
00171         cpl_frame           *   lcal_frame,
00172         cpl_frame           *   illum_frame,
00173         cpl_frame           *   atmos_frame,
00174         cpl_frame           *   solar_frame,
00175         int                     ifu_nr,
00176         cpl_propertylist    *   main_header_tel,
00177         gridDefinition          gd,
00178         int                     low_bound,
00179         int                     high_bound,
00180         const char          *   fmethod,
00181         int                     flux,
00182         int                     xcal_interpolation,
00183         const char          *   mask_method,
00184         const char          *   cmethod,
00185         double                  cpos_rej,
00186         double                  cneg_rej,
00187         int                     citer,
00188         int                     cmax,
00189         int                     cmin,
00190         double                  cen_x,
00191         double                  cen_y,
00192         double                  radius,
00193         const char          *   filter_id,
00194         char                    star_type,
00195         int                     no_noise,
00196         int                     is_stdstarscipatt,
00197         skySkyStruct            sky_sky_struct,
00198         double                  star_temp,
00199         cpl_vector          **  spec_qc,
00200         cpl_propertylist    **  out_sub_tel_data_header,
00201         cpl_propertylist    **  out_sub_psf_header,
00202         cpl_propertylist    **  out_sub_cube_data_header,
00203         cpl_imagelist       **  out_data_cube,
00204         cpl_imagelist       **  out_noise_cube,
00205         cpl_image           **  out_psf_data,
00206         cpl_image           **  out_mask,
00207         cpl_vector          **  out_starspec_data,
00208         cpl_vector          **  out_starspec_noise,
00209         cpl_vector          **  out_noisespec,
00210         cpl_vector          **  out_telluric_data,
00211         cpl_vector          **  out_telluric_noise) ;
00212 static int kmos_std_star_check_inputs(
00213         cpl_frameset            *   frameset,
00214         const char              *   magnitude_txt,
00215         int                     *   is_stdstarscipatt,
00216         int                     *   compute_qcs,
00217         double                  *   magnitude1,
00218         double                  *   magnitude2) ;
00219 static int kmos_std_star_plot(void) ;
00220 static int kmos_std_star_adjust_double(
00221         cpl_propertylist    *   header,
00222         const char          *   key1,
00223         const char          *   key2,
00224         const char          *   key3) ;
00225 static int kmos_std_star_adjust_string(
00226         cpl_propertylist    *   header,
00227         const char          *   key1,
00228         const char          *   key2,
00229         const char          *   key3) ;
00230 static cpl_frameset * kmos_std_star_extract_same_grat_stds(
00231         cpl_frameset        *   in,
00232         int                 *   same_gratings) ;
00233 
00234 static int kmos_std_star_create(cpl_plugin *);
00235 static int kmos_std_star_exec(cpl_plugin *);
00236 static int kmos_std_star_destroy(cpl_plugin *);
00237 static int kmos_std_star(cpl_parameterlist *, cpl_frameset *);
00238 
00239 /*-----------------------------------------------------------------------------
00240  *                          Static variables
00241  *----------------------------------------------------------------------------*/
00242 
00243 static char kmos_std_star_description[] =
00244 "This recipe creates a telluric frame and a PSF frames.\n"
00245 "Since there cannot be 1 std star per IFU in one exposure, we use several\n"
00246 "exposures in order to have at least one standard star and one sky\n"
00247 "in each IFU. The frames are organised following this logic:\n"
00248 "1. For each IFU the first standard star in the list of frames is\n"
00249 "   taken. All subsequent standard star exposures for this IFU are ignored\n"
00250 "2. A closest in time sky exposure is uѕed\n"
00251 "3. IFUs not containing a standard star and a sky will be empty in the result\n"
00252 "\n"
00253 "NOISE_SPEC contains the shot noise [sqrt(counts*gain)/gain]\n"
00254 "If the exposures have been taken with KMOS_spec_cal_stdstarscipatt, an\n"
00255 "additional noise component is added: All existing sky exposures for an IFU\n"
00256 "are subtracted pairwise, spectra are extracted and the std deviation is \n"
00257 "computed\n"
00258 "\n"
00259 "-------------------------------------------------------------------------------\n"
00260 "  Input files:\n"
00261 "\n"
00262 "   DO                      KMOS                                             \n"
00263 "   category                Type  Explanation                Required #Frames\n"
00264 "   --------                ----- -----------                -------- -------\n"
00265 "   STD                     RAW   Std. star & sky exposures      Y     >=1   \n"
00266 "   XCAL                    F2D   x calibration frame            Y      1    \n"
00267 "   YCAL                    F2D   y calibration frame            Y      1    \n"
00268 "   LCAL                    F2D   Wavelength calib. frame        Y      1    \n"
00269 "   MASTER_FLAT             F2D   Master flat frame              Y      1    \n"
00270 "   WAVE_BAND               F2L   Table with start-/end-wl       Y      1    \n"
00271 "   ILLUM_CORR              F2I   Illumination correction        N     0,1   \n"
00272 "   SOLAR_SPEC              F1S   Solar spectrum                 N     0,1   \n"
00273 "                                 (only for G stars)                         \n"
00274 "   ATMOS_MODEL             F1S   Model atmospheric transmisson  N     0,1   \n"
00275 "                                 (only for OBAF stars in K band)            \n"
00276 "   SPEC_TYPE_LOOKUP        F2L   LUT  eff. stellar temperature  N     0,1   \n"
00277 "\n"
00278 "  Output files:                                                            \n"
00279 "\n"
00280 "   DO                      KMOS                                            \n"
00281 "   category                Type   Explanation                              \n"
00282 "   --------                -----  -----------                              \n"
00283 "   TELLURIC                F1I    The normalised telluric spectrum         \n"
00284 "                                  (including errors)                       \n"
00285 "   STAR_SPEC               F1I    The extracted star spectrum              \n"
00286 "                                  (including errors)                       \n"
00287 "   STD_IMAGE               F2I    The standard star PSF images             \n"
00288 "   STD_MASK                F2I    The mask used to extract the star spec   \n"
00289 "   NOISE_SPEC              F1I    The extracted noise spectrum             \n"
00290 "---------------------------------------------------------------------------\n"
00291 "\n";
00292 
00293 /*-----------------------------------------------------------------------------
00294  *                              Functions code
00295  *----------------------------------------------------------------------------*/
00296 
00297 /*----------------------------------------------------------------------------*/
00301 /*----------------------------------------------------------------------------*/
00302 
00305 /*----------------------------------------------------------------------------*/
00314 /*----------------------------------------------------------------------------*/
00315 int cpl_plugin_get_info(cpl_pluginlist *list)
00316 {
00317     cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe);
00318     cpl_plugin *plugin = &recipe->interface;
00319 
00320     cpl_plugin_init(plugin,
00321             CPL_PLUGIN_API,
00322             KMOS_BINARY_VERSION,
00323             CPL_PLUGIN_TYPE_RECIPE,
00324             "kmos_std_star",
00325             "Create the telluric correction frame.",
00326             kmos_std_star_description,
00327             "Alex Agudo Berbel, Y. Jung",
00328             "usd-help@eso.org",
00329             kmos_get_license(),
00330             kmos_std_star_create,
00331             kmos_std_star_exec,
00332             kmos_std_star_destroy);
00333     cpl_pluginlist_append(list, plugin);
00334 
00335     return 0;
00336 }
00337 
00338 /*----------------------------------------------------------------------------*/
00346 /*----------------------------------------------------------------------------*/
00347 static int kmos_std_star_create(cpl_plugin *plugin)
00348 {
00349     cpl_recipe *recipe;
00350     cpl_parameter *p;
00351 
00352     /* Check that the plugin is part of a valid recipe */
00353     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00354         recipe = (cpl_recipe *)plugin;
00355     else
00356         return -1;
00357 
00358     /* Create the parameters list in the cpl_recipe object */
00359     recipe->parameters = cpl_parameterlist_new();
00360 
00361     /* --startype */
00362     p = cpl_parameter_new_value("kmos.kmos_std_star.startype", CPL_TYPE_STRING,
00363             "The spectral type of the star (O, B, A, F, G) e.g. G4V",
00364             "kmos.kmos_std_star", "");
00365     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "startype");
00366     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00367     cpl_parameterlist_append(recipe->parameters, p);
00368 
00369     /* --imethod */
00370     p = cpl_parameter_new_value("kmos.kmos_std_star.imethod", CPL_TYPE_STRING,
00371             "Method to use for interpolation. "
00372             "[\"NN\" (nearest neighbour), "
00373             "\"lwNN\" (linear weighted nearest neighbor), "
00374             "\"swNN\" (square weighted nearest neighbor), "
00375             "\"MS\" (Modified Shepard's method), "
00376             "\"CS\" (Cubic spline)]",
00377             "kmos.kmos_std_star", "CS");
00378     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "imethod");
00379     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00380     cpl_parameterlist_append(recipe->parameters, p);
00381 
00382     /* --fmethod */
00383     p = cpl_parameter_new_value("kmos.kmos_std_star.fmethod", CPL_TYPE_STRING,
00384             "Fitting method (gauss, moffat, profile", "kmos.kmos_std_star",
00385             "gauss");
00386     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "fmethod");
00387     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00388     cpl_parameterlist_append(recipe->parameters, p);
00389 
00390     /* --neighborhoodRange */
00391     p = cpl_parameter_new_value("kmos.kmos_std_star.neighborhoodRange",
00392             CPL_TYPE_DOUBLE,
00393             "Defines the range to search for neighbors in pixels",
00394             "kmos.kmos_std_star", 1.001);
00395     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "neighborhoodRange");
00396     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00397     cpl_parameterlist_append(recipe->parameters, p);
00398 
00399     /* --magnitude */
00400     p = cpl_parameter_new_value("kmos.kmos_std_star.magnitude", CPL_TYPE_STRING,
00401             "Star magnitude (2 values in HK, eg. 12.1,13.2)",
00402             "kmos.kmos_std_star", "");
00403     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "magnitude");
00404     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00405     cpl_parameterlist_append(recipe->parameters, p);
00406 
00407     /* --flux */
00408     p = cpl_parameter_new_value("kmos.kmos_std_star.flux", CPL_TYPE_BOOL,
00409             "TRUE: Apply flux conservation. FALSE: otherwise",
00410             "kmos.kmos_std_star", TRUE);
00411     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "flux");
00412     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00413     cpl_parameterlist_append(recipe->parameters, p);
00414 
00415     /* --save_cubes */
00416     p = cpl_parameter_new_value("kmos.kmos_std_star.save_cubes", CPL_TYPE_BOOL,
00417             "Flag to save reconstructed cubes", "kmos.kmos_std_star", FALSE);
00418     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "save_cubes");
00419     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00420     cpl_parameterlist_append(recipe->parameters, p);
00421 
00422     /* --no_noise */
00423     p = cpl_parameter_new_value("kmos.kmos_std_star.no_noise", CPL_TYPE_BOOL,
00424             "Skip the noise computation on sky exposures", "kmos.kmos_std_star",
00425             FALSE);
00426     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "no_noise");
00427     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00428     cpl_parameterlist_append(recipe->parameters, p);
00429 
00430     /* --xcal_interpolation */
00431     p = cpl_parameter_new_value("kmos.kmos_std_star.xcal_interpolation",
00432             CPL_TYPE_BOOL, "Flag to Interpolate xcal between rotator angles",
00433             "kmos.kmos_std_star", TRUE);
00434     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "xcal_interpolation");
00435     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00436     cpl_parameterlist_append(recipe->parameters, p);
00437 
00438     /* --suppress_extension */
00439     p = cpl_parameter_new_value("kmos.kmos_std_star.suppress_extension",
00440             CPL_TYPE_BOOL, "Flag to Suppress filename extension",
00441             "kmos.kmos_std_star", FALSE);
00442     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "suppress_extension");
00443     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00444     cpl_parameterlist_append(recipe->parameters, p);
00445 
00446     /* Add parameters for band-definition */
00447     kmos_band_pars_create(recipe->parameters, "kmos.kmos_std_star");
00448 
00449     /* --mask_method */
00450     p = cpl_parameter_new_value("kmos.kmos_std_star.mask_method",
00451             CPL_TYPE_STRING, "Method used : mask, integrated or optimal",
00452             "kmos.kmos_std_star", "optimal");
00453     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "mask_method");
00454     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00455     cpl_parameterlist_append(recipe->parameters, p);
00456 
00457     /* --centre */
00458     p = cpl_parameter_new_value("kmos.kmos_std_star.centre",
00459             CPL_TYPE_STRING, "The centre of the circular mask (pixel)",
00460             "kmos.kmos_std_star", "7.5,7.5");
00461     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "centre");
00462     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00463     cpl_parameterlist_append(recipe->parameters, p);
00464 
00465     /* --radius */
00466     p = cpl_parameter_new_value("kmos.kmos_std_star.radius",
00467             CPL_TYPE_DOUBLE, "The radius of the circular mask (pixel)",
00468             "kmos.kmos_std_star", 3.0);
00469     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "radius");
00470     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00471     cpl_parameterlist_append(recipe->parameters, p);
00472 
00473     /* Add parameters for combining */
00474     return kmos_combine_pars_create(recipe->parameters, "kmos.kmos_std_star",
00475             DEF_REJ_METHOD, FALSE);
00476 }
00477 
00478 /*----------------------------------------------------------------------------*/
00484 /*----------------------------------------------------------------------------*/
00485 static int kmos_std_star_exec(cpl_plugin *plugin)
00486 {
00487     cpl_recipe  *recipe;
00488 
00489     /* Get the recipe out of the plugin */
00490     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00491         recipe = (cpl_recipe *)plugin;
00492     else return -1;
00493 
00494     return kmos_std_star(recipe->parameters, recipe->frames);
00495 }
00496 
00497 /*----------------------------------------------------------------------------*/
00503 /*----------------------------------------------------------------------------*/
00504 static int kmos_std_star_destroy(cpl_plugin *plugin)
00505 {
00506     cpl_recipe *recipe;
00507 
00508     /* Get the recipe out of the plugin */
00509     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00510         recipe = (cpl_recipe *)plugin;
00511     else return -1 ;
00512 
00513     cpl_parameterlist_delete(recipe->parameters);
00514     return 0 ;
00515 }
00516 
00517 /*----------------------------------------------------------------------------*/
00530 /*----------------------------------------------------------------------------*/
00531 static int kmos_std_star(cpl_parameterlist *parlist, cpl_frameset *frameset)
00532 {
00533     const cpl_parameter *   par ;
00534     /*********************/
00535     /* Parsed Parameters */
00536     const char          *   imethod ;        
00537     const char          *   cmethod ;        
00538     const char          *   fmethod ;        
00539     const char          *   mask_method ;        
00540     const char          *   centre_txt ;
00541     cpl_vector          *   centre ;
00542     const char          *   spec_type ;        
00543     const char          *   magnitude_txt ;        
00544     double                  cpos_rej, cneg_rej, neighborhoodRange, cen_x, cen_y,
00545                             radius ;
00546     int                     flux, save_cubes, no_noise, citer, cmin, cmax,
00547                             xcal_interpolation, suppress_extension ;
00548     /*********************/
00549     char                *   suffix ;
00550     char                *   keyword ;
00551     char                *   extname ;
00552     char                *   fn_suffix ;
00553     const char          *   filter_id ;
00554     cpl_array           **  unused_ifus_before ;
00555     cpl_array           **  unused_ifus_after ;
00556     const int           *   punused_ifus ;
00557     gridDefinition          gd;
00558     cpl_propertylist    *   tmp_header ;
00559     cpl_propertylist    *   main_header_tel ;
00560     cpl_propertylist    *   sub_header_orig ;
00561     cpl_propertylist    *   main_header_psf ;
00562     int                 *   bounds ;
00563     objSkyStruct        *   obj_sky_struct ;
00564     skySkyStruct        *   sky_sky_struct ;
00565 
00566     cpl_imagelist       **  stored_data_cube ;
00567     cpl_imagelist       **  stored_noise_cube ;
00568     cpl_image           **  stored_psf_data ;
00569     cpl_image           **  stored_mask ;
00570     cpl_vector          **  stored_telluric_data ;
00571     cpl_vector          **  stored_telluric_noise ;
00572     cpl_vector          **  stored_starspec_data ;
00573     cpl_vector          **  stored_starspec_noise ;
00574     cpl_vector          **  stored_noisespec ;
00575     double              *   stored_qc_throughput ;
00576     cpl_propertylist    **  stored_sub_tel_data_headers ;
00577     cpl_propertylist    **  stored_sub_tel_noise_headers ;
00578     cpl_propertylist    **  stored_sub_cube_data_headers ;
00579     cpl_propertylist    **  stored_sub_cube_noise_headers ;
00580     cpl_propertylist    **  stored_sub_psf_headers ;
00581     char                    filename_telluric[256],
00582                             filename_starspec[256],
00583                             filename_psf[256],
00584                             filename_mask[256],
00585                             filename_cubes[256],
00586                             filename_noise[256] ;
00587     cpl_frame           *   obj_frame ;
00588     cpl_frame           *   sky_frame ;
00589     cpl_frame           *   xcal_frame ;
00590     cpl_frame           *   ycal_frame ;
00591     cpl_frame           *   lcal_frame ;
00592     cpl_frame           *   flat_frame ;
00593     cpl_frame           *   illum_frame ;
00594     cpl_frame           *   solar_frame ;
00595     cpl_frame           *   atmos_frame ;
00596     cpl_table           *   band_table ;
00597     cpl_frameset        *   frameset_std ;
00598     cpl_vector          *   spec_qc ;
00599     int                     is_stdstarscipatt, compute_qcs,
00600                             ifu_nr, nifus, nr_std_stars ;
00601     double                  magnitude1, magnitude2, star_temp, exptime, 
00602                             throughput_mean, throughput_sdv, cdelt1, crpix1, 
00603                             crval1, zeropoint, tmp_data, tmp_noise, counts1, 
00604                             counts2, gain ;
00605     char                    star_type ;
00606     kmclipm_vector      *   ddd  ;
00607     int                     i, j ;
00608     
00609     /* Initialise */
00610     nr_std_stars = 0 ;
00611     zeropoint = throughput_mean = throughput_sdv = -1.0 ;
00612     magnitude1 = magnitude2 = -1.0 ;
00613 
00614     /* Check entries */
00615     if (parlist == NULL || frameset == NULL) {
00616         cpl_msg_error(__func__, "Null Inputs") ;
00617         cpl_error_set(__func__, CPL_ERROR_NULL_INPUT) ;
00618         return -1 ;
00619     }
00620 
00621     /* Get parameters */
00622     par = cpl_parameterlist_find_const(parlist, "kmos.kmos_std_star.imethod");
00623     imethod = cpl_parameter_get_string(par) ;
00624     par = cpl_parameterlist_find_const(parlist, "kmos.kmos_std_star.startype");
00625     spec_type = cpl_parameter_get_string(par) ;
00626     par = cpl_parameterlist_find_const(parlist, "kmos.kmos_std_star.fmethod");
00627     fmethod = cpl_parameter_get_string(par) ;
00628     par = cpl_parameterlist_find_const(parlist,
00629             "kmos.kmos_std_star.neighborhoodRange");
00630     neighborhoodRange = cpl_parameter_get_double(par) ;
00631     par = cpl_parameterlist_find_const(parlist, "kmos.kmos_std_star.magnitude");
00632     magnitude_txt = cpl_parameter_get_string(par) ;
00633     par = cpl_parameterlist_find_const(parlist, "kmos.kmos_std_star.flux");
00634     flux = cpl_parameter_get_bool(par);
00635     par = cpl_parameterlist_find_const(parlist,"kmos.kmos_std_star.save_cubes");
00636     save_cubes = cpl_parameter_get_bool(par);
00637     par = cpl_parameterlist_find_const(parlist, "kmos.kmos_std_star.no_noise");
00638     no_noise = cpl_parameter_get_bool(par);
00639     par = cpl_parameterlist_find_const(parlist,
00640         "kmos.kmos_std_star.xcal_interpolation");
00641     xcal_interpolation = cpl_parameter_get_bool(par);
00642     par = cpl_parameterlist_find_const(parlist,
00643         "kmos.kmos_std_star.suppress_extension");
00644     suppress_extension = cpl_parameter_get_bool(par);
00645     kmos_band_pars_load(parlist, "kmos.kmos_std_star");
00646     par = cpl_parameterlist_find_const(parlist,
00647             "kmos.kmos_std_star.mask_method");
00648     mask_method = cpl_parameter_get_string(par) ;
00649     if (!strcmp(mask_method, "integrated")) {
00650         par = cpl_parameterlist_find_const(parlist,"kmos.kmos_std_star.centre");
00651         centre_txt = cpl_parameter_get_string(par) ;
00652         centre = kmo_identify_ranges(centre_txt);
00653         if (cpl_vector_get_size(centre) != 2) {
00654             cpl_msg_error(__func__, "centre must have 2 values like a,b") ;
00655             cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
00656             return -1 ;
00657         }
00658         cen_x = cpl_vector_get(centre, 0);
00659         cen_y = cpl_vector_get(centre, 1);
00660         cpl_vector_delete(centre);
00661         par = cpl_parameterlist_find_const(parlist,"kmos.kmos_std_star.radius");
00662         radius = cpl_parameter_get_double(par) ;
00663         if (radius < 0.0) {
00664             cpl_msg_error(__func__, "radius must be greater than 0.0") ;
00665             cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
00666             return -1 ;
00667         }
00668     } else if (strcmp(mask_method, "optimal")) {
00669         cpl_msg_error(__func__, "Unsupported mask method: %s", mask_method) ;
00670         cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
00671         return -1 ;
00672     }
00673     kmos_combine_pars_load(parlist, "kmos.kmos_std_star", &cmethod,
00674             &cpos_rej, &cneg_rej, &citer, &cmin, &cmax, FALSE);
00675 
00676     /* Check Parameters */
00677     if (strcmp(cmethod, "average") && strcmp(cmethod, "median") &&
00678             strcmp(cmethod, "sum") && strcmp(cmethod, "min_max") &&
00679             strcmp(cmethod, "ksigma")) {
00680         cpl_msg_error(__func__, 
00681                 "cmethod must be average median sum min_max or ksigma") ;
00682         cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
00683         return -1 ;
00684     }
00685     if (strcmp(imethod, "NN") && strcmp(imethod, "lwNN") &&
00686             strcmp(imethod, "swNN") && strcmp(imethod, "MS") &&
00687             strcmp(imethod, "CS")) {
00688         cpl_msg_error(__func__, "imethod must be NN,lwNN,swNN,MS or CS") ;
00689         cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
00690         return -1 ;
00691     }
00692     if (strcmp(fmethod, "gauss") && strcmp(fmethod, "moffat")) {
00693         cpl_msg_error(__func__, "fmethod must be gauss or moffat") ;
00694         cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
00695         return -1 ;
00696     }
00697     if (neighborhoodRange <= 0.0) {
00698         cpl_msg_error(__func__, "neighborhoodRange must be greater than 0.0") ;
00699         cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
00700         return -1 ;
00701     }
00702 
00703     /* Identify the RAW and CALIB frames in the input frameset */
00704     if (kmo_dfs_set_groups(frameset, "kmos_std_star") != 1) {
00705         cpl_msg_error(__func__, "Cannot identify RAW and CALIB frames") ;
00706         cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
00707         return -1 ;
00708     }
00709 
00710     /* Check the inputs consistency */
00711     if (kmos_std_star_check_inputs(frameset, magnitude_txt, &is_stdstarscipatt,
00712                 &compute_qcs, &magnitude1, &magnitude2) != 1) {
00713         cpl_msg_error(__func__, "Input frameset is not consistent") ;
00714         cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
00715         return -1 ;
00716     }
00717     
00718     /* Instrument setup */
00719     suffix = kmo_dfs_get_suffix(kmo_dfs_get_frame(frameset, STD), TRUE, FALSE);
00720     cpl_msg_info("", "Detected instrument setup:   %s", suffix+1);
00721 
00722     /* Check which IFUs are active for all frames */
00723     unused_ifus_before = kmo_get_unused_ifus(frameset, 0, 0);
00724     unused_ifus_after = kmo_duplicate_unused_ifus(unused_ifus_before);
00725     kmo_print_unused_ifus(unused_ifus_before, FALSE);
00726     kmo_free_unused_ifus(unused_ifus_before);
00727 
00728     /* Setup grid definition, wavelength start and end are set later */
00729     kmclipm_setup_grid(&gd, imethod, neighborhoodRange, KMOS_PIX_RESOLUTION,0.);
00730 
00731     /* Get left and right bounds of IFUs from XCAL */
00732     tmp_header = kmo_dfs_load_primary_header(frameset, XCAL);
00733     bounds = kmclipm_extract_bounds(tmp_header);
00734     cpl_propertylist_delete(tmp_header);
00735 
00736     /* Extract STD frames */
00737     frameset_std = kmos_std_star_extract_same_grat_stds(frameset, &i) ;
00738 
00739     /* Get valid STD frames with objects in it and associated sky exposures */
00740     obj_sky_struct = kmo_create_objSkyStruct(frameset_std, STD, FALSE);
00741     kmo_print_objSkyStruct(obj_sky_struct);
00742 
00743     /* Check if there is at least 1 object  */
00744     if (obj_sky_struct->size == 0) {
00745         cpl_free(suffix); 
00746         cpl_free(bounds); 
00747         kmo_free_unused_ifus(unused_ifus_after);
00748         cpl_frameset_delete(frameset_std) ;
00749         cpl_msg_error(cpl_func, "No Object found");
00750         cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
00751         return -1 ;
00752     }
00753 
00754     /* Identify sky-sky-pairs for NOISE_SPEC calculation */
00755     sky_sky_struct = kmo_create_skySkyStruct(frameset_std);
00756 
00757     /* Get frame */
00758     illum_frame = kmo_dfs_get_frame(frameset, ILLUM_CORR);
00759     flat_frame = kmo_dfs_get_frame(frameset, MASTER_FLAT);
00760     xcal_frame = kmo_dfs_get_frame(frameset, XCAL) ;
00761     ycal_frame = kmo_dfs_get_frame(frameset, YCAL) ;
00762     lcal_frame = kmo_dfs_get_frame(frameset, LCAL) ;
00763     atmos_frame = kmo_dfs_get_frame(frameset, ATMOS_MODEL);
00764     solar_frame = kmo_dfs_get_frame(frameset, SOLAR_SPEC);
00765 
00766     /* Allocate intermediate memory */
00767     nifus = KMOS_NR_DETECTORS * KMOS_IFUS_PER_DETECTOR ;
00768     stored_telluric_data = (cpl_vector**)cpl_calloc(nifus, sizeof(cpl_vector*));
00769     stored_telluric_noise = (cpl_vector**)cpl_calloc(nifus,sizeof(cpl_vector*));
00770     stored_starspec_data = (cpl_vector**)cpl_calloc(nifus, sizeof(cpl_vector*));
00771     stored_starspec_noise = (cpl_vector**)cpl_calloc(nifus,sizeof(cpl_vector*));
00772     stored_psf_data = (cpl_image**)cpl_calloc(nifus, sizeof(cpl_image*));
00773     stored_mask = (cpl_image**)cpl_calloc(nifus, sizeof(cpl_image*));
00774     stored_data_cube =(cpl_imagelist**)cpl_calloc(nifus,sizeof(cpl_imagelist*));
00775     stored_noise_cube=(cpl_imagelist**)cpl_calloc(nifus,sizeof(cpl_imagelist*));
00776     stored_qc_throughput = (double*)cpl_calloc(nifus, sizeof(double));
00777     stored_sub_psf_headers = (cpl_propertylist**)cpl_calloc(nifus, 
00778             sizeof(cpl_propertylist*));
00779     stored_sub_tel_data_headers = (cpl_propertylist**)cpl_calloc(nifus, 
00780             sizeof(cpl_propertylist*));
00781     stored_sub_tel_noise_headers = (cpl_propertylist**)cpl_calloc(nifus, 
00782             sizeof(cpl_propertylist*));
00783     stored_sub_cube_data_headers = (cpl_propertylist**)cpl_calloc(nifus, 
00784             sizeof(cpl_propertylist*));
00785     stored_sub_cube_noise_headers=(cpl_propertylist**)cpl_calloc(nifus, 
00786             sizeof(cpl_propertylist*));
00787     stored_noisespec = (cpl_vector**)cpl_calloc(nifus, sizeof(cpl_vector*));
00788 
00789     strcpy(filename_telluric, TELLURIC);
00790     strcpy(filename_starspec, STAR_SPEC);
00791     strcpy(filename_psf, STD_IMAGE);
00792     strcpy(filename_mask, STD_MASK);
00793     strcpy(filename_cubes, STD_CUBE);
00794     strcpy(filename_noise, NOISE_SPEC);
00795 
00796     /*
00797     cpl_free(stored_telluric_data);
00798     cpl_free(stored_telluric_noise);
00799     cpl_free(stored_starspec_data);
00800     cpl_free(stored_starspec_noise); 
00801     cpl_free(stored_psf_data);
00802     cpl_free(stored_sub_tel_data_headers);
00803     cpl_free(stored_sub_tel_noise_headers);
00804     cpl_free(stored_noisespec);
00805     cpl_free(stored_sub_cube_data_headers);
00806     cpl_free(stored_sub_cube_noise_headers);
00807     cpl_free(stored_sub_psf_headers);
00808     cpl_free(stored_mask);
00809     cpl_free(stored_data_cube);
00810     cpl_free(stored_noise_cube);
00811     cpl_free(stored_qc_throughput) ;
00812     kmo_delete_objSkyStruct(obj_sky_struct);
00813     kmo_delete_skySkyStruct(sky_sky_struct);
00814     cpl_free(suffix); 
00815     cpl_free(bounds); 
00816     kmo_free_unused_ifus(unused_ifus_after);
00817     cpl_frameset_delete(frameset_std) ;
00818     return 0 ;
00819     */
00820 
00821     /* Get the first frame containing object */
00822     obj_frame = obj_sky_struct->table[0].objFrame;
00823     main_header_tel = kmclipm_propertylist_load(
00824             cpl_frame_get_filename(obj_frame), 0);
00825     exptime = cpl_propertylist_get_double(main_header_tel, EXPTIME);
00826 
00827     /* Get the star temperature */
00828     star_temp = kmos_get_temperature(frameset, spec_type, &star_type) ; 
00829 
00830     /* Loop on detectors */
00831     for (i = 1; i <= KMOS_NR_DETECTORS ; i++) {
00832         print_cal_angle_msg_once = FALSE;
00833         print_xcal_angle_msg_once = FALSE;
00834         if (i==1) {
00835             print_cal_angle_msg_once = TRUE;
00836             print_xcal_angle_msg_once = TRUE;
00837         }
00838 
00839         /* Get filter for this detector ESO INS FILTi ID */
00840         keyword = cpl_sprintf("%s%d%s", IFU_FILTID_PREFIX, i, 
00841                 IFU_FILTID_POSTFIX);
00842         filter_id = cpl_propertylist_get_string(main_header_tel, keyword);
00843         cpl_free(keyword);
00844 
00845         band_table = kmo_dfs_load_table(frameset, WAVE_BAND, 1, 0);
00846         kmclipm_setup_grid_band_lcal(&gd, filter_id, band_table);
00847         cpl_table_delete(band_table); 
00848 
00849         /* Load extension header */
00850         sub_header_orig = kmclipm_propertylist_load(
00851                 cpl_frame_get_filename(obj_frame), i);
00852 
00853         /* Loop on IFUs */
00854         for (j = 0; j < KMOS_IFUS_PER_DETECTOR; j++) {
00855             ifu_nr = (i-1)*KMOS_IFUS_PER_DETECTOR + j + 1;
00856 
00857             /* Check if IFU valid  */
00858 
00859             /* Check if there is a sky frame available for this IFU */
00860             kmo_collapse_objSkyStruct(obj_sky_struct, ifu_nr, &obj_frame,
00861                     &sky_frame);
00862             punused_ifus = cpl_array_get_data_int_const(unused_ifus_after[i-1]);
00863             /* Search for keyword ESO OCS ARMi NOTUSED */
00864             /* If CPL_ERROR_DATA_NOT_FOUND, process standard star */
00865             keyword = cpl_sprintf("%s%d%s", IFU_VALID_PREFIX, ifu_nr, 
00866                     IFU_VALID_POSTFIX);
00867             cpl_propertylist_get_string(main_header_tel, keyword);
00868             cpl_free(keyword);
00869 
00870             if ((cpl_error_get_code() == CPL_ERROR_DATA_NOT_FOUND) &&
00871                 (bounds[2*(ifu_nr-1)] != -1) &&
00872                 (bounds[2*(ifu_nr-1)+1] != -1) &&
00873                 (sky_frame != NULL) && (punused_ifus[j] == 0)) {
00874                 cpl_error_reset();
00875                 /* IFU is valid */
00876 
00877                 /* Process IFU */
00878                 if (kmos_std_star_compute_ifu(sub_header_orig, obj_frame, 
00879                             sky_frame, flat_frame, xcal_frame, ycal_frame, 
00880                             lcal_frame, illum_frame, atmos_frame, solar_frame, 
00881                             ifu_nr, main_header_tel, gd, bounds[2*(ifu_nr-1)], 
00882                             bounds[2*(ifu_nr-1)+1], fmethod, flux, 
00883                             xcal_interpolation, mask_method, cmethod, cpos_rej,
00884                             cneg_rej, citer, cmax, cmin, cen_x, cen_y, radius, 
00885                             filter_id, star_type, no_noise, is_stdstarscipatt, 
00886                             sky_sky_struct[ifu_nr-1], star_temp, 
00887                             &spec_qc,
00888                             &stored_sub_tel_data_headers[ifu_nr-1],
00889                             &stored_sub_psf_headers[ifu_nr-1],
00890                             &stored_sub_cube_data_headers[ifu_nr-1],
00891                             &stored_data_cube[ifu_nr-1], 
00892                             &stored_noise_cube[ifu_nr-1],
00893                             &stored_psf_data[ifu_nr-1],
00894                             &stored_mask[ifu_nr-1],
00895                             &stored_starspec_data[ifu_nr-1],
00896                             &stored_starspec_noise[ifu_nr-1],
00897                             &stored_noisespec[ifu_nr-1],
00898                             &stored_telluric_data[ifu_nr-1],
00899                             &stored_telluric_noise[ifu_nr-1]) == -1) {
00900                     stored_telluric_data[ifu_nr-1] = NULL ;
00901                     stored_telluric_noise[ifu_nr-1] = NULL ;
00902                     stored_starspec_data[ifu_nr-1] = NULL ;
00903                     stored_starspec_noise[ifu_nr-1] = NULL ;
00904                     stored_psf_data[ifu_nr-1] = NULL ;
00905                     stored_mask[ifu_nr-1] = NULL ;
00906                     stored_data_cube[ifu_nr-1] = NULL ;
00907                     stored_noise_cube[ifu_nr-1] = NULL ;
00908                     stored_noisespec[ifu_nr-1] = NULL ;
00909 
00910                     stored_sub_tel_data_headers[ifu_nr-1] =
00911                         cpl_propertylist_duplicate(sub_header_orig);
00912                     stored_sub_tel_noise_headers[ifu_nr-1] =
00913                         cpl_propertylist_duplicate(sub_header_orig);
00914                     stored_sub_psf_headers[ifu_nr-1] =
00915                         cpl_propertylist_duplicate(sub_header_orig);
00916                     stored_sub_cube_data_headers[ifu_nr-1] =
00917                         cpl_propertylist_duplicate(sub_header_orig);
00918                     stored_sub_cube_noise_headers[ifu_nr-1] =
00919                         cpl_propertylist_duplicate(sub_header_orig);
00920                 } else {
00921                     /* If magnitude is provided, get zeropoint and throughput */
00922                     if (compute_qcs) {
00923                         /* QC THROUGHPUT */
00924                         gain = cpl_propertylist_get_double(
00925                                 stored_sub_tel_data_headers[ifu_nr-1], GAIN);
00926                         crpix1=cpl_propertylist_get_double(
00927                                 stored_sub_tel_data_headers[ifu_nr-1], CRPIX1);
00928                         crval1=cpl_propertylist_get_double(
00929                                 stored_sub_tel_data_headers[ifu_nr-1], CRVAL1);
00930                         cdelt1=cpl_propertylist_get_double(
00931                                 stored_sub_tel_data_headers[ifu_nr-1], CDELT1);
00932                         kmo_calc_counts(spec_qc, filter_id, crpix1, crval1, 
00933                                 cdelt1, &counts1, &counts2);
00934                         counts1 /= exptime;
00935                         counts2 /= exptime;
00936                         stored_qc_throughput[ifu_nr-1] = 
00937                             kmo_calc_throughput(magnitude1, magnitude2,
00938                                     counts1, counts2, gain, filter_id);
00939                         if (kmclipm_is_nan_or_inf(
00940                                     stored_qc_throughput[ifu_nr-1])) 
00941                             stored_qc_throughput[ifu_nr-1] = -1;
00942                         kmclipm_update_property_double(
00943                                 stored_sub_tel_data_headers[ifu_nr-1], 
00944                                 QC_THROUGHPUT, 
00945                                 stored_qc_throughput[ifu_nr-1], 
00946                                 "[] IFU throughput");
00947 
00948                         /* QC ZEROPOINT */
00949                         zeropoint = kmo_calc_zeropoint(magnitude1, magnitude2, 
00950                                 counts1, counts2, cdelt1, filter_id);
00951                         if (kmclipm_is_nan_or_inf(zeropoint)) zeropoint = -1;
00952                         kmclipm_update_property_double(
00953                                 stored_sub_tel_data_headers[ifu_nr-1], 
00954                                 QC_ZEROPOINT, zeropoint, "[mag] IFU zeropoint");
00955                     }
00956                     /* Update number of standard stars */
00957                     nr_std_stars++;
00958                     cpl_vector_delete(spec_qc) ;
00959                 }
00960             } else {
00961                 cpl_error_reset();
00962                 /* IFU is invalid */
00963                 stored_telluric_data[ifu_nr-1] = NULL ;
00964                 stored_telluric_noise[ifu_nr-1] = NULL ;
00965                 stored_starspec_data[ifu_nr-1] = NULL ;
00966                 stored_starspec_noise[ifu_nr-1] = NULL ;
00967                 stored_psf_data[ifu_nr-1] = NULL ;
00968                 stored_mask[ifu_nr-1] = NULL ;
00969                 stored_data_cube[ifu_nr-1] = NULL ;
00970                 stored_noise_cube[ifu_nr-1] = NULL ;
00971                 stored_noisespec[ifu_nr-1] = NULL ;
00972 
00973                 stored_sub_tel_data_headers[ifu_nr-1] =
00974                     cpl_propertylist_duplicate(sub_header_orig);
00975                 stored_sub_tel_noise_headers[ifu_nr-1] =
00976                     cpl_propertylist_duplicate(sub_header_orig);
00977                 stored_sub_psf_headers[ifu_nr-1] =
00978                     cpl_propertylist_duplicate(sub_header_orig);
00979                 stored_sub_cube_data_headers[ifu_nr-1] =
00980                     cpl_propertylist_duplicate(sub_header_orig);
00981                 stored_sub_cube_noise_headers[ifu_nr-1] =
00982                     cpl_propertylist_duplicate(sub_header_orig);
00983             }
00984 
00985             /* EXTNAME for DATA */
00986             extname = kmo_extname_creator(ifu_frame, ifu_nr, EXT_DATA);
00987             kmclipm_update_property_string(
00988                     stored_sub_tel_data_headers[ifu_nr-1], EXTNAME, extname,
00989                     "FITS extension name");
00990             kmclipm_update_property_string(
00991                     stored_sub_psf_headers[ifu_nr-1], EXTNAME, extname, 
00992                     "FITS extension name");
00993             kmclipm_update_property_string(
00994                     stored_sub_cube_data_headers[ifu_nr-1], EXTNAME, 
00995                     extname, "FITS extension name");
00996             cpl_free(extname);
00997 
00998             /* EXTNAME for NOISE */
00999             if (stored_sub_tel_noise_headers[ifu_nr-1] == NULL) {
01000                 stored_sub_tel_noise_headers[ifu_nr-1] =
01001                     cpl_propertylist_duplicate(
01002                             stored_sub_tel_data_headers[ifu_nr-1]);
01003             }
01004             extname = kmo_extname_creator(ifu_frame, ifu_nr, EXT_NOISE);
01005             kmclipm_update_property_string(
01006                     stored_sub_tel_noise_headers[ifu_nr-1], EXTNAME, 
01007                     extname, "FITS extension name");
01008             if (stored_sub_cube_noise_headers[ifu_nr-1] == NULL)
01009                 stored_sub_cube_noise_headers[ifu_nr-1] =
01010                     cpl_propertylist_duplicate(
01011                             stored_sub_cube_data_headers[ifu_nr-1]);
01012             kmclipm_update_property_string(
01013                     stored_sub_cube_noise_headers[ifu_nr-1], EXTNAME,
01014                         extname, "FITS extension name");
01015             cpl_free(extname);
01016         } 
01017         cpl_propertylist_delete(sub_header_orig);
01018     } 
01019     cpl_free(bounds);
01020 
01021     /* Write QC parameter: nr of std stars */
01022     kmclipm_update_property_int(main_header_tel, QC_NR_STD_STARS,
01023             nr_std_stars, "[] Nr. of std stars");
01024 
01025     /* Update which IFUs are not used */
01026     kmo_print_unused_ifus(unused_ifus_after, TRUE);
01027     kmo_set_unused_ifus(unused_ifus_after, main_header_tel,"kmos_std_star");
01028     kmo_free_unused_ifus(unused_ifus_after);
01029 
01030     main_header_psf = cpl_propertylist_duplicate(main_header_tel);
01031 
01032     if (compute_qcs) {
01033         /* QC THROUGHPUT MEAN and QC THROUGHPUT SDV */
01034         kmo_calc_mean_throughput(stored_qc_throughput, nifus, &throughput_mean,
01035                 &throughput_sdv);
01036         kmclipm_update_property_double(main_header_tel, QC_THROUGHPUT_MEAN,
01037                 throughput_mean, "[] mean throughput for all detectors");
01038         kmclipm_update_property_double(main_header_tel, QC_THROUGHPUT_SDV,
01039                 throughput_sdv, "[] stdev throughput for all detectors");
01040     }
01041     cpl_free(stored_qc_throughput);
01042     
01043     /* Save output data */
01044     if (!suppress_extension)    fn_suffix = cpl_sprintf("%s", suffix);
01045     else                        fn_suffix = cpl_sprintf("%s", "");
01046     cpl_free(suffix); 
01047 
01048     /* Save primary extension */
01049     kmo_dfs_save_main_header(frameset, filename_telluric, fn_suffix,
01050             obj_frame, main_header_tel, parlist, cpl_func);
01051     kmo_dfs_save_main_header(frameset, filename_starspec, fn_suffix,
01052             obj_frame, main_header_tel, parlist, cpl_func);
01053     kmo_dfs_save_main_header(frameset, filename_mask, fn_suffix,
01054             obj_frame, main_header_psf, parlist, cpl_func);
01055     kmo_dfs_save_main_header(frameset, filename_psf, fn_suffix,
01056             obj_frame, main_header_psf, parlist, cpl_func) ;
01057     if (!no_noise && is_stdstarscipatt) {
01058         kmo_dfs_save_main_header(frameset, filename_noise, fn_suffix,
01059                 obj_frame, main_header_tel, parlist, cpl_func);
01060     }
01061     cpl_propertylist_delete(main_header_tel);
01062     
01063     if (save_cubes) {
01064         kmo_dfs_save_main_header(frameset, filename_cubes, fn_suffix,
01065                 obj_frame, main_header_psf, parlist, cpl_func);
01066     }
01067     cpl_propertylist_delete(main_header_psf);
01068 
01069     /* Save stored frames */
01070     for (i = 1; i <= KMOS_NR_DETECTORS ; i++) {
01071         for (j = 0; j < KMOS_IFUS_PER_DETECTOR; j++) {
01072             ifu_nr = (i-1)*KMOS_IFUS_PER_DETECTOR + j + 1;
01073 
01074             /* Save telluric-vector */
01075             if (stored_telluric_data[ifu_nr-1] != NULL) {
01076                 ddd = kmclipm_vector_create(cpl_vector_duplicate(
01077                             stored_telluric_data[ifu_nr-1]));
01078                 kmo_dfs_save_vector(ddd, filename_telluric, fn_suffix,
01079                         stored_sub_tel_data_headers[ifu_nr-1], 0./0.);
01080                 kmclipm_vector_delete(ddd) ;
01081             } else {
01082                 kmo_dfs_save_vector(NULL, filename_telluric, fn_suffix,
01083                         stored_sub_tel_data_headers[ifu_nr-1], 0./0.);
01084             }
01085             if (stored_telluric_noise[ifu_nr-1] != NULL) {
01086                 ddd = kmclipm_vector_create(cpl_vector_duplicate(
01087                             stored_telluric_noise[ifu_nr-1]));
01088                 kmo_dfs_save_vector(ddd, filename_telluric, fn_suffix,
01089                         stored_sub_tel_noise_headers[ifu_nr-1], 0./0.);
01090                 kmclipm_vector_delete(ddd) ;
01091             } else {
01092                 kmo_dfs_save_vector(NULL, filename_telluric, fn_suffix,
01093                         stored_sub_tel_noise_headers[ifu_nr-1], 0./0.);
01094             }
01095 
01096             /* Save star_spec-vector */
01097             if (stored_starspec_data[ifu_nr-1] != NULL) {
01098                 ddd = kmclipm_vector_create(cpl_vector_duplicate(
01099                             stored_starspec_data[ifu_nr-1]));
01100                 kmo_dfs_save_vector(ddd, filename_starspec, fn_suffix,
01101                         stored_sub_tel_data_headers[ifu_nr-1], 0./0.);
01102                 kmclipm_vector_delete(ddd); 
01103             } else {
01104                 kmo_dfs_save_vector(NULL, filename_starspec, fn_suffix,
01105                         stored_sub_tel_data_headers[ifu_nr-1], 0./0.);
01106             }
01107             if (stored_starspec_noise[ifu_nr-1] != NULL) {
01108                 ddd = kmclipm_vector_create(cpl_vector_duplicate(
01109                             stored_starspec_noise[ifu_nr-1]));
01110                 kmo_dfs_save_vector(ddd, filename_starspec, fn_suffix,
01111                         stored_sub_tel_noise_headers[ifu_nr-1], 0./0.);
01112                 kmclipm_vector_delete(ddd); 
01113             } else {
01114                 kmo_dfs_save_vector(NULL, filename_starspec, fn_suffix,
01115                         stored_sub_tel_noise_headers[ifu_nr-1], 0./0.);
01116             }
01117 
01118             /* Save psf-image */
01119             kmo_dfs_save_image(stored_psf_data[ifu_nr-1], filename_psf, 
01120                     fn_suffix, stored_sub_psf_headers[ifu_nr-1], 0./0.);
01121 
01122             /* Save mask-image */
01123             kmo_dfs_save_image(stored_mask[ifu_nr-1], filename_mask, 
01124                     fn_suffix, stored_sub_psf_headers[ifu_nr-1], 0./0.);
01125 
01126             /* Save noise_spec-vector */
01127             if (!no_noise && is_stdstarscipatt && stored_noisespec != NULL && 
01128                     stored_noisespec[ifu_nr-1] != NULL && 
01129                     stored_starspec_data[ifu_nr-1] != NULL) {
01130                 /* QC SNR */
01131                 kmo_calc_band_mean(stored_sub_tel_data_headers[ifu_nr-1],
01132                         filter_id, stored_starspec_data[ifu_nr-1], NULL,
01133                         &tmp_data, NULL);
01134                 kmo_calc_band_mean(stored_sub_tel_data_headers[ifu_nr-1],
01135                         filter_id, stored_noisespec[ifu_nr-1], NULL,
01136                         &tmp_noise, NULL);
01137                 kmclipm_update_property_double(
01138                         stored_sub_tel_data_headers[ifu_nr-1], QC_SNR,
01139                         tmp_data/tmp_noise, "[] SNR");
01140             }
01141 
01142             if (!no_noise && is_stdstarscipatt) {
01143                 if ((stored_noisespec != NULL) && 
01144                         stored_noisespec[ifu_nr-1] != NULL) {
01145                     ddd = kmclipm_vector_create(cpl_vector_duplicate(
01146                                 stored_noisespec[ifu_nr-1]));
01147                     kmo_dfs_save_vector(ddd, filename_noise, fn_suffix,
01148                             stored_sub_tel_data_headers[ifu_nr-1], 0./0.);
01149                     kmclipm_vector_delete(ddd); 
01150                 } else {
01151                     kmo_dfs_save_vector(NULL, filename_noise, fn_suffix,
01152                             stored_sub_tel_data_headers[ifu_nr-1], 0./0.);
01153                 }
01154             }
01155 
01156             /* Save reonstructed cubes */
01157             if (save_cubes) {
01158                 kmo_dfs_save_cube(stored_data_cube[ifu_nr-1],
01159                         filename_cubes, fn_suffix,
01160                         stored_sub_cube_data_headers[ifu_nr-1], 0./0.);
01161                 kmo_dfs_save_cube(stored_noise_cube[ifu_nr-1],
01162                         filename_cubes, fn_suffix,
01163                         stored_sub_cube_noise_headers[ifu_nr-1], 0./0.);
01164             }
01165         } 
01166     } 
01167     cpl_free(fn_suffix);
01168 
01169     /* DE-Allocate Warning ---  Frames (e.g obj_frame) point to  */
01170     /*                          obj_..._struct which point to frameset_ѕtd */
01171     kmo_delete_objSkyStruct(obj_sky_struct);
01172     kmo_delete_skySkyStruct(sky_sky_struct);
01173     cpl_frameset_delete(frameset_std);
01174     
01175     for (i = 0; i < nifus ; i++) {
01176         cpl_vector_delete(stored_telluric_data[i]);
01177         cpl_vector_delete(stored_telluric_noise[i]);
01178         cpl_vector_delete(stored_starspec_data[i]); 
01179         cpl_vector_delete(stored_starspec_noise[i]);
01180         cpl_image_delete(stored_psf_data[i]);
01181         cpl_propertylist_delete(stored_sub_tel_data_headers[i]); 
01182         cpl_propertylist_delete(stored_sub_tel_noise_headers[i]);
01183         cpl_vector_delete(stored_noisespec[i]); 
01184         cpl_propertylist_delete(stored_sub_cube_data_headers[i]); 
01185         cpl_propertylist_delete(stored_sub_cube_noise_headers[i]);
01186         cpl_propertylist_delete(stored_sub_psf_headers[i]); 
01187         cpl_image_delete(stored_mask[i]);
01188         cpl_imagelist_delete(stored_data_cube[i]);
01189         cpl_imagelist_delete(stored_noise_cube[i]);
01190     }
01191     cpl_free(stored_telluric_data);
01192     cpl_free(stored_telluric_noise);
01193     cpl_free(stored_starspec_data);
01194     cpl_free(stored_starspec_noise); 
01195     cpl_free(stored_psf_data);
01196     cpl_free(stored_sub_tel_data_headers);
01197     cpl_free(stored_sub_tel_noise_headers);
01198     cpl_free(stored_noisespec);
01199     cpl_free(stored_sub_cube_data_headers);
01200     cpl_free(stored_sub_cube_noise_headers);
01201     cpl_free(stored_sub_psf_headers);
01202     cpl_free(stored_mask);
01203     cpl_free(stored_data_cube);
01204     cpl_free(stored_noise_cube);
01205 
01206     return 0;
01207 }
01208 
01211 /*----------------------------------------------------------------------------*/
01216 /*----------------------------------------------------------------------------*/
01217 static int kmos_std_star_compute_ifu(
01218         cpl_propertylist    *   sub_header_orig,
01219         cpl_frame           *   obj_frame,
01220         cpl_frame           *   sky_frame,
01221         cpl_frame           *   flat_frame,
01222         cpl_frame           *   xcal_frame,
01223         cpl_frame           *   ycal_frame,
01224         cpl_frame           *   lcal_frame,
01225         cpl_frame           *   illum_frame,
01226         cpl_frame           *   atmos_frame,
01227         cpl_frame           *   solar_frame,
01228         int                     ifu_nr,
01229         cpl_propertylist    *   main_header_tel,
01230         gridDefinition          gd,
01231         int                     low_bound,
01232         int                     high_bound,
01233         const char          *   fmethod,
01234         int                     flux,
01235         int                     xcal_interpolation,
01236         const char          *   mask_method,
01237         const char          *   cmethod,
01238         double                  cpos_rej,
01239         double                  cneg_rej,
01240         int                     citer,
01241         int                     cmax,
01242         int                     cmin,
01243         double                  cen_x,
01244         double                  cen_y,
01245         double                  radius,
01246         const char          *   filter_id,
01247         char                    star_type,
01248         int                     no_noise,
01249         int                     is_stdstarscipatt,
01250         skySkyStruct            sky_sky_struct,
01251         double                  star_temp,
01252         cpl_vector          **  spec_qc,
01253         cpl_propertylist    **  out_sub_tel_data_header,
01254         cpl_propertylist    **  out_sub_psf_header,
01255         cpl_propertylist    **  out_sub_cube_data_header,
01256         cpl_imagelist       **  out_data_cube,
01257         cpl_imagelist       **  out_noise_cube,
01258         cpl_image           **  out_psf_data,
01259         cpl_image           **  out_mask,
01260         cpl_vector          **  out_starspec_data,
01261         cpl_vector          **  out_starspec_noise,
01262         cpl_vector          **  out_noisespec,
01263         cpl_vector          **  out_telluric_data,
01264         cpl_vector          **  out_telluric_noise)
01265 {
01266     char                *   keyword ;
01267     cpl_propertylist    *   tmp_head ;
01268     cpl_image           *   illum_corr ;
01269     cpl_propertylist    *   pl_psf ;
01270     double                  std_trace, factor_fwhm, spat_res, x_lo, y_lo, x_hi,
01271                             y_hi, loc_cen_x, loc_cen_y, r ;
01272     cpl_size                auto_cen_x, auto_cen_y, nx, ny ;
01273     cpl_vector          *   tmp_vec ;
01274     cpl_vector          *   tmp_spec_data ;
01275     cpl_vector          *   tmp_spec_noise ;
01276     cpl_vector          *   shot_noise ;
01277     cpl_vector          *   solar_spec ;
01278     double              *   ppp ;
01279     double                  gain, mean_data, mean_data2, flux_scale_factor ;
01280     double              **  pvec_array ;
01281     double              *   ptmp_vec ;
01282     double              *   pstored_noisespec ;
01283     cpl_vector          **  vec_array ;
01284     const double        *   ptmp_spec_data ;
01285     double              *   ptmp_spec_noise ;
01286     float               *   pmask ;
01287     cpl_imagelist       *   tmp_cube ;
01288     cpl_vector          *   lambda_x ;
01289     cpl_vector          *   atmos_model ;
01290     int                     i, j, k, nr_sky_pairs, npix, x, y ;
01291  
01292     /* Check inputs */
01293     
01294     /* Initialise */
01295     std_trace = -1.0 ;
01296 
01297     /* Messages */
01298     if (sky_frame != NO_CORRESPONDING_SKYFRAME) {
01299         cpl_msg_info(cpl_func, "Processing standard star in IFU %d", ifu_nr);
01300         cpl_msg_info(cpl_func, "   (obj: %s, sky: %s)",
01301                 cpl_frame_get_filename(obj_frame),
01302                 cpl_frame_get_filename(sky_frame));
01303     } else {
01304         sky_frame = NULL;
01305         cpl_msg_warning(cpl_func, 
01306                 "Processing standard star in IFU %d", ifu_nr);
01307         cpl_msg_warning(cpl_func, 
01308                 "   (obj: %s, no corresponding sky frame)",
01309                 cpl_frame_get_filename(obj_frame));
01310     }
01311 
01312     keyword = cpl_sprintf("%s%d", PRO_STD, ifu_nr);
01313     cpl_propertylist_update_int(main_header_tel, keyword, 1);
01314     cpl_free(keyword);
01315 
01316     /* Compute WCS and make copies of sub_header */
01317     tmp_head=cpl_propertylist_duplicate(sub_header_orig);
01318     kmo_calc_wcs_gd(main_header_tel, tmp_head, ifu_nr,gd);
01319     *out_sub_tel_data_header = cpl_propertylist_duplicate(tmp_head);
01320     *out_sub_psf_header = cpl_propertylist_duplicate(tmp_head);
01321     *out_sub_cube_data_header = cpl_propertylist_duplicate(tmp_head);
01322     cpl_propertylist_delete(tmp_head);
01323     
01324     /* Adjust telluric-headers: copy key3 to key1 - rm key2 key3*/
01325     kmos_std_star_adjust_double(*out_sub_tel_data_header, CRVAL1,CRVAL2,CRVAL3);
01326     kmos_std_star_adjust_double(*out_sub_tel_data_header, CRPIX1,CRPIX2,CRPIX3);
01327     kmos_std_star_adjust_double(*out_sub_tel_data_header, CDELT1,CDELT2,CDELT3);
01328     kmos_std_star_adjust_string(*out_sub_tel_data_header, CTYPE1,CTYPE2,CTYPE3);
01329     kmos_std_star_adjust_string(*out_sub_tel_data_header, CUNIT1,CUNIT2,CUNIT3);
01330 
01331     /* CDx_x */
01332     cpl_propertylist_erase(*out_sub_tel_data_header, CD1_1);
01333     cpl_propertylist_erase(*out_sub_tel_data_header, CD1_2);
01334     cpl_propertylist_erase(*out_sub_tel_data_header, CD1_3);
01335     cpl_propertylist_erase(*out_sub_tel_data_header, CD2_1);
01336     cpl_propertylist_erase(*out_sub_tel_data_header, CD2_2);
01337     cpl_propertylist_erase(*out_sub_tel_data_header, CD2_3);
01338     cpl_propertylist_erase(*out_sub_tel_data_header, CD3_1);
01339     cpl_propertylist_erase(*out_sub_tel_data_header, CD3_2);
01340     cpl_propertylist_erase(*out_sub_tel_data_header, CD3_3);
01341 
01342     /* Adjust psf-headers: delete CRPIX3 etc. */
01343     cpl_propertylist_erase(*out_sub_psf_header, CRPIX3);
01344     cpl_propertylist_erase(*out_sub_psf_header, CRPIX3);
01345     cpl_propertylist_erase(*out_sub_psf_header, CDELT3);
01346     cpl_propertylist_erase(*out_sub_psf_header, CRVAL3);
01347     cpl_propertylist_erase(*out_sub_psf_header, CTYPE3);
01348     cpl_propertylist_erase(*out_sub_psf_header, CUNIT3);
01349     cpl_propertylist_erase(*out_sub_psf_header, CD1_3);
01350     cpl_propertylist_erase(*out_sub_psf_header, CD2_3);
01351     cpl_propertylist_erase(*out_sub_psf_header, CD3_1);
01352     cpl_propertylist_erase(*out_sub_psf_header, CD3_2);
01353     cpl_propertylist_erase(*out_sub_psf_header, CD3_3);
01354         
01355     /* Reconstruct */
01356     kmo_reconstruct_sci(ifu_nr, low_bound, high_bound, obj_frame, STD,
01357             sky_frame, STD, flat_frame, xcal_frame, ycal_frame, lcal_frame,
01358             NULL, NULL, &gd, out_data_cube, out_noise_cube, flux, FALSE,
01359             xcal_interpolation, FALSE);
01360 
01361     /* Illumination correction */
01362     /* Illumination noise small versus noise - skipped */
01363     if (illum_frame != NULL) {
01364         illum_corr = kmo_dfs_load_image_frame(illum_frame, 
01365                 ifu_nr, FALSE, FALSE, NULL);
01366         cpl_imagelist_divide_image(*out_data_cube, illum_corr);
01367         cpl_image_delete(illum_corr);
01368     }
01369 
01370     /* QC_STD_TRACE (distance of the PSF to the centre) */
01371     kmo_calculate_std_trace(*out_data_cube, fmethod, &std_trace);
01372     kmclipm_update_property_double(*out_sub_psf_header, QC_STD_TRACE, std_trace,
01373             "[pix] distance PSF - IFU center");
01374 
01375     /* Collapse cube and get PSF image */
01376     kmclipm_make_image(*out_data_cube, NULL, out_psf_data, NULL, NULL,
01377             cmethod, cpos_rej, cneg_rej, citer, cmax, cmin);
01378 
01379     /* Fit a 2D profile to get a mask and fwhm in x and y */
01380     tmp_vec = kmo_fit_profile_2D(*out_psf_data, NULL, fmethod,out_mask,&pl_psf);
01381 
01382     if (!strcmp(mask_method, "integrated")) {
01383         if (cen_x < 1.0 || cen_y < 1.0) {
01384             cpl_image_get_maxpos(*out_psf_data,&auto_cen_x,&auto_cen_y);
01385             loc_cen_x = (double)auto_cen_x - 1.0 ;
01386             loc_cen_y = (double)auto_cen_y - 1.0 ;
01387         } else {
01388             loc_cen_x = cen_x - 1.0 ;
01389             loc_cen_y = cen_y - 1.0 ;
01390         }
01391         kmo_image_fill(*out_mask,0.0);
01392         pmask = cpl_image_get_data_float(*out_mask);
01393         nx = cpl_image_get_size_x(*out_mask);
01394         ny = cpl_image_get_size_y(*out_mask);
01395 
01396         /* draw circle */
01397         x_lo = floor(loc_cen_x - radius);
01398         if (x_lo < 0) x_lo = 0;
01399         y_lo = floor(loc_cen_y - radius);
01400         if (y_lo < 0) y_lo = 0;
01401         x_hi = ceil(loc_cen_x + radius);
01402         if (x_hi > nx) x_hi = nx;
01403         y_hi = ceil(loc_cen_y + radius);
01404         if (y_hi > ny) y_hi = ny;
01405         for (x = x_lo; x < x_hi; x++) {
01406             for (y = y_lo; y < y_hi; y++) {
01407                 r = sqrt(pow(x - loc_cen_x,2) + pow(y - loc_cen_y,2));
01408                 if (r <= radius) pmask[x + y * nx] = 1.0;
01409             }
01410         }
01411     } else {
01412         /* Normalise mask to 1 and clip values below 0.5 */
01413         cpl_image_divide_scalar(*out_mask, cpl_image_get_max(*out_mask));
01414         for (i = 1; i <= cpl_image_get_size_x(*out_mask); i++) {
01415             for (j = 1; j <= cpl_image_get_size_y(*out_mask); j++) {
01416                 if (cpl_image_get(*out_mask, i, j, &k) < 0.5) 
01417                     cpl_image_set(*out_mask, i, j, 0.);
01418                 else   
01419                     cpl_image_set(*out_mask, i, j, 1.);
01420             }
01421         }
01422     }
01423 
01424     /* Update subheader with fit parameters */
01425     cpl_propertylist_append(*out_sub_tel_data_header, pl_psf);
01426     cpl_propertylist_delete(pl_psf);
01427 
01428     /* QC_SPAT_RES (RMS of fwhm_x and fwhm_y) */
01429     factor_fwhm = 2*sqrt(2*log(2));
01430     spat_res = pow(cpl_vector_get(tmp_vec, 4) * factor_fwhm, 2);
01431     spat_res += pow(cpl_vector_get(tmp_vec, 5)* factor_fwhm, 2);
01432     spat_res /= 2;
01433     kmclipm_update_property_double(*out_sub_psf_header, QC_SPAT_RES,
01434             sqrt(spat_res)*KMOS_PIX_RESOLUTION,
01435             "[arcsec] mean fwhm resolution of PSF");
01436     cpl_vector_delete(tmp_vec);
01437     
01438     /* Extract spectrum with mask  */
01439     /* Convert Mean to Sum (* mask area) */
01440     tmp_spec_data = tmp_spec_noise = NULL ;
01441     kmo_priv_extract_spec(*out_data_cube, *out_noise_cube, *out_mask,
01442             &tmp_spec_data, &tmp_spec_noise);
01443     cpl_vector_multiply_scalar(tmp_spec_data, cpl_image_get_flux(*out_mask));
01444     if (tmp_spec_noise != NULL) {
01445         cpl_vector_multiply_scalar(tmp_spec_noise,
01446                 cpl_image_get_flux(*out_mask));
01447     }
01448    
01449     /* Extract spectrum of whole area for QCs */
01450     /* Convert mean to sum (* 196, IFU area) */
01451     tmp_vec = *spec_qc = NULL ;
01452     kmo_priv_extract_spec(*out_data_cube, *out_noise_cube, NULL, spec_qc,
01453             &tmp_vec);
01454     npix = cpl_image_get_size_x(cpl_imagelist_get(*out_data_cube, 0)) * 
01455         cpl_image_get_size_y(cpl_imagelist_get(*out_data_cube, 0)) ;
01456     cpl_vector_multiply_scalar(*spec_qc, npix);
01457     if (tmp_vec != NULL) cpl_vector_multiply_scalar(tmp_vec, npix);
01458 
01459     /* Shot noise */
01460     gain = cpl_propertylist_get_double(*out_sub_tel_data_header, GAIN);
01461 
01462     /* Shot_noise = sqrt(tmp_spec_data*gain)/gain */
01463     /* set negative values and NaN's to zero before sqrt */
01464     shot_noise = cpl_vector_duplicate(tmp_spec_data);
01465     cpl_vector_multiply_scalar(shot_noise, gain);
01466     ppp = cpl_vector_get_data(shot_noise);
01467     for (i = 0; i < cpl_vector_get_size(shot_noise); i++) {
01468         if ((ppp[i] < 0.0) || kmclipm_is_nan_or_inf(ppp[i])) 
01469             ppp[i] = 0.0;
01470     }
01471     cpl_vector_sqrt(shot_noise);
01472     cpl_vector_divide_scalar(shot_noise, gain);
01473 
01474     /* Scale extracted spectrum to match the one  */
01475     /* calculated over the whole area (band specific) */
01476     kmo_calc_band_mean(*out_sub_tel_data_header, filter_id, tmp_spec_data, 
01477             tmp_spec_noise, &mean_data, NULL);
01478     kmo_calc_band_mean(*out_sub_tel_data_header, filter_id, *spec_qc, tmp_vec, 
01479             &mean_data2, NULL);
01480     cpl_vector_delete(tmp_vec) ;
01481 
01482     flux_scale_factor = mean_data2/mean_data;
01483 
01484     cpl_vector_multiply_scalar(shot_noise, flux_scale_factor);
01485     cpl_vector_multiply_scalar(tmp_spec_data,flux_scale_factor);
01486     if ((tmp_spec_noise != NULL) && (fabs(mean_data) > 1e-8))
01487         cpl_vector_multiply_scalar(tmp_spec_noise, flux_scale_factor);
01488 
01489     /* Store to save to disk later on */
01490     *out_starspec_data = cpl_vector_duplicate(tmp_spec_data);
01491     if (tmp_spec_noise != NULL) 
01492         *out_starspec_noise = cpl_vector_duplicate(tmp_spec_noise);
01493     else
01494         *out_starspec_noise = NULL ;
01495 
01496     /* Noise spectra */
01497     if (!no_noise && is_stdstarscipatt) {
01498         nr_sky_pairs = sky_sky_struct.nrSkyPairs;
01499         if (nr_sky_pairs > 2) {
01500             cpl_msg_info(__func__, "Get noise spec on sky for IFU %d", ifu_nr);
01501             vec_array = cpl_calloc(nr_sky_pairs,sizeof(cpl_vector*));
01502             pvec_array = cpl_calloc(nr_sky_pairs, sizeof(double*));
01503             /* Reconstruct all sky-Pairs, extract spectra  */
01504             for (i = 0; i < nr_sky_pairs; i++) {
01505                 // reconstruct (sky1-sky2)/flatfield
01506                 kmo_reconstruct_sci(ifu_nr, low_bound, high_bound,
01507                         sky_sky_struct.skyPairs[i].skyFrame1, STD, 
01508                         sky_sky_struct.skyPairs[i].skyFrame2, STD, flat_frame,
01509                         xcal_frame, ycal_frame, lcal_frame, NULL, NULL, &gd, 
01510                         &tmp_cube, NULL, FALSE, FALSE,
01511                         xcal_interpolation, FALSE);
01512 
01513                 /* Extract spectrum using masked   */
01514                 /* convert mean to sum (* mask aperture) */
01515                 kmo_priv_extract_spec(tmp_cube, NULL, *out_mask, 
01516                         &(vec_array[i]), NULL);
01517                 cpl_vector_multiply_scalar(vec_array[i], 
01518                         cpl_image_get_flux(*out_mask));
01519 
01520                 /* Scale extracted spectrum to match the one  */
01521                 /* calculated over the whole area (band spec) */
01522                 cpl_vector_multiply_scalar(vec_array[i], flux_scale_factor);
01523                 pvec_array[i] = cpl_vector_get_data(vec_array[i]);
01524                 cpl_imagelist_delete(tmp_cube);
01525             }
01526 
01527             /* stddev on each wavelength of all extrac spec */
01528             *out_noisespec = cpl_vector_new(gd.l.dim);
01529             pstored_noisespec = cpl_vector_get_data(*out_noisespec);
01530             tmp_vec = cpl_vector_new(nr_sky_pairs);
01531             ptmp_vec = cpl_vector_get_data(tmp_vec);
01532             for (i = 0; i < gd.l.dim; i++) {
01533                 for (j = 0; j < nr_sky_pairs; j++) 
01534                     ptmp_vec[j] = pvec_array[j][i];
01535                 pstored_noisespec[i] = cpl_vector_get_stdev(tmp_vec);
01536             }
01537             for (i = 0; i < nr_sky_pairs; i++) cpl_vector_delete(vec_array[i]);
01538             cpl_free(vec_array);
01539             cpl_free(pvec_array);
01540             cpl_vector_delete(tmp_vec);
01541             
01542             /* total noise = sqrt (shot_noise^2+sky_noise^2) */
01543             // and set negative values and NaN's to zero
01544             cpl_vector_power(*out_noisespec, 2.);
01545             cpl_vector_power(shot_noise, 2.);
01546             cpl_vector_add(*out_noisespec, shot_noise);
01547             ppp = cpl_vector_get_data(*out_noisespec);
01548             for (i = 0; i < cpl_vector_get_size(*out_noisespec); i++) {
01549                 if ((ppp[i] < 0.0) || kmclipm_is_nan_or_inf(ppp[i])) ppp[i]=0.0;
01550             }
01551             cpl_vector_sqrt(*out_noisespec);
01552             cpl_vector_delete(shot_noise); 
01553         } else {
01554             cpl_msg_warning(__func__, "Omit noise-spectra (<2 sky pairs)");
01555             *out_noisespec = shot_noise;
01556         }
01557     } else {
01558         *out_noisespec = shot_noise;
01559     } 
01560 
01561     /* Spectrum correction */
01562     /* Abscissa of output spectrum */
01563     lambda_x = kmo_create_lambda_vec(gd.l.dim, 1, gd.l.start, gd.l.delta);
01564 
01565     if (star_type=='O' || star_type=='B' || star_type=='A' || star_type=='F') {
01566         /* OBAF star */
01567 
01568         /* Remove lines if ATMOS_MODEL is provided */
01569         if (atmos_frame != NULL) {
01570             /* Interpolate ATMOS_MODEL to same scale as data */
01571             atmos_model = kmo_interpolate_vector_wcs(atmos_frame, lambda_x);
01572 
01573             /* Remove band-specific lines */
01574             if (!strcmp(filter_id, "H")) 
01575                 for (i = 0; i < nr_lines_h; i++) 
01576                     kmo_remove_line(tmp_spec_data, lambda_x, atmos_model, 
01577                             lines_center_h[i], lines_width_h[i]);
01578             else if (!strcmp(filter_id, "HK"))
01579                 for (i = 0; i < nr_lines_hk; i++) 
01580                     kmo_remove_line(tmp_spec_data, lambda_x, atmos_model, 
01581                             lines_center_hk[i], lines_width_hk[i]);
01582             else if (!strcmp(filter_id, "K")) 
01583                 for (i = 0; i < nr_lines_k; i++) 
01584                     kmo_remove_line(tmp_spec_data, lambda_x, atmos_model, 
01585                             lines_center_k[i], lines_width_k[i]);
01586             else if (!strcmp(filter_id, "IZ")) 
01587                 for (i = 0; i < nr_lines_iz; i++) 
01588                     kmo_remove_line(tmp_spec_data, lambda_x, atmos_model, 
01589                             lines_center_iz[i], lines_width_iz[i]);
01590             else if (strcmp(filter_id, "YJ") == 0)
01591                 for (i = 0; i < nr_lines_yj; i++) 
01592                     kmo_remove_line(tmp_spec_data, lambda_x, atmos_model, 
01593                             lines_center_yj[i], lines_width_yj[i]);
01594             
01595             if (0) kmos_std_star_plot() ;
01596             cpl_vector_delete(atmos_model);
01597         } else {
01598             cpl_msg_warning(__func__, "Missing ATMOS_MODEL");
01599         }
01600     } else if (star_type == 'G') {
01601         /* G star */
01602         if (solar_frame != NULL) {
01603             /* Interpolate SOLAR_SPEC to same scale and divide it */
01604             solar_spec = kmo_interpolate_vector_wcs(solar_frame, 
01605                     lambda_x);
01606             /* Set to zero if solar_spec isn't overlapping  */
01607             /* wavelength range of star apectrum completely */
01608             cpl_vector_divide(tmp_spec_data, solar_spec);
01609             cpl_vector_delete(solar_spec); 
01610         } else {
01611             cpl_msg_warning(__func__, "Missing SOLAR_SPEC");
01612         }
01613     }
01614 
01615     if (star_temp > 0.0) {
01616         /* Divide blackbody from tmp_spec_data */
01617         kmo_divide_blackbody(tmp_spec_data, lambda_x, star_temp);
01618     }
01619     cpl_vector_delete(lambda_x);
01620 
01621     /* Normalise telluric and its noise */
01622     /* mean is taken in lambda defined range */
01623     kmo_calc_band_mean(*out_sub_tel_data_header, filter_id, tmp_spec_data, 
01624             tmp_spec_noise, &mean_data, NULL);
01625     cpl_vector_divide_scalar(tmp_spec_data, mean_data);
01626 
01627     if (tmp_spec_noise != NULL) {
01628         /* Scale noise with the same factor as data */
01629         cpl_vector_divide_scalar(tmp_spec_noise, mean_data);
01630 
01631         /* Set noise spectrum to zero when solar_spec is short*/
01632         ptmp_spec_data = cpl_vector_get_data_const(tmp_spec_data);
01633         ptmp_spec_noise = cpl_vector_get_data(tmp_spec_noise);
01634         for (i = 0; i < cpl_vector_get_size(tmp_spec_data);i++)
01635             if (ptmp_spec_data[i]==0.0) ptmp_spec_noise[i]=0.0;
01636     }
01637 
01638     /* Store telluric & error spectrum */
01639     *out_telluric_data = tmp_spec_data;
01640     *out_telluric_noise = tmp_spec_noise;
01641     return 0 ;
01642 }
01643 
01644 /*----------------------------------------------------------------------------*/
01654 /*----------------------------------------------------------------------------*/
01655 static int kmos_std_star_check_inputs(
01656         cpl_frameset            *   frameset,
01657         const char              *   magnitude_txt,
01658         int                     *   is_stdstarscipatt,
01659         int                     *   compute_qcs,
01660         double                  *   magnitude1,
01661         double                  *   magnitude2)
01662 {
01663     int                     nb_std, nb_illum, nb_xcal, nb_ycal, nb_lcal,
01664                             nb_flat, nb_wave ;
01665     cpl_frame           *   tmp_frame ;
01666     cpl_frameset        *   frameset_std ;
01667     cpl_propertylist    *   tmp_head ;
01668     const char          *   my_mag_txt ;
01669     int                     nr_split_mag ;
01670     char                **  split_mag ;
01671     char                *   grat_id ;
01672     int                     same_gratings ;
01673     const char          *   tmp_str ;
01674 
01675     /* Check Entries */
01676     if (frameset == NULL || is_stdstarscipatt == NULL || compute_qcs == NULL ||
01677             magnitude1 == NULL || magnitude2 == NULL) return -1;
01678 
01679     /* Count frames */
01680     nb_std = cpl_frameset_count_tags(frameset, STD) ;
01681     nb_illum = cpl_frameset_count_tags(frameset, ILLUM_CORR) ;
01682     nb_xcal = cpl_frameset_count_tags(frameset, XCAL) ;
01683     nb_ycal = cpl_frameset_count_tags(frameset, YCAL) ;
01684     nb_lcal = cpl_frameset_count_tags(frameset, LCAL) ;
01685     nb_flat = cpl_frameset_count_tags(frameset, MASTER_FLAT) ;
01686     nb_wave = cpl_frameset_count_tags(frameset, WAVE_BAND) ;
01687 
01688     /* Check numbers */
01689     if (nb_std < 1) {
01690         cpl_msg_error(__func__, "At least one STD frame is required") ;
01691         cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
01692         return 0 ;
01693     }
01694     if (nb_std == 1) 
01695         cpl_msg_warning(__func__, "2 STD frames needed for sky subtraction") ;
01696 
01697     if (nb_illum < 0 || nb_illum > 1) {
01698         cpl_msg_error(__func__, "0 or 1 ILLUM frame expected") ;
01699         cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
01700         return 0 ;
01701     }
01702     if (nb_xcal != 1 || nb_ycal != 1 || nb_lcal != 1) {
01703         cpl_msg_error(__func__, "1 X/Y/LCAL required") ;
01704         cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
01705         return 0 ;
01706     }
01707     if (nb_flat != 1) {
01708         cpl_msg_error(__func__, "1 MASTER_FLAT required") ;
01709         cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
01710         return 0 ;
01711     }
01712     if (nb_wave != 1) {
01713         cpl_msg_error(__func__, "1 WAVE_BAND required") ;
01714         cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
01715         return 0 ;
01716     }
01717     
01718     /* Extract STD frames with same gratings as the first STD frame */
01719     frameset_std=kmos_std_star_extract_same_grat_stds(frameset,&same_gratings) ;
01720     
01721     /* Get infos from the first STD frame */
01722     tmp_frame = kmo_dfs_get_frame(frameset_std, STD);
01723     tmp_head=kmclipm_propertylist_load(cpl_frame_get_filename(tmp_frame),0);
01724     grat_id = cpl_sprintf("%s", cpl_propertylist_get_string(tmp_head,
01725                 "ESO INS GRAT1 ID"));
01726     if (!strcmp(cpl_propertylist_get_string(tmp_head, TPL_ID),
01727                 "KMOS_spec_cal_stdstarscipatt"))    *is_stdstarscipatt = TRUE ;
01728     else                                            *is_stdstarscipatt = FALSE ;
01729     cpl_propertylist_delete(tmp_head);
01730     cpl_frameset_delete(frameset_std) ;
01731 
01732     /* Check if QC are computed */
01733     if (same_gratings) {
01734         *compute_qcs = TRUE ;
01735         // now check source of magnitude (user or keyword)
01736         tmp_frame = kmo_dfs_get_frame(frameset, STD);
01737         tmp_head=kmclipm_propertylist_load(cpl_frame_get_filename(tmp_frame),0);
01738 
01739         if (!strcmp(magnitude_txt, "")) {
01740             /* No user defined magnitude */
01741             if ((cpl_propertylist_has(tmp_head, STDSTAR_MAG)) &&
01742                 (cpl_propertylist_get_type(tmp_head, STDSTAR_MAG) == 
01743                  CPL_TYPE_STRING)) {
01744                 my_mag_txt = cpl_propertylist_get_string(tmp_head, STDSTAR_MAG);
01745                 split_mag = kmo_strsplit(my_mag_txt, ",", &nr_split_mag);
01746 
01747                 /* Check if band and number of magnitudes matches */
01748                 if (nr_split_mag == 2 && !strcmp(grat_id, "HK")) {
01749                     *magnitude1 = atof(split_mag[0]);
01750                     *magnitude2 = atof(split_mag[1]);
01751                     cpl_msg_info("", "Magnitude in H: %g", *magnitude1);
01752                     cpl_msg_info("", "Magnitude in K: %g", *magnitude2);
01753                 } else if (nr_split_mag >= 1 && (!strcmp(grat_id, "K") ||
01754                             !strcmp(grat_id, "H") || !strcmp(grat_id, "IZ") ||
01755                             !strcmp(grat_id, "YJ"))) {
01756                     *magnitude1 = atof(split_mag[0]);
01757                     cpl_msg_info("", "Magnitude in %s: %g",grat_id,*magnitude1);
01758                 } else {
01759                     // keyword STDSTAR_MAG doesn't match filter
01760                     *compute_qcs = FALSE;
01761                     cpl_msg_warning(cpl_func, "Wrong Mag, QCs not computed") ;
01762                 }
01763                 kmo_strfreev(split_mag);
01764             } else {
01765                 /* STDSTAR_MAG unavailable or wrong type */
01766                 *compute_qcs = FALSE;
01767                 cpl_msg_warning(cpl_func, "%s is not set, QCs not computed", 
01768                         STDSTAR_MAG);
01769             }
01770         } else {
01771             // magnitude is user specified
01772             cpl_msg_info(cpl_func, "Magnitude entered by user, ignore header");
01773 
01774             split_mag = kmo_strsplit(magnitude_txt, ",", &nr_split_mag);
01775             switch (nr_split_mag) {
01776                 case 1:
01777                     *magnitude1 = atof(split_mag[0]);
01778                     cpl_msg_info(cpl_func, "Magnitude in %s: %g", grat_id, 
01779                             *magnitude1);
01780                     break;
01781                 case 2:
01782                     *magnitude1 = atof(split_mag[0]);
01783                     *magnitude2 = atof(split_mag[1]);
01784                     cpl_msg_info("", "Magnitude in H: %g", *magnitude1);
01785                     cpl_msg_info("", "Magnitude in K: %g", *magnitude2);
01786                     break;
01787                 default:
01788                     kmo_strfreev(split_mag);
01789                     cpl_propertylist_delete(tmp_head);
01790                     cpl_msg_error(__func__, "Wrong Magnitude Specified") ;
01791                     cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
01792                     return 0 ;
01793             }
01794             kmo_strfreev(split_mag);
01795         }
01796         cpl_propertylist_delete(tmp_head);
01797     } else {
01798         *compute_qcs = FALSE ;
01799     }
01800 
01801     /* Check SOLAR_SPEC grating */
01802     tmp_frame = kmo_dfs_get_frame(frameset, SOLAR_SPEC);
01803     if (tmp_frame != NULL) {
01804         tmp_head=kmclipm_propertylist_load(cpl_frame_get_filename(tmp_frame),0);
01805         tmp_str = cpl_propertylist_get_string(tmp_head, FILT_ID);
01806         if (strcmp(tmp_str, grat_id)) {
01807             cpl_propertylist_delete(tmp_head) ;
01808             cpl_msg_error(__func__, "Wrong SOLAR_SPEC grating") ;
01809             cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
01810             return 0 ;
01811         }
01812         cpl_propertylist_delete(tmp_head) ;
01813     }
01814 
01815     /* Check ATMOS_MODEL grating */
01816     tmp_frame = kmo_dfs_get_frame(frameset, ATMOS_MODEL);
01817     if (tmp_frame != NULL) {
01818         tmp_head=kmclipm_propertylist_load(cpl_frame_get_filename(tmp_frame),0);
01819         tmp_str = cpl_propertylist_get_string(tmp_head, FILT_ID);
01820         if (strcmp(tmp_str, grat_id)) {
01821             cpl_propertylist_delete(tmp_head) ;
01822             cpl_msg_error(__func__, "Wrong ATMOS_MODEL grating") ;
01823             cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
01824             return 0 ;
01825         }
01826         cpl_propertylist_delete(tmp_head) ;
01827     }
01828     cpl_free(grat_id) ;
01829 
01830     /* Check if filter_id and grating_id match for all detectors */
01831     kmo_check_frameset_setup(frameset, XCAL, FALSE, FALSE, TRUE);
01832     kmo_check_frame_setup(frameset, XCAL, YCAL, TRUE, FALSE, TRUE);
01833     kmo_check_frame_setup(frameset, XCAL, LCAL, TRUE, FALSE, TRUE);
01834     kmo_check_frame_setup(frameset, XCAL, MASTER_FLAT, TRUE, FALSE, TRUE);
01835     kmo_check_frame_setup(frameset, XCAL, STD, FALSE, FALSE, TRUE);
01836     if (nb_illum == 1) 
01837         kmo_check_frame_setup(frameset, XCAL, ILLUM_CORR, TRUE, FALSE, FALSE);
01838     kmo_check_frame_setup_md5_xycal(frameset);
01839     kmo_check_frame_setup_md5(frameset);
01840     return 1 ;
01841 }
01842 
01843 /*----------------------------------------------------------------------------*/
01849 /*----------------------------------------------------------------------------*/
01850 static int kmos_std_star_plot(void)
01851 {
01852 
01853     /*
01854     cpl_vector *tmp_spec_data_atmo = NULL;
01855     cpl_vector *tmp_spec_data_new = NULL;
01856                         tmp_spec_data_orig=cpl_vector_duplicate(tmp_spec_data);
01857     KMO_TRY_EXIT_IF_NULL(
01858         tmp_spec_data_atmo = cpl_vector_duplicate(tmp_spec_data_orig));
01859     KMO_TRY_EXIT_IF_NULL(
01860         tmp_spec_data_new = cpl_vector_duplicate(tmp_spec_data));
01861     KMO_TRY_EXIT_IF_ERROR(
01862         cpl_vector_divide(tmp_spec_data_atmo, atmos_model));
01863 
01864     char *sss = cpl_sprintf("atmo_div_%s.fits", filter_id);
01865     if (i == 1) {
01866         cpl_vector_save(tmp_spec_data_atmo, sss, CPL_BPP_IEEE_DOUBLE, stored_sub_tel_data_headers[ifu_nr-1], CPL_IO_CREATE);
01867     } else {
01868         cpl_vector_save(tmp_spec_data_atmo, sss, CPL_BPP_IEEE_DOUBLE, stored_sub_tel_data_headers[ifu_nr-1], CPL_IO_EXTEND);
01869     }
01870 
01871     cpl_vector *med_vec = cpl_vector_duplicate(tmp_spec_data_orig);
01872     double  median = cpl_vector_get_median(med_vec);
01873     cpl_vector_delete(med_vec);
01874     int ii = 0;
01875     for (ii = 0; ii < cpl_vector_get_size(tmp_spec_data_orig); ii++) {
01876         if (cpl_vector_get(tmp_spec_data_orig, ii) < median/8)
01877             cpl_vector_set(tmp_spec_data_orig, ii, 0);
01878         if (cpl_vector_get(tmp_spec_data_atmo, ii) < median/8)
01879             cpl_vector_set(tmp_spec_data_atmo, ii, 0);
01880         if (cpl_vector_get(tmp_spec_data_new, ii) < median/8)
01881             cpl_vector_set(tmp_spec_data_new, ii, 0);
01882 
01883         if (cpl_vector_get(tmp_spec_data_orig, ii) > 3*median)
01884             cpl_vector_set(tmp_spec_data_orig, ii, 3*median);
01885         if (cpl_vector_get(tmp_spec_data_atmo, ii) > 3*median)
01886             cpl_vector_set(tmp_spec_data_atmo, ii, 3*median);
01887         if (cpl_vector_get(tmp_spec_data_new, ii) > 3*median)
01888             cpl_vector_set(tmp_spec_data_new, ii, 3*median);
01889     }
01890 
01891     double *pspec_dup = cpl_vector_get_data(tmp_spec_data_atmo);
01892     for (ii = 0; ii < cpl_vector_get_size(tmp_spec_data_atmo); ii++) {
01893         if (kmclipm_is_nan_or_inf(pspec_dup[ii])) {
01894             pspec_dup[ii] = 0.;
01895         }
01896     }
01897 
01898     cpl_bivector *plots[3];
01899     plots[0] = cpl_bivector_wrap_vectors((cpl_vector*)lambda_x, tmp_spec_data_orig);
01900     plots[1] = cpl_bivector_wrap_vectors((cpl_vector*)lambda_x, tmp_spec_data_atmo);
01901     plots[2] = cpl_bivector_wrap_vectors((cpl_vector*)lambda_x, tmp_spec_data_new);
01902     char *options[3] = {"w l t 'original'",
01903                         "w l t 'atmo divided'",
01904                         "w l t 'lines removed'"};
01905     sss = cpl_sprintf("set title '%s-band line removal (DET #%d)';", filter_id, i);
01906     cpl_plot_bivectors(sss,
01907                        (const char**)options, "", (const cpl_bivector**)plots, 3);
01908     cpl_bivector_unwrap_vectors(plots[0]);
01909     cpl_bivector_unwrap_vectors(plots[1]);
01910     cpl_bivector_unwrap_vectors(plots[2]);
01911     cpl_free(sss); sss = NULL;
01912     cpl_vector_delete(tmp_spec_data_orig); tmp_spec_data_orig = NULL;
01913     cpl_vector_delete(tmp_spec_data_atmo); tmp_spec_data_atmo = NULL;
01914     cpl_vector_delete(tmp_spec_data_new); tmp_spec_data_new = NULL;
01915 
01916 */
01917     return 0 ;
01918 }
01919 
01920 /*----------------------------------------------------------------------------*/
01926 /*----------------------------------------------------------------------------*/
01927 static int kmos_std_star_adjust_double(
01928         cpl_propertylist    *   header,
01929         const char          *   key1,
01930         const char          *   key2,
01931         const char          *   key3)
01932 {
01933     if (header==NULL || key1==NULL || key2==NULL || key3==NULL) return -1 ;
01934     cpl_propertylist_update_double(header, key1, 
01935             cpl_propertylist_get_double(header, key3));
01936     cpl_propertylist_erase(header, key2) ;
01937     cpl_propertylist_erase(header, key3) ;
01938     return 0 ;
01939 }
01940 
01941 /*----------------------------------------------------------------------------*/
01947 /*----------------------------------------------------------------------------*/
01948 static int kmos_std_star_adjust_string(
01949         cpl_propertylist    *   header,
01950         const char          *   key1,
01951         const char          *   key2,
01952         const char          *   key3)
01953 {
01954     if (header==NULL || key1==NULL || key2==NULL || key3==NULL) return -1 ;
01955     cpl_propertylist_update_string(header, key1, 
01956             cpl_propertylist_get_string(header, key3));
01957     cpl_propertylist_erase(header, key2) ;
01958     cpl_propertylist_erase(header, key3) ;
01959     return 0 ;
01960 }
01961 
01962 /*----------------------------------------------------------------------------*/
01970 /*----------------------------------------------------------------------------*/
01971 static cpl_frameset * kmos_std_star_extract_same_grat_stds(
01972         cpl_frameset        *   in,
01973         int                 *   same_gratings)
01974 {
01975     cpl_frameset        *   frameset_std ;
01976     cpl_frame           *   tmp_frame ;
01977     cpl_propertylist    *   tmp_header ;
01978     char                *   grat_id ;
01979 
01980     /* Check entries */
01981     if (in == NULL ||  same_gratings== NULL) return NULL ;
01982 
01983     /* Create new frameset */
01984     frameset_std = cpl_frameset_new();
01985 
01986     tmp_frame = kmo_dfs_get_frame(in, STD);
01987     tmp_header = kmclipm_propertylist_load(cpl_frame_get_filename(tmp_frame),0);
01988     grat_id = cpl_sprintf("%s", cpl_propertylist_get_string(tmp_header, 
01989                 "ESO INS GRAT1 ID"));
01990     cpl_propertylist_delete(tmp_header); 
01991     cpl_frameset_insert(frameset_std, cpl_frame_duplicate(tmp_frame));
01992 
01993     tmp_frame = kmo_dfs_get_frame(in, NULL);
01994     *same_gratings = TRUE ;
01995     while (tmp_frame != NULL ) {
01996         tmp_header=kmclipm_propertylist_load(cpl_frame_get_filename(tmp_frame),
01997                 0);
01998         if (!strcmp(grat_id, cpl_propertylist_get_string(tmp_header, 
01999                         "ESO INS GRAT1 ID"))) {
02000             cpl_frameset_insert(frameset_std, cpl_frame_duplicate(tmp_frame));
02001         } else {
02002             *same_gratings = FALSE;
02003         }
02004         cpl_propertylist_delete(tmp_header);
02005 
02006         tmp_frame = kmo_dfs_get_frame(in, NULL);
02007     }
02008     cpl_free(grat_id) ;
02009     return frameset_std ;
02010 }