|
KMOS Pipeline Reference Manual
1.1.1
|
00001 /* $Id: kmo_wave_cal.c,v 1.44 2013/03/21 11:26:23 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/03/21 11:26:23 $ 00024 * $Revision: 1.44 $ 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 KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, XCAL) == 1, 00402 CPL_ERROR_FILE_NOT_FOUND, 00403 "Exactly one XCAL frame is required!"); 00404 00405 KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, YCAL) == 1, 00406 CPL_ERROR_FILE_NOT_FOUND, 00407 "Exactly one YCAL frame is required!"); 00408 00409 KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, ARC_LIST) == 1, 00410 CPL_ERROR_FILE_NOT_FOUND, 00411 "Exactly one ARC_LIST frame is required!"); 00412 00413 KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, FLAT_EDGE) == 1, 00414 CPL_ERROR_FILE_NOT_FOUND, 00415 "Exactly one FLAT_EDGE frame is required!"); 00416 00417 KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, WAVE_BAND) == 1, 00418 CPL_ERROR_FILE_NOT_FOUND, 00419 "Exactly one WAVE_BAND frame is required!"); 00420 00421 if (line_estimate_method == 2) { 00422 KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, REF_LINES) == 1, 00423 CPL_ERROR_FILE_NOT_FOUND, 00424 "Exactly one REF_LINES frame is required!"); 00425 } 00426 00427 KMO_TRY_ASSURE(kmo_dfs_set_groups(frameset, "kmo_wave_cal") == 1, 00428 CPL_ERROR_ILLEGAL_INPUT, 00429 "Cannot identify RAW and CALIB frames!"); 00430 00431 // 00432 // ------------ get parameters ------------ 00433 // 00434 cpl_msg_info("", "--- Parameter setup for kmo_wave_cal ------"); 00435 00436 fit_order_par = kmo_dfs_get_parameter_int(parlist, 00437 "kmos.kmo_wave_cal.order"); 00438 KMO_TRY_CHECK_ERROR_STATE(); 00439 KMO_TRY_EXIT_IF_ERROR( 00440 kmo_dfs_print_parameter_help(parlist, "kmos.kmo_wave_cal.order")); 00441 KMO_TRY_ASSURE((fit_order_par >= 0) && 00442 (fit_order_par <= 8), 00443 CPL_ERROR_ILLEGAL_INPUT, 00444 "order must be between 1 and 8!"); 00445 00446 flip_trace = kmo_dfs_get_parameter_bool(parlist, 00447 "kmos.kmo_wave_cal.dev_flip"); 00448 KMO_TRY_CHECK_ERROR_STATE(); 00449 KMO_TRY_EXIT_IF_ERROR( 00450 kmo_dfs_print_parameter_help(parlist, "kmos.kmo_wave_cal.dev_flip")); 00451 KMO_TRY_ASSURE((flip_trace == TRUE) || 00452 (flip_trace == FALSE), 00453 CPL_ERROR_ILLEGAL_INPUT, 00454 "flip must be TRUE or FALSE!"); 00455 00456 disp = kmo_dfs_get_parameter_double(parlist, 00457 "kmos.kmo_wave_cal.dev_disp"); 00458 KMO_TRY_CHECK_ERROR_STATE(); 00459 KMO_TRY_EXIT_IF_ERROR( 00460 kmo_dfs_print_parameter_help(parlist, "kmos.kmo_wave_cal.dev_disp")); 00461 00462 KMO_TRY_ASSURE((disp > 0.0) || (disp == -1.0), 00463 CPL_ERROR_ILLEGAL_INPUT, 00464 "dispersion must be greater than 0.0!"); 00465 00466 kmo_band_pars_load(parlist, "kmos.kmo_wave_cal"); 00467 00468 cpl_msg_info("", "-------------------------------------------"); 00469 00470 // 00471 // ------------ check EXPTIME, NDIT, READMODE and lamps ------------ 00472 // 00473 00474 // check ARC_OFF 00475 KMO_TRY_EXIT_IF_NULL( 00476 frame = kmo_dfs_get_frame(frameset, ARC_OFF)); 00477 00478 main_header = kmclipm_propertylist_load(cpl_frame_get_filename(frame), 0); 00479 00480 ndit = cpl_propertylist_get_int(main_header, NDIT); 00481 KMO_TRY_CHECK_ERROR_STATE("NDIT keyword in main header " 00482 "missing!"); 00483 00484 exptime = cpl_propertylist_get_double(main_header, EXPTIME); 00485 KMO_TRY_CHECK_ERROR_STATE("EXPTIME keyword in main header " 00486 "missing!"); 00487 00488 readmode = cpl_strdup(cpl_propertylist_get_string(main_header, READMODE)); 00489 KMO_TRY_CHECK_ERROR_STATE("ESO DET READ CURNAME keyword in main " 00490 "header missing!"); 00491 00492 desc1 = kmo_identify_fits_header( 00493 cpl_frame_get_filename(frame)); 00494 KMO_TRY_CHECK_ERROR_STATE_MSG("ARC_OFF frame doesn't seem to " 00495 "be in KMOS-format!"); 00496 00497 KMO_TRY_ASSURE(desc1.fits_type == raw_fits, 00498 CPL_ERROR_ILLEGAL_INPUT, 00499 "ARC_OFF frame hasn't correct data type " 00500 "(%s must be a raw, unprocessed file)!", 00501 cpl_frame_get_filename(frame)); 00502 00503 nx = desc1.naxis1; 00504 ny = desc1.naxis2; 00505 nz = desc1.naxis3; 00506 nr_devices = desc1.nr_ext; 00507 00508 // assure that flat lamps are off 00509 KMO_TRY_ASSURE((kmo_check_lamp(main_header, INS_LAMP3_ST) == FALSE) && 00510 (kmo_check_lamp(main_header, INS_LAMP4_ST) == FALSE), 00511 CPL_ERROR_ILLEGAL_INPUT, 00512 "Flat lamps must be switched off (%s)!", 00513 cpl_frame_get_filename(frame)); 00514 00515 // check if arc lamps are off (or at least blocked by filter wheel) 00516 if ((kmo_check_lamp(main_header, INS_LAMP1_ST) == TRUE) || 00517 (kmo_check_lamp(main_header, INS_LAMP2_ST) == TRUE)) 00518 { 00519 if (!(strcmp(cpl_propertylist_get_string(main_header, "ESO INS FILT1 ID"), "Block") == 0) || 00520 !(strcmp(cpl_propertylist_get_string(main_header, "ESO INS FILT3 ID"), "Block") == 0) || 00521 !(strcmp(cpl_propertylist_get_string(main_header, "ESO INS FILT3 ID"), "Block") == 0)) 00522 { 00523 cpl_msg_warning("","At least one arc lamp is on! Check if the lamps are blocked!"); 00524 } 00525 } 00526 cpl_propertylist_delete(main_header); main_header = NULL; 00527 00528 // check REF_LINES 00529 if (line_estimate_method == 2) { 00530 KMO_TRY_EXIT_IF_NULL( 00531 frame = kmo_dfs_get_frame(frameset, REF_LINES)); 00532 desc2 = kmo_identify_fits_header( 00533 cpl_frame_get_filename(frame)); 00534 KMO_TRY_CHECK_ERROR_STATE_MSG("REF_LINES frame doesn't seem to " 00535 "be in KMOS-format!"); 00536 00537 KMO_TRY_ASSURE(desc2.fits_type == f2l_fits, 00538 CPL_ERROR_ILLEGAL_INPUT, 00539 "REF_LINES frame hasn't correct frame type " 00540 "(%s must be a F2L frame)!", 00541 cpl_frame_get_filename(frame)); 00542 kmo_free_fits_desc(&desc2); 00543 } 00544 00545 // check ARC_ON 00546 KMO_TRY_EXIT_IF_NULL( 00547 frame = kmo_dfs_get_frame(frameset, ARC_ON)); 00548 00549 while (frame != NULL) { 00550 main_header = kmclipm_propertylist_load(cpl_frame_get_filename(frame), 0); 00551 00552 KMO_TRY_ASSURE(cpl_propertylist_get_int(main_header, NDIT) == ndit, 00553 CPL_ERROR_ILLEGAL_INPUT, 00554 "NDIT isn't the same for all frames: (is %d and %d).", 00555 cpl_propertylist_get_int(main_header, NDIT), ndit); 00556 00557 KMO_TRY_ASSURE(cpl_propertylist_get_double(main_header, EXPTIME) == exptime, 00558 CPL_ERROR_ILLEGAL_INPUT, 00559 "EXPTIME isn't the same for all frames: (is %g and %g).", 00560 cpl_propertylist_get_double(main_header, EXPTIME), exptime); 00561 00562 KMO_TRY_ASSURE(strcmp(cpl_propertylist_get_string(main_header, READMODE), readmode) == 0, 00563 CPL_ERROR_ILLEGAL_INPUT, 00564 "ESO DET READ CURNAME isn't the same for all frames: (is %s and %s).", 00565 cpl_propertylist_get_string(main_header, READMODE), readmode); 00566 00567 desc2 = kmo_identify_fits_header( 00568 cpl_frame_get_filename(frame)); 00569 KMO_TRY_CHECK_ERROR_STATE_MSG("ARC_ON frame doesn't seem to " 00570 "be in KMOS-format!"); 00571 00572 KMO_TRY_ASSURE(desc2.fits_type == raw_fits, 00573 CPL_ERROR_ILLEGAL_INPUT, 00574 "ARC_ON frame hasn't correct data type " 00575 "(%s must be a raw, unprocessed file)!", 00576 cpl_frame_get_filename(frame)); 00577 00578 KMO_TRY_ASSURE((desc2.naxis1 == nx) && 00579 (desc2.naxis2 == ny) && 00580 (desc2.naxis3 == nz), 00581 CPL_ERROR_ILLEGAL_INPUT, 00582 "ARC_ON frame hasn't correct dimensions! (x,y): (%d,%d) " 00583 "vs (%d,%d)", desc2.naxis1, desc2.naxis2, nx, ny); 00584 00585 00586 // assure that flat lamp is off (LAMP3 and 4) 00587 // and that either arc lamp is on (LAMP1 and 2) 00588 KMO_TRY_ASSURE(((kmo_check_lamp(main_header, INS_LAMP1_ST) == TRUE) || 00589 (kmo_check_lamp(main_header, INS_LAMP2_ST) == TRUE)) && 00590 (kmo_check_lamp(main_header, INS_LAMP3_ST) == FALSE) && 00591 (kmo_check_lamp(main_header, INS_LAMP4_ST) == FALSE), 00592 CPL_ERROR_ILLEGAL_INPUT, 00593 "Lamp1 or Lamp2 must be switched on, 3 and 4 must be " 00594 "off for the ARC_ON frame"); 00595 00596 frame = kmo_dfs_get_frame(frameset, NULL); 00597 KMO_TRY_CHECK_ERROR_STATE(); 00598 00599 kmo_free_fits_desc(&desc2); 00600 kmo_init_fits_desc(&desc2); 00601 cpl_propertylist_delete(main_header); main_header = NULL; 00602 } 00603 00604 // load first ARC_ON main header 00605 KMO_TRY_EXIT_IF_NULL( 00606 frame = kmo_dfs_get_frame(frameset, ARC_ON)); 00607 KMO_TRY_EXIT_IF_NULL( 00608 main_header = kmclipm_propertylist_load(cpl_frame_get_filename(frame), 0)); 00609 00610 // check FLAT_EDGE 00611 KMO_TRY_EXIT_IF_NULL( 00612 frame = kmo_dfs_get_frame(frameset, FLAT_EDGE)); 00613 00614 desc2 = kmo_identify_fits_header(cpl_frame_get_filename(frame)); 00615 KMO_TRY_CHECK_ERROR_STATE(); 00616 00617 KMO_TRY_ASSURE((desc2.nr_ext % 24== 0) && 00618 (desc2.fits_type == f2l_fits), 00619 CPL_ERROR_ILLEGAL_INPUT, 00620 "FLAT_EDGE isn't in the correct format!!!"); 00621 00622 kmo_free_fits_desc(&desc2); 00623 kmo_init_fits_desc(&desc2); 00624 00625 // 00626 // ------------ check filter_id, grating_id and rotator offset --------- 00627 // assure that filters, grating and rotation offsets match for 00628 // ARC_ON, XCAL and YCAL 00629 // check if filter_id, grating_id and rotator offset match for all 00630 // detectors 00631 // 00632 KMO_TRY_EXIT_IF_ERROR( 00633 kmo_check_frame_setup(frameset, ARC_ON, XCAL, 00634 TRUE, FALSE, FALSE)); 00635 KMO_TRY_EXIT_IF_ERROR( 00636 kmo_check_frame_setup(frameset, ARC_ON, YCAL, 00637 TRUE, FALSE, FALSE)); 00638 00639 KMO_TRY_EXIT_IF_ERROR( 00640 kmo_check_frame_setup_md5_xycal(frameset)); 00641 00642 strcpy(filename_lcal, LCAL); 00643 strcpy(filename_det_img, DET_IMG_WAVE); 00644 00645 KMO_TRY_EXIT_IF_NULL( 00646 frame = kmo_dfs_get_frame(frameset, XCAL)); 00647 KMO_TRY_EXIT_IF_NULL( 00648 suffix = kmo_dfs_get_suffix(frame, TRUE, FALSE)); 00649 00650 cpl_msg_info("", "Detected instrument setup: %s", suffix+1); 00651 cpl_msg_info("", "(grating 1, 2 & 3)"); 00652 00653 // setup lamp config 00654 if ((kmo_check_lamp(main_header, INS_LAMP1_ST) == TRUE) && 00655 (kmo_check_lamp(main_header, INS_LAMP2_ST) == FALSE)) 00656 { 00657 lamp_config = ARGON; 00658 strcpy(tmpstr, "Argon"); 00659 } else if ((kmo_check_lamp(main_header, INS_LAMP1_ST) == FALSE) && 00660 (kmo_check_lamp(main_header, INS_LAMP2_ST) == TRUE)) 00661 { 00662 lamp_config = NEON; 00663 strcpy(tmpstr, "Neon"); 00664 } else if ((kmo_check_lamp(main_header, INS_LAMP1_ST) == TRUE) && 00665 (kmo_check_lamp(main_header, INS_LAMP2_ST) == TRUE)) 00666 { 00667 lamp_config = ARGON_NEON; 00668 strcpy(tmpstr, "Argon + Neon"); 00669 } 00670 00671 cpl_msg_info("", "Detected arc lamp configuration: %s", tmpstr); 00672 00673 //assert that filter and grating match for each detector 00674 // filter/grating can be different for each detector 00675 KMO_TRY_EXIT_IF_NULL( 00676 filter_ids = kmo_get_filter_setup(main_header, nr_devices, TRUE)); 00677 00678 // 00679 // ---- scan for rotator angles 00680 // 00681 #define ANGLE_DIM 360 00682 int rotang_found[ANGLE_DIM]; 00683 int rotang_cnt[ANGLE_DIM]; 00684 for (int i=0; i<ANGLE_DIM; i++) { 00685 rotang_found[i] = 0; 00686 rotang_cnt[i] = 0; 00687 } 00688 KMO_TRY_EXIT_IF_NULL( 00689 frame = kmo_dfs_get_frame(frameset, ARC_ON)); 00690 while (frame != NULL) { 00691 header = kmclipm_propertylist_load(cpl_frame_get_filename(frame), 0); 00692 if (cpl_propertylist_has(header, ROTANGLE)) { 00693 int rot_angle = (int) rint(cpl_propertylist_get_double(header, ROTANGLE)); 00694 if (rot_angle < 0) { 00695 rot_angle += 360; 00696 } 00697 if (rot_angle < 360 && rot_angle >= 0) { 00698 rotang_cnt[rot_angle]++; 00699 // char * tag = cpl_sprintf("FLAT_ON_%3.3d",rot_angle); 00700 // KMO_TRY_EXIT_IF_ERROR( 00701 // cpl_frame_set_tag(frame, tag)); 00702 // cpl_free(tag); 00703 } 00704 } else { 00705 cpl_msg_warning("","File %s has no keyword \"ROTANGLE\"", 00706 cpl_frame_get_filename(frame)); 00707 } 00708 00709 cpl_propertylist_delete(header); header = NULL; 00710 frame = kmo_dfs_get_frame(frameset, NULL); 00711 KMO_TRY_CHECK_ERROR_STATE(); 00712 } 00713 for (int ax=0; ax<ANGLE_DIM; ax++) { 00714 if (rotang_cnt[ax] != 0) { 00715 if (rotang_cnt[ax] == 1 ) { 00716 cpl_msg_info("","Found %d frame with rotator angle %d",rotang_cnt[ax],ax); 00717 } else { 00718 cpl_msg_warning("","Found %d frames with rotator angle %d but only one will be used", 00719 rotang_cnt[ax],ax); 00720 } 00721 rotang_found[nr_angles] = ax; 00722 nr_angles++; 00723 } 00724 } 00725 00726 KMO_TRY_EXIT_IF_NULL ( 00727 angle_frameset = (cpl_frameset **) cpl_malloc(nr_angles * sizeof(cpl_frameset*))); 00728 for (int i =0; i<nr_angles; i++) { 00729 angle_frameset[i] = cpl_frameset_new(); 00730 } 00731 00732 KMO_TRY_EXIT_IF_NULL( 00733 frame = kmo_dfs_get_frame(frameset, ARC_ON)); 00734 while (frame != NULL) { 00735 header = kmclipm_propertylist_load(cpl_frame_get_filename(frame), 0); 00736 if (cpl_propertylist_has(header, ROTANGLE)) { 00737 int rot_angle = (int) rint(cpl_propertylist_get_double(header, ROTANGLE)); 00738 if (rot_angle < 0) { 00739 rot_angle += 360; 00740 } 00741 int ix = -1; 00742 for (ix = 0; ix<nr_angles; ix++) { 00743 if (rotang_found[ix] == rot_angle) { 00744 break; 00745 } 00746 } 00747 if (ix<nr_angles) { 00748 KMO_TRY_EXIT_IF_ERROR( 00749 cpl_frameset_insert(angle_frameset[ix], cpl_frame_duplicate(frame))); 00750 } 00751 } 00752 00753 cpl_propertylist_delete(header); header = NULL; 00754 frame = kmo_dfs_get_frame(frameset, NULL); 00755 KMO_TRY_CHECK_ERROR_STATE(); 00756 } 00757 00758 // ############################################################################# 00759 // ### allocate temporary memory 00760 // ############################################################################# 00761 // allocate here a edge table structure for all detectors 00762 KMO_TRY_EXIT_IF_NULL( 00763 edge_table = (cpl_table***)cpl_calloc(nr_devices, 00764 sizeof(cpl_table**))); 00765 for (int i = 0; i < nr_devices; i++) { 00766 KMO_TRY_EXIT_IF_NULL( 00767 edge_table[i] = (cpl_table**)cpl_calloc(KMOS_IFUS_PER_DETECTOR, 00768 sizeof(cpl_table*))); 00769 } 00770 00771 // the frames have to be stored temporarily because the QC parameters 00772 // for the main header are calculated from each detector. So they can be 00773 // stored only when all detectors are processed 00774 KMO_TRY_EXIT_IF_NULL( 00775 stored_lcal = (cpl_image**)cpl_calloc(nr_devices * nr_angles, 00776 sizeof(cpl_image*))); 00777 KMO_TRY_EXIT_IF_NULL( 00778 stored_det_img = (cpl_image**)cpl_calloc(nr_devices * nr_angles, 00779 sizeof(cpl_image*))); 00780 KMO_TRY_EXIT_IF_NULL( 00781 stored_sub_headers_lcal = (cpl_propertylist**)cpl_calloc(nr_devices * nr_angles, 00782 sizeof(cpl_propertylist*))); 00783 KMO_TRY_EXIT_IF_NULL( 00784 stored_sub_headers_det_img = (cpl_propertylist**)cpl_calloc(nr_devices * nr_angles, 00785 sizeof(cpl_propertylist*))); 00786 KMO_TRY_EXIT_IF_NULL( 00787 stored_qc_arc_sat = 00788 (int*)cpl_calloc(nr_devices, nr_angles * sizeof(int))); 00789 KMO_TRY_EXIT_IF_NULL( 00790 stored_qc_ar_eff = 00791 (double*)cpl_calloc(nr_devices, nr_angles * sizeof(double))); 00792 KMO_TRY_EXIT_IF_NULL( 00793 stored_qc_ne_eff = 00794 (double*)cpl_calloc(nr_devices, nr_angles * sizeof(double))); 00795 00796 // ############################################################################# 00797 // ### process data 00798 // ############################################################################# 00799 // load arclines and reference lines 00800 KMO_TRY_EXIT_IF_NULL( 00801 frame = kmo_dfs_get_frame(frameset, ARC_LIST)); 00802 00803 // check if ARC_LIST is the filter_id-one 00804 KMO_TRY_EXIT_IF_NULL( 00805 tmp_header = kmclipm_propertylist_load(cpl_frame_get_filename(frame), 0)); 00806 KMO_TRY_EXIT_IF_NULL( 00807 tmp_str = cpl_propertylist_get_string(tmp_header, FILT_ID)); 00808 KMO_TRY_ASSURE(strcmp(filter_ids[0], tmp_str) == 0, 00809 CPL_ERROR_ILLEGAL_INPUT, 00810 "ARC_LIST model must have primary " 00811 "keyword '%s' equal '%s'!!!", FILT_ID, filter_ids[0]); 00812 cpl_propertylist_delete(tmp_header); tmp_header = NULL; 00813 00814 desc2 = kmo_identify_fits_header(cpl_frame_get_filename(frame)); 00815 KMO_TRY_CHECK_ERROR_STATE(); 00816 00817 KMO_TRY_ASSURE((desc2.nr_ext == 1) && 00818 (desc2.fits_type == f2l_fits), 00819 CPL_ERROR_ILLEGAL_INPUT, 00820 "ARC_LIST isn't in the correct format!!!"); 00821 kmo_free_fits_desc(&desc2); 00822 kmo_init_fits_desc(&desc2); 00823 00824 KMO_TRY_EXIT_IF_NULL( 00825 arclines = kmo_dfs_load_table(frameset, ARC_LIST, 1, 0)); 00826 00827 KMO_TRY_EXIT_IF_NULL( 00828 lines = kmo_get_lines(arclines, lamp_config)); 00829 00830 cpl_msg_info("", "Nr. of lines in arclist for this configuration: %lld", 00831 cpl_bivector_get_size(lines)); 00832 00833 if (line_estimate_method == 2) { 00834 KMO_TRY_EXIT_IF_NULL( 00835 reflines = kmo_dfs_load_table(frameset, REF_LINES, 1, 0)); 00836 } 00837 00838 // check which IFUs are active for all FLAT frames 00839 KMO_TRY_EXIT_IF_NULL( 00840 unused_ifus_before = kmo_get_unused_ifus(frameset, 0, 0)); 00841 00842 KMO_TRY_EXIT_IF_NULL( 00843 unused_ifus_after = kmo_duplicate_unused_ifus(unused_ifus_before)); 00844 00845 kmo_print_unused_ifus(unused_ifus_before, FALSE); 00846 00847 // make sure no reconstruction lookup table (LUT) is used 00848 if (getenv("KMCLIPM_PRIV_RECONSTRUCT_LUT_MODE") != NULL) { 00849 last_env = getenv("KMCLIPM_PRIV_RECONSTRUCT_LUT_MODE"); 00850 } 00851 setenv("KMCLIPM_PRIV_RECONSTRUCT_LUT_MODE","NONE",1); 00852 00853 // 00854 // ------------ loop all rotator angles and detectors ------------ 00855 // 00856 for (int a = 0; a<nr_angles; a++) { 00857 cpl_msg_info("","Processing rotator angle %d -> %d degree", a,rotang_found[a]); 00858 00859 for (int i = 1; i <= nr_devices; i++) { 00860 // use loop below for line identification 00861 cpl_msg_info("","Processing detector No. %d", i); 00862 00863 int sx = a * nr_devices + (i - 1); 00864 00865 // load edge parameters 00866 KMO_TRY_EXIT_IF_NULL( 00867 frame = kmo_dfs_get_frame(frameset, FLAT_EDGE)); 00868 00869 for (int j = 0; j < KMOS_IFUS_PER_DETECTOR; j++) { 00870 edge_table[i-1][j] = kmclipm_cal_table_load(cpl_frame_get_filename(frame), 00871 (i-1) * KMOS_IFUS_PER_DETECTOR + j + 1, 00872 rotang_found[a], 0, &angle_found); 00873 if (cpl_error_get_code() == CPL_ERROR_ILLEGAL_INPUT) { 00874 // IFU is inactive: proceed 00875 cpl_error_reset(); 00876 } 00877 } 00878 00879 if (fit_order_par == 0) { 00880 // set default fit orders for the different bands 00881 if ((strcmp(filter_ids[i-1], "H") == 0) || 00882 (strcmp(filter_ids[i-1], "K") == 0) || 00883 (strcmp(filter_ids[i-1], "YJ") == 0)) 00884 { 00885 fit_order = 6; 00886 } else if (strcmp(filter_ids[i-1], "IZ") == 0) { 00887 fit_order = 4; 00888 } else if (strcmp(filter_ids[i-1], "HK") == 0) { 00889 fit_order = 5; 00890 } 00891 cpl_msg_info("", "Order of wavelength spectrum fit for %s-band: %d", 00892 filter_ids[i-1], 00893 fit_order); 00894 } else { 00895 fit_order = fit_order_par; 00896 } 00897 00898 // lamp_on 00899 KMO_TRY_EXIT_IF_NULL( 00900 frame = kmo_dfs_get_frame(angle_frameset[a], ARC_ON)); 00901 00902 // if sat_mode is set to TRUE here, then the calculation of the 00903 // saturated pixels has to be updated like in kmo_flat-recipe 00904 KMO_TRY_EXIT_IF_NULL( 00905 det_lamp_on = kmo_dfs_load_image_frame(frame, i, FALSE, TRUE, &nr_sat)); 00906 00907 // count saturated pixels for each detector 00908 if (strcmp(cpl_propertylist_get_string(main_header, READMODE), "Nondest") == 0) { 00909 // NDR: non-destructive readout mode 00910 stored_qc_arc_sat[sx] = nr_sat; 00911 } else { 00912 // normal readout mode 00913 stored_qc_arc_sat[sx] = kmo_image_get_saturated(det_lamp_on, 00914 KMO_FLAT_SATURATED); 00915 } 00916 KMO_TRY_CHECK_ERROR_STATE(); 00917 00918 00919 KMO_TRY_EXIT_IF_NULL( 00920 det_lamp_on_copy = cpl_image_duplicate(det_lamp_on)); 00921 00922 // lamp_off 00923 KMO_TRY_EXIT_IF_NULL( 00924 frame = kmo_dfs_get_frame(frameset, ARC_OFF)); 00925 00926 KMO_TRY_EXIT_IF_NULL( 00927 det_lamp_off = kmo_dfs_load_image_frame(frame, i, FALSE, FALSE, NULL)); 00928 00929 // 00930 // process imagelist 00931 // 00932 KMO_TRY_CHECK_ERROR_STATE(); 00933 00934 // subtract lamp_off from lamp_on 00935 KMO_TRY_EXIT_IF_ERROR( 00936 cpl_image_subtract(det_lamp_on, det_lamp_off)); 00937 00938 // load flat calibration frames 00939 KMO_TRY_EXIT_IF_NULL( 00940 xcal = kmo_dfs_load_cal_image(frameset, XCAL, i, 0, 00941 (double) rotang_found[a], FALSE, 00942 NULL, &angle_found)); 00943 00944 KMO_TRY_EXIT_IF_NULL( 00945 ycal = kmo_dfs_load_cal_image(frameset, YCAL, i, 0, 00946 (double) rotang_found[a], FALSE, 00947 NULL, &angle_found)); 00948 00949 // load bad pixel mask from XCAL and set NaNs to 0 and all other values to 1 00950 KMO_TRY_EXIT_IF_NULL( 00951 bad_pix_mask = cpl_image_duplicate(xcal)); 00952 00953 KMO_TRY_EXIT_IF_NULL( 00954 pbad_pix_mask = cpl_image_get_data_float(bad_pix_mask)); 00955 for (int x = 0; x < nx; x++) { 00956 for (int y = 0; y < ny; y++) { 00957 if (isnan(pbad_pix_mask[x+nx*y])) { 00958 pbad_pix_mask[x+nx*y] = 0.; 00959 } else { 00960 pbad_pix_mask[x+nx*y] = 1.; 00961 } 00962 } 00963 } 00964 00965 // calculate spectral curvature here 00966 err = kmo_calc_wave_calib(det_lamp_on, 00967 bad_pix_mask, 00968 xcal, 00969 ycal, 00970 filter_ids[i-1], 00971 lamp_config, 00972 i, 00973 unused_ifus_after[i-1], 00974 edge_table[i-1], 00975 lines, 00976 reflines, 00977 disp, 00978 &lcal, 00979 &(stored_qc_ar_eff[sx]), 00980 &(stored_qc_ne_eff[sx]), 00981 flip_trace, 00982 fit_order, 00983 line_estimate_method); 00984 00985 if (err == CPL_ERROR_NONE) { 00986 // calculate QC parameters 00987 if (stored_qc_ar_eff[sx] != -1.0) { 00988 stored_qc_ar_eff[sx] /= exptime; 00989 } 00990 if (stored_qc_ne_eff[sx] != -1.0) { 00991 stored_qc_ne_eff[sx] /= exptime; 00992 } 00993 00994 // apply the badpixel mask to the produced frame 00995 00996 KMO_TRY_EXIT_IF_ERROR( 00997 cpl_image_multiply(lcal, bad_pix_mask)); 00998 00999 KMO_TRY_EXIT_IF_ERROR( 01000 kmo_image_reject_from_mask(lcal, bad_pix_mask)); 01001 01002 // store flat frames, badpixel mask and calibration frames 01003 stored_lcal[sx] = lcal; 01004 } else if (err == CPL_ERROR_UNSPECIFIED) { 01005 // all IFUs seem to be deativated, continue processing 01006 // just save empty frame 01007 cpl_error_reset(); 01008 stored_lcal[sx] = cpl_image_new(nx, ny, CPL_TYPE_FLOAT); 01009 kmo_image_fill(stored_lcal[sx], 0.0); 01010 } else { 01011 cpl_msg_warning(cpl_func, 01012 "Couldn't identify any lines! Is the line " 01013 "list defined correctly?"); 01014 cpl_msg_warning(cpl_func, 01015 "Band defined in header of detector %d: %s", 01016 i, filter_ids[i-1]); 01017 cpl_msg_warning(cpl_func, 01018 "Arc line file defined: %s", 01019 cpl_frame_get_filename( 01020 kmo_dfs_get_frame(frameset, ARC_LIST))); 01021 cpl_error_reset(); 01022 } 01023 01024 01025 // 01026 // create reconstructed and resampled arc frame 01027 // 01028 stored_det_img[sx] = kmo_reconstructed_arc_image(frameset, 01029 det_lamp_on_copy, 01030 det_lamp_off, 01031 xcal, 01032 ycal, 01033 stored_lcal[sx], 01034 unused_ifus_after[i-1], 01035 flip_trace, 01036 i, 01037 suffix, 01038 filter_ids[i-1], 01039 lamp_config, 01040 rotang_found[a], 01041 &qc_header); 01042 if (cpl_error_get_code() != CPL_ERROR_NONE) { 01043 // couldn't reconstruct 01044 cpl_msg_error("","Couldn't reconstruct IFUs on detector %d", i); 01045 cpl_error_reset(); 01046 } 01047 01048 // load and update sub_header with QC parameters 01049 KMO_TRY_EXIT_IF_NULL( 01050 stored_sub_headers_lcal[sx] = kmo_dfs_load_sub_header(frameset, 01051 ARC_ON, i, 01052 FALSE)); 01053 01054 // update EXTNAME 01055 KMO_TRY_EXIT_IF_NULL( 01056 extname = kmo_extname_creator(detector_frame, i, EXT_DATA)); 01057 KMO_TRY_EXIT_IF_ERROR( 01058 kmclipm_update_property_string(stored_sub_headers_lcal[sx], 01059 EXTNAME, 01060 extname, 01061 "FITS extension name")); 01062 cpl_free(extname); extname = NULL; 01063 01064 // add first QC parameters 01065 KMO_TRY_EXIT_IF_ERROR( 01066 kmclipm_update_property_int(stored_sub_headers_lcal[sx], 01067 QC_ARC_SAT, 01068 stored_qc_arc_sat[sx], 01069 "[] nr. saturated pixels of arc exp.")); 01070 01071 gain = kmo_dfs_get_property_double(stored_sub_headers_lcal[sx], GAIN); 01072 KMO_TRY_CHECK_ERROR_STATE_MSG( 01073 "GAIN-keyword in fits-header is missing!"); 01074 01075 if (stored_qc_ar_eff[sx] != -1.0) { 01076 KMO_TRY_EXIT_IF_ERROR( 01077 kmclipm_update_property_double(stored_sub_headers_lcal[sx], 01078 QC_ARC_AR_EFF, 01079 stored_qc_ar_eff[sx]/gain, 01080 "[e-/s] Argon lamp efficiency")); 01081 } 01082 01083 if (stored_qc_ne_eff[sx] != -1.0) { 01084 KMO_TRY_EXIT_IF_ERROR( 01085 kmclipm_update_property_double(stored_sub_headers_lcal[sx], 01086 QC_ARC_NE_EFF, 01087 stored_qc_ne_eff[sx]/gain, 01088 "[e-/s] Neon lamp efficiency")); 01089 } 01090 01091 KMO_TRY_EXIT_IF_ERROR( 01092 kmclipm_update_property_double(stored_sub_headers_lcal[sx], 01093 CAL_ROTANGLE, 01094 ((double) rotang_found[a]), 01095 "[deg] Rotator relative to nasmyth")); 01096 01097 // append QC parameters 01098 KMO_TRY_EXIT_IF_ERROR( 01099 cpl_propertylist_append(stored_sub_headers_lcal[sx], 01100 qc_header)); 01101 cpl_propertylist_delete(qc_header); qc_header = NULL; 01102 01103 KMO_TRY_EXIT_IF_NULL( 01104 stored_sub_headers_det_img[sx] = cpl_propertylist_duplicate( 01105 stored_sub_headers_lcal[sx])); 01106 01107 cpl_propertylist_erase(stored_sub_headers_lcal[sx], CRVAL1); 01108 cpl_propertylist_erase(stored_sub_headers_lcal[sx], CRVAL2); 01109 cpl_propertylist_erase(stored_sub_headers_lcal[sx], CTYPE1); 01110 cpl_propertylist_erase(stored_sub_headers_lcal[sx], CTYPE2); 01111 cpl_propertylist_erase(stored_sub_headers_lcal[sx], CDELT1); 01112 cpl_propertylist_erase(stored_sub_headers_lcal[sx], CDELT2); 01113 01114 cpl_propertylist_erase(stored_sub_headers_lcal[sx], CRPIX1); 01115 cpl_propertylist_erase(stored_sub_headers_lcal[sx], CRPIX2); 01116 if (cpl_propertylist_has(stored_sub_headers_lcal[sx], CRPIX1)) { 01117 cpl_propertylist_erase(stored_sub_headers_lcal[sx], CRPIX1); 01118 } 01119 if (cpl_propertylist_has(stored_sub_headers_lcal[sx], CRPIX2)) { 01120 cpl_propertylist_erase(stored_sub_headers_lcal[sx], CRPIX2); 01121 } 01122 01123 // free memory 01124 cpl_image_delete(det_lamp_on); det_lamp_on = NULL; 01125 cpl_image_delete(det_lamp_on_copy); det_lamp_on_copy = NULL; 01126 cpl_image_delete(det_lamp_off); det_lamp_off = NULL; 01127 cpl_image_delete(bad_pix_mask); bad_pix_mask = NULL; 01128 cpl_image_delete(xcal); xcal = NULL; 01129 cpl_image_delete(ycal); ycal = NULL; 01130 01131 for (int j = 0; j < KMOS_IFUS_PER_DETECTOR; j++) { 01132 cpl_table_delete(edge_table[i-1][j]); edge_table[i-1][j] = NULL; 01133 } 01134 } // for i devices 01135 } // for a angles 01136 01137 if (line_estimate_method == 2) { 01138 cpl_table_delete(reflines); reflines = NULL; 01139 } 01140 // ########################################################################### 01141 // ### QC parameters & saving 01142 // ########################################################################### 01143 cpl_msg_info("","Saving data..."); 01144 01145 // 01146 // ------------ load, update & save primary header ------------ 01147 // 01148 01149 // update which IFUs are not used 01150 KMO_TRY_EXIT_IF_ERROR( 01151 kmo_set_unused_ifus(unused_ifus_after, main_header, 01152 "kmo_wave_cal")); 01153 01154 KMO_TRY_EXIT_IF_NULL( 01155 frame = kmo_dfs_get_frame(frameset, ARC_ON)); 01156 01157 KMO_TRY_EXIT_IF_ERROR( 01158 kmo_dfs_save_main_header(frameset, filename_lcal, suffix, frame, 01159 main_header, parlist, cpl_func)); 01160 01161 KMO_TRY_EXIT_IF_ERROR( 01162 kmo_dfs_save_main_header(frameset, filename_det_img, suffix, frame, 01163 main_header, parlist, cpl_func)); 01164 01165 cpl_propertylist_delete(main_header); main_header = NULL; 01166 01167 // 01168 // --- save sub-frames --- 01169 // 01170 for (int a = 0; a<nr_angles; a++) { 01171 for (int i = 1; i <= nr_devices; i++) { 01172 int sx = a * nr_devices + (i - 1); 01173 // save lcal-frame 01174 KMO_TRY_EXIT_IF_ERROR( 01175 kmo_dfs_save_image(stored_lcal[sx], filename_lcal, suffix, 01176 stored_sub_headers_lcal[sx], 0./0.)); 01177 01178 // save detector image 01179 KMO_TRY_EXIT_IF_ERROR( 01180 kmo_dfs_save_image(stored_det_img[sx], filename_det_img, suffix, 01181 stored_sub_headers_det_img[sx], 0./0.)); 01182 } // for i = nr_devices 01183 } // for a angles 01184 01185 // Alex: was ist das alles? 01186 // KMO_TRY_EXIT_IF_NULL( 01187 // sub_header = cpl_propertylist_new()); 01188 // 01189 // KMO_TRY_EXIT_IF_NULL( 01190 // extname = kmo_extname_creator(list_frame, -1, EXT_LIST)); 01191 // KMO_TRY_EXIT_IF_ERROR( 01192 // kmclipm_update_property_string(sub_header, 01193 // EXTNAME, 01194 // extname, 01195 // "FITS extension name")); 01196 // cpl_free(extname); extname = NULL; 01197 // 01198 // // save table with wavelengths and 01199 // KMO_TRY_EXIT_IF_ERROR( 01200 // kmo_dfs_save_table(arclines, filename_img, sub_header)); 01201 01202 // print which IFUs are not used 01203 kmo_print_unused_ifus(unused_ifus_after, TRUE); 01204 } 01205 KMO_CATCH 01206 { 01207 KMO_CATCH_MSG(); 01208 ret_val = -1; 01209 } 01210 01211 if (last_env != NULL) { 01212 setenv("KMCLIPM_PRIV_RECONSTRUCT_LUT_MODE",last_env,1); 01213 } else { 01214 unsetenv("KMCLIPM_PRIV_RECONSTRUCT_LUT_MODE"); 01215 } 01216 01217 kmo_free_fits_desc(&desc1); 01218 kmo_free_fits_desc(&desc2); 01219 if (unused_ifus_before != NULL) { 01220 kmo_free_unused_ifus(unused_ifus_before); unused_ifus_before = NULL; 01221 } 01222 if (unused_ifus_after != NULL) { 01223 kmo_free_unused_ifus(unused_ifus_after); unused_ifus_after = NULL; 01224 } 01225 cpl_propertylist_delete(main_header); main_header = NULL; 01226 cpl_image_delete(det_lamp_on); det_lamp_on = NULL; 01227 cpl_image_delete(det_lamp_off); det_lamp_off = NULL; 01228 cpl_image_delete(bad_pix_mask); bad_pix_mask = NULL; 01229 cpl_table_delete(arclines); arclines = NULL; 01230 cpl_table_delete(reflines); reflines = NULL; 01231 cpl_free(stored_qc_arc_sat); stored_qc_arc_sat = NULL; 01232 cpl_free(stored_qc_ar_eff); stored_qc_ar_eff = NULL; 01233 cpl_free(stored_qc_ne_eff); stored_qc_ne_eff = NULL; 01234 for (int i = 0; i < nr_devices * nr_angles; i++) { 01235 cpl_image_delete(stored_lcal[i]); stored_lcal[i] = NULL; 01236 cpl_image_delete(stored_det_img[i]); stored_det_img[i] = NULL; 01237 cpl_propertylist_delete(stored_sub_headers_lcal[i]); 01238 stored_sub_headers_lcal[i] = NULL; 01239 cpl_propertylist_delete(stored_sub_headers_det_img[i]); 01240 stored_sub_headers_det_img[i] = NULL; 01241 } 01242 for (int i = 0; i < nr_angles; i++) { 01243 cpl_frameset_delete(angle_frameset[i]); angle_frameset[i] = NULL; 01244 } 01245 for (int i = 0; i < nr_devices; i++) { 01246 cpl_free(filter_ids[i]); filter_ids[i] = NULL; 01247 cpl_free(edge_table[i]); edge_table[i] = NULL; 01248 } 01249 cpl_free(angle_frameset); angle_frameset = NULL; 01250 cpl_free(stored_lcal); stored_lcal = NULL; 01251 cpl_free(stored_det_img); stored_det_img = NULL; 01252 cpl_free(stored_sub_headers_lcal); stored_sub_headers_lcal = NULL; 01253 cpl_free(stored_sub_headers_det_img); stored_sub_headers_det_img = NULL; 01254 cpl_free(filter_ids); filter_ids = NULL; 01255 cpl_free(edge_table); edge_table = NULL; 01256 cpl_free(readmode); readmode = NULL; 01257 cpl_bivector_delete(lines); lines = NULL; 01258 cpl_free(suffix); suffix = NULL; 01259 01260 return ret_val; 01261 } 01262
1.7.6.1