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