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