|
KMOS Pipeline Reference Manual
1.3.17
|
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 <string.h> 00029 #include <math.h> 00030 00031 #ifdef __USE_XOPEN2K 00032 #include <stdlib.h> 00033 #define GGG 00034 #else 00035 #define __USE_XOPEN2K /* to get the definition for setenv in stdlib.h */ 00036 #include <stdlib.h> 00037 #undef __USE_XOPEN2K 00038 #endif 00039 00040 #include <cpl.h> 00041 00042 #include "kmo_utils.h" 00043 #include "kmos_pfits.h" 00044 #include "kmo_functions.h" 00045 #include "kmo_priv_wave_cal.h" 00046 #include "kmo_priv_functions.h" 00047 #include "kmo_cpl_extensions.h" 00048 #include "kmo_dfs.h" 00049 #include "kmo_error.h" 00050 #include "kmo_constants.h" 00051 #include "kmo_debug.h" 00052 00053 /*----------------------------------------------------------------------------- 00054 * Functions prototypes 00055 *----------------------------------------------------------------------------*/ 00056 00057 static int kmos_wave_cal_check_inputs(cpl_frameset *, int *, int *, int *, 00058 double *, int *, lampConfiguration *); 00059 00060 static int kmos_wave_cal_create(cpl_plugin *); 00061 static int kmos_wave_cal_exec(cpl_plugin *); 00062 static int kmos_wave_cal_destroy(cpl_plugin *); 00063 static int kmos_wave_cal(cpl_parameterlist *, cpl_frameset *); 00064 00065 /*----------------------------------------------------------------------------- 00066 * Static variables 00067 *----------------------------------------------------------------------------*/ 00068 00069 static char kmos_wave_cal_description[] = 00070 "This recipe creates the wavelength calibration frame needed for all three\n" 00071 "detectors. It must be called after the kmo_flat recipe, which generates the\n" 00072 "two spatial calibration frames needed in this recipe. As input a lamp-on \n" 00073 "frame, a lamp-off frame, the spatial calibration frames and the list with \n" 00074 "the reference arclines are required.\n" 00075 "An additional output frame is the resampled image of the reconstructed arc\n" 00076 "frame. All slitlets of all IFUs are aligned one next to the other. This \n" 00077 "frame serves for quality control. One can immediately see if the \n" 00078 "calibration was successful.\n" 00079 "The lists of reference arclines are supposed to contain the lines for both\n" 00080 "available calibration arc-lamps, i.e. Argon and Neon. The list is supposed\n" 00081 "to be a F2L KMOS FITS file with three columns:\n" 00082 "\t1. Reference wavelength\n" 00083 "\t2. Relative strength\n" 00084 "\t3. String either containing “Ar” or “Ne”\n" 00085 "The recipe extracts, based on the header keywords, either the applying\n" 00086 "argon and/or neon emission lines. Below are the plots of the emission lines\n" 00087 "for both argon and neon. The marked lines are the ones used for wavelength \n" 00088 "calibration.\n" 00089 "\n" 00090 "Furthermore frames can be provided for several rotator angles. In this case\n" 00091 "the resulting calibration frames for each detector are repeatedly saved as \n" 00092 "extension for every angle.\n" 00093 "\n" 00094 "BASIC PARAMETERS:\n" 00095 "-----------------\n" 00096 "--order\n" 00097 "The polynomial order to use for the fit of the wavelength solution.\n" 00098 "0: (default) The appropriate order is choosen automatically depending on\n" 00099 "the waveband (4 for IZ band, 5 for HK, 6 for the others)\n" 00100 "\n" 00101 "ADVANCED PARAMETERS\n" 00102 "-------------------\n" 00103 "--b_samples\n" 00104 "The number of samples in spectral direction for the reconstructed cube.\n" 00105 "Ideally this number should be greater than 2048, the detector size.\n" 00106 "\n" 00107 "--b_start\n" 00108 "--b_end\n" 00109 "Used to define manually the start and end wavelength for the reconstructed\n" 00110 "cube. By default the internally defined values are used.\n" 00111 "\n" 00112 "--suppress_extension\n" 00113 "If set to TRUE, the arbitrary filename extensions are supressed. If\n" 00114 "multiple products with the same category are produced, they will be numered\n" 00115 "consecutively starting from 0.\n" 00116 "\n" 00117 "--lines_estimation\n" 00118 "If set to TRUE, the lines estimation method is used\n" 00119 "\n" 00120 "----------------------------------------------------------------------------\n" 00121 "Input files:\n" 00122 "\n" 00123 " DO category Type Explanation Required #Frames\n" 00124 " ----------- ----- ----------- -------- -------\n" 00125 " ARC_ON RAW Arclamp-on exposure Y >=1\n" 00126 " ARC_OFF RAW Arclamp-off exposure Y 1\n" 00127 " XCAL F2D x calibration frame Y 1\n" 00128 " YCAL F2D y calibration frame Y 1\n" 00129 " ARC_LIST F2L List of arclines Y 1\n" 00130 " FLAT_EDGE F2L Fitted edge parameters Y 1\n" 00131 " REF_LINES F2L Reference line table Y 1\n" 00132 " WAVE_BAND F2L Table with start-/end-wavelengths Y 1\n" 00133 "\n" 00134 "Output files:\n" 00135 "\n" 00136 " DO category Type Explanation\n" 00137 " ----------- ----- -----------\n" 00138 " LCAL F2D Wavelength calibration frame\n" 00139 " (3 Extensions)\n" 00140 " DET_IMG_WAVE F2D reconstructed arclamp-on exposure\n" 00141 " (4 extensions: 3 detector images + \n" 00142 " the arclines list table)\n" 00143 "----------------------------------------------------------------------------\n" 00144 "\n"; 00145 00146 /*----------------------------------------------------------------------------- 00147 * Functions code 00148 *----------------------------------------------------------------------------*/ 00149 00156 /*----------------------------------------------------------------------------*/ 00165 /*----------------------------------------------------------------------------*/ 00166 int cpl_plugin_get_info(cpl_pluginlist *list) 00167 { 00168 cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe); 00169 cpl_plugin *plugin = &recipe->interface; 00170 00171 cpl_plugin_init(plugin, 00172 CPL_PLUGIN_API, 00173 KMOS_BINARY_VERSION, 00174 CPL_PLUGIN_TYPE_RECIPE, 00175 "kmos_wave_cal", 00176 "Create a wavelength calibration frame", 00177 kmos_wave_cal_description, 00178 "Alex Agudo Berbel, Yves Jung", 00179 "usd-help@eso.org", 00180 kmos_get_license(), 00181 kmos_wave_cal_create, 00182 kmos_wave_cal_exec, 00183 kmos_wave_cal_destroy); 00184 cpl_pluginlist_append(list, plugin); 00185 00186 return 0; 00187 } 00188 00189 /*----------------------------------------------------------------------------*/ 00197 /*----------------------------------------------------------------------------*/ 00198 static int kmos_wave_cal_create(cpl_plugin *plugin) 00199 { 00200 cpl_recipe *recipe; 00201 cpl_parameter *p; 00202 00203 // Check that the plugin is part of a valid recipe 00204 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00205 recipe = (cpl_recipe *)plugin; 00206 else 00207 return -1; 00208 00209 // Create the parameters list in the cpl_recipe object 00210 recipe->parameters = cpl_parameterlist_new(); 00211 00212 // Fill the parameters list 00213 p = cpl_parameter_new_range("kmos.kmos_wave_cal.order", CPL_TYPE_INT, 00214 "The fitting polynomial order used for the wavelength solution. " 00215 "By default, 4 for IZ band, 5 for HK, 6 for the others", 00216 "kmos.kmos_wave_cal", 0, 0, 7); 00217 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "order"); 00218 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00219 cpl_parameterlist_append(recipe->parameters, p); 00220 00221 /* --suppress_extension */ 00222 p = cpl_parameter_new_value("kmos.kmos_wave_cal.suppress_extension", 00223 CPL_TYPE_BOOL, "Suppress arbitrary filename extension", 00224 "kmos.kmos_wave_cal", FALSE); 00225 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "suppress_extension"); 00226 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00227 cpl_parameterlist_append(recipe->parameters, p); 00228 00229 /* --lines_estimation */ 00230 p = cpl_parameter_new_value("kmos.kmos_wave_cal.lines_estimation", 00231 CPL_TYPE_BOOL, "Trigger lines estimation method", 00232 "kmos.kmos_wave_cal", FALSE); 00233 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "lines_estimation"); 00234 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00235 cpl_parameterlist_append(recipe->parameters, p); 00236 00237 /* Add parameters for band-definition */ 00238 kmos_band_pars_create(recipe->parameters, "kmos.kmos_wave_cal"); 00239 00240 /* --detector */ 00241 p = cpl_parameter_new_value("kmos.kmos_wave_cal.detector", 00242 CPL_TYPE_INT, "Only reduce the specified detector", 00243 "kmos.kmos_wave_cal", 0); 00244 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "det"); 00245 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00246 cpl_parameterlist_append(recipe->parameters, p); 00247 00248 /* --angle */ 00249 p = cpl_parameter_new_value("kmos.kmos_wave_cal.angle", 00250 CPL_TYPE_DOUBLE, "Only reduce the specified angle", 00251 "kmos.kmos_wave_cal", 370.0); 00252 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "angle"); 00253 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00254 cpl_parameterlist_append(recipe->parameters, p); 00255 00256 return 0; 00257 } 00258 00259 /*----------------------------------------------------------------------------*/ 00265 /*----------------------------------------------------------------------------*/ 00266 static int kmos_wave_cal_exec(cpl_plugin *plugin) 00267 { 00268 cpl_recipe *recipe; 00269 00270 // Get the recipe out of the plugin 00271 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00272 recipe = (cpl_recipe *)plugin; 00273 else return -1; 00274 00275 return kmos_wave_cal(recipe->parameters, recipe->frames); 00276 } 00277 00278 /*----------------------------------------------------------------------------*/ 00284 /*----------------------------------------------------------------------------*/ 00285 static int kmos_wave_cal_destroy(cpl_plugin *plugin) 00286 { 00287 cpl_recipe *recipe; 00288 00289 // Get the recipe out of the plugin 00290 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00291 recipe = (cpl_recipe *)plugin; 00292 else return -1 ; 00293 00294 cpl_parameterlist_delete(recipe->parameters); 00295 return 0 ; 00296 } 00297 00298 /*----------------------------------------------------------------------------*/ 00312 /*----------------------------------------------------------------------------*/ 00313 static int kmos_wave_cal(cpl_parameterlist *parlist, cpl_frameset *frameset) 00314 { 00315 const cpl_parameter * par ; 00316 int suppress_extension, fit_order_par, fit_order ; 00317 int nx, ny, next, reduce_det, lines_estimation ; 00318 double exptime, gain, angle_found, reduce_angle ; 00319 cpl_frame * frame ; 00320 cpl_propertylist * mh_on ; 00321 cpl_propertylist * plist ; 00322 char * suffix ; 00323 lampConfiguration lamp_config; 00324 char ** filter_ids ; 00325 int * angles_array ; 00326 int nb_angles ; 00327 int non_dest_rom ; 00328 00329 cpl_propertylist ** stored_sub_headers_lcal ; 00330 cpl_propertylist ** stored_sub_headers_det_img ; 00331 cpl_image ** stored_lcal ; 00332 cpl_image ** stored_det_img ; 00333 int * stored_qc_arc_sat ; 00334 double * stored_qc_ar_eff ; 00335 double * stored_qc_ne_eff ; 00336 cpl_table * detector_edges[KMOS_IFUS_PER_DETECTOR] ; 00337 00338 int a, i, j, x, y ; 00339 00340 cpl_image * det_lamp_on ; 00341 cpl_image * det_lamp_off ; 00342 cpl_image * det_lamp_on_copy ; 00343 00344 cpl_table * arclines ; 00345 cpl_table * reflines ; 00346 cpl_bivector * lines ; 00347 00348 cpl_image * bad_pix_mask ; 00349 float * pbad_pix_mask ; 00350 cpl_image * xcal ; 00351 cpl_image * ycal ; 00352 cpl_image * lcal ; 00353 00354 int nr_sat ; 00355 00356 cpl_propertylist * qc_header ; 00357 00358 cpl_array ** unused_ifus_before ; 00359 cpl_array ** unused_ifus_after ; 00360 char * extname ; 00361 char * fn_suffix ; 00362 char * last_env ; 00363 const char * tmp_str ; 00364 cpl_error_code err ; 00365 00366 /* Check entries */ 00367 if (parlist == NULL || frameset == NULL) { 00368 cpl_msg_error(__func__, "Null Inputs") ; 00369 cpl_error_set(__func__, CPL_ERROR_NULL_INPUT) ; 00370 return -1 ; 00371 } 00372 00373 /* Get Parameters */ 00374 par = cpl_parameterlist_find_const(parlist, "kmos.kmos_wave_cal.order"); 00375 fit_order_par = cpl_parameter_get_int(par); 00376 par=cpl_parameterlist_find_const(parlist, 00377 "kmos.kmos_wave_cal.lines_estimation"); 00378 lines_estimation = cpl_parameter_get_bool(par); 00379 par=cpl_parameterlist_find_const(parlist, 00380 "kmos.kmos_wave_cal.suppress_extension"); 00381 suppress_extension = cpl_parameter_get_bool(par); 00382 par = cpl_parameterlist_find_const(parlist, "kmos.kmos_wave_cal.angle"); 00383 reduce_angle = cpl_parameter_get_double(par); 00384 par = cpl_parameterlist_find_const(parlist, "kmos.kmos_wave_cal.detector"); 00385 reduce_det = cpl_parameter_get_int(par); 00386 00387 kmos_band_pars_load(parlist, "kmos.kmos_wave_cal"); 00388 00389 /* Check Parameters */ 00390 if (fit_order_par < 0 || fit_order_par > 7) { 00391 cpl_msg_error(__func__, "Fitting Order must be in [0,7]") ; 00392 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00393 return -1 ; 00394 } 00395 if (reduce_det < 0 || reduce_det > 3) { 00396 cpl_msg_error(__func__, "detector must be in [1,3]") ; 00397 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00398 return -1 ; 00399 } 00400 00401 /* Identify the RAW and CALIB frames in the input frameset */ 00402 if (kmo_dfs_set_groups(frameset, "kmos_wave_cal") != 1) { 00403 cpl_msg_error(__func__, "Cannot identify RAW and CALIB frames") ; 00404 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00405 return -1 ; 00406 } 00407 00408 /* Check the inputs consistency */ 00409 if (kmos_wave_cal_check_inputs(frameset, &nx, &ny, &next, &exptime, 00410 &non_dest_rom, &lamp_config) != 1) { 00411 cpl_msg_error(__func__, "Input frameset is not consistent") ; 00412 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00413 return -1 ; 00414 } 00415 00416 /* Instrument setup */ 00417 suffix = kmo_dfs_get_suffix(kmo_dfs_get_frame(frameset, XCAL), TRUE, FALSE); 00418 cpl_msg_info(__func__, "Detected instrument setup: %s", suffix+1); 00419 00420 /* Check that filter and grating match for each detector */ 00421 /* filter/grating can be different for each detector */ 00422 frame = kmo_dfs_get_frame(frameset, ARC_ON); 00423 mh_on = cpl_propertylist_load(cpl_frame_get_filename(frame), 0); 00424 filter_ids = kmo_get_filter_setup(mh_on, next, TRUE) ; 00425 cpl_propertylist_delete(mh_on); 00426 if (filter_ids == NULL) { 00427 cpl_free(suffix); 00428 cpl_msg_error(__func__, "Cannot get Filter informations") ; 00429 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00430 return -1 ; 00431 } 00432 00433 /* Get Rotator angles */ 00434 if ((angles_array = kmos_get_angles(frameset, &nb_angles, ARC_ON)) == NULL){ 00435 cpl_msg_error(__func__, "Cannot get Angles informations") ; 00436 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00437 for (i = 0; i < next ; i++) cpl_free(filter_ids[i]); 00438 cpl_free(filter_ids); 00439 cpl_free(suffix); 00440 return -1 ; 00441 } 00442 00443 /* Check the ARC_LIST filter */ 00444 frame = kmo_dfs_get_frame(frameset, ARC_LIST); 00445 plist = cpl_propertylist_load(cpl_frame_get_filename(frame), 0); 00446 tmp_str = cpl_propertylist_get_string(plist, FILT_ID); 00447 if (strcmp(filter_ids[0], tmp_str) != 0) { 00448 cpl_msg_error(__func__, "Wrong ARC_LIST filter") ; 00449 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00450 for (i = 0; i < next ; i++) cpl_free(filter_ids[i]); 00451 cpl_free(filter_ids); 00452 cpl_free(angles_array); 00453 cpl_propertylist_delete(plist); 00454 return -1 ; 00455 } 00456 cpl_propertylist_delete(plist); 00457 00458 /* Load the lines as a CPL table */ 00459 arclines = kmo_dfs_load_table(frameset, ARC_LIST, 1, 0); 00460 lines = kmos_get_lines(arclines, lamp_config); 00461 cpl_table_delete(arclines); 00462 /* TODO : check not null */ 00463 cpl_msg_info(__func__, "Arc lines: %lld", cpl_bivector_get_size(lines)); 00464 00465 /* Load REFLINES */ 00466 if ((reflines = kmo_dfs_load_table(frameset, REF_LINES, 1, 0)) == NULL) { 00467 cpl_msg_error(__func__, "Missing REF_LINES calibration file") ; 00468 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00469 for (i = 0; i < next ; i++) cpl_free(filter_ids[i]); 00470 cpl_free(filter_ids); 00471 cpl_free(angles_array); 00472 cpl_bivector_delete(lines) ; 00473 return -1 ; 00474 } 00475 00476 /* Check which IFUs are active for all FLAT frames */ 00477 unused_ifus_before = kmo_get_unused_ifus(frameset, 0, 0); 00478 unused_ifus_after = kmo_duplicate_unused_ifus(unused_ifus_before); 00479 kmo_print_unused_ifus(unused_ifus_before, FALSE); 00480 if (unused_ifus_before != NULL) kmo_free_unused_ifus(unused_ifus_before); 00481 00482 /* make sure no reconstruction lookup table (LUT) is used */ 00483 if (getenv("KMCLIPM_PRIV_RECONSTRUCT_LUT_MODE") != NULL) { 00484 last_env = getenv("KMCLIPM_PRIV_RECONSTRUCT_LUT_MODE"); 00485 } else { 00486 last_env = NULL ; 00487 } 00488 setenv("KMCLIPM_PRIV_RECONSTRUCT_LUT_MODE","NONE",1); 00489 00490 /* the frames have to be stored temporarily because the QC params */ 00491 /* for the main header are calculated per detector. So they can be */ 00492 /* stored only when all detectors are processed */ 00493 stored_lcal = (cpl_image**)cpl_calloc(next * nb_angles, sizeof(cpl_image*)); 00494 stored_det_img = (cpl_image**)cpl_calloc(next*nb_angles,sizeof(cpl_image*)); 00495 stored_sub_headers_lcal = (cpl_propertylist**)cpl_calloc(next * nb_angles, 00496 sizeof(cpl_propertylist*)); 00497 stored_sub_headers_det_img = (cpl_propertylist**)cpl_calloc(next*nb_angles, 00498 sizeof(cpl_propertylist*)); 00499 stored_qc_arc_sat = (int*)cpl_calloc(next, nb_angles * sizeof(int)); 00500 stored_qc_ar_eff=(double*)cpl_calloc(next, nb_angles * sizeof(double)); 00501 stored_qc_ne_eff=(double*)cpl_calloc(next, nb_angles * sizeof(double)); 00502 00503 /* Loop all Rotator Angles and Detectors */ 00504 for (a = 0; a < nb_angles; a++) { 00505 /* Reduce only one angle */ 00506 if (reduce_angle <= 360 && angles_array[a] != reduce_angle) continue ; 00507 00508 cpl_msg_info(__func__, "Processing rotator angle %d -> %d degree", 00509 a, angles_array[a]); 00510 cpl_msg_indent_more(); 00511 for (i = 1; i <= next ; i++) { 00512 /* Compute only one detetor */ 00513 if (reduce_det != 0 && i != reduce_det) continue ; 00514 00515 cpl_msg_info(__func__,"Processing detector No. %d", i); 00516 cpl_msg_indent_more(); 00517 00518 /* Load edge parameters */ 00519 frame=kmo_dfs_get_frame(frameset, FLAT_EDGE); 00520 for (j = 0; j < KMOS_IFUS_PER_DETECTOR; j++) { 00521 detector_edges[j] = kmclipm_cal_table_load( 00522 cpl_frame_get_filename(frame), 00523 (i-1) * KMOS_IFUS_PER_DETECTOR + j + 1, 00524 angles_array[a], 0, &angle_found); 00525 00526 /* IFU is inactive: proceed */ 00527 if (cpl_error_get_code() == CPL_ERROR_ILLEGAL_INPUT) { 00528 cpl_error_reset(); 00529 } 00530 } 00531 00532 /* Set default fit orders for the different bands */ 00533 if (fit_order_par == 0) { 00534 if ((strcmp(filter_ids[i-1], "H") == 0) || 00535 (strcmp(filter_ids[i-1], "K") == 0) || 00536 (strcmp(filter_ids[i-1], "YJ") == 0)) { 00537 fit_order = 6; 00538 } else if (strcmp(filter_ids[i-1], "IZ") == 0) { 00539 fit_order = 4; 00540 } else if (strcmp(filter_ids[i-1], "HK") == 0) { 00541 fit_order = 5; 00542 } 00543 cpl_msg_info(__func__, 00544 "Order of wavelength spectrum fit for %s-band: %d", 00545 filter_ids[i-1], fit_order); 00546 } else { 00547 fit_order = fit_order_par; 00548 } 00549 00550 /* Get ARC_ON frame and Load it */ 00551 frame = kmos_get_angle_frame(frameset, angles_array[a], ARC_ON); 00552 det_lamp_on = kmo_dfs_load_image_frame(frame,i,FALSE, TRUE,&nr_sat); 00553 int sx = a * next + (i - 1); 00554 00555 /* Count saturated pixels for each detector */ 00556 if (non_dest_rom) 00557 stored_qc_arc_sat[sx] = nr_sat; 00558 else 00559 stored_qc_arc_sat[sx] = kmo_image_get_saturated(det_lamp_on, 00560 KMO_FLAT_SATURATED); 00561 00562 det_lamp_on_copy = cpl_image_duplicate(det_lamp_on); 00563 00564 /* Get ARC_OFF frame and Load it */ 00565 frame = kmo_dfs_get_frame(frameset, ARC_OFF); 00566 det_lamp_off = kmo_dfs_load_image_frame(frame, i, FALSE, FALSE, 00567 NULL); 00568 00569 /* ARC_ON = ARC_ON - ARC_OFF */ 00570 cpl_image_subtract(det_lamp_on, det_lamp_off); 00571 00572 /* Load XCAL,YCAL */ 00573 xcal = kmo_dfs_load_cal_image(frameset, XCAL, i, 0, 00574 (double)angles_array[a], FALSE, NULL, &angle_found, -1,0,0); 00575 ycal = kmo_dfs_load_cal_image(frameset, YCAL, i, 0, 00576 (double)angles_array[a], FALSE, NULL, &angle_found, -1,0,0); 00577 if (xcal == NULL || ycal == NULL) { 00578 /* Missing calibration for this detector */ 00579 cpl_error_reset() ; 00580 stored_det_img[sx] = NULL ; 00581 stored_lcal[sx] = cpl_image_new(nx, ny, CPL_TYPE_FLOAT); 00582 kmo_image_fill(stored_lcal[sx], 0.0); 00583 if (xcal != NULL) cpl_image_delete(xcal) ; 00584 if (ycal != NULL) cpl_image_delete(ycal) ; 00585 cpl_image_delete(det_lamp_on_copy) ; 00586 cpl_image_delete(det_lamp_on) ; 00587 cpl_image_delete(det_lamp_off) ; 00588 continue ; 00589 } 00590 00591 /* Derive BPM from XCAL : NaNs to 0, Others to 1 */ 00592 bad_pix_mask = cpl_image_duplicate(xcal); 00593 pbad_pix_mask = cpl_image_get_data_float(bad_pix_mask); 00594 for (x = 0; x < nx; x++) { 00595 for (y = 0; y < ny; y++) { 00596 if (isnan(pbad_pix_mask[x+nx*y])) { 00597 pbad_pix_mask[x+nx*y] = 0.; 00598 } else { 00599 pbad_pix_mask[x+nx*y] = 1.; 00600 } 00601 } 00602 } 00603 00604 /* Compute wavelength calibration */ 00605 err = kmos_calc_wave_calib(det_lamp_on, bad_pix_mask, 00606 filter_ids[i-1], lamp_config, i, unused_ifus_after[i-1], 00607 detector_edges, lines, reflines, &lcal, 00608 &(stored_qc_ar_eff[sx]), &(stored_qc_ne_eff[sx]), fit_order, 00609 lines_estimation); 00610 cpl_image_delete(det_lamp_on); 00611 for (j = 0; j < KMOS_IFUS_PER_DETECTOR; j++) { 00612 cpl_table_delete(detector_edges[j]); 00613 } 00614 if (err == CPL_ERROR_NONE) { 00615 /* Update QC parameters */ 00616 if (stored_qc_ar_eff[sx] != -1.0) 00617 stored_qc_ar_eff[sx] /= exptime; 00618 if (stored_qc_ne_eff[sx] != -1.0) 00619 stored_qc_ne_eff[sx] /= exptime; 00620 00621 /* Apply the badpixel mask to the produced frame */ 00622 cpl_image_multiply(lcal, bad_pix_mask); 00623 kmo_image_reject_from_mask(lcal, bad_pix_mask); 00624 00625 /* Store Result frame */ 00626 stored_lcal[sx] = lcal; 00627 } else if (err == CPL_ERROR_UNSPECIFIED) { 00628 /* All IFUs seem to be deactivated */ 00629 /* Continue processing - just save empty frame */ 00630 cpl_error_reset(); 00631 stored_lcal[sx] = cpl_image_new(nx, ny, CPL_TYPE_FLOAT); 00632 kmo_image_fill(stored_lcal[sx], 0.0); 00633 } else { 00634 cpl_error_reset(); 00635 cpl_msg_warning(__func__, 00636 "Couldn't identify any line - Check the line list"); 00637 cpl_msg_warning(__func__, 00638 "Band defined in header of detector %d: %s", 00639 i, filter_ids[i-1]); 00640 cpl_msg_warning(__func__, "Arc line file defined: %s", 00641 cpl_frame_get_filename(kmo_dfs_get_frame(frameset, 00642 ARC_LIST))); 00643 } 00644 cpl_image_delete(bad_pix_mask); 00645 00646 /* CREATE RECONSTRUCTED AND RESAMPLED ARC FRAME */ 00647 stored_det_img[sx] = kmo_reconstructed_arc_image(frameset, 00648 det_lamp_on_copy, det_lamp_off, xcal, ycal, stored_lcal[sx], 00649 unused_ifus_after[i-1], FALSE, i, suffix, filter_ids[i-1], 00650 lamp_config, &qc_header); 00651 cpl_image_delete(det_lamp_on_copy); 00652 cpl_image_delete(det_lamp_off); 00653 cpl_image_delete(xcal); 00654 cpl_image_delete(ycal); 00655 if (cpl_error_get_code() != CPL_ERROR_NONE) { 00656 cpl_msg_error(__func__,"Cannot reconstruct IFUs on detector %d", 00657 i); 00658 cpl_error_reset(); 00659 } 00660 00661 /* CREATE EXTENSION HEADER FOR THE PRODUCT */ 00662 stored_sub_headers_lcal[sx] = kmo_dfs_load_sub_header(frameset, 00663 ARC_ON, i, FALSE); 00664 /* update EXTNAME */ 00665 extname = kmo_extname_creator(detector_frame, i, EXT_DATA); 00666 kmclipm_update_property_string(stored_sub_headers_lcal[sx], EXTNAME, 00667 extname, "FITS extension name"); 00668 cpl_free(extname); 00669 00670 kmclipm_update_property_int(stored_sub_headers_lcal[sx], EXTVER, 00671 sx+1, "FITS extension ver"); 00672 00673 // add first QC parameters 00674 kmclipm_update_property_int(stored_sub_headers_lcal[sx], 00675 QC_ARC_SAT, stored_qc_arc_sat[sx], 00676 "[] nr. saturated pixels of arc exp."); 00677 00678 gain=kmo_dfs_get_property_double(stored_sub_headers_lcal[sx],GAIN); 00679 00680 if (stored_qc_ar_eff[sx] != -1.0) { 00681 kmclipm_update_property_double(stored_sub_headers_lcal[sx], 00682 QC_ARC_AR_EFF, stored_qc_ar_eff[sx]/gain, 00683 "[e-/s] Argon lamp efficiency"); 00684 } 00685 00686 if (stored_qc_ne_eff[sx] != -1.0) { 00687 kmclipm_update_property_double(stored_sub_headers_lcal[sx], 00688 QC_ARC_NE_EFF, stored_qc_ne_eff[sx]/gain, 00689 "[e-/s] Neon lamp efficiency"); 00690 } 00691 00692 kmclipm_update_property_double(stored_sub_headers_lcal[sx], 00693 CAL_ROTANGLE, ((double) angles_array[a]), 00694 "[deg] Rotator relative to nasmyth"); 00695 00696 /* append QC parameters */ 00697 cpl_propertylist_append(stored_sub_headers_lcal[sx], qc_header); 00698 cpl_propertylist_delete(qc_header); 00699 00700 stored_sub_headers_det_img[sx]=cpl_propertylist_duplicate( 00701 stored_sub_headers_lcal[sx]); 00702 00703 cpl_propertylist_erase(stored_sub_headers_lcal[sx], CRVAL1); 00704 cpl_propertylist_erase(stored_sub_headers_lcal[sx], CRVAL2); 00705 cpl_propertylist_erase(stored_sub_headers_lcal[sx], CTYPE1); 00706 cpl_propertylist_erase(stored_sub_headers_lcal[sx], CTYPE2); 00707 cpl_propertylist_erase(stored_sub_headers_lcal[sx], CDELT1); 00708 cpl_propertylist_erase(stored_sub_headers_lcal[sx], CDELT2); 00709 00710 cpl_msg_indent_less(); 00711 } // for i devices 00712 cpl_msg_indent_less() ; 00713 } // for a angles 00714 00715 /* Free */ 00716 cpl_free(angles_array) ; 00717 for (i = 0; i < next; i++) cpl_free(filter_ids[i]); 00718 cpl_free(filter_ids); 00719 cpl_bivector_delete(lines); 00720 00721 cpl_free(stored_qc_arc_sat); 00722 cpl_free(stored_qc_ar_eff); 00723 cpl_free(stored_qc_ne_eff); 00724 cpl_table_delete(reflines); 00725 00726 /* QC parameters & saving */ 00727 cpl_msg_info(__func__, "Saving data..."); 00728 00729 /* load, update & save primary header */ 00730 if (!suppress_extension) fn_suffix = cpl_sprintf("%s", suffix); 00731 else fn_suffix = cpl_sprintf("%s", ""); 00732 cpl_free(suffix); 00733 00734 /* update which IFUs are not used */ 00735 frame = kmo_dfs_get_frame(frameset, ARC_ON); 00736 mh_on = kmclipm_propertylist_load(cpl_frame_get_filename(frame), 0); 00737 kmo_set_unused_ifus(unused_ifus_after, mh_on, "kmos_wave_cal"); 00738 kmo_dfs_save_main_header(frameset, LCAL, fn_suffix, frame, mh_on, parlist, 00739 cpl_func); 00740 kmo_dfs_save_main_header(frameset, DET_IMG_WAVE, fn_suffix, frame, mh_on, 00741 parlist, cpl_func); 00742 cpl_propertylist_delete(mh_on); 00743 00744 /* Save sub-frames */ 00745 for (a = 0; a < nb_angles; a++) { 00746 for (i = 1; i <= next ; i++) { 00747 int sx = a * next + (i - 1); 00748 /* save lcal-frame */ 00749 kmo_dfs_save_image(stored_lcal[sx], LCAL, fn_suffix, 00750 stored_sub_headers_lcal[sx], 0./0.); 00751 00752 /* save detector image */ 00753 kmo_dfs_save_image(stored_det_img[sx], DET_IMG_WAVE, fn_suffix, 00754 stored_sub_headers_det_img[sx], 0./0.); 00755 } // for i = nxte 00756 } // for a angles 00757 00758 /* Free */ 00759 cpl_free(fn_suffix); 00760 for (i = 0; i < next * nb_angles; i++) { 00761 cpl_image_delete(stored_lcal[i]); 00762 cpl_image_delete(stored_det_img[i]); 00763 cpl_propertylist_delete(stored_sub_headers_lcal[i]); 00764 cpl_propertylist_delete(stored_sub_headers_det_img[i]); 00765 } 00766 cpl_free(stored_lcal); 00767 cpl_free(stored_det_img); 00768 cpl_free(stored_sub_headers_lcal); 00769 cpl_free(stored_sub_headers_det_img); 00770 00771 /* print which IFUs are not used */ 00772 kmo_print_unused_ifus(unused_ifus_after, TRUE); 00773 if (unused_ifus_after != NULL) kmo_free_unused_ifus(unused_ifus_after); 00774 00775 if (last_env != NULL) { 00776 setenv("KMCLIPM_PRIV_RECONSTRUCT_LUT_MODE",last_env,1); 00777 } else { 00778 unsetenv("KMCLIPM_PRIV_RECONSTRUCT_LUT_MODE"); 00779 } 00780 return 0; 00781 } 00782 00785 /*----------------------------------------------------------------------------*/ 00797 /*----------------------------------------------------------------------------*/ 00798 static int kmos_wave_cal_check_inputs( 00799 cpl_frameset * frameset, 00800 int * nx, 00801 int * ny, 00802 int * next, 00803 double * exptime, 00804 int * non_dest_rom, 00805 lampConfiguration * lamp_config) 00806 { 00807 const cpl_frame * frame_off ; 00808 const cpl_frame * frame_on ; 00809 cpl_propertylist * mh_off ; 00810 cpl_propertylist * mh_on ; 00811 cpl_propertylist * eh_off ; 00812 cpl_propertylist * eh_on ; 00813 int ext, next_off, next_on, nx_on, ny_on, nx_off,ny_off; 00814 double ndit_off, ndit_on, exptime_off, exptime_on ; 00815 const char * readmode_off ; 00816 const char * readmode_on ; 00817 00818 /* TODO Check Lamps TODO */ 00819 00820 /* Check Entries */ 00821 if (nx == NULL || ny == NULL || next == NULL || frameset == NULL) return -1; 00822 00823 /* Setup lamp config */ 00824 frame_on = kmo_dfs_get_frame(frameset, ARC_ON); 00825 mh_on = cpl_propertylist_load(cpl_frame_get_filename(frame_on), 0); 00826 if ((kmo_check_lamp(mh_on, INS_LAMP1_ST) == TRUE) && 00827 (kmo_check_lamp(mh_on, INS_LAMP2_ST) == FALSE)) { 00828 *lamp_config = ARGON; 00829 cpl_msg_info(__func__, "Arc lamp: Argon"); 00830 } else if ((kmo_check_lamp(mh_on, INS_LAMP1_ST) == FALSE) && 00831 (kmo_check_lamp(mh_on, INS_LAMP2_ST) == TRUE)) { 00832 *lamp_config = NEON; 00833 cpl_msg_info(__func__, "Arc lamp: Neon"); 00834 } else if ((kmo_check_lamp(mh_on, INS_LAMP1_ST) == TRUE) && 00835 (kmo_check_lamp(mh_on, INS_LAMP2_ST) == TRUE)) { 00836 *lamp_config = ARGON_NEON; 00837 cpl_msg_info(__func__, "Arc lamp: Argon + Neon"); 00838 } else { 00839 *lamp_config = -1 ; 00840 cpl_msg_warning(__func__, "Arc lamp: UNDEFINED"); 00841 } 00842 00843 /* Check READ OUT MODE */ 00844 readmode_on = kmos_pfits_get_readmode(mh_on); 00845 if (!strcmp(readmode_on, "Nondest")) { 00846 *non_dest_rom = 1 ; 00847 } else { 00848 *non_dest_rom = 0 ; 00849 } 00850 cpl_propertylist_delete(mh_on); 00851 00852 /* Get ARC_OFF */ 00853 frame_off = kmo_dfs_get_frame(frameset, ARC_OFF); 00854 if (frame_off == NULL) { 00855 cpl_msg_error(__func__, "No ARC_OFF frame found") ; 00856 return -1 ; 00857 } 00858 00859 /* Get ARC_OFF main header infos */ 00860 next_off = cpl_frame_get_nextensions(frame_off); 00861 mh_off = cpl_propertylist_load(cpl_frame_get_filename(frame_off), 0); 00862 ndit_off = kmos_pfits_get_ndit(mh_off) ; 00863 exptime_off = kmos_pfits_get_exptime(mh_off) ; 00864 readmode_off = kmos_pfits_get_readmode(mh_off); 00865 00866 /* Get ARC_ON frames and loop on them */ 00867 frame_on = kmo_dfs_get_frame(frameset, ARC_ON); 00868 if (frame_on == NULL) { 00869 cpl_msg_error(__func__, "No ARC_ON frame found") ; 00870 cpl_propertylist_delete(mh_off); 00871 return -1 ; 00872 } 00873 while (frame_on != NULL) { 00874 /* Get ARC_ON main header infos */ 00875 next_on = cpl_frame_get_nextensions(frame_on); 00876 mh_on = cpl_propertylist_load(cpl_frame_get_filename(frame_on), 0); 00877 ndit_on = kmos_pfits_get_ndit(mh_on) ; 00878 exptime_on = kmos_pfits_get_exptime(mh_on) ; 00879 readmode_on = kmos_pfits_get_readmode(mh_on); 00880 00881 /* Check consistency */ 00882 if (ndit_on != ndit_off || strcmp(readmode_on, readmode_off) || 00883 fabs(exptime_on-exptime_off) > 0.01 || next_off != next_on) { 00884 cpl_msg_warning(__func__, "Inconsistency for frame %s", 00885 cpl_frame_get_filename(frame_on)) ; 00886 cpl_propertylist_delete(mh_off); 00887 cpl_propertylist_delete(mh_on); 00888 return 0 ; 00889 } 00890 cpl_propertylist_delete(mh_on); 00891 00892 /* Get next frame */ 00893 frame_on = kmo_dfs_get_frame(frameset, NULL); 00894 } 00895 cpl_propertylist_delete(mh_off); 00896 00897 /* Check the extensions */ 00898 for (ext = 1; ext <= next_off ; ext++) { 00899 eh_off = cpl_propertylist_load(cpl_frame_get_filename(frame_off), ext); 00900 nx_off = kmos_pfits_get_naxis1(eh_off) ; 00901 ny_off = kmos_pfits_get_naxis2(eh_off) ; 00902 00903 frame_on = kmo_dfs_get_frame(frameset, ARC_ON); 00904 while (frame_on != NULL) { 00905 eh_on = cpl_propertylist_load(cpl_frame_get_filename(frame_on),ext); 00906 nx_on = kmos_pfits_get_naxis1(eh_on) ; 00907 ny_on = kmos_pfits_get_naxis2(eh_on) ; 00908 /* Check consistency */ 00909 if (nx_on != nx_off || ny_off != ny_on) { 00910 cpl_msg_warning(__func__, "Inconsistency for frame %s", 00911 cpl_frame_get_filename(frame_on)) ; 00912 cpl_propertylist_delete(eh_off); 00913 cpl_propertylist_delete(eh_on); 00914 return 0 ; 00915 } 00916 cpl_propertylist_delete(eh_on); 00917 00918 /* Get next frame */ 00919 frame_on = kmo_dfs_get_frame(frameset, NULL); 00920 } 00921 cpl_propertylist_delete(eh_off); 00922 } 00923 00924 /* FLAT_EDGE Checks */ 00925 frame_on = kmo_dfs_get_frame(frameset, FLAT_EDGE); 00926 if (cpl_frame_get_nextensions(frame_on) % 24 != 0) { 00927 cpl_msg_warning(__func__, "FLAT_EDGE frame is not consistent") ; 00928 return 0 ; 00929 } 00930 00931 /* Checks on XCAL YCAL */ 00932 kmo_check_frame_setup(frameset, ARC_ON, XCAL, TRUE, FALSE, FALSE); 00933 kmo_check_frame_setup(frameset, ARC_ON, YCAL, TRUE, FALSE, FALSE); 00934 kmo_check_frame_setup_md5_xycal(frameset); 00935 if (cpl_error_get_code() != CPL_ERROR_NONE) { 00936 cpl_msg_warning(__func__, "XCAL / YCAL checks failed") ; 00937 return 0 ; 00938 } 00939 00940 /* Return */ 00941 *nx = nx_off ; 00942 *ny = ny_off ; 00943 *next = next_off ; 00944 *exptime = exptime_off ; 00945 return 1 ; 00946 } 00947 00948
1.7.6.1