|
KMOS Pipeline Reference Manual
1.3.7
|
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_value("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); 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, ne, 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, &ne, &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, ne, 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 < ne ; 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 < ne ; 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 (lines_estimation == 0) { 00467 reflines = kmo_dfs_load_table(frameset, REF_LINES, 1, 0); 00468 } 00469 00470 /* Check which IFUs are active for all FLAT frames */ 00471 unused_ifus_before = kmo_get_unused_ifus(frameset, 0, 0); 00472 unused_ifus_after = kmo_duplicate_unused_ifus(unused_ifus_before); 00473 kmo_print_unused_ifus(unused_ifus_before, FALSE); 00474 if (unused_ifus_before != NULL) kmo_free_unused_ifus(unused_ifus_before); 00475 00476 /* make sure no reconstruction lookup table (LUT) is used */ 00477 if (getenv("KMCLIPM_PRIV_RECONSTRUCT_LUT_MODE") != NULL) { 00478 last_env = getenv("KMCLIPM_PRIV_RECONSTRUCT_LUT_MODE"); 00479 } 00480 setenv("KMCLIPM_PRIV_RECONSTRUCT_LUT_MODE","NONE",1); 00481 00482 /* the frames have to be stored temporarily because the QC params */ 00483 /* for the main header are calculated per detector. So they can be */ 00484 /* stored only when all detectors are processed */ 00485 stored_lcal = (cpl_image**)cpl_calloc(ne * nb_angles, sizeof(cpl_image*)); 00486 stored_det_img = (cpl_image**)cpl_calloc(ne * nb_angles,sizeof(cpl_image*)); 00487 stored_sub_headers_lcal = (cpl_propertylist**)cpl_calloc(ne * nb_angles, 00488 sizeof(cpl_propertylist*)); 00489 stored_sub_headers_det_img = (cpl_propertylist**)cpl_calloc(ne * nb_angles, 00490 sizeof(cpl_propertylist*)); 00491 stored_qc_arc_sat = (int*)cpl_calloc(ne, nb_angles * sizeof(int)); 00492 stored_qc_ar_eff=(double*)cpl_calloc(ne, nb_angles * sizeof(double)); 00493 stored_qc_ne_eff=(double*)cpl_calloc(ne, nb_angles * sizeof(double)); 00494 00495 /* Loop all Rotator Angles and Detectors */ 00496 for (a = 0; a < nb_angles; a++) { 00497 /* Reduce only one angle */ 00498 if (reduce_angle <= 360 && angles_array[a] != reduce_angle) continue ; 00499 00500 cpl_msg_info(__func__, "Processing rotator angle %d -> %d degree", 00501 a, angles_array[a]); 00502 cpl_msg_indent_more(); 00503 for (i = 1; i <= ne ; i++) { 00504 /* Compute only one detetor */ 00505 if (reduce_det != 0 && i != reduce_det) continue ; 00506 00507 cpl_msg_info(__func__,"Processing detector No. %d", i); 00508 cpl_msg_indent_more(); 00509 00510 /* Load edge parameters */ 00511 frame=kmo_dfs_get_frame(frameset, FLAT_EDGE); 00512 for (j = 0; j < KMOS_IFUS_PER_DETECTOR; j++) { 00513 detector_edges[j] = kmclipm_cal_table_load( 00514 cpl_frame_get_filename(frame), 00515 (i-1) * KMOS_IFUS_PER_DETECTOR + j + 1, 00516 angles_array[a], 0, &angle_found); 00517 00518 /* IFU is inactive: proceed */ 00519 if (cpl_error_get_code() == CPL_ERROR_ILLEGAL_INPUT) { 00520 cpl_error_reset(); 00521 } 00522 } 00523 00524 /* Set default fit orders for the different bands */ 00525 if (fit_order_par == 0) { 00526 if ((strcmp(filter_ids[i-1], "H") == 0) || 00527 (strcmp(filter_ids[i-1], "K") == 0) || 00528 (strcmp(filter_ids[i-1], "YJ") == 0)) { 00529 fit_order = 6; 00530 } else if (strcmp(filter_ids[i-1], "IZ") == 0) { 00531 fit_order = 4; 00532 } else if (strcmp(filter_ids[i-1], "HK") == 0) { 00533 fit_order = 5; 00534 } 00535 cpl_msg_info(__func__, 00536 "Order of wavelength spectrum fit for %s-band: %d", 00537 filter_ids[i-1], fit_order); 00538 } else { 00539 fit_order = fit_order_par; 00540 } 00541 00542 /* Get ARC_ON frame and Load it */ 00543 frame = kmos_get_angle_frame(frameset, angles_array[a], ARC_ON); 00544 det_lamp_on = kmo_dfs_load_image_frame(frame,i,FALSE, TRUE,&nr_sat); 00545 int sx = a * ne + (i - 1); 00546 00547 /* Count saturated pixels for each detector */ 00548 if (non_dest_rom) 00549 stored_qc_arc_sat[sx] = nr_sat; 00550 else 00551 stored_qc_arc_sat[sx] = kmo_image_get_saturated(det_lamp_on, 00552 KMO_FLAT_SATURATED); 00553 00554 det_lamp_on_copy = cpl_image_duplicate(det_lamp_on); 00555 00556 /* Get ARC_OFF frame and Load it */ 00557 frame = kmo_dfs_get_frame(frameset, ARC_OFF); 00558 det_lamp_off = kmo_dfs_load_image_frame(frame, i, FALSE, FALSE, 00559 NULL); 00560 00561 /* ARC_ON = ARC_ON - ARC_OFF */ 00562 cpl_image_subtract(det_lamp_on, det_lamp_off); 00563 00564 /* Load XCAL,YCAL */ 00565 xcal = kmo_dfs_load_cal_image(frameset, XCAL, i, 0, 00566 (double)angles_array[a], FALSE, NULL, &angle_found, -1,0,0); 00567 ycal = kmo_dfs_load_cal_image(frameset, YCAL, i, 0, 00568 (double)angles_array[a], FALSE, NULL, &angle_found, -1,0,0); 00569 if (xcal == NULL || ycal == NULL) { 00570 /* Missing calibration for this detector */ 00571 cpl_error_reset() ; 00572 stored_det_img[sx] = NULL ; 00573 stored_lcal[sx] = cpl_image_new(nx, ny, CPL_TYPE_FLOAT); 00574 kmo_image_fill(stored_lcal[sx], 0.0); 00575 if (xcal != NULL) cpl_image_delete(xcal) ; 00576 if (ycal != NULL) cpl_image_delete(ycal) ; 00577 cpl_image_delete(det_lamp_on_copy) ; 00578 cpl_image_delete(det_lamp_on) ; 00579 cpl_image_delete(det_lamp_off) ; 00580 continue ; 00581 } 00582 00583 /* Derive BPM from XCAL : NaNs to 0, Others to 1 */ 00584 bad_pix_mask = cpl_image_duplicate(xcal); 00585 pbad_pix_mask = cpl_image_get_data_float(bad_pix_mask); 00586 for (x = 0; x < nx; x++) { 00587 for (y = 0; y < ny; y++) { 00588 if (isnan(pbad_pix_mask[x+nx*y])) { 00589 pbad_pix_mask[x+nx*y] = 0.; 00590 } else { 00591 pbad_pix_mask[x+nx*y] = 1.; 00592 } 00593 } 00594 } 00595 00596 /* Compute wavelength calibration */ 00597 err = kmos_calc_wave_calib(det_lamp_on, bad_pix_mask, 00598 filter_ids[i-1], lamp_config, i, unused_ifus_after[i-1], 00599 detector_edges, lines, reflines, &lcal, 00600 &(stored_qc_ar_eff[sx]), &(stored_qc_ne_eff[sx]), fit_order, 00601 lines_estimation); 00602 cpl_image_delete(det_lamp_on); 00603 for (j = 0; j < KMOS_IFUS_PER_DETECTOR; j++) { 00604 cpl_table_delete(detector_edges[j]); 00605 } 00606 if (err == CPL_ERROR_NONE) { 00607 /* Update QC parameters */ 00608 if (stored_qc_ar_eff[sx] != -1.0) 00609 stored_qc_ar_eff[sx] /= exptime; 00610 if (stored_qc_ne_eff[sx] != -1.0) 00611 stored_qc_ne_eff[sx] /= exptime; 00612 00613 /* Apply the badpixel mask to the produced frame */ 00614 cpl_image_multiply(lcal, bad_pix_mask); 00615 kmo_image_reject_from_mask(lcal, bad_pix_mask); 00616 00617 /* Store Result frame */ 00618 stored_lcal[sx] = lcal; 00619 } else if (err == CPL_ERROR_UNSPECIFIED) { 00620 /* All IFUs seem to be deactivated */ 00621 /* Continue processing - just save empty frame */ 00622 cpl_error_reset(); 00623 stored_lcal[sx] = cpl_image_new(nx, ny, CPL_TYPE_FLOAT); 00624 kmo_image_fill(stored_lcal[sx], 0.0); 00625 } else { 00626 cpl_error_reset(); 00627 cpl_msg_warning(__func__, 00628 "Couldn't identify any line - Check the line list"); 00629 cpl_msg_warning(__func__, 00630 "Band defined in header of detector %d: %s", 00631 i, filter_ids[i-1]); 00632 cpl_msg_warning(__func__, "Arc line file defined: %s", 00633 cpl_frame_get_filename(kmo_dfs_get_frame(frameset, 00634 ARC_LIST))); 00635 } 00636 cpl_image_delete(bad_pix_mask); 00637 00638 /* CREATE RECONSTRUCTED AND RESAMPLED ARC FRAME */ 00639 stored_det_img[sx] = kmo_reconstructed_arc_image(frameset, 00640 det_lamp_on_copy, det_lamp_off, xcal, ycal, stored_lcal[sx], 00641 unused_ifus_after[i-1], FALSE, i, suffix, filter_ids[i-1], 00642 lamp_config, &qc_header); 00643 cpl_image_delete(det_lamp_on_copy); 00644 cpl_image_delete(det_lamp_off); 00645 cpl_image_delete(xcal); 00646 cpl_image_delete(ycal); 00647 if (cpl_error_get_code() != CPL_ERROR_NONE) { 00648 cpl_msg_error(__func__,"Cannot reconstruct IFUs on detector %d", 00649 i); 00650 cpl_error_reset(); 00651 } 00652 00653 /* CREATE EXTENSION HEADER FOR THE PRODUCT */ 00654 stored_sub_headers_lcal[sx] = kmo_dfs_load_sub_header(frameset, 00655 ARC_ON, i, FALSE); 00656 /* update EXTNAME */ 00657 extname = kmo_extname_creator(detector_frame, i, EXT_DATA); 00658 kmclipm_update_property_string(stored_sub_headers_lcal[sx], EXTNAME, 00659 extname, "FITS extension name"); 00660 cpl_free(extname); 00661 00662 kmclipm_update_property_int(stored_sub_headers_lcal[sx], EXTVER, 00663 sx+1, "FITS extension ver"); 00664 00665 // add first QC parameters 00666 kmclipm_update_property_int(stored_sub_headers_lcal[sx], 00667 QC_ARC_SAT, stored_qc_arc_sat[sx], 00668 "[] nr. saturated pixels of arc exp."); 00669 00670 gain=kmo_dfs_get_property_double(stored_sub_headers_lcal[sx],GAIN); 00671 00672 if (stored_qc_ar_eff[sx] != -1.0) { 00673 kmclipm_update_property_double(stored_sub_headers_lcal[sx], 00674 QC_ARC_AR_EFF, stored_qc_ar_eff[sx]/gain, 00675 "[e-/s] Argon lamp efficiency"); 00676 } 00677 00678 if (stored_qc_ne_eff[sx] != -1.0) { 00679 kmclipm_update_property_double(stored_sub_headers_lcal[sx], 00680 QC_ARC_NE_EFF, stored_qc_ne_eff[sx]/gain, 00681 "[e-/s] Neon lamp efficiency"); 00682 } 00683 00684 kmclipm_update_property_double(stored_sub_headers_lcal[sx], 00685 CAL_ROTANGLE, ((double) angles_array[a]), 00686 "[deg] Rotator relative to nasmyth"); 00687 00688 /* append QC parameters */ 00689 cpl_propertylist_append(stored_sub_headers_lcal[sx], qc_header); 00690 cpl_propertylist_delete(qc_header); 00691 00692 stored_sub_headers_det_img[sx]=cpl_propertylist_duplicate( 00693 stored_sub_headers_lcal[sx]); 00694 00695 cpl_propertylist_erase(stored_sub_headers_lcal[sx], CRVAL1); 00696 cpl_propertylist_erase(stored_sub_headers_lcal[sx], CRVAL2); 00697 cpl_propertylist_erase(stored_sub_headers_lcal[sx], CTYPE1); 00698 cpl_propertylist_erase(stored_sub_headers_lcal[sx], CTYPE2); 00699 cpl_propertylist_erase(stored_sub_headers_lcal[sx], CDELT1); 00700 cpl_propertylist_erase(stored_sub_headers_lcal[sx], CDELT2); 00701 00702 cpl_msg_indent_less(); 00703 } // for i devices 00704 cpl_msg_indent_less() ; 00705 } // for a angles 00706 00707 /* Free */ 00708 cpl_free(angles_array) ; 00709 for (i = 0; i < ne; i++) cpl_free(filter_ids[i]); 00710 cpl_free(filter_ids); 00711 cpl_bivector_delete(lines); 00712 00713 cpl_free(stored_qc_arc_sat); 00714 cpl_free(stored_qc_ar_eff); 00715 cpl_free(stored_qc_ne_eff); 00716 if (lines_estimation == 0) cpl_table_delete(reflines); 00717 00718 /* QC parameters & saving */ 00719 cpl_msg_info(__func__, "Saving data..."); 00720 00721 /* load, update & save primary header */ 00722 if (!suppress_extension) fn_suffix = cpl_sprintf("%s", suffix); 00723 else fn_suffix = cpl_sprintf("%s", ""); 00724 cpl_free(suffix); 00725 00726 /* update which IFUs are not used */ 00727 frame = kmo_dfs_get_frame(frameset, ARC_ON); 00728 mh_on = kmclipm_propertylist_load(cpl_frame_get_filename(frame), 0); 00729 kmo_set_unused_ifus(unused_ifus_after, mh_on, "kmos_wave_cal"); 00730 kmo_dfs_save_main_header(frameset, LCAL, fn_suffix, frame, mh_on, parlist, 00731 cpl_func); 00732 kmo_dfs_save_main_header(frameset, DET_IMG_WAVE, fn_suffix, frame, mh_on, 00733 parlist, cpl_func); 00734 cpl_propertylist_delete(mh_on); 00735 00736 /* Save sub-frames */ 00737 for (a = 0; a < nb_angles; a++) { 00738 for (i = 1; i <= ne ; i++) { 00739 int sx = a * ne + (i - 1); 00740 /* save lcal-frame */ 00741 kmo_dfs_save_image(stored_lcal[sx], LCAL, fn_suffix, 00742 stored_sub_headers_lcal[sx], 0./0.); 00743 00744 /* save detector image */ 00745 kmo_dfs_save_image(stored_det_img[sx], DET_IMG_WAVE, fn_suffix, 00746 stored_sub_headers_det_img[sx], 0./0.); 00747 } // for i = ne 00748 } // for a angles 00749 00750 /* Free */ 00751 cpl_free(fn_suffix); 00752 for (i = 0; i < ne * nb_angles; i++) { 00753 cpl_image_delete(stored_lcal[i]); 00754 cpl_image_delete(stored_det_img[i]); 00755 cpl_propertylist_delete(stored_sub_headers_lcal[i]); 00756 cpl_propertylist_delete(stored_sub_headers_det_img[i]); 00757 } 00758 cpl_free(stored_lcal); 00759 cpl_free(stored_det_img); 00760 cpl_free(stored_sub_headers_lcal); 00761 cpl_free(stored_sub_headers_det_img); 00762 00763 /* print which IFUs are not used */ 00764 kmo_print_unused_ifus(unused_ifus_after, TRUE); 00765 if (unused_ifus_after != NULL) kmo_free_unused_ifus(unused_ifus_after); 00766 00767 if (last_env != NULL) { 00768 setenv("KMCLIPM_PRIV_RECONSTRUCT_LUT_MODE",last_env,1); 00769 } else { 00770 unsetenv("KMCLIPM_PRIV_RECONSTRUCT_LUT_MODE"); 00771 } 00772 return 0; 00773 } 00774 00777 /*----------------------------------------------------------------------------*/ 00789 /*----------------------------------------------------------------------------*/ 00790 static int kmos_wave_cal_check_inputs( 00791 cpl_frameset * frameset, 00792 int * nx, 00793 int * ny, 00794 int * ne, 00795 double * exptime, 00796 int * non_dest_rom, 00797 lampConfiguration * lamp_config) 00798 { 00799 const cpl_frame * frame_off ; 00800 const cpl_frame * frame_on ; 00801 cpl_propertylist * mh_off ; 00802 cpl_propertylist * mh_on ; 00803 cpl_propertylist * eh_off ; 00804 cpl_propertylist * eh_on ; 00805 int ext, next_off, next_on, nx_on, ny_on, nx_off,ny_off; 00806 double ndit_off, ndit_on, exptime_off, exptime_on ; 00807 const char * readmode_off ; 00808 const char * readmode_on ; 00809 00810 /* TODO Check Lamps TODO */ 00811 00812 /* Check Entries */ 00813 if (nx == NULL || ny == NULL || ne == NULL || frameset == NULL) return -1; 00814 00815 /* Setup lamp config */ 00816 frame_on = kmo_dfs_get_frame(frameset, ARC_ON); 00817 mh_on = cpl_propertylist_load(cpl_frame_get_filename(frame_on), 0); 00818 if ((kmo_check_lamp(mh_on, INS_LAMP1_ST) == TRUE) && 00819 (kmo_check_lamp(mh_on, INS_LAMP2_ST) == FALSE)) { 00820 *lamp_config = ARGON; 00821 cpl_msg_info(__func__, "Arc lamp: Argon"); 00822 } else if ((kmo_check_lamp(mh_on, INS_LAMP1_ST) == FALSE) && 00823 (kmo_check_lamp(mh_on, INS_LAMP2_ST) == TRUE)) { 00824 *lamp_config = NEON; 00825 cpl_msg_info(__func__, "Arc lamp: Neon"); 00826 } else if ((kmo_check_lamp(mh_on, INS_LAMP1_ST) == TRUE) && 00827 (kmo_check_lamp(mh_on, INS_LAMP2_ST) == TRUE)) { 00828 *lamp_config = ARGON_NEON; 00829 cpl_msg_info(__func__, "Arc lamp: Argon + Neon"); 00830 } else { 00831 *lamp_config = -1 ; 00832 cpl_warning_info(__func__, "Arc lamp: UNDEFINED"); 00833 } 00834 00835 /* Check READ OUT MODE */ 00836 readmode_on = kmos_pfits_get_readmode(mh_on); 00837 if (!strcmp(readmode_on, "Nondest")) { 00838 *non_dest_rom = 1 ; 00839 } else { 00840 *non_dest_rom = 0 ; 00841 } 00842 cpl_propertylist_delete(mh_on); 00843 00844 /* Get ARC_OFF */ 00845 frame_off = kmo_dfs_get_frame(frameset, ARC_OFF); 00846 if (frame_off == NULL) { 00847 cpl_msg_error(__func__, "No ARC_OFF frame found") ; 00848 return -1 ; 00849 } 00850 00851 /* Get ARC_OFF main header infos */ 00852 next_off = cpl_frame_get_nextensions(frame_off); 00853 mh_off = cpl_propertylist_load(cpl_frame_get_filename(frame_off), 0); 00854 ndit_off = kmos_pfits_get_ndit(mh_off) ; 00855 exptime_off = kmos_pfits_get_exptime(mh_off) ; 00856 readmode_off = kmos_pfits_get_readmode(mh_off); 00857 00858 /* Get ARC_ON frames and loop on them */ 00859 frame_on = kmo_dfs_get_frame(frameset, ARC_ON); 00860 if (frame_on == NULL) { 00861 cpl_msg_error(__func__, "No ARC_ON frame found") ; 00862 cpl_propertylist_delete(mh_off); 00863 return -1 ; 00864 } 00865 while (frame_on != NULL) { 00866 /* Get ARC_ON main header infos */ 00867 next_on = cpl_frame_get_nextensions(frame_on); 00868 mh_on = cpl_propertylist_load(cpl_frame_get_filename(frame_on), 0); 00869 ndit_on = kmos_pfits_get_ndit(mh_on) ; 00870 exptime_on = kmos_pfits_get_exptime(mh_on) ; 00871 readmode_on = kmos_pfits_get_readmode(mh_on); 00872 00873 /* Check consistency */ 00874 if (ndit_on != ndit_off || strcmp(readmode_on, readmode_off) || 00875 fabs(exptime_on-exptime_off) > 0.01 || next_off != next_on) { 00876 cpl_msg_warning(__func__, "Inconsistency for frame %s", 00877 cpl_frame_get_filename(frame_on)) ; 00878 cpl_propertylist_delete(mh_off); 00879 cpl_propertylist_delete(mh_on); 00880 return 0 ; 00881 } 00882 cpl_propertylist_delete(mh_on); 00883 00884 /* Get next frame */ 00885 frame_on = kmo_dfs_get_frame(frameset, NULL); 00886 } 00887 cpl_propertylist_delete(mh_off); 00888 00889 /* Check the extensions */ 00890 for (ext = 1; ext <= next_off ; ext++) { 00891 eh_off = cpl_propertylist_load(cpl_frame_get_filename(frame_off), ext); 00892 nx_off = kmos_pfits_get_naxis1(eh_off) ; 00893 ny_off = kmos_pfits_get_naxis2(eh_off) ; 00894 00895 frame_on = kmo_dfs_get_frame(frameset, ARC_ON); 00896 while (frame_on != NULL) { 00897 eh_on = cpl_propertylist_load(cpl_frame_get_filename(frame_on),ext); 00898 nx_on = kmos_pfits_get_naxis1(eh_on) ; 00899 ny_on = kmos_pfits_get_naxis2(eh_on) ; 00900 /* Check consistency */ 00901 if (nx_on != nx_off || ny_off != ny_on) { 00902 cpl_msg_warning(__func__, "Inconsistency for frame %s", 00903 cpl_frame_get_filename(frame_on)) ; 00904 cpl_propertylist_delete(eh_off); 00905 cpl_propertylist_delete(eh_on); 00906 return 0 ; 00907 } 00908 cpl_propertylist_delete(eh_on); 00909 00910 /* Get next frame */ 00911 frame_on = kmo_dfs_get_frame(frameset, NULL); 00912 } 00913 cpl_propertylist_delete(eh_off); 00914 } 00915 00916 /* FLAT_EDGE Checks */ 00917 frame_on = kmo_dfs_get_frame(frameset, FLAT_EDGE); 00918 if (cpl_frame_get_nextensions(frame_on) % 24 != 0) { 00919 cpl_msg_warning(__func__, "FLAT_EDGE frame is not consistent") ; 00920 return 0 ; 00921 } 00922 00923 /* Checks on XCAL YCAL */ 00924 kmo_check_frame_setup(frameset, ARC_ON, XCAL, TRUE, FALSE, FALSE); 00925 kmo_check_frame_setup(frameset, ARC_ON, YCAL, TRUE, FALSE, FALSE); 00926 kmo_check_frame_setup_md5_xycal(frameset); 00927 if (cpl_error_get_code() != CPL_ERROR_NONE) { 00928 cpl_msg_warning(__func__, "XCAL / YCAL checks failed") ; 00929 return 0 ; 00930 } 00931 00932 /* Return */ 00933 *nx = nx_off ; 00934 *ny = ny_off ; 00935 *ne = next_off ; 00936 *exptime = exptime_off ; 00937 return 1 ; 00938 } 00939 00940
1.7.6.1