|
KMOS Pipeline Reference Manual
1.0.8
|
00001 /* $Id: kmo_wave_cal.c,v 1.42 2013/02/19 14:31:05 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/02/19 14:31:05 $ 00024 * $Revision: 1.42 $ 00025 * $Name: kmosp_v1_0_8__20130220 $ 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 " 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 strcpy(filename_lcal, LCAL); 00640 strcpy(filename_det_img, DET_IMG_WAVE); 00641 00642 KMO_TRY_EXIT_IF_NULL( 00643 frame = kmo_dfs_get_frame(frameset, XCAL)); 00644 KMO_TRY_EXIT_IF_NULL( 00645 suffix = kmo_dfs_get_suffix(frame, TRUE, FALSE)); 00646 00647 cpl_msg_info("", "Detected instrument setup: %s", suffix+1); 00648 cpl_msg_info("", "(grating 1, 2 & 3)"); 00649 00650 // setup lamp config 00651 if ((kmo_check_lamp(main_header, INS_LAMP1_ST) == TRUE) && 00652 (kmo_check_lamp(main_header, INS_LAMP2_ST) == FALSE)) 00653 { 00654 lamp_config = ARGON; 00655 strcpy(tmpstr, "Argon"); 00656 } else if ((kmo_check_lamp(main_header, INS_LAMP1_ST) == FALSE) && 00657 (kmo_check_lamp(main_header, INS_LAMP2_ST) == TRUE)) 00658 { 00659 lamp_config = NEON; 00660 strcpy(tmpstr, "Neon"); 00661 } else if ((kmo_check_lamp(main_header, INS_LAMP1_ST) == TRUE) && 00662 (kmo_check_lamp(main_header, INS_LAMP2_ST) == TRUE)) 00663 { 00664 lamp_config = ARGON_NEON; 00665 strcpy(tmpstr, "Argon + Neon"); 00666 } 00667 00668 cpl_msg_info("", "Detected arc lamp configuration: %s", tmpstr); 00669 00670 //assert that filter and grating match for each detector 00671 // filter/grating can be different for each detector 00672 KMO_TRY_EXIT_IF_NULL( 00673 filter_ids = kmo_get_filter_setup(main_header, nr_devices, TRUE)); 00674 00675 // 00676 // ---- scan for rotator angles 00677 // 00678 #define ANGLE_DIM 360 00679 int rotang_found[ANGLE_DIM]; 00680 int rotang_cnt[ANGLE_DIM]; 00681 for (int i=0; i<ANGLE_DIM; i++) { 00682 rotang_found[i] = 0; 00683 rotang_cnt[i] = 0; 00684 } 00685 KMO_TRY_EXIT_IF_NULL( 00686 frame = kmo_dfs_get_frame(frameset, ARC_ON)); 00687 while (frame != NULL) { 00688 header = kmclipm_propertylist_load(cpl_frame_get_filename(frame), 0); 00689 if (cpl_propertylist_has(header, ROTANGLE)) { 00690 int rot_angle = (int) rint(cpl_propertylist_get_double(header, ROTANGLE)); 00691 if (rot_angle < 0) { 00692 rot_angle += 360; 00693 } 00694 if (rot_angle < 360 && rot_angle >= 0) { 00695 rotang_cnt[rot_angle]++; 00696 // char * tag = cpl_sprintf("FLAT_ON_%3.3d",rot_angle); 00697 // KMO_TRY_EXIT_IF_ERROR( 00698 // cpl_frame_set_tag(frame, tag)); 00699 // cpl_free(tag); 00700 } 00701 } else { 00702 cpl_msg_warning("","File %s has no keyword \"ROTANGLE\"", 00703 cpl_frame_get_filename(frame)); 00704 } 00705 00706 cpl_propertylist_delete(header); header = NULL; 00707 frame = kmo_dfs_get_frame(frameset, NULL); 00708 KMO_TRY_CHECK_ERROR_STATE(); 00709 } 00710 for (int ax=0; ax<ANGLE_DIM; ax++) { 00711 if (rotang_cnt[ax] != 0) { 00712 if (rotang_cnt[ax] == 1 ) { 00713 cpl_msg_info("","Found %d frame with rotator angle %d",rotang_cnt[ax],ax); 00714 } else { 00715 cpl_msg_warning("","Found %d frames with rotator angle %d but only one will be used", 00716 rotang_cnt[ax],ax); 00717 } 00718 rotang_found[nr_angles] = ax; 00719 nr_angles++; 00720 } 00721 } 00722 00723 KMO_TRY_EXIT_IF_NULL ( 00724 angle_frameset = (cpl_frameset **) cpl_malloc(nr_angles * sizeof(cpl_frameset*))); 00725 for (int i =0; i<nr_angles; i++) { 00726 angle_frameset[i] = cpl_frameset_new(); 00727 } 00728 00729 KMO_TRY_EXIT_IF_NULL( 00730 frame = kmo_dfs_get_frame(frameset, ARC_ON)); 00731 while (frame != NULL) { 00732 header = kmclipm_propertylist_load(cpl_frame_get_filename(frame), 0); 00733 if (cpl_propertylist_has(header, ROTANGLE)) { 00734 int rot_angle = (int) rint(cpl_propertylist_get_double(header, ROTANGLE)); 00735 if (rot_angle < 0) { 00736 rot_angle += 360; 00737 } 00738 int ix = -1; 00739 for (ix = 0; ix<nr_angles; ix++) { 00740 if (rotang_found[ix] == rot_angle) { 00741 break; 00742 } 00743 } 00744 if (ix<nr_angles) { 00745 KMO_TRY_EXIT_IF_ERROR( 00746 cpl_frameset_insert(angle_frameset[ix], cpl_frame_duplicate(frame))); 00747 } 00748 } 00749 00750 cpl_propertylist_delete(header); header = NULL; 00751 frame = kmo_dfs_get_frame(frameset, NULL); 00752 KMO_TRY_CHECK_ERROR_STATE(); 00753 } 00754 00755 // ############################################################################# 00756 // ### allocate temporary memory 00757 // ############################################################################# 00758 // allocate here a edge table structure for all detectors 00759 KMO_TRY_EXIT_IF_NULL( 00760 edge_table = (cpl_table***)cpl_calloc(nr_devices, 00761 sizeof(cpl_table**))); 00762 for (int i = 0; i < nr_devices; i++) { 00763 KMO_TRY_EXIT_IF_NULL( 00764 edge_table[i] = (cpl_table**)cpl_calloc(KMOS_IFUS_PER_DETECTOR, 00765 sizeof(cpl_table*))); 00766 } 00767 00768 // the frames have to be stored temporarily because the QC parameters 00769 // for the main header are calculated from each detector. So they can be 00770 // stored only when all detectors are processed 00771 KMO_TRY_EXIT_IF_NULL( 00772 stored_lcal = (cpl_image**)cpl_calloc(nr_devices * nr_angles, 00773 sizeof(cpl_image*))); 00774 KMO_TRY_EXIT_IF_NULL( 00775 stored_det_img = (cpl_image**)cpl_calloc(nr_devices * nr_angles, 00776 sizeof(cpl_image*))); 00777 KMO_TRY_EXIT_IF_NULL( 00778 stored_sub_headers_lcal = (cpl_propertylist**)cpl_calloc(nr_devices * nr_angles, 00779 sizeof(cpl_propertylist*))); 00780 KMO_TRY_EXIT_IF_NULL( 00781 stored_sub_headers_det_img = (cpl_propertylist**)cpl_calloc(nr_devices * nr_angles, 00782 sizeof(cpl_propertylist*))); 00783 KMO_TRY_EXIT_IF_NULL( 00784 stored_qc_arc_sat = 00785 (int*)cpl_calloc(nr_devices, nr_angles * sizeof(int))); 00786 KMO_TRY_EXIT_IF_NULL( 00787 stored_qc_ar_eff = 00788 (double*)cpl_calloc(nr_devices, nr_angles * sizeof(double))); 00789 KMO_TRY_EXIT_IF_NULL( 00790 stored_qc_ne_eff = 00791 (double*)cpl_calloc(nr_devices, nr_angles * sizeof(double))); 00792 00793 // ############################################################################# 00794 // ### process data 00795 // ############################################################################# 00796 // load arclines and reference lines 00797 KMO_TRY_EXIT_IF_NULL( 00798 frame = kmo_dfs_get_frame(frameset, ARC_LIST)); 00799 00800 // check if ARC_LIST is the filter_id-one 00801 KMO_TRY_EXIT_IF_NULL( 00802 tmp_header = kmclipm_propertylist_load(cpl_frame_get_filename(frame), 0)); 00803 KMO_TRY_EXIT_IF_NULL( 00804 tmp_str = cpl_propertylist_get_string(tmp_header, FILT_ID)); 00805 KMO_TRY_ASSURE(strcmp(filter_ids[0], tmp_str) == 0, 00806 CPL_ERROR_ILLEGAL_INPUT, 00807 "ARC_LIST model must have primary " 00808 "keyword '%s' equal '%s'!!!", FILT_ID, filter_ids[0]); 00809 cpl_propertylist_delete(tmp_header); tmp_header = NULL; 00810 00811 desc2 = kmo_identify_fits_header(cpl_frame_get_filename(frame)); 00812 KMO_TRY_CHECK_ERROR_STATE(); 00813 00814 KMO_TRY_ASSURE((desc2.nr_ext == 1) && 00815 (desc2.fits_type == f2l_fits), 00816 CPL_ERROR_ILLEGAL_INPUT, 00817 "ARC_LIST isn't in the correct format!!!"); 00818 kmo_free_fits_desc(&desc2); 00819 kmo_init_fits_desc(&desc2); 00820 00821 KMO_TRY_EXIT_IF_NULL( 00822 arclines = kmo_dfs_load_table(frameset, ARC_LIST, 1, 0)); 00823 00824 KMO_TRY_EXIT_IF_NULL( 00825 lines = kmo_get_lines(arclines, lamp_config)); 00826 00827 cpl_msg_info("", "Nr. of lines in arclist for this configuration: %lld", 00828 cpl_bivector_get_size(lines)); 00829 00830 if (line_estimate_method == 2) { 00831 KMO_TRY_EXIT_IF_NULL( 00832 reflines = kmo_dfs_load_table(frameset, REF_LINES, 1, 0)); 00833 } 00834 00835 // check which IFUs are active for all FLAT frames 00836 KMO_TRY_EXIT_IF_NULL( 00837 unused_ifus_before = kmo_get_unused_ifus(frameset, 0, 0)); 00838 00839 KMO_TRY_EXIT_IF_NULL( 00840 unused_ifus_after = kmo_duplicate_unused_ifus(unused_ifus_before)); 00841 00842 kmo_print_unused_ifus(unused_ifus_before, FALSE); 00843 00844 // make sure no reconstruction lookup table (LUT) is used 00845 if (getenv("KMCLIPM_PRIV_RECONSTRUCT_LUT_MODE") != NULL) { 00846 last_env = getenv("KMCLIPM_PRIV_RECONSTRUCT_LUT_MODE"); 00847 } 00848 setenv("KMCLIPM_PRIV_RECONSTRUCT_LUT_MODE","NONE",1); 00849 00850 // 00851 // ------------ loop all rotator angles and detectors ------------ 00852 // 00853 for (int a = 0; a<nr_angles; a++) { 00854 cpl_msg_info("","Processing rotator angle %d -> %d degree", a,rotang_found[a]); 00855 00856 for (int i = 1; i <= nr_devices; i++) { 00857 // use loop below for line identification 00858 cpl_msg_info("","Processing detector No. %d", i); 00859 00860 int sx = a * nr_devices + (i - 1); 00861 00862 // load edge parameters 00863 KMO_TRY_EXIT_IF_NULL( 00864 frame = kmo_dfs_get_frame(frameset, FLAT_EDGE)); 00865 00866 for (int j = 0; j < KMOS_IFUS_PER_DETECTOR; j++) { 00867 edge_table[i-1][j] = kmclipm_cal_table_load(cpl_frame_get_filename(frame), 00868 (i-1) * KMOS_IFUS_PER_DETECTOR + j + 1, 00869 rotang_found[a], 0, &angle_found); 00870 if (cpl_error_get_code() == CPL_ERROR_ILLEGAL_INPUT) { 00871 // IFU is inactive: proceed 00872 cpl_error_reset(); 00873 } 00874 } 00875 00876 if (fit_order_par == 0) { 00877 // set default fit orders for the different bands 00878 if ((strcmp(filter_ids[i-1], "H") == 0) || 00879 (strcmp(filter_ids[i-1], "K") == 0) || 00880 (strcmp(filter_ids[i-1], "YJ") == 0)) 00881 { 00882 fit_order = 6; 00883 } else if (strcmp(filter_ids[i-1], "IZ") == 0) { 00884 fit_order = 4; 00885 } else if (strcmp(filter_ids[i-1], "HK") == 0) { 00886 fit_order = 5; 00887 } 00888 cpl_msg_info("", "Order of wavelength spectrum fit for %s-band: %d", 00889 filter_ids[i-1], 00890 fit_order); 00891 } else { 00892 fit_order = fit_order_par; 00893 } 00894 00895 // lamp_on 00896 KMO_TRY_EXIT_IF_NULL( 00897 frame = kmo_dfs_get_frame(angle_frameset[a], ARC_ON)); 00898 00899 // if sat_mode is set to TRUE here, then the calculation of the 00900 // saturated pixels has to be updated like in kmo_flat-recipe 00901 KMO_TRY_EXIT_IF_NULL( 00902 det_lamp_on = kmo_dfs_load_image_frame(frame, i, FALSE, TRUE, &nr_sat)); 00903 00904 // count saturated pixels for each detector 00905 if (strcmp(cpl_propertylist_get_string(main_header, READMODE), "Nondest") == 0) { 00906 // NDR: non-destructive readout mode 00907 stored_qc_arc_sat[sx] = nr_sat; 00908 } else { 00909 // normal readout mode 00910 stored_qc_arc_sat[sx] = kmo_image_get_saturated(det_lamp_on, 00911 KMO_FLAT_SATURATED); 00912 } 00913 KMO_TRY_CHECK_ERROR_STATE(); 00914 00915 00916 KMO_TRY_EXIT_IF_NULL( 00917 det_lamp_on_copy = cpl_image_duplicate(det_lamp_on)); 00918 00919 // lamp_off 00920 KMO_TRY_EXIT_IF_NULL( 00921 frame = kmo_dfs_get_frame(frameset, ARC_OFF)); 00922 00923 KMO_TRY_EXIT_IF_NULL( 00924 det_lamp_off = kmo_dfs_load_image_frame(frame, i, FALSE, FALSE, NULL)); 00925 00926 // 00927 // process imagelist 00928 // 00929 KMO_TRY_CHECK_ERROR_STATE(); 00930 00931 // subtract lamp_off from lamp_on 00932 KMO_TRY_EXIT_IF_ERROR( 00933 cpl_image_subtract(det_lamp_on, det_lamp_off)); 00934 00935 // load flat calibration frames 00936 KMO_TRY_EXIT_IF_NULL( 00937 xcal = kmo_dfs_load_cal_image(frameset, XCAL, i, 0, 00938 (double) rotang_found[a], FALSE, 00939 NULL, &angle_found)); 00940 00941 KMO_TRY_EXIT_IF_NULL( 00942 ycal = kmo_dfs_load_cal_image(frameset, YCAL, i, 0, 00943 (double) rotang_found[a], FALSE, 00944 NULL, &angle_found)); 00945 00946 // load bad pixel mask from XCAL and set NaNs to 0 and all other values to 1 00947 KMO_TRY_EXIT_IF_NULL( 00948 bad_pix_mask = cpl_image_duplicate(xcal)); 00949 00950 KMO_TRY_EXIT_IF_NULL( 00951 pbad_pix_mask = cpl_image_get_data_float(bad_pix_mask)); 00952 for (int x = 0; x < nx; x++) { 00953 for (int y = 0; y < ny; y++) { 00954 if (isnan(pbad_pix_mask[x+nx*y])) { 00955 pbad_pix_mask[x+nx*y] = 0.; 00956 } else { 00957 pbad_pix_mask[x+nx*y] = 1.; 00958 } 00959 } 00960 } 00961 00962 // calculate spectral curvature here 00963 err = kmo_calc_wave_calib(det_lamp_on, 00964 bad_pix_mask, 00965 xcal, 00966 ycal, 00967 filter_ids[i-1], 00968 lamp_config, 00969 i, 00970 unused_ifus_after[i-1], 00971 edge_table[i-1], 00972 lines, 00973 reflines, 00974 disp, 00975 &lcal, 00976 &(stored_qc_ar_eff[sx]), 00977 &(stored_qc_ne_eff[sx]), 00978 flip_trace, 00979 fit_order, 00980 line_estimate_method); 00981 00982 if (err == CPL_ERROR_NONE) { 00983 // calculate QC parameters 00984 if (stored_qc_ar_eff[sx] != -1.0) { 00985 stored_qc_ar_eff[sx] /= exptime; 00986 } 00987 if (stored_qc_ne_eff[sx] != -1.0) { 00988 stored_qc_ne_eff[sx] /= exptime; 00989 } 00990 00991 // apply the badpixel mask to the produced frame 00992 00993 KMO_TRY_EXIT_IF_ERROR( 00994 cpl_image_multiply(lcal, bad_pix_mask)); 00995 00996 KMO_TRY_EXIT_IF_ERROR( 00997 kmo_image_reject_from_mask(lcal, bad_pix_mask)); 00998 00999 // store flat frames, badpixel mask and calibration frames 01000 stored_lcal[sx] = lcal; 01001 } else if (err == CPL_ERROR_UNSPECIFIED) { 01002 // all IFUs seem to be deativated, continue processing 01003 // just save empty frame 01004 cpl_error_reset(); 01005 stored_lcal[sx] = cpl_image_new(nx, ny, CPL_TYPE_FLOAT); 01006 kmo_image_fill(stored_lcal[sx], 0.0); 01007 } else { 01008 cpl_msg_warning(cpl_func, 01009 "Couldn't identify any lines! Is the line " 01010 "list defined correctly?"); 01011 cpl_msg_warning(cpl_func, 01012 "Band defined in header of detector %d: %s", 01013 i, filter_ids[i-1]); 01014 cpl_msg_warning(cpl_func, 01015 "Arc line file defined: %s", 01016 cpl_frame_get_filename( 01017 kmo_dfs_get_frame(frameset, ARC_LIST))); 01018 cpl_error_reset(); 01019 } 01020 01021 01022 // 01023 // create reconstructed and resampled arc frame 01024 // 01025 stored_det_img[sx] = kmo_reconstructed_arc_image(frameset, 01026 det_lamp_on_copy, 01027 det_lamp_off, 01028 xcal, 01029 ycal, 01030 stored_lcal[sx], 01031 unused_ifus_after[i-1], 01032 flip_trace, 01033 i, 01034 suffix, 01035 filter_ids[i-1], 01036 lamp_config, 01037 rotang_found[a], 01038 &qc_header); 01039 if (cpl_error_get_code() != CPL_ERROR_NONE) { 01040 // couldn't reconstruct 01041 cpl_msg_error("","Couldn't reconstruct IFUs on detector %d", i); 01042 cpl_error_reset(); 01043 } 01044 01045 // load and update sub_header with QC parameters 01046 KMO_TRY_EXIT_IF_NULL( 01047 stored_sub_headers_lcal[sx] = kmo_dfs_load_sub_header(frameset, 01048 ARC_ON, i, 01049 FALSE)); 01050 01051 // update EXTNAME 01052 KMO_TRY_EXIT_IF_NULL( 01053 extname = kmo_extname_creator(detector_frame, i, EXT_DATA)); 01054 KMO_TRY_EXIT_IF_ERROR( 01055 kmclipm_update_property_string(stored_sub_headers_lcal[sx], 01056 EXTNAME, 01057 extname, 01058 "FITS extension name")); 01059 cpl_free(extname); extname = NULL; 01060 01061 // add first QC parameters 01062 KMO_TRY_EXIT_IF_ERROR( 01063 kmclipm_update_property_int(stored_sub_headers_lcal[sx], 01064 QC_ARC_SAT, 01065 stored_qc_arc_sat[sx], 01066 "[] nr. saturated pixels of arc exp.")); 01067 01068 gain = kmo_dfs_get_property_double(stored_sub_headers_lcal[sx], GAIN); 01069 KMO_TRY_CHECK_ERROR_STATE_MSG( 01070 "GAIN-keyword in fits-header is missing!"); 01071 01072 if (stored_qc_ar_eff[sx] != -1.0) { 01073 KMO_TRY_EXIT_IF_ERROR( 01074 kmclipm_update_property_double(stored_sub_headers_lcal[sx], 01075 QC_ARC_AR_EFF, 01076 stored_qc_ar_eff[sx]/gain, 01077 "[e-/s] Argon lamp efficiency")); 01078 } 01079 01080 if (stored_qc_ne_eff[sx] != -1.0) { 01081 KMO_TRY_EXIT_IF_ERROR( 01082 kmclipm_update_property_double(stored_sub_headers_lcal[sx], 01083 QC_ARC_NE_EFF, 01084 stored_qc_ne_eff[sx]/gain, 01085 "[e-/s] Neon lamp efficiency")); 01086 } 01087 01088 KMO_TRY_EXIT_IF_ERROR( 01089 kmclipm_update_property_double(stored_sub_headers_lcal[sx], 01090 CAL_ROTANGLE, 01091 ((double) rotang_found[a]), 01092 "[deg] Rotator relative to nasmyth")); 01093 01094 // append QC parameters 01095 KMO_TRY_EXIT_IF_ERROR( 01096 cpl_propertylist_append(stored_sub_headers_lcal[sx], 01097 qc_header)); 01098 cpl_propertylist_delete(qc_header); qc_header = NULL; 01099 01100 KMO_TRY_EXIT_IF_NULL( 01101 stored_sub_headers_det_img[sx] = cpl_propertylist_duplicate( 01102 stored_sub_headers_lcal[sx])); 01103 01104 cpl_propertylist_erase(stored_sub_headers_lcal[sx], CRVAL1); 01105 cpl_propertylist_erase(stored_sub_headers_lcal[sx], CRVAL2); 01106 cpl_propertylist_erase(stored_sub_headers_lcal[sx], CTYPE1); 01107 cpl_propertylist_erase(stored_sub_headers_lcal[sx], CTYPE2); 01108 cpl_propertylist_erase(stored_sub_headers_lcal[sx], CDELT1); 01109 cpl_propertylist_erase(stored_sub_headers_lcal[sx], CDELT2); 01110 01111 cpl_propertylist_erase(stored_sub_headers_lcal[sx], CRPIX1); 01112 cpl_propertylist_erase(stored_sub_headers_lcal[sx], CRPIX2); 01113 if (cpl_propertylist_has(stored_sub_headers_lcal[sx], CRPIX1)) { 01114 cpl_propertylist_erase(stored_sub_headers_lcal[sx], CRPIX1); 01115 } 01116 if (cpl_propertylist_has(stored_sub_headers_lcal[sx], CRPIX2)) { 01117 cpl_propertylist_erase(stored_sub_headers_lcal[sx], CRPIX2); 01118 } 01119 01120 // free memory 01121 cpl_image_delete(det_lamp_on); det_lamp_on = NULL; 01122 cpl_image_delete(det_lamp_on_copy); det_lamp_on_copy = NULL; 01123 cpl_image_delete(det_lamp_off); det_lamp_off = NULL; 01124 cpl_image_delete(bad_pix_mask); bad_pix_mask = NULL; 01125 cpl_image_delete(xcal); xcal = NULL; 01126 cpl_image_delete(ycal); ycal = NULL; 01127 01128 for (int j = 0; j < KMOS_IFUS_PER_DETECTOR; j++) { 01129 cpl_table_delete(edge_table[i-1][j]); edge_table[i-1][j] = NULL; 01130 } 01131 } // for i devices 01132 } // for a angles 01133 01134 if (line_estimate_method == 2) { 01135 cpl_table_delete(reflines); reflines = NULL; 01136 } 01137 // ########################################################################### 01138 // ### QC parameters & saving 01139 // ########################################################################### 01140 cpl_msg_info("","Saving data..."); 01141 01142 // 01143 // ------------ load, update & save primary header ------------ 01144 // 01145 01146 // update which IFUs are not used 01147 KMO_TRY_EXIT_IF_ERROR( 01148 kmo_set_unused_ifus(unused_ifus_after, main_header, 01149 "kmo_wave_cal")); 01150 01151 KMO_TRY_EXIT_IF_NULL( 01152 frame = kmo_dfs_get_frame(frameset, ARC_ON)); 01153 01154 KMO_TRY_EXIT_IF_ERROR( 01155 kmo_dfs_save_main_header(frameset, filename_lcal, suffix, frame, 01156 main_header, parlist, cpl_func)); 01157 01158 KMO_TRY_EXIT_IF_ERROR( 01159 kmo_dfs_save_main_header(frameset, filename_det_img, suffix, frame, 01160 main_header, parlist, cpl_func)); 01161 01162 cpl_propertylist_delete(main_header); main_header = NULL; 01163 01164 // 01165 // --- save sub-frames --- 01166 // 01167 for (int a = 0; a<nr_angles; a++) { 01168 for (int i = 1; i <= nr_devices; i++) { 01169 int sx = a * nr_devices + (i - 1); 01170 // save lcal-frame 01171 KMO_TRY_EXIT_IF_ERROR( 01172 kmo_dfs_save_image(stored_lcal[sx], filename_lcal, suffix, 01173 stored_sub_headers_lcal[sx], 0./0.)); 01174 01175 // save detector image 01176 KMO_TRY_EXIT_IF_ERROR( 01177 kmo_dfs_save_image(stored_det_img[sx], filename_det_img, suffix, 01178 stored_sub_headers_det_img[sx], 0./0.)); 01179 } // for i = nr_devices 01180 } // for a angles 01181 01182 // Alex: was ist das alles? 01183 // KMO_TRY_EXIT_IF_NULL( 01184 // sub_header = cpl_propertylist_new()); 01185 // 01186 // KMO_TRY_EXIT_IF_NULL( 01187 // extname = kmo_extname_creator(list_frame, -1, EXT_LIST)); 01188 // KMO_TRY_EXIT_IF_ERROR( 01189 // kmclipm_update_property_string(sub_header, 01190 // EXTNAME, 01191 // extname, 01192 // "FITS extension name")); 01193 // cpl_free(extname); extname = NULL; 01194 // 01195 // // save table with wavelengths and 01196 // KMO_TRY_EXIT_IF_ERROR( 01197 // kmo_dfs_save_table(arclines, filename_img, sub_header)); 01198 01199 // print which IFUs are not used 01200 kmo_print_unused_ifus(unused_ifus_after, TRUE); 01201 } 01202 KMO_CATCH 01203 { 01204 KMO_CATCH_MSG(); 01205 ret_val = -1; 01206 } 01207 01208 if (last_env != NULL) { 01209 setenv("KMCLIPM_PRIV_RECONSTRUCT_LUT_MODE",last_env,1); 01210 } else { 01211 unsetenv("KMCLIPM_PRIV_RECONSTRUCT_LUT_MODE"); 01212 } 01213 01214 kmo_free_fits_desc(&desc1); 01215 kmo_free_fits_desc(&desc2); 01216 if (unused_ifus_before != NULL) { 01217 kmo_free_unused_ifus(unused_ifus_before); unused_ifus_before = NULL; 01218 } 01219 if (unused_ifus_after != NULL) { 01220 kmo_free_unused_ifus(unused_ifus_after); unused_ifus_after = NULL; 01221 } 01222 cpl_propertylist_delete(main_header); main_header = NULL; 01223 cpl_image_delete(det_lamp_on); det_lamp_on = NULL; 01224 cpl_image_delete(det_lamp_off); det_lamp_off = NULL; 01225 cpl_image_delete(bad_pix_mask); bad_pix_mask = NULL; 01226 cpl_table_delete(arclines); arclines = NULL; 01227 cpl_table_delete(reflines); reflines = NULL; 01228 cpl_free(stored_qc_arc_sat); stored_qc_arc_sat = NULL; 01229 cpl_free(stored_qc_ar_eff); stored_qc_ar_eff = NULL; 01230 cpl_free(stored_qc_ne_eff); stored_qc_ne_eff = NULL; 01231 for (int i = 0; i < nr_devices * nr_angles; i++) { 01232 cpl_image_delete(stored_lcal[i]); stored_lcal[i] = NULL; 01233 cpl_image_delete(stored_det_img[i]); stored_det_img[i] = NULL; 01234 cpl_propertylist_delete(stored_sub_headers_lcal[i]); 01235 stored_sub_headers_lcal[i] = NULL; 01236 cpl_propertylist_delete(stored_sub_headers_det_img[i]); 01237 stored_sub_headers_det_img[i] = NULL; 01238 } 01239 for (int i = 0; i < nr_angles; i++) { 01240 cpl_frameset_delete(angle_frameset[i]); angle_frameset[i] = NULL; 01241 } 01242 for (int i = 0; i < nr_devices; i++) { 01243 cpl_free(filter_ids[i]); filter_ids[i] = NULL; 01244 cpl_free(edge_table[i]); edge_table[i] = NULL; 01245 } 01246 cpl_free(angle_frameset); angle_frameset = NULL; 01247 cpl_free(stored_lcal); stored_lcal = NULL; 01248 cpl_free(stored_det_img); stored_det_img = NULL; 01249 cpl_free(stored_sub_headers_lcal); stored_sub_headers_lcal = NULL; 01250 cpl_free(stored_sub_headers_det_img); stored_sub_headers_det_img = NULL; 01251 cpl_free(filter_ids); filter_ids = NULL; 01252 cpl_free(edge_table); edge_table = NULL; 01253 cpl_free(readmode); readmode = NULL; 01254 cpl_bivector_delete(lines); lines = NULL; 01255 cpl_free(suffix); suffix = NULL; 01256 01257 return ret_val; 01258 } 01259
1.7.6.1