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