|
KMOS Pipeline Reference Manual
1.3.4
|
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 *, enum 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 "----------------------------------------------------------------------------\n" 00118 "Input files:\n" 00119 "\n" 00120 " DO category Type Explanation Required #Frames\n" 00121 " ----------- ----- ----------- -------- -------\n" 00122 " ARC_ON RAW Arclamp-on exposure Y >=1\n" 00123 " ARC_OFF RAW Arclamp-off exposure Y 1\n" 00124 " XCAL F2D x calibration frame Y 1\n" 00125 " YCAL F2D y calibration frame Y 1\n" 00126 " ARC_LIST F2L List of arclines Y 1\n" 00127 " FLAT_EDGE F2L Fitted edge parameters Y 1\n" 00128 " REF_LINES F2L Reference line table Y 1\n" 00129 " WAVE_BAND F2L Table with start-/end-wavelengths Y 1\n" 00130 "\n" 00131 "Output files:\n" 00132 "\n" 00133 " DO category Type Explanation\n" 00134 " ----------- ----- -----------\n" 00135 " LCAL F2D Wavelength calibration frame\n" 00136 " (3 Extensions)\n" 00137 " DET_IMG_WAVE F2D reconstructed arclamp-on exposure\n" 00138 " (4 extensions: 3 detector images + \n" 00139 " the arclines list table)\n" 00140 "----------------------------------------------------------------------------\n" 00141 "\n"; 00142 00143 /*----------------------------------------------------------------------------- 00144 * Functions code 00145 *----------------------------------------------------------------------------*/ 00146 00153 /*----------------------------------------------------------------------------*/ 00162 /*----------------------------------------------------------------------------*/ 00163 int cpl_plugin_get_info(cpl_pluginlist *list) 00164 { 00165 cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe); 00166 cpl_plugin *plugin = &recipe->interface; 00167 00168 cpl_plugin_init(plugin, 00169 CPL_PLUGIN_API, 00170 KMOS_BINARY_VERSION, 00171 CPL_PLUGIN_TYPE_RECIPE, 00172 "kmos_wave_cal", 00173 "Create a wavelength calibration frame", 00174 kmos_wave_cal_description, 00175 "Alex Agudo Berbel, Yves Jung", 00176 "usd-help@eso.org", 00177 kmos_get_license(), 00178 kmos_wave_cal_create, 00179 kmos_wave_cal_exec, 00180 kmos_wave_cal_destroy); 00181 cpl_pluginlist_append(list, plugin); 00182 00183 return 0; 00184 } 00185 00186 /*----------------------------------------------------------------------------*/ 00194 /*----------------------------------------------------------------------------*/ 00195 static int kmos_wave_cal_create(cpl_plugin *plugin) 00196 { 00197 cpl_recipe *recipe; 00198 cpl_parameter *p; 00199 00200 // Check that the plugin is part of a valid recipe 00201 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00202 recipe = (cpl_recipe *)plugin; 00203 else 00204 return -1; 00205 00206 // Create the parameters list in the cpl_recipe object 00207 recipe->parameters = cpl_parameterlist_new(); 00208 00209 // Fill the parameters list 00210 p = cpl_parameter_new_value("kmos.kmos_wave_cal.order", CPL_TYPE_INT, 00211 "The fitting polynomial order used for the wavelength solution. " 00212 "By default, 4 for IZ band, 5 for HK, 6 for the others", 00213 "kmos.kmos_wave_cal", 0); 00214 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "order"); 00215 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00216 cpl_parameterlist_append(recipe->parameters, p); 00217 00218 /* --suppress_extension */ 00219 p = cpl_parameter_new_value("kmos.kmos_wave_cal.suppress_extension", 00220 CPL_TYPE_BOOL, "Suppress arbitrary filename extension", 00221 "kmos.kmos_wave_cal", FALSE); 00222 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "suppress_extension"); 00223 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00224 cpl_parameterlist_append(recipe->parameters, p); 00225 00226 /* Add parameters for band-definition */ 00227 kmos_band_pars_create(recipe->parameters, "kmos.kmos_wave_cal"); 00228 00229 /* --detector */ 00230 p = cpl_parameter_new_value("kmos.kmos_wave_cal.detector", 00231 CPL_TYPE_INT, "Only reduce the specified detector", 00232 "kmos.kmos_wave_cal", 0); 00233 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "det"); 00234 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00235 cpl_parameterlist_append(recipe->parameters, p); 00236 00237 /* --angle */ 00238 p = cpl_parameter_new_value("kmos.kmos_wave_cal.angle", 00239 CPL_TYPE_DOUBLE, "Only reduce the specified angle", 00240 "kmos.kmos_wave_cal", 370.0); 00241 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "angle"); 00242 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00243 cpl_parameterlist_append(recipe->parameters, p); 00244 00245 return 0; 00246 } 00247 00248 /*----------------------------------------------------------------------------*/ 00254 /*----------------------------------------------------------------------------*/ 00255 static int kmos_wave_cal_exec(cpl_plugin *plugin) 00256 { 00257 cpl_recipe *recipe; 00258 00259 // Get the recipe out of the plugin 00260 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00261 recipe = (cpl_recipe *)plugin; 00262 else return -1; 00263 00264 return kmos_wave_cal(recipe->parameters, recipe->frames); 00265 } 00266 00267 /*----------------------------------------------------------------------------*/ 00273 /*----------------------------------------------------------------------------*/ 00274 static int kmos_wave_cal_destroy(cpl_plugin *plugin) 00275 { 00276 cpl_recipe *recipe; 00277 00278 // Get the recipe out of the plugin 00279 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00280 recipe = (cpl_recipe *)plugin; 00281 else return -1 ; 00282 00283 cpl_parameterlist_delete(recipe->parameters); 00284 return 0 ; 00285 } 00286 00287 /*----------------------------------------------------------------------------*/ 00301 /*----------------------------------------------------------------------------*/ 00302 static int kmos_wave_cal(cpl_parameterlist *parlist, cpl_frameset *frameset) 00303 { 00304 char * str_line_estimate_method ; 00305 int line_estimate_method ; 00306 const cpl_parameter * par ; 00307 int suppress_extension, fit_order_par, fit_order ; 00308 int nx, ny, ne, reduce_det ; 00309 double exptime, gain, angle_found, reduce_angle ; 00310 cpl_frame * frame ; 00311 cpl_propertylist * mh_on ; 00312 cpl_propertylist * plist ; 00313 char * suffix ; 00314 enum lampConfiguration lamp_config; 00315 char ** filter_ids ; 00316 int * angles_array ; 00317 int nb_angles ; 00318 int non_dest_rom ; 00319 00320 cpl_propertylist ** stored_sub_headers_lcal ; 00321 cpl_propertylist ** stored_sub_headers_det_img ; 00322 cpl_image ** stored_lcal ; 00323 cpl_image ** stored_det_img ; 00324 int * stored_qc_arc_sat ; 00325 double * stored_qc_ar_eff ; 00326 double * stored_qc_ne_eff ; 00327 cpl_table * detector_edges[KMOS_IFUS_PER_DETECTOR] ; 00328 00329 int a, i, j, x, y ; 00330 00331 cpl_image * det_lamp_on ; 00332 cpl_image * det_lamp_off ; 00333 cpl_image * det_lamp_on_copy ; 00334 00335 cpl_table * arclines ; 00336 cpl_table * reflines ; 00337 cpl_bivector * lines ; 00338 00339 cpl_image * bad_pix_mask ; 00340 float * pbad_pix_mask ; 00341 cpl_image * xcal ; 00342 cpl_image * ycal ; 00343 cpl_image * lcal ; 00344 00345 int nr_sat ; 00346 00347 cpl_propertylist * qc_header ; 00348 00349 cpl_array ** unused_ifus_before ; 00350 cpl_array ** unused_ifus_after ; 00351 char * extname ; 00352 char * fn_suffix ; 00353 char * last_env ; 00354 const char * tmp_str ; 00355 cpl_error_code err ; 00356 00357 00358 /* Lines method TODO */ 00359 str_line_estimate_method = getenv("KMO_WAVE_LINE_ESTIMATE"); 00360 if (str_line_estimate_method != NULL) { 00361 line_estimate_method = atoi(str_line_estimate_method); 00362 } else { 00363 line_estimate_method = 2 ; 00364 } 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.suppress_extension"); 00378 suppress_extension = cpl_parameter_get_bool(par); 00379 par = cpl_parameterlist_find_const(parlist, "kmos.kmos_wave_cal.angle"); 00380 reduce_angle = cpl_parameter_get_double(par); 00381 par = cpl_parameterlist_find_const(parlist, "kmos.kmos_wave_cal.detector"); 00382 reduce_det = cpl_parameter_get_int(par); 00383 00384 kmos_band_pars_load(parlist, "kmos.kmos_wave_cal"); 00385 00386 /* Check Parameters */ 00387 if (fit_order_par < 0 || fit_order_par > 7) { 00388 cpl_msg_error(__func__, "Fitting Order must be in [0,7]") ; 00389 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00390 return -1 ; 00391 } 00392 if (reduce_det < 0 || reduce_det > 3) { 00393 cpl_msg_error(__func__, "detector must be in [1,3]") ; 00394 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00395 return -1 ; 00396 } 00397 00398 /* Identify the RAW and CALIB frames in the input frameset */ 00399 if (kmo_dfs_set_groups(frameset, "kmos_wave_cal") != 1) { 00400 cpl_msg_error(__func__, "Cannot identify RAW and CALIB frames") ; 00401 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00402 return -1 ; 00403 } 00404 00405 /* Check the inputs consistency */ 00406 if (kmos_wave_cal_check_inputs(frameset, &nx, &ny, &ne, &exptime, 00407 &non_dest_rom, &lamp_config) != 1) { 00408 cpl_msg_error(__func__, "Input frameset is not consistent") ; 00409 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00410 return -1 ; 00411 } 00412 00413 /* Instrument setup */ 00414 suffix = kmo_dfs_get_suffix(kmo_dfs_get_frame(frameset, XCAL), TRUE, FALSE); 00415 cpl_msg_info(__func__, "Detected instrument setup: %s", suffix+1); 00416 00417 /* Check that filter and grating match for each detector */ 00418 /* filter/grating can be different for each detector */ 00419 frame = kmo_dfs_get_frame(frameset, ARC_ON); 00420 mh_on = cpl_propertylist_load(cpl_frame_get_filename(frame), 0); 00421 filter_ids = kmo_get_filter_setup(mh_on, ne, TRUE) ; 00422 cpl_propertylist_delete(mh_on); 00423 if (filter_ids == NULL) { 00424 cpl_free(suffix); 00425 cpl_msg_error(__func__, "Cannot get Filter informations") ; 00426 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00427 return -1 ; 00428 } 00429 00430 /* Get Rotator angles */ 00431 if ((angles_array = kmos_get_angles(frameset, &nb_angles, ARC_ON)) == NULL){ 00432 cpl_msg_error(__func__, "Cannot get Angles informations") ; 00433 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00434 for (i = 0; i < ne ; i++) cpl_free(filter_ids[i]); 00435 cpl_free(filter_ids); 00436 cpl_free(suffix); 00437 return -1 ; 00438 } 00439 00440 /* Check the ARC_LIST filter */ 00441 frame = kmo_dfs_get_frame(frameset, ARC_LIST); 00442 plist = cpl_propertylist_load(cpl_frame_get_filename(frame), 0); 00443 tmp_str = cpl_propertylist_get_string(plist, FILT_ID); 00444 if (strcmp(filter_ids[0], tmp_str) != 0) { 00445 cpl_msg_error(__func__, "Wrong ARC_LIST filter") ; 00446 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00447 for (i = 0; i < ne ; i++) cpl_free(filter_ids[i]); 00448 cpl_free(filter_ids); 00449 cpl_free(angles_array); 00450 cpl_propertylist_delete(plist); 00451 return -1 ; 00452 } 00453 cpl_propertylist_delete(plist); 00454 00455 /* Load the lines as a CPL table */ 00456 arclines = kmo_dfs_load_table(frameset, ARC_LIST, 1, 0); 00457 lines = kmo_get_lines(arclines, lamp_config); 00458 cpl_table_delete(arclines); 00459 /* TODO : check not null */ 00460 cpl_msg_info(__func__, "Arc lines: %lld", cpl_bivector_get_size(lines)); 00461 00462 /* Load REFLINES */ 00463 if (line_estimate_method == 2) { 00464 reflines = kmo_dfs_load_table(frameset, REF_LINES, 1, 0); 00465 /* TODO : check not null */ 00466 } 00467 00468 /* Check which IFUs are active for all FLAT frames */ 00469 unused_ifus_before = kmo_get_unused_ifus(frameset, 0, 0); 00470 unused_ifus_after = kmo_duplicate_unused_ifus(unused_ifus_before); 00471 kmo_print_unused_ifus(unused_ifus_before, FALSE); 00472 if (unused_ifus_before != NULL) kmo_free_unused_ifus(unused_ifus_before); 00473 00474 /* make sure no reconstruction lookup table (LUT) is used */ 00475 if (getenv("KMCLIPM_PRIV_RECONSTRUCT_LUT_MODE") != NULL) { 00476 last_env = getenv("KMCLIPM_PRIV_RECONSTRUCT_LUT_MODE"); 00477 } 00478 setenv("KMCLIPM_PRIV_RECONSTRUCT_LUT_MODE","NONE",1); 00479 00480 /* the frames have to be stored temporarily because the QC params */ 00481 /* for the main header are calculated per detector. So they can be */ 00482 /* stored only when all detectors are processed */ 00483 stored_lcal = (cpl_image**)cpl_calloc(ne * nb_angles, sizeof(cpl_image*)); 00484 stored_det_img = (cpl_image**)cpl_calloc(ne * nb_angles,sizeof(cpl_image*)); 00485 stored_sub_headers_lcal = (cpl_propertylist**)cpl_calloc(ne * nb_angles, 00486 sizeof(cpl_propertylist*)); 00487 stored_sub_headers_det_img = (cpl_propertylist**)cpl_calloc(ne * nb_angles, 00488 sizeof(cpl_propertylist*)); 00489 stored_qc_arc_sat = (int*)cpl_calloc(ne, nb_angles * sizeof(int)); 00490 stored_qc_ar_eff=(double*)cpl_calloc(ne, nb_angles * sizeof(double)); 00491 stored_qc_ne_eff=(double*)cpl_calloc(ne, nb_angles * sizeof(double)); 00492 00493 /* Loop all Rotator Angles and Detectors */ 00494 for (a = 0; a < nb_angles; a++) { 00495 /* Reduce only one angle */ 00496 if (reduce_angle <= 360 && angles_array[a] != reduce_angle) continue ; 00497 00498 cpl_msg_info(__func__, "Processing rotator angle %d -> %d degree", 00499 a, angles_array[a]); 00500 cpl_msg_indent_more(); 00501 for (i = 1; i <= ne ; i++) { 00502 /* Compute only one detector */ 00503 if (reduce_det != 0 && i != reduce_det) continue ; 00504 00505 cpl_msg_info(__func__,"Processing detector No. %d", i); 00506 cpl_msg_indent_more(); 00507 00508 /* Load edge parameters */ 00509 frame=kmo_dfs_get_frame(frameset, FLAT_EDGE); 00510 for (j = 0; j < KMOS_IFUS_PER_DETECTOR; j++) { 00511 detector_edges[j] = kmclipm_cal_table_load( 00512 cpl_frame_get_filename(frame), 00513 (i-1) * KMOS_IFUS_PER_DETECTOR + j + 1, 00514 angles_array[a], 0, &angle_found); 00515 00516 /* IFU is inactive: proceed */ 00517 if (cpl_error_get_code() == CPL_ERROR_ILLEGAL_INPUT) { 00518 cpl_error_reset(); 00519 } 00520 } 00521 00522 /* Set default fit orders for the different bands */ 00523 if (fit_order_par == 0) { 00524 if ((strcmp(filter_ids[i-1], "H") == 0) || 00525 (strcmp(filter_ids[i-1], "K") == 0) || 00526 (strcmp(filter_ids[i-1], "YJ") == 0)) { 00527 fit_order = 6; 00528 } else if (strcmp(filter_ids[i-1], "IZ") == 0) { 00529 fit_order = 4; 00530 } else if (strcmp(filter_ids[i-1], "HK") == 0) { 00531 fit_order = 5; 00532 } 00533 cpl_msg_info(__func__, 00534 "Order of wavelength spectrum fit for %s-band: %d", 00535 filter_ids[i-1], fit_order); 00536 } else { 00537 fit_order = fit_order_par; 00538 } 00539 00540 /* Get ARC_ON frame and Load it */ 00541 frame = kmos_get_angle_frame(frameset, angles_array[a], ARC_ON); 00542 det_lamp_on = kmo_dfs_load_image_frame(frame,i,FALSE, TRUE,&nr_sat); 00543 int sx = a * ne + (i - 1); 00544 00545 /* Count saturated pixels for each detector */ 00546 if (non_dest_rom) 00547 stored_qc_arc_sat[sx] = nr_sat; 00548 else 00549 stored_qc_arc_sat[sx] = kmo_image_get_saturated(det_lamp_on, 00550 KMO_FLAT_SATURATED); 00551 00552 det_lamp_on_copy = cpl_image_duplicate(det_lamp_on); 00553 00554 /* Get ARC_OFF frame and Load it */ 00555 frame = kmo_dfs_get_frame(frameset, ARC_OFF); 00556 det_lamp_off = kmo_dfs_load_image_frame(frame, i, FALSE, FALSE, 00557 NULL); 00558 00559 /* ARC_ON = ARC_ON - ARC_OFF */ 00560 cpl_image_subtract(det_lamp_on, det_lamp_off); 00561 00562 /* Load XCAL,YCAL */ 00563 xcal = kmo_dfs_load_cal_image(frameset, XCAL, i, 0, 00564 (double)angles_array[a], FALSE, NULL, &angle_found, -1,0,0); 00565 ycal = kmo_dfs_load_cal_image(frameset, YCAL, i, 0, 00566 (double)angles_array[a], FALSE, NULL, &angle_found, -1,0,0); 00567 00568 /* Derive BPM from XCAL : NaNs to 0, Others to 1 */ 00569 bad_pix_mask = cpl_image_duplicate(xcal); 00570 pbad_pix_mask = cpl_image_get_data_float(bad_pix_mask); 00571 for (x = 0; x < nx; x++) { 00572 for (y = 0; y < ny; y++) { 00573 if (isnan(pbad_pix_mask[x+nx*y])) { 00574 pbad_pix_mask[x+nx*y] = 0.; 00575 } else { 00576 pbad_pix_mask[x+nx*y] = 1.; 00577 } 00578 } 00579 } 00580 00581 /* Compute wavelength calibration */ 00582 err = kmos_calc_wave_calib(det_lamp_on, bad_pix_mask, xcal, ycal, 00583 filter_ids[i-1], lamp_config, i, unused_ifus_after[i-1], 00584 detector_edges, lines, reflines, -1.0, &lcal, 00585 &(stored_qc_ar_eff[sx]), &(stored_qc_ne_eff[sx]), fit_order, 00586 line_estimate_method); 00587 cpl_image_delete(det_lamp_on); 00588 for (j = 0; j < KMOS_IFUS_PER_DETECTOR; j++) { 00589 cpl_table_delete(detector_edges[j]); 00590 } 00591 if (err == CPL_ERROR_NONE) { 00592 /* Update QC parameters */ 00593 if (stored_qc_ar_eff[sx] != -1.0) 00594 stored_qc_ar_eff[sx] /= exptime; 00595 if (stored_qc_ne_eff[sx] != -1.0) 00596 stored_qc_ne_eff[sx] /= exptime; 00597 00598 /* Apply the badpixel mask to the produced frame */ 00599 cpl_image_multiply(lcal, bad_pix_mask); 00600 kmo_image_reject_from_mask(lcal, bad_pix_mask); 00601 00602 /* Store Result frame */ 00603 stored_lcal[sx] = lcal; 00604 } else if (err == CPL_ERROR_UNSPECIFIED) { 00605 /* All IFUs seem to be deactivated */ 00606 /* Continue processing - just save empty frame */ 00607 cpl_error_reset(); 00608 stored_lcal[sx] = cpl_image_new(nx, ny, CPL_TYPE_FLOAT); 00609 kmo_image_fill(stored_lcal[sx], 0.0); 00610 } else { 00611 cpl_error_reset(); 00612 cpl_msg_warning(__func__, 00613 "Couldn't identify any line - Check the line list"); 00614 cpl_msg_warning(__func__, 00615 "Band defined in header of detector %d: %s", 00616 i, filter_ids[i-1]); 00617 cpl_msg_warning(__func__, "Arc line file defined: %s", 00618 cpl_frame_get_filename(kmo_dfs_get_frame(frameset, 00619 ARC_LIST))); 00620 } 00621 cpl_image_delete(bad_pix_mask); 00622 00623 /* CREATE RECONSTRUCTED AND RESAMPLED ARC FRAME */ 00624 stored_det_img[sx] = kmo_reconstructed_arc_image(frameset, 00625 det_lamp_on_copy, det_lamp_off, xcal, ycal, stored_lcal[sx], 00626 unused_ifus_after[i-1], FALSE, i, suffix, filter_ids[i-1], 00627 lamp_config, &qc_header); 00628 cpl_image_delete(det_lamp_on_copy); 00629 cpl_image_delete(det_lamp_off); 00630 cpl_image_delete(xcal); 00631 cpl_image_delete(ycal); 00632 if (cpl_error_get_code() != CPL_ERROR_NONE) { 00633 cpl_msg_error(__func__,"Cannot reconstruct IFUs on detector %d", 00634 i); 00635 cpl_error_reset(); 00636 } 00637 00638 /* CREATE EXTENSION HEADER FOR THE PRODUCT */ 00639 stored_sub_headers_lcal[sx] = kmo_dfs_load_sub_header(frameset, 00640 ARC_ON, i, FALSE); 00641 /* update EXTNAME */ 00642 extname = kmo_extname_creator(detector_frame, i, EXT_DATA); 00643 kmclipm_update_property_string(stored_sub_headers_lcal[sx], EXTNAME, 00644 extname, "FITS extension name"); 00645 cpl_free(extname); 00646 00647 kmclipm_update_property_int(stored_sub_headers_lcal[sx], EXTVER, 00648 sx+1, "FITS extension ver"); 00649 00650 // add first QC parameters 00651 kmclipm_update_property_int(stored_sub_headers_lcal[sx], 00652 QC_ARC_SAT, stored_qc_arc_sat[sx], 00653 "[] nr. saturated pixels of arc exp."); 00654 00655 gain=kmo_dfs_get_property_double(stored_sub_headers_lcal[sx],GAIN); 00656 00657 if (stored_qc_ar_eff[sx] != -1.0) { 00658 kmclipm_update_property_double(stored_sub_headers_lcal[sx], 00659 QC_ARC_AR_EFF, stored_qc_ar_eff[sx]/gain, 00660 "[e-/s] Argon lamp efficiency"); 00661 } 00662 00663 if (stored_qc_ne_eff[sx] != -1.0) { 00664 kmclipm_update_property_double(stored_sub_headers_lcal[sx], 00665 QC_ARC_NE_EFF, stored_qc_ne_eff[sx]/gain, 00666 "[e-/s] Neon lamp efficiency"); 00667 } 00668 00669 kmclipm_update_property_double(stored_sub_headers_lcal[sx], 00670 CAL_ROTANGLE, ((double) angles_array[a]), 00671 "[deg] Rotator relative to nasmyth"); 00672 00673 /* append QC parameters */ 00674 cpl_propertylist_append(stored_sub_headers_lcal[sx], qc_header); 00675 cpl_propertylist_delete(qc_header); 00676 00677 stored_sub_headers_det_img[sx]=cpl_propertylist_duplicate( 00678 stored_sub_headers_lcal[sx]); 00679 00680 cpl_propertylist_erase(stored_sub_headers_lcal[sx], CRVAL1); 00681 cpl_propertylist_erase(stored_sub_headers_lcal[sx], CRVAL2); 00682 cpl_propertylist_erase(stored_sub_headers_lcal[sx], CTYPE1); 00683 cpl_propertylist_erase(stored_sub_headers_lcal[sx], CTYPE2); 00684 cpl_propertylist_erase(stored_sub_headers_lcal[sx], CDELT1); 00685 cpl_propertylist_erase(stored_sub_headers_lcal[sx], CDELT2); 00686 00687 cpl_msg_indent_less(); 00688 } // for i devices 00689 cpl_msg_indent_less() ; 00690 } // for a angles 00691 00692 /* Free */ 00693 cpl_free(angles_array) ; 00694 for (i = 0; i < ne; i++) cpl_free(filter_ids[i]); 00695 cpl_free(filter_ids); 00696 cpl_bivector_delete(lines); 00697 00698 cpl_free(stored_qc_arc_sat); 00699 cpl_free(stored_qc_ar_eff); 00700 cpl_free(stored_qc_ne_eff); 00701 if (line_estimate_method == 2) cpl_table_delete(reflines); 00702 00703 /* QC parameters & saving */ 00704 cpl_msg_info(__func__, "Saving data..."); 00705 00706 /* load, update & save primary header */ 00707 if (!suppress_extension) fn_suffix = cpl_sprintf("%s", suffix); 00708 else fn_suffix = cpl_sprintf("%s", ""); 00709 cpl_free(suffix); 00710 00711 /* update which IFUs are not used */ 00712 frame = kmo_dfs_get_frame(frameset, ARC_ON); 00713 mh_on = kmclipm_propertylist_load(cpl_frame_get_filename(frame), 0); 00714 kmo_set_unused_ifus(unused_ifus_after, mh_on, "kmos_wave_cal"); 00715 kmo_dfs_save_main_header(frameset, LCAL, fn_suffix, frame, mh_on, parlist, 00716 cpl_func); 00717 kmo_dfs_save_main_header(frameset, DET_IMG_WAVE, fn_suffix, frame, mh_on, 00718 parlist, cpl_func); 00719 cpl_propertylist_delete(mh_on); 00720 00721 /* Save sub-frames */ 00722 for (a = 0; a < nb_angles; a++) { 00723 for (i = 1; i <= ne ; i++) { 00724 int sx = a * ne + (i - 1); 00725 /* save lcal-frame */ 00726 kmo_dfs_save_image(stored_lcal[sx], LCAL, fn_suffix, 00727 stored_sub_headers_lcal[sx], 0./0.); 00728 00729 /* save detector image */ 00730 kmo_dfs_save_image(stored_det_img[sx], DET_IMG_WAVE, fn_suffix, 00731 stored_sub_headers_det_img[sx], 0./0.); 00732 } // for i = ne 00733 } // for a angles 00734 00735 /* Free */ 00736 cpl_free(fn_suffix); 00737 for (i = 0; i < ne * nb_angles; i++) { 00738 cpl_image_delete(stored_lcal[i]); 00739 cpl_image_delete(stored_det_img[i]); 00740 cpl_propertylist_delete(stored_sub_headers_lcal[i]); 00741 cpl_propertylist_delete(stored_sub_headers_det_img[i]); 00742 } 00743 cpl_free(stored_lcal); 00744 cpl_free(stored_det_img); 00745 cpl_free(stored_sub_headers_lcal); 00746 cpl_free(stored_sub_headers_det_img); 00747 00748 /* print which IFUs are not used */ 00749 kmo_print_unused_ifus(unused_ifus_after, TRUE); 00750 if (unused_ifus_after != NULL) kmo_free_unused_ifus(unused_ifus_after); 00751 00752 if (last_env != NULL) { 00753 setenv("KMCLIPM_PRIV_RECONSTRUCT_LUT_MODE",last_env,1); 00754 } else { 00755 unsetenv("KMCLIPM_PRIV_RECONSTRUCT_LUT_MODE"); 00756 } 00757 return 0; 00758 } 00759 00762 /*----------------------------------------------------------------------------*/ 00774 /*----------------------------------------------------------------------------*/ 00775 static int kmos_wave_cal_check_inputs( 00776 cpl_frameset * frameset, 00777 int * nx, 00778 int * ny, 00779 int * ne, 00780 double * exptime, 00781 int * non_dest_rom, 00782 enum lampConfiguration * lamp_config) 00783 { 00784 const cpl_frame * frame_off ; 00785 const cpl_frame * frame_on ; 00786 cpl_propertylist * mh_off ; 00787 cpl_propertylist * mh_on ; 00788 cpl_propertylist * eh_off ; 00789 cpl_propertylist * eh_on ; 00790 int ext, next_off, next_on, nx_on, ny_on, nx_off,ny_off; 00791 double ndit_off, ndit_on, exptime_off, exptime_on ; 00792 const char * readmode_off ; 00793 const char * readmode_on ; 00794 00795 /* TODO Check Lamps TODO */ 00796 00797 /* Check Entries */ 00798 if (nx == NULL || ny == NULL || ne == NULL || frameset == NULL) return -1; 00799 00800 /* Setup lamp config */ 00801 frame_on = kmo_dfs_get_frame(frameset, ARC_ON); 00802 mh_on = cpl_propertylist_load(cpl_frame_get_filename(frame_on), 0); 00803 if ((kmo_check_lamp(mh_on, INS_LAMP1_ST) == TRUE) && 00804 (kmo_check_lamp(mh_on, INS_LAMP2_ST) == FALSE)) { 00805 *lamp_config = ARGON; 00806 cpl_msg_info(__func__, "Arc lamp: Argon"); 00807 } else if ((kmo_check_lamp(mh_on, INS_LAMP1_ST) == FALSE) && 00808 (kmo_check_lamp(mh_on, INS_LAMP2_ST) == TRUE)) { 00809 *lamp_config = NEON; 00810 cpl_msg_info(__func__, "Arc lamp: Neon"); 00811 } else if ((kmo_check_lamp(mh_on, INS_LAMP1_ST) == TRUE) && 00812 (kmo_check_lamp(mh_on, INS_LAMP2_ST) == TRUE)) { 00813 *lamp_config = ARGON_NEON; 00814 cpl_msg_info(__func__, "Arc lamp: Argon + Neon"); 00815 } else { 00816 *lamp_config = -1 ; 00817 cpl_warning_info(__func__, "Arc lamp: UNDEFINED"); 00818 } 00819 00820 /* Check READ OUT MODE */ 00821 readmode_on = kmos_pfits_get_readmode(mh_on); 00822 if (!strcmp(readmode_on, "Nondest")) { 00823 *non_dest_rom = 1 ; 00824 } else { 00825 *non_dest_rom = 0 ; 00826 } 00827 cpl_propertylist_delete(mh_on); 00828 00829 /* Get ARC_OFF */ 00830 frame_off = kmo_dfs_get_frame(frameset, ARC_OFF); 00831 if (frame_off == NULL) { 00832 cpl_msg_error(__func__, "No ARC_OFF frame found") ; 00833 return -1 ; 00834 } 00835 00836 /* Get ARC_OFF main header infos */ 00837 next_off = cpl_frame_get_nextensions(frame_off); 00838 mh_off = cpl_propertylist_load(cpl_frame_get_filename(frame_off), 0); 00839 ndit_off = kmos_pfits_get_ndit(mh_off) ; 00840 exptime_off = kmos_pfits_get_exptime(mh_off) ; 00841 readmode_off = kmos_pfits_get_readmode(mh_off); 00842 00843 /* Get ARC_ON frames and loop on them */ 00844 frame_on = kmo_dfs_get_frame(frameset, ARC_ON); 00845 if (frame_on == NULL) { 00846 cpl_msg_error(__func__, "No ARC_ON frame found") ; 00847 cpl_propertylist_delete(mh_off); 00848 return -1 ; 00849 } 00850 while (frame_on != NULL) { 00851 /* Get ARC_ON main header infos */ 00852 next_on = cpl_frame_get_nextensions(frame_on); 00853 mh_on = cpl_propertylist_load(cpl_frame_get_filename(frame_on), 0); 00854 ndit_on = kmos_pfits_get_ndit(mh_on) ; 00855 exptime_on = kmos_pfits_get_exptime(mh_on) ; 00856 readmode_on = kmos_pfits_get_readmode(mh_on); 00857 00858 /* Check consistency */ 00859 if (ndit_on != ndit_off || strcmp(readmode_on, readmode_off) || 00860 fabs(exptime_on-exptime_off) > 0.01 || next_off != next_on) { 00861 cpl_msg_warning(__func__, "Inconsistency for frame %s", 00862 cpl_frame_get_filename(frame_on)) ; 00863 cpl_propertylist_delete(mh_off); 00864 cpl_propertylist_delete(mh_on); 00865 return 0 ; 00866 } 00867 cpl_propertylist_delete(mh_on); 00868 00869 /* Get next frame */ 00870 frame_on = kmo_dfs_get_frame(frameset, NULL); 00871 } 00872 cpl_propertylist_delete(mh_off); 00873 00874 /* Check the extensions */ 00875 for (ext = 1; ext <= next_off ; ext++) { 00876 eh_off = cpl_propertylist_load(cpl_frame_get_filename(frame_off), ext); 00877 nx_off = kmos_pfits_get_naxis1(eh_off) ; 00878 ny_off = kmos_pfits_get_naxis2(eh_off) ; 00879 00880 frame_on = kmo_dfs_get_frame(frameset, ARC_ON); 00881 while (frame_on != NULL) { 00882 eh_on = cpl_propertylist_load(cpl_frame_get_filename(frame_on),ext); 00883 nx_on = kmos_pfits_get_naxis1(eh_on) ; 00884 ny_on = kmos_pfits_get_naxis2(eh_on) ; 00885 /* Check consistency */ 00886 if (nx_on != nx_off || ny_off != ny_on) { 00887 cpl_msg_warning(__func__, "Inconsistency for frame %s", 00888 cpl_frame_get_filename(frame_on)) ; 00889 cpl_propertylist_delete(eh_off); 00890 cpl_propertylist_delete(eh_on); 00891 return 0 ; 00892 } 00893 cpl_propertylist_delete(eh_on); 00894 00895 /* Get next frame */ 00896 frame_on = kmo_dfs_get_frame(frameset, NULL); 00897 } 00898 cpl_propertylist_delete(eh_off); 00899 } 00900 00901 /* FLAT_EDGE Checks */ 00902 frame_on = kmo_dfs_get_frame(frameset, FLAT_EDGE); 00903 if (cpl_frame_get_nextensions(frame_on) % 24 != 0) { 00904 cpl_msg_warning(__func__, "FLAT_EDGE frame is not consistent") ; 00905 return 0 ; 00906 } 00907 00908 /* Checks on XCAL YCAL */ 00909 kmo_check_frame_setup(frameset, ARC_ON, XCAL, TRUE, FALSE, FALSE); 00910 kmo_check_frame_setup(frameset, ARC_ON, YCAL, TRUE, FALSE, FALSE); 00911 kmo_check_frame_setup_md5_xycal(frameset); 00912 if (cpl_error_get_code() != CPL_ERROR_NONE) { 00913 cpl_msg_warning(__func__, "XCAL / YCAL checks failed") ; 00914 return 0 ; 00915 } 00916 00917 /* Return */ 00918 *nx = nx_off ; 00919 *ny = ny_off ; 00920 *ne = next_off ; 00921 *exptime = exptime_off ; 00922 return 1 ; 00923 } 00924 00925
1.7.6.1