|
KMOS Pipeline Reference Manual
1.2.3
|
00001 /* $Id: kmo_wave_cal.c,v 1.52 2013/06/17 07:52:26 aagudo Exp $ 00002 * 00003 * This file is part of the KMOS Pipeline 00004 * Copyright (C) 2002,2003 European Southern Observatory 00005 * 00006 * This program is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software 00018 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00019 */ 00020 00021 /* 00022 * $Author: aagudo $ 00023 * $Date: 2013/06/17 07:52:26 $ 00024 * $Revision: 1.52 $ 00025 * $Name: HEAD $ 00026 */ 00027 00028 #ifdef HAVE_CONFIG_H 00029 #include <config.h> 00030 #endif 00031 00032 /*----------------------------------------------------------------------------- 00033 * Includes 00034 *----------------------------------------------------------------------------*/ 00035 #include <string.h> 00036 #include <math.h> 00037 00038 #ifdef __USE_XOPEN2K 00039 #include <stdlib.h> 00040 #define GGG 00041 #else 00042 #define __USE_XOPEN2K /* to get the definition for setenv in stdlib.h */ 00043 #include <stdlib.h> 00044 #undef __USE_XOPEN2K 00045 #endif 00046 00047 #include <cpl.h> 00048 00049 #include "kmo_utils.h" 00050 #include "kmo_functions.h" 00051 #include "kmo_priv_wave_cal.h" 00052 #include "kmo_priv_functions.h" 00053 #include "kmo_cpl_extensions.h" 00054 #include "kmo_dfs.h" 00055 #include "kmo_error.h" 00056 #include "kmo_constants.h" 00057 #include "kmo_debug.h" 00058 00059 /*----------------------------------------------------------------------------- 00060 * Functions prototypes 00061 *----------------------------------------------------------------------------*/ 00062 00063 static int kmo_wave_cal_create(cpl_plugin *); 00064 static int kmo_wave_cal_exec(cpl_plugin *); 00065 static int kmo_wave_cal_destroy(cpl_plugin *); 00066 static int kmo_wave_cal(cpl_parameterlist *, cpl_frameset *); 00067 00068 /*----------------------------------------------------------------------------- 00069 * Static variables 00070 *----------------------------------------------------------------------------*/ 00071 00072 static char kmo_wave_cal_description[] = 00073 "This recipe creates the wavelength calibration frame needed for all three\n" 00074 "detectors. It must be called after the kmo_flat recipe, which generates the\n" 00075 "two spatial calibration frames needed in this recipe. As input a lamp-on frame,\n" 00076 "a lamp-off frame, the spatial calibration frames and the list with the\n" 00077 "reference arclines are required." 00078 "An additional output frame is the resampled image of the reconstructed arc\n" 00079 "frame. All slitlets of all IFUs are aligned one next to the other. This frame\n" 00080 "serves for quality control. One can immediately see if the calibration was\n" 00081 "successful.\n" 00082 "The lists of reference arclines are supposed to contain the lines for both\n" 00083 "available calibration arc-lamps, i.e. Argon and Neon. The list is supposed to\n" 00084 "be a F2L KMOS FITS file with three columns:\n" 00085 "1. Reference wavelength\n" 00086 "2. Relative strength\n" 00087 "3. String either containing “Ar” or “Ne”\n" 00088 "The recipe extracts, based on the header keywords, either the applying argon\n" 00089 "and/or neon emission lines. Below are the plots of the emission lines for both\n" 00090 "argon and neon. The marked lines are the ones used for wavelength calibration.\n" 00091 "\n" 00092 "Furthermore frames can be provided for several rotator angles. In this case\n" 00093 "the resulting calibration frames for each detector are repeatedly saved as \n" 00094 "extension for every angle.\n" 00095 "\n" 00096 "BASIC PARAMETERS:\n" 00097 "-----------------\n" 00098 "--order\n" 00099 "The polynomial order to use for the fit of the wavelength solution.\n" 00100 "0: (default) The appropriate order is choosen automatically depending on the\n" 00101 "waveband. Otherwise an order of 6 is recommended, except for IZ-band, there\n" 00102 "order 4 should be used.\n" 00103 "\n" 00104 "ADVANCED PARAMETERS\n" 00105 "-------------------\n" 00106 "--b_samples\n" 00107 "The number of samples in spectral direction for the reconstructed cube.\n" 00108 "Ideally this number should be greater than 2048, the detector size.\n" 00109 "\n" 00110 "--b_start\n" 00111 "--b_end\n" 00112 "Used to define manually the start and end wavelength for the reconstructed\n" 00113 "cube. By default the internally defined values are used.\n" 00114 "\n" 00115 "--suppress_extension\n" 00116 "If set to TRUE, the arbitrary filename extensions are supressed. If multiple\n" 00117 "products with the same category are produced, they will be numered consecutively\n" 00118 "starting from 0.\n" 00119 "\n" 00120 "-------------------------------------------------------------------------------\n" 00121 " Input files:\n" 00122 "\n" 00123 " DO KMOS \n" 00124 " category Type Explanation Required #Frames\n" 00125 " -------- ----- ----------- -------- -------\n" 00126 " ARC_ON RAW Arclamp-on exposure Y >=1\n" 00127 " ARC_OFF RAW Arclamp-off exposure Y 1\n" 00128 " XCAL F2D x calibration frame Y 1\n" 00129 " YCAL F2D y calibration frame Y 1\n" 00130 " ARC_LIST F2L List of arclines Y 1\n" 00131 " FLAT_EDGE F2L Fitted edge parameters Y 1\n" 00132 " REF_LINES F2L Reference line table Y 1\n" 00133 " WAVE_BAND F2L Table with start-/end-wavelengths Y 1\n" 00134 "\n" 00135 " Output files:\n" 00136 "\n" 00137 " DO KMOS\n" 00138 " category Type Explanation\n" 00139 " -------- ----- -----------\n" 00140 " LCAL F2D Wavelength calibration frame\n" 00141 " (3 Extensions)\n" 00142 " DET_IMG_WAVE F2D reconstructed arclamp-on exposure\n" 00143 " (4 extensions: 3 detector images + \n" 00144 " the arclines list table)\n" 00145 "-------------------------------------------------------------------------------\n" 00146 "\n"; 00147 00148 /*----------------------------------------------------------------------------- 00149 * Functions code 00150 *----------------------------------------------------------------------------*/ 00151 00168 int cpl_plugin_get_info(cpl_pluginlist *list) 00169 { 00170 cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe); 00171 cpl_plugin *plugin = &recipe->interface; 00172 00173 cpl_plugin_init(plugin, 00174 CPL_PLUGIN_API, 00175 KMOS_BINARY_VERSION, 00176 CPL_PLUGIN_TYPE_RECIPE, 00177 "kmo_wave_cal", 00178 "Create a calibration frame encoding the spectral " 00179 "position (i.e. wavelength) of each pixel on the " 00180 "detector.", 00181 kmo_wave_cal_description, 00182 "Alex Agudo Berbel", 00183 "kmos-spark@mpe.mpg.de", 00184 kmos_get_license(), 00185 kmo_wave_cal_create, 00186 kmo_wave_cal_exec, 00187 kmo_wave_cal_destroy); 00188 00189 cpl_pluginlist_append(list, plugin); 00190 00191 return 0; 00192 } 00193 00201 static int kmo_wave_cal_create(cpl_plugin *plugin) 00202 { 00203 cpl_recipe *recipe; 00204 cpl_parameter *p; 00205 00206 // Check that the plugin is part of a valid recipe 00207 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00208 recipe = (cpl_recipe *)plugin; 00209 else 00210 return -1; 00211 00212 // Create the parameters list in the cpl_recipe object 00213 recipe->parameters = cpl_parameterlist_new(); 00214 00215 // Fill the parameters list 00216 p = cpl_parameter_new_value("kmos.kmo_wave_cal.order", 00217 CPL_TYPE_INT, 00218 "The polynomial order to use for the fit of " 00219 "the wavelength solution. 0: (default) The " 00220 "appropriate order is choosen automatically " 00221 "depending on the waveband. Otherwise an order " 00222 "of 6 is recommended, except for IZ-band, there " 00223 "order 4 should be used", 00224 "kmos.kmo_wave_cal", 00225 0); 00226 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "order"); 00227 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00228 cpl_parameterlist_append(recipe->parameters, p); 00229 00230 p = cpl_parameter_new_value("kmos.kmo_wave_cal.dev_flip", 00231 CPL_TYPE_BOOL, 00232 "Set this parameter to TRUE if the wavelengths" 00233 " are ascending on the detector from top to " 00234 "bottom.", 00235 "kmos.kmo_wave_cal", 00236 FALSE); 00237 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "dev_flip"); 00238 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00239 cpl_parameterlist_append(recipe->parameters, p); 00240 00241 p = cpl_parameter_new_value("kmos.kmo_wave_cal.dev_disp", 00242 CPL_TYPE_DOUBLE, 00243 "The expected dispersion of the wavelength " 00244 "in microns/pixel. If the default isn't " 00245 "changed it will automatically be selected " 00246 "upon header keywords.", 00247 "kmos.kmo_wave_cal", 00248 -1.0); 00249 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "dev_disp"); 00250 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00251 cpl_parameterlist_append(recipe->parameters, p); 00252 00253 /* --suppress_extension */ 00254 p = cpl_parameter_new_value("kmos.kmo_wave_cal.suppress_extension", 00255 CPL_TYPE_BOOL, 00256 "Suppress arbitrary filename extension." 00257 "(TRUE (apply) or FALSE (don't apply)", 00258 "kmos.kmo_wave_cal", 00259 FALSE); 00260 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "suppress_extension"); 00261 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00262 cpl_parameterlist_append(recipe->parameters, p); 00263 00264 // add parameters for band-definition 00265 kmo_band_pars_create(recipe->parameters, 00266 "kmos.kmo_wave_cal"); 00267 00268 return 0; 00269 } 00270 00276 static int kmo_wave_cal_exec(cpl_plugin *plugin) 00277 { 00278 cpl_recipe *recipe; 00279 00280 // Get the recipe out of the plugin 00281 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00282 recipe = (cpl_recipe *)plugin; 00283 else return -1; 00284 00285 return kmo_wave_cal(recipe->parameters, recipe->frames); 00286 } 00287 00293 static int kmo_wave_cal_destroy(cpl_plugin *plugin) 00294 { 00295 cpl_recipe *recipe; 00296 00297 // Get the recipe out of the plugin 00298 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00299 recipe = (cpl_recipe *)plugin; 00300 else return -1 ; 00301 00302 cpl_parameterlist_delete(recipe->parameters); 00303 return 0 ; 00304 } 00305 00320 static int kmo_wave_cal(cpl_parameterlist *parlist, cpl_frameset *frameset) 00321 { 00322 cpl_image *det_lamp_on = NULL, 00323 *det_lamp_on_copy = NULL, 00324 *det_lamp_off = NULL, 00325 *bad_pix_mask = NULL, 00326 *xcal = NULL, 00327 *ycal = NULL, 00328 *lcal = NULL; 00329 00330 cpl_image **stored_lcal = NULL, 00331 **stored_det_img = NULL; 00332 00333 cpl_frame *frame = NULL; 00334 cpl_frameset ** angle_frameset = NULL; 00335 00336 int ret_val = 0, 00337 nr_devices = 0, 00338 nr_angles = 0, 00339 nx = 0, 00340 ny = 0, 00341 nz = 0, 00342 *stored_qc_arc_sat = NULL, 00343 flip_trace = FALSE, 00344 fit_order_par = 0, 00345 fit_order = 0, 00346 ndit = 0, 00347 suppress_extension = FALSE, 00348 line_estimate_method = 2, 00349 nr_sat = 0, 00350 i = 0, j = 0, a = 0, ax = 0, x = 0, y = 0; 00351 float *pbad_pix_mask = NULL; 00352 double exptime = 0.0, 00353 gain = 0.0, 00354 *stored_qc_ar_eff = NULL, 00355 *stored_qc_ne_eff = NULL, 00356 disp = 0.0, 00357 angle_found = 0.0; 00358 00359 cpl_table *arclines = NULL, 00360 *reflines = NULL, 00361 ***edge_table = NULL; 00362 00363 cpl_propertylist *main_header = NULL, 00364 **stored_sub_headers_lcal = NULL, 00365 **stored_sub_headers_det_img = NULL, 00366 *qc_header = NULL, 00367 *tmp_header = NULL, 00368 *header = NULL; 00369 00370 cpl_array **unused_ifus_before = NULL, 00371 **unused_ifus_after = NULL; 00372 00373 cpl_bivector *lines = NULL; 00374 00375 main_fits_desc desc1, 00376 desc2; 00377 00378 char *extname = NULL, 00379 filename_lcal[256], 00380 filename_det_img[256], 00381 *suffix = NULL, 00382 *fn_suffix = NULL, 00383 tmpstr[256], 00384 **filter_ids = NULL, 00385 *readmode = NULL, 00386 *str_line_estimate_method = NULL, 00387 *last_env = NULL; 00388 00389 const char *tmp_str = NULL; 00390 00391 cpl_error_code err = CPL_ERROR_NONE; 00392 00393 enum lampConfiguration lamp_config; 00394 00395 KMO_TRY 00396 { 00397 kmo_init_fits_desc(&desc1); 00398 kmo_init_fits_desc(&desc2); 00399 00400 str_line_estimate_method = getenv("KMO_WAVE_LINE_ESTIMATE"); 00401 if (str_line_estimate_method != NULL) { 00402 line_estimate_method = atoi(str_line_estimate_method); 00403 } 00404 cpl_msg_debug(cpl_func, "Line estimation method: %d\n", 00405 line_estimate_method); 00406 00407 // ############################################################################# 00408 // ### check inputs 00409 // ############################################################################# 00410 KMO_TRY_ASSURE((parlist != NULL) && 00411 (frameset != NULL), 00412 CPL_ERROR_NULL_INPUT, 00413 "Not all input data is provided!"); 00414 00415 KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, ARC_ON) >= 1, 00416 CPL_ERROR_NULL_INPUT, 00417 "At least one ARC_ON frame is required!"); 00418 00419 KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, ARC_OFF) >= 1, 00420 CPL_ERROR_NULL_INPUT, 00421 "Exactly one ARC_OFF frame is required!"); 00422 00423 if (cpl_frameset_count_tags(frameset, ARC_OFF) > 1) { 00424 cpl_msg_warning("", "Exactly one ARC_OFF frame is required. " 00425 "Just the first frame will be used"); 00426 } 00427 00428 KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, XCAL) == 1, 00429 CPL_ERROR_FILE_NOT_FOUND, 00430 "Exactly one XCAL frame is required!"); 00431 00432 KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, YCAL) == 1, 00433 CPL_ERROR_FILE_NOT_FOUND, 00434 "Exactly one YCAL frame is required!"); 00435 00436 KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, ARC_LIST) == 1, 00437 CPL_ERROR_FILE_NOT_FOUND, 00438 "Exactly one ARC_LIST frame is required!"); 00439 00440 KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, FLAT_EDGE) == 1, 00441 CPL_ERROR_FILE_NOT_FOUND, 00442 "Exactly one FLAT_EDGE frame is required!"); 00443 00444 KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, WAVE_BAND) == 1, 00445 CPL_ERROR_FILE_NOT_FOUND, 00446 "Exactly one WAVE_BAND frame is required!"); 00447 00448 if (line_estimate_method == 2) { 00449 KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, REF_LINES) == 1, 00450 CPL_ERROR_FILE_NOT_FOUND, 00451 "Exactly one REF_LINES frame is required!"); 00452 } 00453 00454 KMO_TRY_ASSURE(kmo_dfs_set_groups(frameset, "kmo_wave_cal") == 1, 00455 CPL_ERROR_ILLEGAL_INPUT, 00456 "Cannot identify RAW and CALIB frames!"); 00457 00458 // 00459 // ------------ get parameters ------------ 00460 // 00461 cpl_msg_info("", "--- Parameter setup for kmo_wave_cal ------"); 00462 00463 fit_order_par = kmo_dfs_get_parameter_int(parlist, 00464 "kmos.kmo_wave_cal.order"); 00465 KMO_TRY_CHECK_ERROR_STATE(); 00466 KMO_TRY_EXIT_IF_ERROR( 00467 kmo_dfs_print_parameter_help(parlist, "kmos.kmo_wave_cal.order")); 00468 KMO_TRY_ASSURE((fit_order_par >= 0) && 00469 (fit_order_par <= 8), 00470 CPL_ERROR_ILLEGAL_INPUT, 00471 "order must be between 1 and 8!"); 00472 00473 flip_trace = kmo_dfs_get_parameter_bool(parlist, 00474 "kmos.kmo_wave_cal.dev_flip"); 00475 KMO_TRY_CHECK_ERROR_STATE(); 00476 KMO_TRY_EXIT_IF_ERROR( 00477 kmo_dfs_print_parameter_help(parlist, "kmos.kmo_wave_cal.dev_flip")); 00478 KMO_TRY_ASSURE((flip_trace == TRUE) || 00479 (flip_trace == FALSE), 00480 CPL_ERROR_ILLEGAL_INPUT, 00481 "flip must be TRUE or FALSE!"); 00482 00483 disp = kmo_dfs_get_parameter_double(parlist, 00484 "kmos.kmo_wave_cal.dev_disp"); 00485 KMO_TRY_CHECK_ERROR_STATE(); 00486 KMO_TRY_EXIT_IF_ERROR( 00487 kmo_dfs_print_parameter_help(parlist, "kmos.kmo_wave_cal.dev_disp")); 00488 00489 KMO_TRY_ASSURE((disp > 0.0) || (disp == -1.0), 00490 CPL_ERROR_ILLEGAL_INPUT, 00491 "dispersion must be greater than 0.0!"); 00492 00493 suppress_extension = kmo_dfs_get_parameter_bool(parlist, 00494 "kmos.kmo_wave_cal.suppress_extension"); 00495 KMO_TRY_CHECK_ERROR_STATE(); 00496 KMO_TRY_EXIT_IF_ERROR( 00497 kmo_dfs_print_parameter_help(parlist, "kmos.kmo_wave_cal.suppress_extension")); 00498 00499 KMO_TRY_ASSURE((suppress_extension == TRUE) || (suppress_extension == FALSE), 00500 CPL_ERROR_ILLEGAL_INPUT, 00501 "suppress_extension must be TRUE or FALSE!"); 00502 00503 kmo_band_pars_load(parlist, "kmos.kmo_wave_cal"); 00504 00505 cpl_msg_info("", "-------------------------------------------"); 00506 00507 // 00508 // ------------ check EXPTIME, NDIT, READMODE and lamps ------------ 00509 // 00510 00511 // check ARC_OFF 00512 KMO_TRY_EXIT_IF_NULL( 00513 frame = kmo_dfs_get_frame(frameset, ARC_OFF)); 00514 00515 main_header = kmclipm_propertylist_load(cpl_frame_get_filename(frame), 0); 00516 00517 ndit = cpl_propertylist_get_int(main_header, NDIT); 00518 KMO_TRY_CHECK_ERROR_STATE("NDIT keyword in main header " 00519 "missing!"); 00520 00521 exptime = cpl_propertylist_get_double(main_header, EXPTIME); 00522 KMO_TRY_CHECK_ERROR_STATE("EXPTIME keyword in main header " 00523 "missing!"); 00524 00525 readmode = cpl_strdup(cpl_propertylist_get_string(main_header, READMODE)); 00526 KMO_TRY_CHECK_ERROR_STATE("ESO DET READ CURNAME keyword in main " 00527 "header missing!"); 00528 00529 desc1 = kmo_identify_fits_header( 00530 cpl_frame_get_filename(frame)); 00531 KMO_TRY_CHECK_ERROR_STATE_MSG("ARC_OFF frame doesn't seem to " 00532 "be in KMOS-format!"); 00533 00534 KMO_TRY_ASSURE(desc1.fits_type == raw_fits, 00535 CPL_ERROR_ILLEGAL_INPUT, 00536 "ARC_OFF frame hasn't correct data type " 00537 "(%s must be a raw, unprocessed file)!", 00538 cpl_frame_get_filename(frame)); 00539 00540 nx = desc1.naxis1; 00541 ny = desc1.naxis2; 00542 nz = desc1.naxis3; 00543 nr_devices = desc1.nr_ext; 00544 00545 // assure that flat lamps are off 00546 KMO_TRY_ASSURE((kmo_check_lamp(main_header, INS_LAMP3_ST) == FALSE) && 00547 (kmo_check_lamp(main_header, INS_LAMP4_ST) == FALSE), 00548 CPL_ERROR_ILLEGAL_INPUT, 00549 "Flat lamps must be switched off (%s)!", 00550 cpl_frame_get_filename(frame)); 00551 00552 // check if arc lamps are off (or at least blocked by filter wheel) 00553 if ((kmo_check_lamp(main_header, INS_LAMP1_ST) == TRUE) || 00554 (kmo_check_lamp(main_header, INS_LAMP2_ST) == TRUE)) 00555 { 00556 if (!(strcmp(cpl_propertylist_get_string(main_header, "ESO INS FILT1 ID"), "Block") == 0) || 00557 !(strcmp(cpl_propertylist_get_string(main_header, "ESO INS FILT3 ID"), "Block") == 0) || 00558 !(strcmp(cpl_propertylist_get_string(main_header, "ESO INS FILT3 ID"), "Block") == 0)) 00559 { 00560 cpl_msg_warning("","At least one arc lamp is on! Check if the lamps are blocked!"); 00561 } 00562 } 00563 cpl_propertylist_delete(main_header); main_header = NULL; 00564 00565 // check REF_LINES 00566 if (line_estimate_method == 2) { 00567 KMO_TRY_EXIT_IF_NULL( 00568 frame = kmo_dfs_get_frame(frameset, REF_LINES)); 00569 desc2 = kmo_identify_fits_header( 00570 cpl_frame_get_filename(frame)); 00571 KMO_TRY_CHECK_ERROR_STATE_MSG("REF_LINES frame doesn't seem to " 00572 "be in KMOS-format!"); 00573 00574 KMO_TRY_ASSURE(desc2.fits_type == f2l_fits, 00575 CPL_ERROR_ILLEGAL_INPUT, 00576 "REF_LINES frame hasn't correct frame type " 00577 "(%s must be a F2L frame)!", 00578 cpl_frame_get_filename(frame)); 00579 kmo_free_fits_desc(&desc2); 00580 } 00581 00582 // check ARC_ON 00583 KMO_TRY_EXIT_IF_NULL( 00584 frame = kmo_dfs_get_frame(frameset, ARC_ON)); 00585 00586 while (frame != NULL) { 00587 main_header = kmclipm_propertylist_load(cpl_frame_get_filename(frame), 0); 00588 00589 KMO_TRY_ASSURE(cpl_propertylist_get_int(main_header, NDIT) == ndit, 00590 CPL_ERROR_ILLEGAL_INPUT, 00591 "NDIT isn't the same for all frames: (is %d and %d).", 00592 cpl_propertylist_get_int(main_header, NDIT), ndit); 00593 00594 KMO_TRY_ASSURE(cpl_propertylist_get_double(main_header, EXPTIME) == exptime, 00595 CPL_ERROR_ILLEGAL_INPUT, 00596 "EXPTIME isn't the same for all frames: (is %g and %g).", 00597 cpl_propertylist_get_double(main_header, EXPTIME), exptime); 00598 00599 KMO_TRY_ASSURE(strcmp(cpl_propertylist_get_string(main_header, READMODE), readmode) == 0, 00600 CPL_ERROR_ILLEGAL_INPUT, 00601 "ESO DET READ CURNAME isn't the same for all frames: (is %s and %s).", 00602 cpl_propertylist_get_string(main_header, READMODE), readmode); 00603 00604 desc2 = kmo_identify_fits_header( 00605 cpl_frame_get_filename(frame)); 00606 KMO_TRY_CHECK_ERROR_STATE_MSG("ARC_ON frame doesn't seem to " 00607 "be in KMOS-format!"); 00608 00609 KMO_TRY_ASSURE(desc2.fits_type == raw_fits, 00610 CPL_ERROR_ILLEGAL_INPUT, 00611 "ARC_ON frame hasn't correct data type " 00612 "(%s must be a raw, unprocessed file)!", 00613 cpl_frame_get_filename(frame)); 00614 00615 KMO_TRY_ASSURE((desc2.naxis1 == nx) && 00616 (desc2.naxis2 == ny) && 00617 (desc2.naxis3 == nz), 00618 CPL_ERROR_ILLEGAL_INPUT, 00619 "ARC_ON frame hasn't correct dimensions! (x,y): (%d,%d) " 00620 "vs (%d,%d)", desc2.naxis1, desc2.naxis2, nx, ny); 00621 00622 00623 // assure that flat lamp is off (LAMP3 and 4) 00624 // and that either arc lamp is on (LAMP1 and 2) 00625 KMO_TRY_ASSURE(((kmo_check_lamp(main_header, INS_LAMP1_ST) == TRUE) || 00626 (kmo_check_lamp(main_header, INS_LAMP2_ST) == TRUE)) && 00627 (kmo_check_lamp(main_header, INS_LAMP3_ST) == FALSE) && 00628 (kmo_check_lamp(main_header, INS_LAMP4_ST) == FALSE), 00629 CPL_ERROR_ILLEGAL_INPUT, 00630 "Lamp1 or Lamp2 must be switched on, 3 and 4 must be " 00631 "off for the ARC_ON frame"); 00632 00633 frame = kmo_dfs_get_frame(frameset, NULL); 00634 KMO_TRY_CHECK_ERROR_STATE(); 00635 00636 kmo_free_fits_desc(&desc2); 00637 kmo_init_fits_desc(&desc2); 00638 cpl_propertylist_delete(main_header); main_header = NULL; 00639 } 00640 00641 // load first ARC_ON main header 00642 KMO_TRY_EXIT_IF_NULL( 00643 frame = kmo_dfs_get_frame(frameset, ARC_ON)); 00644 KMO_TRY_EXIT_IF_NULL( 00645 main_header = kmclipm_propertylist_load(cpl_frame_get_filename(frame), 0)); 00646 00647 // check FLAT_EDGE 00648 KMO_TRY_EXIT_IF_NULL( 00649 frame = kmo_dfs_get_frame(frameset, FLAT_EDGE)); 00650 00651 desc2 = kmo_identify_fits_header(cpl_frame_get_filename(frame)); 00652 KMO_TRY_CHECK_ERROR_STATE(); 00653 00654 KMO_TRY_ASSURE((desc2.nr_ext % 24== 0) && 00655 (desc2.fits_type == f2l_fits), 00656 CPL_ERROR_ILLEGAL_INPUT, 00657 "FLAT_EDGE isn't in the correct format!!!"); 00658 00659 kmo_free_fits_desc(&desc2); 00660 kmo_init_fits_desc(&desc2); 00661 00662 // 00663 // ------------ check filter_id, grating_id and rotator offset --------- 00664 // assure that filters, grating and rotation offsets match for 00665 // ARC_ON, XCAL and YCAL 00666 // check if filter_id, grating_id and rotator offset match for all 00667 // detectors 00668 // 00669 KMO_TRY_EXIT_IF_ERROR( 00670 kmo_check_frame_setup(frameset, ARC_ON, XCAL, 00671 TRUE, FALSE, FALSE)); 00672 KMO_TRY_EXIT_IF_ERROR( 00673 kmo_check_frame_setup(frameset, ARC_ON, YCAL, 00674 TRUE, FALSE, FALSE)); 00675 00676 KMO_TRY_EXIT_IF_ERROR( 00677 kmo_check_frame_setup_md5_xycal(frameset)); 00678 00679 strcpy(filename_lcal, LCAL); 00680 strcpy(filename_det_img, DET_IMG_WAVE); 00681 00682 KMO_TRY_EXIT_IF_NULL( 00683 frame = kmo_dfs_get_frame(frameset, XCAL)); 00684 KMO_TRY_EXIT_IF_NULL( 00685 suffix = kmo_dfs_get_suffix(frame, TRUE, FALSE)); 00686 00687 cpl_msg_info("", "Detected instrument setup: %s", suffix+1); 00688 cpl_msg_info("", "(grating 1, 2 & 3)"); 00689 00690 // setup lamp config 00691 if ((kmo_check_lamp(main_header, INS_LAMP1_ST) == TRUE) && 00692 (kmo_check_lamp(main_header, INS_LAMP2_ST) == FALSE)) 00693 { 00694 lamp_config = ARGON; 00695 strcpy(tmpstr, "Argon"); 00696 } else if ((kmo_check_lamp(main_header, INS_LAMP1_ST) == FALSE) && 00697 (kmo_check_lamp(main_header, INS_LAMP2_ST) == TRUE)) 00698 { 00699 lamp_config = NEON; 00700 strcpy(tmpstr, "Neon"); 00701 } else if ((kmo_check_lamp(main_header, INS_LAMP1_ST) == TRUE) && 00702 (kmo_check_lamp(main_header, INS_LAMP2_ST) == TRUE)) 00703 { 00704 lamp_config = ARGON_NEON; 00705 strcpy(tmpstr, "Argon + Neon"); 00706 } 00707 00708 cpl_msg_info("", "Detected arc lamp configuration: %s", tmpstr); 00709 00710 //assert that filter and grating match for each detector 00711 // filter/grating can be different for each detector 00712 KMO_TRY_EXIT_IF_NULL( 00713 filter_ids = kmo_get_filter_setup(main_header, nr_devices, TRUE)); 00714 00715 // 00716 // ---- scan for rotator angles 00717 // 00718 #define ANGLE_DIM 360 00719 int rotang_found[ANGLE_DIM]; 00720 int rotang_cnt[ANGLE_DIM]; 00721 for (i = 0; i < ANGLE_DIM; i++) { 00722 rotang_found[i] = 0; 00723 rotang_cnt[i] = 0; 00724 } 00725 KMO_TRY_EXIT_IF_NULL( 00726 frame = kmo_dfs_get_frame(frameset, ARC_ON)); 00727 while (frame != NULL) { 00728 header = kmclipm_propertylist_load(cpl_frame_get_filename(frame), 0); 00729 if (cpl_propertylist_has(header, ROTANGLE)) { 00730 int rot_angle = (int) rint(cpl_propertylist_get_double(header, ROTANGLE)); 00731 if (rot_angle < 0) { 00732 rot_angle += 360; 00733 } 00734 if (rot_angle < 360 && rot_angle >= 0) { 00735 rotang_cnt[rot_angle]++; 00736 // char * tag = cpl_sprintf("FLAT_ON_%3.3d",rot_angle); 00737 // KMO_TRY_EXIT_IF_ERROR( 00738 // cpl_frame_set_tag(frame, tag)); 00739 // cpl_free(tag); 00740 } 00741 } else { 00742 cpl_msg_warning("","File %s has no keyword \"ROTANGLE\"", 00743 cpl_frame_get_filename(frame)); 00744 } 00745 00746 cpl_propertylist_delete(header); header = NULL; 00747 frame = kmo_dfs_get_frame(frameset, NULL); 00748 KMO_TRY_CHECK_ERROR_STATE(); 00749 } 00750 for (ax = 0; ax < ANGLE_DIM; ax++) { 00751 if (rotang_cnt[ax] != 0) { 00752 if (rotang_cnt[ax] == 1 ) { 00753 cpl_msg_info("","Found %d frame with rotator angle %d",rotang_cnt[ax],ax); 00754 } else { 00755 cpl_msg_warning("","Found %d frames with rotator angle %d but only one will be used", 00756 rotang_cnt[ax],ax); 00757 } 00758 rotang_found[nr_angles] = ax; 00759 nr_angles++; 00760 } 00761 } 00762 00763 KMO_TRY_EXIT_IF_NULL ( 00764 angle_frameset = (cpl_frameset **) cpl_malloc(nr_angles * sizeof(cpl_frameset*))); 00765 for (i = 0; i < nr_angles; i++) { 00766 angle_frameset[i] = cpl_frameset_new(); 00767 } 00768 00769 KMO_TRY_EXIT_IF_NULL( 00770 frame = kmo_dfs_get_frame(frameset, ARC_ON)); 00771 while (frame != NULL) { 00772 header = kmclipm_propertylist_load(cpl_frame_get_filename(frame), 0); 00773 if (cpl_propertylist_has(header, ROTANGLE)) { 00774 int rot_angle = (int) rint(cpl_propertylist_get_double(header, ROTANGLE)); 00775 if (rot_angle < 0) { 00776 rot_angle += 360; 00777 } 00778 int ix = -1; 00779 for (ix = 0; ix<nr_angles; ix++) { 00780 if (rotang_found[ix] == rot_angle) { 00781 break; 00782 } 00783 } 00784 if (ix<nr_angles) { 00785 KMO_TRY_EXIT_IF_ERROR( 00786 cpl_frameset_insert(angle_frameset[ix], cpl_frame_duplicate(frame))); 00787 } 00788 } 00789 00790 cpl_propertylist_delete(header); header = NULL; 00791 frame = kmo_dfs_get_frame(frameset, NULL); 00792 KMO_TRY_CHECK_ERROR_STATE(); 00793 } 00794 00795 // ############################################################################# 00796 // ### allocate temporary memory 00797 // ############################################################################# 00798 // allocate here a edge table structure for all detectors 00799 KMO_TRY_EXIT_IF_NULL( 00800 edge_table = (cpl_table***)cpl_calloc(nr_devices, 00801 sizeof(cpl_table**))); 00802 for (i = 0; i < nr_devices; i++) { 00803 KMO_TRY_EXIT_IF_NULL( 00804 edge_table[i] = (cpl_table**)cpl_calloc(KMOS_IFUS_PER_DETECTOR, 00805 sizeof(cpl_table*))); 00806 } 00807 00808 // the frames have to be stored temporarily because the QC parameters 00809 // for the main header are calculated from each detector. So they can be 00810 // stored only when all detectors are processed 00811 KMO_TRY_EXIT_IF_NULL( 00812 stored_lcal = (cpl_image**)cpl_calloc(nr_devices * nr_angles, 00813 sizeof(cpl_image*))); 00814 KMO_TRY_EXIT_IF_NULL( 00815 stored_det_img = (cpl_image**)cpl_calloc(nr_devices * nr_angles, 00816 sizeof(cpl_image*))); 00817 KMO_TRY_EXIT_IF_NULL( 00818 stored_sub_headers_lcal = (cpl_propertylist**)cpl_calloc(nr_devices * nr_angles, 00819 sizeof(cpl_propertylist*))); 00820 KMO_TRY_EXIT_IF_NULL( 00821 stored_sub_headers_det_img = (cpl_propertylist**)cpl_calloc(nr_devices * nr_angles, 00822 sizeof(cpl_propertylist*))); 00823 KMO_TRY_EXIT_IF_NULL( 00824 stored_qc_arc_sat = 00825 (int*)cpl_calloc(nr_devices, nr_angles * sizeof(int))); 00826 KMO_TRY_EXIT_IF_NULL( 00827 stored_qc_ar_eff = 00828 (double*)cpl_calloc(nr_devices, nr_angles * sizeof(double))); 00829 KMO_TRY_EXIT_IF_NULL( 00830 stored_qc_ne_eff = 00831 (double*)cpl_calloc(nr_devices, nr_angles * sizeof(double))); 00832 00833 // ############################################################################# 00834 // ### process data 00835 // ############################################################################# 00836 // load arclines and reference lines 00837 KMO_TRY_EXIT_IF_NULL( 00838 frame = kmo_dfs_get_frame(frameset, ARC_LIST)); 00839 00840 // check if ARC_LIST is the filter_id-one 00841 KMO_TRY_EXIT_IF_NULL( 00842 tmp_header = kmclipm_propertylist_load(cpl_frame_get_filename(frame), 0)); 00843 KMO_TRY_EXIT_IF_NULL( 00844 tmp_str = cpl_propertylist_get_string(tmp_header, FILT_ID)); 00845 KMO_TRY_ASSURE(strcmp(filter_ids[0], tmp_str) == 0, 00846 CPL_ERROR_ILLEGAL_INPUT, 00847 "ARC_LIST model must have primary " 00848 "keyword '%s' equal '%s'!!!", FILT_ID, filter_ids[0]); 00849 cpl_propertylist_delete(tmp_header); tmp_header = NULL; 00850 00851 desc2 = kmo_identify_fits_header(cpl_frame_get_filename(frame)); 00852 KMO_TRY_CHECK_ERROR_STATE(); 00853 00854 KMO_TRY_ASSURE((desc2.nr_ext == 1) && 00855 (desc2.fits_type == f2l_fits), 00856 CPL_ERROR_ILLEGAL_INPUT, 00857 "ARC_LIST isn't in the correct format!!!"); 00858 kmo_free_fits_desc(&desc2); 00859 kmo_init_fits_desc(&desc2); 00860 00861 KMO_TRY_EXIT_IF_NULL( 00862 arclines = kmo_dfs_load_table(frameset, ARC_LIST, 1, 0)); 00863 00864 KMO_TRY_EXIT_IF_NULL( 00865 lines = kmo_get_lines(arclines, lamp_config)); 00866 00867 cpl_msg_info("", "Nr. of lines in arclist for this configuration: %lld", 00868 cpl_bivector_get_size(lines)); 00869 00870 if (line_estimate_method == 2) { 00871 KMO_TRY_EXIT_IF_NULL( 00872 reflines = kmo_dfs_load_table(frameset, REF_LINES, 1, 0)); 00873 } 00874 00875 // check which IFUs are active for all FLAT frames 00876 KMO_TRY_EXIT_IF_NULL( 00877 unused_ifus_before = kmo_get_unused_ifus(frameset, 0, 0)); 00878 00879 KMO_TRY_EXIT_IF_NULL( 00880 unused_ifus_after = kmo_duplicate_unused_ifus(unused_ifus_before)); 00881 00882 kmo_print_unused_ifus(unused_ifus_before, FALSE); 00883 00884 // make sure no reconstruction lookup table (LUT) is used 00885 if (getenv("KMCLIPM_PRIV_RECONSTRUCT_LUT_MODE") != NULL) { 00886 last_env = getenv("KMCLIPM_PRIV_RECONSTRUCT_LUT_MODE"); 00887 } 00888 setenv("KMCLIPM_PRIV_RECONSTRUCT_LUT_MODE","NONE",1); 00889 00890 // 00891 // ------------ loop all rotator angles and detectors ------------ 00892 // 00893 for (a = 0; a < nr_angles; a++) { 00894 cpl_msg_info("","Processing rotator angle %d -> %d degree", a,rotang_found[a]); 00895 00896 for (i = 1; i <= nr_devices; i++) { 00897 // use loop below for line identification 00898 cpl_msg_info("","Processing detector No. %d", i); 00899 00900 int sx = a * nr_devices + (i - 1); 00901 00902 // load edge parameters 00903 KMO_TRY_EXIT_IF_NULL( 00904 frame = kmo_dfs_get_frame(frameset, FLAT_EDGE)); 00905 00906 for (j = 0; j < KMOS_IFUS_PER_DETECTOR; j++) { 00907 edge_table[i-1][j] = kmclipm_cal_table_load(cpl_frame_get_filename(frame), 00908 (i-1) * KMOS_IFUS_PER_DETECTOR + j + 1, 00909 rotang_found[a], 0, &angle_found); 00910 if (cpl_error_get_code() == CPL_ERROR_ILLEGAL_INPUT) { 00911 // IFU is inactive: proceed 00912 cpl_error_reset(); 00913 } 00914 } 00915 00916 if (fit_order_par == 0) { 00917 // set default fit orders for the different bands 00918 if ((strcmp(filter_ids[i-1], "H") == 0) || 00919 (strcmp(filter_ids[i-1], "K") == 0) || 00920 (strcmp(filter_ids[i-1], "YJ") == 0)) 00921 { 00922 fit_order = 6; 00923 } else if (strcmp(filter_ids[i-1], "IZ") == 0) { 00924 fit_order = 4; 00925 } else if (strcmp(filter_ids[i-1], "HK") == 0) { 00926 fit_order = 5; 00927 } 00928 cpl_msg_info("", "Order of wavelength spectrum fit for %s-band: %d", 00929 filter_ids[i-1], 00930 fit_order); 00931 } else { 00932 fit_order = fit_order_par; 00933 } 00934 00935 // lamp_on 00936 KMO_TRY_EXIT_IF_NULL( 00937 frame = kmo_dfs_get_frame(angle_frameset[a], ARC_ON)); 00938 00939 // if sat_mode is set to TRUE here, then the calculation of the 00940 // saturated pixels has to be updated like in kmo_flat-recipe 00941 KMO_TRY_EXIT_IF_NULL( 00942 det_lamp_on = kmo_dfs_load_image_frame(frame, i, FALSE, TRUE, &nr_sat)); 00943 00944 // count saturated pixels for each detector 00945 if (strcmp(cpl_propertylist_get_string(main_header, READMODE), "Nondest") == 0) { 00946 // NDR: non-destructive readout mode 00947 stored_qc_arc_sat[sx] = nr_sat; 00948 } else { 00949 // normal readout mode 00950 stored_qc_arc_sat[sx] = kmo_image_get_saturated(det_lamp_on, 00951 KMO_FLAT_SATURATED); 00952 } 00953 KMO_TRY_CHECK_ERROR_STATE(); 00954 00955 00956 KMO_TRY_EXIT_IF_NULL( 00957 det_lamp_on_copy = cpl_image_duplicate(det_lamp_on)); 00958 00959 // lamp_off 00960 KMO_TRY_EXIT_IF_NULL( 00961 frame = kmo_dfs_get_frame(frameset, ARC_OFF)); 00962 00963 KMO_TRY_EXIT_IF_NULL( 00964 det_lamp_off = kmo_dfs_load_image_frame(frame, i, FALSE, FALSE, NULL)); 00965 00966 // 00967 // process imagelist 00968 // 00969 KMO_TRY_CHECK_ERROR_STATE(); 00970 00971 // subtract lamp_off from lamp_on 00972 KMO_TRY_EXIT_IF_ERROR( 00973 cpl_image_subtract(det_lamp_on, det_lamp_off)); 00974 00975 // load flat calibration frames 00976 KMO_TRY_EXIT_IF_NULL( 00977 xcal = kmo_dfs_load_cal_image(frameset, XCAL, i, 0, 00978 (double) rotang_found[a], FALSE, 00979 NULL, &angle_found, -1, 0, 0)); 00980 00981 KMO_TRY_EXIT_IF_NULL( 00982 ycal = kmo_dfs_load_cal_image(frameset, YCAL, i, 0, 00983 (double) rotang_found[a], FALSE, 00984 NULL, &angle_found, -1, 0, 0)); 00985 00986 // load bad pixel mask from XCAL and set NaNs to 0 and all other values to 1 00987 KMO_TRY_EXIT_IF_NULL( 00988 bad_pix_mask = cpl_image_duplicate(xcal)); 00989 00990 KMO_TRY_EXIT_IF_NULL( 00991 pbad_pix_mask = cpl_image_get_data_float(bad_pix_mask)); 00992 for (x = 0; x < nx; x++) { 00993 for (y = 0; y < ny; y++) { 00994 if (isnan(pbad_pix_mask[x+nx*y])) { 00995 pbad_pix_mask[x+nx*y] = 0.; 00996 } else { 00997 pbad_pix_mask[x+nx*y] = 1.; 00998 } 00999 } 01000 } 01001 01002 // calculate spectral curvature here 01003 err = kmo_calc_wave_calib(det_lamp_on, 01004 bad_pix_mask, 01005 xcal, 01006 ycal, 01007 filter_ids[i-1], 01008 lamp_config, 01009 i, 01010 unused_ifus_after[i-1], 01011 edge_table[i-1], 01012 lines, 01013 reflines, 01014 disp, 01015 &lcal, 01016 &(stored_qc_ar_eff[sx]), 01017 &(stored_qc_ne_eff[sx]), 01018 flip_trace, 01019 fit_order, 01020 line_estimate_method); 01021 01022 if (err == CPL_ERROR_NONE) { 01023 // calculate QC parameters 01024 if (stored_qc_ar_eff[sx] != -1.0) { 01025 stored_qc_ar_eff[sx] /= exptime; 01026 } 01027 if (stored_qc_ne_eff[sx] != -1.0) { 01028 stored_qc_ne_eff[sx] /= exptime; 01029 } 01030 01031 // apply the badpixel mask to the produced frame 01032 01033 KMO_TRY_EXIT_IF_ERROR( 01034 cpl_image_multiply(lcal, bad_pix_mask)); 01035 01036 KMO_TRY_EXIT_IF_ERROR( 01037 kmo_image_reject_from_mask(lcal, bad_pix_mask)); 01038 01039 // store flat frames, badpixel mask and calibration frames 01040 stored_lcal[sx] = lcal; 01041 } else if (err == CPL_ERROR_UNSPECIFIED) { 01042 // all IFUs seem to be deativated, continue processing 01043 // just save empty frame 01044 cpl_error_reset(); 01045 stored_lcal[sx] = cpl_image_new(nx, ny, CPL_TYPE_FLOAT); 01046 kmo_image_fill(stored_lcal[sx], 0.0); 01047 } else { 01048 cpl_msg_warning(cpl_func, 01049 "Couldn't identify any lines! Is the line " 01050 "list defined correctly?"); 01051 cpl_msg_warning(cpl_func, 01052 "Band defined in header of detector %d: %s", 01053 i, filter_ids[i-1]); 01054 cpl_msg_warning(cpl_func, 01055 "Arc line file defined: %s", 01056 cpl_frame_get_filename( 01057 kmo_dfs_get_frame(frameset, ARC_LIST))); 01058 cpl_error_reset(); 01059 } 01060 01061 01062 // 01063 // create reconstructed and resampled arc frame 01064 // 01065 stored_det_img[sx] = kmo_reconstructed_arc_image(frameset, 01066 det_lamp_on_copy, 01067 det_lamp_off, 01068 xcal, 01069 ycal, 01070 stored_lcal[sx], 01071 unused_ifus_after[i-1], 01072 flip_trace, 01073 i, 01074 suffix, 01075 filter_ids[i-1], 01076 lamp_config, 01077 rotang_found[a], 01078 &qc_header); 01079 if (cpl_error_get_code() != CPL_ERROR_NONE) { 01080 // couldn't reconstruct 01081 cpl_msg_error("","Couldn't reconstruct IFUs on detector %d", i); 01082 cpl_error_reset(); 01083 } 01084 01085 // load and update sub_header with QC parameters 01086 KMO_TRY_EXIT_IF_NULL( 01087 stored_sub_headers_lcal[sx] = kmo_dfs_load_sub_header(frameset, 01088 ARC_ON, i, 01089 FALSE)); 01090 01091 // update EXTNAME 01092 KMO_TRY_EXIT_IF_NULL( 01093 extname = kmo_extname_creator(detector_frame, i, EXT_DATA)); 01094 KMO_TRY_EXIT_IF_ERROR( 01095 kmclipm_update_property_string(stored_sub_headers_lcal[sx], 01096 EXTNAME, 01097 extname, 01098 "FITS extension name")); 01099 cpl_free(extname); extname = NULL; 01100 01101 KMO_TRY_EXIT_IF_ERROR( 01102 kmclipm_update_property_int(stored_sub_headers_lcal[sx], 01103 EXTVER, 01104 sx+1, 01105 "FITS extension ver")); 01106 01107 // add first QC parameters 01108 KMO_TRY_EXIT_IF_ERROR( 01109 kmclipm_update_property_int(stored_sub_headers_lcal[sx], 01110 QC_ARC_SAT, 01111 stored_qc_arc_sat[sx], 01112 "[] nr. saturated pixels of arc exp.")); 01113 01114 gain = kmo_dfs_get_property_double(stored_sub_headers_lcal[sx], GAIN); 01115 KMO_TRY_CHECK_ERROR_STATE_MSG( 01116 "GAIN-keyword in fits-header is missing!"); 01117 01118 if (stored_qc_ar_eff[sx] != -1.0) { 01119 KMO_TRY_EXIT_IF_ERROR( 01120 kmclipm_update_property_double(stored_sub_headers_lcal[sx], 01121 QC_ARC_AR_EFF, 01122 stored_qc_ar_eff[sx]/gain, 01123 "[e-/s] Argon lamp efficiency")); 01124 } 01125 01126 if (stored_qc_ne_eff[sx] != -1.0) { 01127 KMO_TRY_EXIT_IF_ERROR( 01128 kmclipm_update_property_double(stored_sub_headers_lcal[sx], 01129 QC_ARC_NE_EFF, 01130 stored_qc_ne_eff[sx]/gain, 01131 "[e-/s] Neon lamp efficiency")); 01132 } 01133 01134 KMO_TRY_EXIT_IF_ERROR( 01135 kmclipm_update_property_double(stored_sub_headers_lcal[sx], 01136 CAL_ROTANGLE, 01137 ((double) rotang_found[a]), 01138 "[deg] Rotator relative to nasmyth")); 01139 01140 // append QC parameters 01141 KMO_TRY_EXIT_IF_ERROR( 01142 cpl_propertylist_append(stored_sub_headers_lcal[sx], 01143 qc_header)); 01144 cpl_propertylist_delete(qc_header); qc_header = NULL; 01145 01146 KMO_TRY_EXIT_IF_NULL( 01147 stored_sub_headers_det_img[sx] = cpl_propertylist_duplicate( 01148 stored_sub_headers_lcal[sx])); 01149 01150 cpl_propertylist_erase(stored_sub_headers_lcal[sx], CRVAL1); 01151 cpl_propertylist_erase(stored_sub_headers_lcal[sx], CRVAL2); 01152 cpl_propertylist_erase(stored_sub_headers_lcal[sx], CTYPE1); 01153 cpl_propertylist_erase(stored_sub_headers_lcal[sx], CTYPE2); 01154 cpl_propertylist_erase(stored_sub_headers_lcal[sx], CDELT1); 01155 cpl_propertylist_erase(stored_sub_headers_lcal[sx], CDELT2); 01156 01157 cpl_propertylist_erase(stored_sub_headers_lcal[sx], CRPIX1); 01158 cpl_propertylist_erase(stored_sub_headers_lcal[sx], CRPIX2); 01159 if (cpl_propertylist_has(stored_sub_headers_lcal[sx], CRPIX1)) { 01160 cpl_propertylist_erase(stored_sub_headers_lcal[sx], CRPIX1); 01161 } 01162 if (cpl_propertylist_has(stored_sub_headers_lcal[sx], CRPIX2)) { 01163 cpl_propertylist_erase(stored_sub_headers_lcal[sx], CRPIX2); 01164 } 01165 01166 // free memory 01167 cpl_image_delete(det_lamp_on); det_lamp_on = NULL; 01168 cpl_image_delete(det_lamp_on_copy); det_lamp_on_copy = NULL; 01169 cpl_image_delete(det_lamp_off); det_lamp_off = NULL; 01170 cpl_image_delete(bad_pix_mask); bad_pix_mask = NULL; 01171 cpl_image_delete(xcal); xcal = NULL; 01172 cpl_image_delete(ycal); ycal = NULL; 01173 01174 for (j = 0; j < KMOS_IFUS_PER_DETECTOR; j++) { 01175 cpl_table_delete(edge_table[i-1][j]); edge_table[i-1][j] = NULL; 01176 } 01177 } // for i devices 01178 } // for a angles 01179 01180 if (line_estimate_method == 2) { 01181 cpl_table_delete(reflines); reflines = NULL; 01182 } 01183 // ########################################################################### 01184 // ### QC parameters & saving 01185 // ########################################################################### 01186 cpl_msg_info("","Saving data..."); 01187 01188 // 01189 // ------------ load, update & save primary header ------------ 01190 // 01191 if (!suppress_extension) { 01192 KMO_TRY_EXIT_IF_NULL( 01193 fn_suffix = cpl_sprintf("%s", suffix)); 01194 } else { 01195 KMO_TRY_EXIT_IF_NULL( 01196 fn_suffix = cpl_sprintf("%s", "")); 01197 } 01198 01199 // update which IFUs are not used 01200 KMO_TRY_EXIT_IF_ERROR( 01201 kmo_set_unused_ifus(unused_ifus_after, main_header, 01202 "kmo_wave_cal")); 01203 01204 KMO_TRY_EXIT_IF_NULL( 01205 frame = kmo_dfs_get_frame(frameset, ARC_ON)); 01206 01207 KMO_TRY_EXIT_IF_ERROR( 01208 kmo_dfs_save_main_header(frameset, filename_lcal, fn_suffix, frame, 01209 main_header, parlist, cpl_func)); 01210 01211 KMO_TRY_EXIT_IF_ERROR( 01212 kmo_dfs_save_main_header(frameset, filename_det_img, fn_suffix, frame, 01213 main_header, parlist, cpl_func)); 01214 01215 cpl_propertylist_delete(main_header); main_header = NULL; 01216 01217 // 01218 // --- save sub-frames --- 01219 // 01220 for (a = 0; a < nr_angles; a++) { 01221 for (i = 1; i <= nr_devices; i++) { 01222 int sx = a * nr_devices + (i - 1); 01223 // save lcal-frame 01224 KMO_TRY_EXIT_IF_ERROR( 01225 kmo_dfs_save_image(stored_lcal[sx], filename_lcal, fn_suffix, 01226 stored_sub_headers_lcal[sx], 0./0.)); 01227 01228 // save detector image 01229 KMO_TRY_EXIT_IF_ERROR( 01230 kmo_dfs_save_image(stored_det_img[sx], filename_det_img, fn_suffix, 01231 stored_sub_headers_det_img[sx], 0./0.)); 01232 } // for i = nr_devices 01233 } // for a angles 01234 01235 // print which IFUs are not used 01236 kmo_print_unused_ifus(unused_ifus_after, TRUE); 01237 } 01238 KMO_CATCH 01239 { 01240 KMO_CATCH_MSG(); 01241 ret_val = -1; 01242 } 01243 01244 if (last_env != NULL) { 01245 setenv("KMCLIPM_PRIV_RECONSTRUCT_LUT_MODE",last_env,1); 01246 } else { 01247 unsetenv("KMCLIPM_PRIV_RECONSTRUCT_LUT_MODE"); 01248 } 01249 01250 kmo_free_fits_desc(&desc1); 01251 kmo_free_fits_desc(&desc2); 01252 if (unused_ifus_before != NULL) { 01253 kmo_free_unused_ifus(unused_ifus_before); unused_ifus_before = NULL; 01254 } 01255 if (unused_ifus_after != NULL) { 01256 kmo_free_unused_ifus(unused_ifus_after); unused_ifus_after = NULL; 01257 } 01258 cpl_propertylist_delete(main_header); main_header = NULL; 01259 cpl_image_delete(det_lamp_on); det_lamp_on = NULL; 01260 cpl_image_delete(det_lamp_off); det_lamp_off = NULL; 01261 cpl_image_delete(bad_pix_mask); bad_pix_mask = NULL; 01262 cpl_table_delete(arclines); arclines = NULL; 01263 cpl_table_delete(reflines); reflines = NULL; 01264 cpl_free(stored_qc_arc_sat); stored_qc_arc_sat = NULL; 01265 cpl_free(stored_qc_ar_eff); stored_qc_ar_eff = NULL; 01266 cpl_free(stored_qc_ne_eff); stored_qc_ne_eff = NULL; 01267 for (i = 0; i < nr_devices * nr_angles; i++) { 01268 cpl_image_delete(stored_lcal[i]); stored_lcal[i] = NULL; 01269 cpl_image_delete(stored_det_img[i]); stored_det_img[i] = NULL; 01270 cpl_propertylist_delete(stored_sub_headers_lcal[i]); 01271 stored_sub_headers_lcal[i] = NULL; 01272 cpl_propertylist_delete(stored_sub_headers_det_img[i]); 01273 stored_sub_headers_det_img[i] = NULL; 01274 } 01275 for (i = 0; i < nr_angles; i++) { 01276 cpl_frameset_delete(angle_frameset[i]); angle_frameset[i] = NULL; 01277 } 01278 if (filter_ids != NULL) { 01279 for (i = 0; i < nr_devices; i++) { 01280 cpl_free(filter_ids[i]); filter_ids[i] = NULL; 01281 01282 } 01283 cpl_free(filter_ids); filter_ids = NULL; 01284 } 01285 if (edge_table != NULL) { 01286 for (i = 0; i < nr_devices; i++) { 01287 cpl_free(edge_table[i]); edge_table[i] = NULL; 01288 } 01289 cpl_free(edge_table); edge_table = NULL; 01290 } 01291 01292 cpl_free(angle_frameset); angle_frameset = NULL; 01293 cpl_free(stored_lcal); stored_lcal = NULL; 01294 cpl_free(stored_det_img); stored_det_img = NULL; 01295 cpl_free(stored_sub_headers_lcal); stored_sub_headers_lcal = NULL; 01296 cpl_free(stored_sub_headers_det_img); stored_sub_headers_det_img = NULL; 01297 cpl_free(readmode); readmode = NULL; 01298 cpl_bivector_delete(lines); lines = NULL; 01299 cpl_free(suffix); suffix = NULL; 01300 cpl_free(fn_suffix); fn_suffix = NULL; 01301 01302 return ret_val; 01303 } 01304
1.7.6.1