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