KMOS Pipeline Reference Manual
1.3.0
|
00001 /* 00002 * This file is part of the KMOS Pipeline 00003 * Copyright (C) 2002,2003 European Southern Observatory 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License as published by 00007 * the Free Software Foundation; either version 2 of the License, or 00008 * (at your option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 * GNU General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU General Public License 00016 * along with this program; if not, write to the Free Software 00017 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00018 */ 00019 00020 #ifdef HAVE_CONFIG_H 00021 #include <config.h> 00022 #endif 00023 00024 /*----------------------------------------------------------------------------- 00025 * Includes 00026 *----------------------------------------------------------------------------*/ 00027 00028 #include <string.h> 00029 #include <math.h> 00030 00031 #ifdef __USE_XOPEN2K 00032 #include <stdlib.h> 00033 #define GGG 00034 #else 00035 #define __USE_XOPEN2K /* to get the definition for setenv in stdlib.h */ 00036 #include <stdlib.h> 00037 #undef __USE_XOPEN2K 00038 #endif 00039 00040 #include <cpl.h> 00041 00042 #include "kmo_utils.h" 00043 #include "kmo_functions.h" 00044 #include "kmo_priv_wave_cal.h" 00045 #include "kmo_priv_functions.h" 00046 #include "kmo_cpl_extensions.h" 00047 #include "kmo_dfs.h" 00048 #include "kmo_error.h" 00049 #include "kmo_constants.h" 00050 #include "kmo_debug.h" 00051 00052 /*----------------------------------------------------------------------------- 00053 * Functions prototypes 00054 *----------------------------------------------------------------------------*/ 00055 00056 static int kmo_wave_cal_create(cpl_plugin *); 00057 static int kmo_wave_cal_exec(cpl_plugin *); 00058 static int kmo_wave_cal_destroy(cpl_plugin *); 00059 static int kmo_wave_cal(cpl_parameterlist *, cpl_frameset *); 00060 00061 /*----------------------------------------------------------------------------- 00062 * Static variables 00063 *----------------------------------------------------------------------------*/ 00064 00065 static char kmo_wave_cal_description[] = 00066 "This recipe creates the wavelength calibration frame needed for all three\n" 00067 "detectors. It must be called after the kmo_flat recipe, which generates the\n" 00068 "two spatial calibration frames needed in this recipe. As input a lamp-on \n" 00069 "frame, a lamp-off frame, the spatial calibration frames and the list with \n" 00070 "the reference arclines are required.\n" 00071 "An additional output frame is the resampled image of the reconstructed arc\n" 00072 "frame. All slitlets of all IFUs are aligned one next to the other. This \n" 00073 "frame serves for quality control. One can immediately see if the \n" 00074 "calibration was successful.\n" 00075 "The lists of reference arclines are supposed to contain the lines for both\n" 00076 "available calibration arc-lamps, i.e. Argon and Neon. The list is supposed\n" 00077 "to be a F2L KMOS FITS file with three columns:\n" 00078 "\t1. Reference wavelength\n" 00079 "\t2. Relative strength\n" 00080 "\t3. String either containing “Ar” or “Ne”\n" 00081 "The recipe extracts, based on the header keywords, either the applying\n" 00082 "argon and/or neon emission lines. Below are the plots of the emission lines\n" 00083 "for both argon and neon. The marked lines are the ones used for wavelength \n" 00084 "calibration.\n" 00085 "\n" 00086 "Furthermore frames can be provided for several rotator angles. In this case\n" 00087 "the resulting calibration frames for each detector are repeatedly saved as \n" 00088 "extension for every angle.\n" 00089 "\n" 00090 "BASIC PARAMETERS:\n" 00091 "-----------------\n" 00092 "--order\n" 00093 "The polynomial order to use for the fit of the wavelength solution.\n" 00094 "0: (default) The appropriate order is choosen automatically depending on\n" 00095 "the waveband (4 for IZ band, 5 for HK, 6 for the others)\n" 00096 "\n" 00097 "ADVANCED PARAMETERS\n" 00098 "-------------------\n" 00099 "--b_samples\n" 00100 "The number of samples in spectral direction for the reconstructed cube.\n" 00101 "Ideally this number should be greater than 2048, the detector size.\n" 00102 "\n" 00103 "--b_start\n" 00104 "--b_end\n" 00105 "Used to define manually the start and end wavelength for the reconstructed\n" 00106 "cube. By default the internally defined values are used.\n" 00107 "\n" 00108 "--suppress_extension\n" 00109 "If set to TRUE, the arbitrary filename extensions are supressed. If\n" 00110 "multiple products with the same category are produced, they will be numered\n" 00111 "consecutively starting from 0.\n" 00112 "\n" 00113 "----------------------------------------------------------------------------\n" 00114 "Input files:\n" 00115 "\n" 00116 " DO 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 category Type Explanation\n" 00130 " ----------- ----- -----------\n" 00131 " LCAL F2D Wavelength calibration frame\n" 00132 " (3 Extensions)\n" 00133 " DET_IMG_WAVE F2D reconstructed arclamp-on exposure\n" 00134 " (4 extensions: 3 detector images + \n" 00135 " the arclines list table)\n" 00136 "----------------------------------------------------------------------------\n" 00137 "\n"; 00138 00139 /*----------------------------------------------------------------------------- 00140 * Functions code 00141 *----------------------------------------------------------------------------*/ 00142 00149 /*----------------------------------------------------------------------------*/ 00158 /*----------------------------------------------------------------------------*/ 00159 int cpl_plugin_get_info(cpl_pluginlist *list) 00160 { 00161 cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe); 00162 cpl_plugin *plugin = &recipe->interface; 00163 00164 cpl_plugin_init(plugin, 00165 CPL_PLUGIN_API, 00166 KMOS_BINARY_VERSION, 00167 CPL_PLUGIN_TYPE_RECIPE, 00168 "kmo_wave_cal", 00169 "Create a calibration frame encoding the spectral " 00170 "position (i.e. wavelength) of each pixel on the " 00171 "detector.", 00172 kmo_wave_cal_description, 00173 "Alex Agudo Berbel", 00174 "usd-help@eso.org", 00175 kmos_get_license(), 00176 kmo_wave_cal_create, 00177 kmo_wave_cal_exec, 00178 kmo_wave_cal_destroy); 00179 00180 cpl_pluginlist_append(list, plugin); 00181 00182 return 0; 00183 } 00184 00185 /*----------------------------------------------------------------------------*/ 00193 /*----------------------------------------------------------------------------*/ 00194 static int kmo_wave_cal_create(cpl_plugin *plugin) 00195 { 00196 cpl_recipe *recipe; 00197 cpl_parameter *p; 00198 00199 // Check that the plugin is part of a valid recipe 00200 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00201 recipe = (cpl_recipe *)plugin; 00202 else 00203 return -1; 00204 00205 // Create the parameters list in the cpl_recipe object 00206 recipe->parameters = cpl_parameterlist_new(); 00207 00208 // Fill the parameters list 00209 p = cpl_parameter_new_value("kmos.kmo_wave_cal.order", CPL_TYPE_INT, 00210 "The fitting polynomial order used for the wavelength solution. " 00211 "By default, 4 for IZ band, 5 for HK, 6 for the others", 00212 "kmos.kmo_wave_cal", 0); 00213 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "order"); 00214 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00215 cpl_parameterlist_append(recipe->parameters, p); 00216 00217 /* --suppress_extension */ 00218 p = cpl_parameter_new_value("kmos.kmo_wave_cal.suppress_extension", 00219 CPL_TYPE_BOOL, "Suppress arbitrary filename extension" 00220 "kmos.kmo_wave_cal", FALSE); 00221 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "suppress_extension"); 00222 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00223 cpl_parameterlist_append(recipe->parameters, p); 00224 00225 // add parameters for band-definition 00226 kmo_band_pars_create(recipe->parameters, "kmos.kmo_wave_cal"); 00227 00228 return 0; 00229 } 00230 00231 /*----------------------------------------------------------------------------*/ 00237 /*----------------------------------------------------------------------------*/ 00238 static int kmo_wave_cal_exec(cpl_plugin *plugin) 00239 { 00240 cpl_recipe *recipe; 00241 00242 // Get the recipe out of the plugin 00243 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00244 recipe = (cpl_recipe *)plugin; 00245 else return -1; 00246 00247 return kmo_wave_cal(recipe->parameters, recipe->frames); 00248 } 00249 00250 /*----------------------------------------------------------------------------*/ 00256 /*----------------------------------------------------------------------------*/ 00257 static int kmo_wave_cal_destroy(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 cpl_parameterlist_delete(recipe->parameters); 00267 return 0 ; 00268 } 00269 00270 /*----------------------------------------------------------------------------*/ 00285 /*----------------------------------------------------------------------------*/ 00286 static int kmo_wave_cal(cpl_parameterlist *parlist, cpl_frameset *frameset) 00287 { 00288 cpl_image *det_lamp_on = NULL, 00289 *det_lamp_on_copy = NULL, 00290 *det_lamp_off = NULL, 00291 *bad_pix_mask = NULL, 00292 *xcal = NULL, 00293 *ycal = NULL, 00294 *lcal = NULL; 00295 00296 cpl_image **stored_lcal = NULL, 00297 **stored_det_img = NULL; 00298 00299 cpl_frame *frame = NULL; 00300 cpl_frameset ** angle_frameset = NULL; 00301 00302 int ret_val = 0, 00303 nr_devices = 0, 00304 nr_angles = 0, 00305 nx = 0, 00306 ny = 0, 00307 nz = 0, 00308 *stored_qc_arc_sat = NULL, 00309 fit_order_par = 0, 00310 fit_order = 0, 00311 ndit = 0, 00312 suppress_extension = FALSE, 00313 line_estimate_method = 2, 00314 nr_sat = 0, 00315 i = 0, j = 0, a = 0, ax = 0, x = 0, y = 0; 00316 float *pbad_pix_mask = NULL; 00317 double exptime = 0.0, 00318 gain = 0.0, 00319 *stored_qc_ar_eff = NULL, 00320 *stored_qc_ne_eff = NULL, 00321 angle_found = 0.0; 00322 00323 cpl_table *arclines = NULL, 00324 *reflines = NULL, 00325 ***edge_table = NULL; 00326 00327 cpl_propertylist *main_header = NULL, 00328 **stored_sub_headers_lcal = NULL, 00329 **stored_sub_headers_det_img = NULL, 00330 *qc_header = NULL, 00331 *tmp_header = NULL, 00332 *header = NULL; 00333 00334 cpl_array **unused_ifus_before = NULL, 00335 **unused_ifus_after = NULL; 00336 00337 cpl_bivector *lines = NULL; 00338 00339 main_fits_desc desc1, 00340 desc2; 00341 00342 char *extname = NULL, 00343 filename_lcal[256], 00344 filename_det_img[256], 00345 *suffix = NULL, 00346 *fn_suffix = NULL, 00347 tmpstr[256], 00348 **filter_ids = NULL, 00349 *readmode = NULL, 00350 *str_line_estimate_method = NULL, 00351 *last_env = NULL; 00352 00353 const char *tmp_str = NULL; 00354 00355 cpl_error_code err = CPL_ERROR_NONE; 00356 00357 enum lampConfiguration lamp_config; 00358 00359 KMO_TRY 00360 { 00361 kmo_init_fits_desc(&desc1); 00362 kmo_init_fits_desc(&desc2); 00363 00364 str_line_estimate_method = getenv("KMO_WAVE_LINE_ESTIMATE"); 00365 if (str_line_estimate_method != NULL) { 00366 line_estimate_method = atoi(str_line_estimate_method); 00367 } 00368 cpl_msg_debug(__func__, "Line estimation method: %d\n", 00369 line_estimate_method); 00370 00371 /* Check inputs */ 00372 KMO_TRY_ASSURE((parlist != NULL) && (frameset != NULL), 00373 CPL_ERROR_NULL_INPUT, "Not all input data is provided!"); 00374 00375 KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, ARC_ON) >= 1, 00376 CPL_ERROR_NULL_INPUT, "At least 1 ARC_ON frame is required!"); 00377 00378 KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, ARC_OFF) >= 1, 00379 CPL_ERROR_NULL_INPUT, "Exactly 1 ARC_OFF frame is required!"); 00380 00381 if (cpl_frameset_count_tags(frameset, ARC_OFF) > 1) { 00382 cpl_msg_warning(__func__, 00383 "Only 1 ARC_OFF frame required. Frame #1 will be used"); 00384 } 00385 00386 KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, XCAL) == 1, 00387 CPL_ERROR_FILE_NOT_FOUND, "Exactly 1 XCAL frame is required!"); 00388 00389 KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, YCAL) == 1, 00390 CPL_ERROR_FILE_NOT_FOUND, "Exactly 1 YCAL frame is required!"); 00391 00392 KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, ARC_LIST) == 1, 00393 CPL_ERROR_FILE_NOT_FOUND, "Exactly 1 ARC_LIST is required!"); 00394 00395 KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, FLAT_EDGE) == 1, 00396 CPL_ERROR_FILE_NOT_FOUND, "Exactly 1 FLAT_EDGE is required!"); 00397 00398 KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, WAVE_BAND) == 1, 00399 CPL_ERROR_FILE_NOT_FOUND, "Exactly 1 WAVE_BAND is required!"); 00400 00401 if (line_estimate_method == 2) { 00402 KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, REF_LINES) == 1, 00403 CPL_ERROR_FILE_NOT_FOUND, "Exactly 1 REF_LINES required!"); 00404 } 00405 00406 KMO_TRY_ASSURE(kmo_dfs_set_groups(frameset, "kmo_wave_cal") == 1, 00407 CPL_ERROR_ILLEGAL_INPUT, 00408 "Cannot identify RAW and CALIB frames!"); 00409 00410 /* Get Parameters */ 00411 cpl_msg_info(__func__, "--- Parameter setup for kmo_wave_cal ------"); 00412 00413 fit_order_par = kmo_dfs_get_parameter_int(parlist, 00414 "kmos.kmo_wave_cal.order"); 00415 KMO_TRY_CHECK_ERROR_STATE(); 00416 KMO_TRY_EXIT_IF_ERROR( 00417 kmo_dfs_print_parameter_help(parlist, "kmos.kmo_wave_cal.order")); 00418 KMO_TRY_ASSURE((fit_order_par >= 0) && (fit_order_par <= 7), 00419 CPL_ERROR_ILLEGAL_INPUT, "order must be between 1 and 7"); 00420 00421 suppress_extension = kmo_dfs_get_parameter_bool(parlist, 00422 "kmos.kmo_wave_cal.suppress_extension"); 00423 KMO_TRY_CHECK_ERROR_STATE(); 00424 KMO_TRY_EXIT_IF_ERROR( 00425 kmo_dfs_print_parameter_help(parlist, 00426 "kmos.kmo_wave_cal.suppress_extension")); 00427 00428 KMO_TRY_ASSURE((suppress_extension == TRUE) || 00429 (suppress_extension == FALSE), CPL_ERROR_ILLEGAL_INPUT, 00430 "suppress_extension must be TRUE or FALSE!"); 00431 00432 kmo_band_pars_load(parlist, "kmos.kmo_wave_cal"); 00433 00434 cpl_msg_info(__func__, "-------------------------------------------"); 00435 00436 /* check EXPTIME, NDIT, READMODE and lamps */ 00437 /* check ARC_OFF */ 00438 KMO_TRY_EXIT_IF_NULL( 00439 frame = kmo_dfs_get_frame(frameset, ARC_OFF)); 00440 00441 main_header=kmclipm_propertylist_load(cpl_frame_get_filename(frame), 0); 00442 00443 ndit = cpl_propertylist_get_int(main_header, NDIT); 00444 KMO_TRY_CHECK_ERROR_STATE("NDIT keyword in main header missing!"); 00445 00446 exptime = cpl_propertylist_get_double(main_header, EXPTIME); 00447 KMO_TRY_CHECK_ERROR_STATE("EXPTIME keyword in main header missing!"); 00448 00449 readmode = cpl_strdup(cpl_propertylist_get_string(main_header, 00450 READMODE)); 00451 KMO_TRY_CHECK_ERROR_STATE( 00452 "ESO DET READ CURNAME keyword in main header missing!"); 00453 00454 desc1 = kmo_identify_fits_header(cpl_frame_get_filename(frame)); 00455 KMO_TRY_CHECK_ERROR_STATE_MSG( 00456 "ARC_OFF frame doesn't seem to be in KMOS-format!"); 00457 00458 KMO_TRY_ASSURE(desc1.fits_type == raw_fits, CPL_ERROR_ILLEGAL_INPUT, 00459 "ARC_OFF frame hasn't correct data type " 00460 "(%s must be a raw, unprocessed file)!", 00461 cpl_frame_get_filename(frame)); 00462 00463 nx = desc1.naxis1; 00464 ny = desc1.naxis2; 00465 nz = desc1.naxis3; 00466 nr_devices = desc1.nr_ext; 00467 00468 /* assure that flat lamps are off */ 00469 KMO_TRY_ASSURE((kmo_check_lamp(main_header, INS_LAMP3_ST) == FALSE) && 00470 (kmo_check_lamp(main_header, INS_LAMP4_ST) == FALSE), 00471 CPL_ERROR_ILLEGAL_INPUT,"Flat lamps must be switched off (%s)!", 00472 cpl_frame_get_filename(frame)); 00473 00474 /* check if arc lamps are off (or at least blocked by filter wheel) */ 00475 if ((kmo_check_lamp(main_header, INS_LAMP1_ST) == TRUE) || 00476 (kmo_check_lamp(main_header, INS_LAMP2_ST) == TRUE)) { 00477 if (!(strcmp(cpl_propertylist_get_string(main_header, 00478 "ESO INS FILT1 ID"), "Block") == 0) || 00479 !(strcmp(cpl_propertylist_get_string(main_header, 00480 "ESO INS FILT3 ID"), "Block") == 0) || 00481 !(strcmp(cpl_propertylist_get_string(main_header, 00482 "ESO INS FILT3 ID"), "Block") == 0)) { 00483 cpl_msg_warning(__func__, 00484 "At least one arc lamp is on! Check if the lamps are blocked!"); 00485 } 00486 } 00487 cpl_propertylist_delete(main_header); main_header = NULL; 00488 00489 /* check REF_LINES */ 00490 if (line_estimate_method == 2) { 00491 KMO_TRY_EXIT_IF_NULL( 00492 frame = kmo_dfs_get_frame(frameset, REF_LINES)); 00493 desc2 = kmo_identify_fits_header( 00494 cpl_frame_get_filename(frame)); 00495 KMO_TRY_CHECK_ERROR_STATE_MSG( 00496 "REF_LINES frame doesn't seem to be in KMOS-format!"); 00497 00498 KMO_TRY_ASSURE(desc2.fits_type == f2l_fits, CPL_ERROR_ILLEGAL_INPUT, 00499 "REF_LINES frame hasn't correct frame type " 00500 "(%s must be a F2L frame)!", 00501 cpl_frame_get_filename(frame)); 00502 kmo_free_fits_desc(&desc2); 00503 } 00504 00505 /* check ARC_ON */ 00506 KMO_TRY_EXIT_IF_NULL( 00507 frame = kmo_dfs_get_frame(frameset, ARC_ON)); 00508 00509 while (frame != NULL) { 00510 main_header = kmclipm_propertylist_load( 00511 cpl_frame_get_filename(frame), 0); 00512 00513 KMO_TRY_ASSURE(cpl_propertylist_get_int(main_header, NDIT) == ndit, 00514 CPL_ERROR_ILLEGAL_INPUT, 00515 "NDIT isn't the same for all frames: (is %d and %d).", 00516 cpl_propertylist_get_int(main_header, NDIT), ndit); 00517 00518 KMO_TRY_ASSURE( 00519 cpl_propertylist_get_double(main_header, EXPTIME)==exptime, 00520 CPL_ERROR_ILLEGAL_INPUT, 00521 "EXPTIME isn't the same for all frames: (is %g and %g).", 00522 cpl_propertylist_get_double(main_header, EXPTIME), exptime); 00523 00524 KMO_TRY_ASSURE( 00525 strcmp(cpl_propertylist_get_string(main_header, READMODE), readmode) == 0, 00526 CPL_ERROR_ILLEGAL_INPUT, 00527 "ESO DET READ CURNAME isn't the same for all frames: (is %s and %s).", 00528 cpl_propertylist_get_string(main_header, READMODE), readmode); 00529 00530 desc2 = kmo_identify_fits_header(cpl_frame_get_filename(frame)); 00531 KMO_TRY_CHECK_ERROR_STATE_MSG( 00532 "ARC_ON frame doesn't seem to be in KMOS-format!"); 00533 00534 KMO_TRY_ASSURE(desc2.fits_type == raw_fits, CPL_ERROR_ILLEGAL_INPUT, 00535 "ARC_ON frame hasn't correct data type " 00536 "(%s must be a raw, unprocessed file)!", 00537 cpl_frame_get_filename(frame)); 00538 00539 KMO_TRY_ASSURE((desc2.naxis1 == nx) && (desc2.naxis2 == ny) && 00540 (desc2.naxis3 == nz), CPL_ERROR_ILLEGAL_INPUT, 00541 "ARC_ON frame hasn't correct dimensions! (x,y): (%d,%d) vs (%d,%d)", 00542 desc2.naxis1, desc2.naxis2, nx, ny); 00543 00544 // assure that flat lamp is off (LAMP3 and 4) 00545 // and that either arc lamp is on (LAMP1 and 2) 00546 KMO_TRY_ASSURE( 00547 ((kmo_check_lamp(main_header, INS_LAMP1_ST) == TRUE) || 00548 (kmo_check_lamp(main_header, INS_LAMP2_ST) == TRUE)) && 00549 (kmo_check_lamp(main_header, INS_LAMP3_ST) == FALSE) && 00550 (kmo_check_lamp(main_header, INS_LAMP4_ST) == FALSE), 00551 CPL_ERROR_ILLEGAL_INPUT, 00552 "Lamp1 or Lamp2 must be switched on, 3 and 4 must be " 00553 "off for the ARC_ON frame"); 00554 00555 frame = kmo_dfs_get_frame(frameset, NULL); 00556 KMO_TRY_CHECK_ERROR_STATE(); 00557 00558 kmo_free_fits_desc(&desc2); 00559 kmo_init_fits_desc(&desc2); 00560 cpl_propertylist_delete(main_header); main_header = NULL; 00561 } 00562 00563 // load first ARC_ON main header 00564 KMO_TRY_EXIT_IF_NULL(frame = kmo_dfs_get_frame(frameset, ARC_ON)); 00565 KMO_TRY_EXIT_IF_NULL( 00566 main_header = kmclipm_propertylist_load( 00567 cpl_frame_get_filename(frame), 0)); 00568 00569 // check FLAT_EDGE 00570 KMO_TRY_EXIT_IF_NULL(frame = kmo_dfs_get_frame(frameset, FLAT_EDGE)); 00571 00572 desc2 = kmo_identify_fits_header(cpl_frame_get_filename(frame)); 00573 KMO_TRY_CHECK_ERROR_STATE(); 00574 00575 KMO_TRY_ASSURE((desc2.nr_ext % 24== 0) && (desc2.fits_type == f2l_fits), 00576 CPL_ERROR_ILLEGAL_INPUT, "FLAT_EDGE has a wrong format."); 00577 00578 kmo_free_fits_desc(&desc2); 00579 kmo_init_fits_desc(&desc2); 00580 00581 // ------------ check filter_id, grating_id and rotator offset --------- 00582 // assure that filters, grating and rotation offsets match for 00583 // ARC_ON, XCAL and YCAL 00584 // check if filter_id, grating_id and rotator offset match for all 00585 // detectors 00586 KMO_TRY_EXIT_IF_ERROR( 00587 kmo_check_frame_setup(frameset, ARC_ON, XCAL,TRUE,FALSE,FALSE)); 00588 KMO_TRY_EXIT_IF_ERROR( 00589 kmo_check_frame_setup(frameset, ARC_ON, YCAL, TRUE, FALSE, FALSE)); 00590 00591 KMO_TRY_EXIT_IF_ERROR(kmo_check_frame_setup_md5_xycal(frameset)); 00592 00593 strcpy(filename_lcal, LCAL); 00594 strcpy(filename_det_img, DET_IMG_WAVE); 00595 00596 KMO_TRY_EXIT_IF_NULL(frame = kmo_dfs_get_frame(frameset, XCAL)); 00597 KMO_TRY_EXIT_IF_NULL(suffix = kmo_dfs_get_suffix(frame, TRUE, FALSE)); 00598 00599 cpl_msg_info(__func__, "Detected instrument setup: %s", suffix+1); 00600 cpl_msg_info(__func__, "(grating 1, 2 & 3)"); 00601 00602 // setup lamp config 00603 if ((kmo_check_lamp(main_header, INS_LAMP1_ST) == TRUE) && 00604 (kmo_check_lamp(main_header, INS_LAMP2_ST) == FALSE)) { 00605 lamp_config = ARGON; 00606 strcpy(tmpstr, "Argon"); 00607 } else if ((kmo_check_lamp(main_header, INS_LAMP1_ST) == FALSE) && 00608 (kmo_check_lamp(main_header, INS_LAMP2_ST) == TRUE)) { 00609 lamp_config = NEON; 00610 strcpy(tmpstr, "Neon"); 00611 } else if ((kmo_check_lamp(main_header, INS_LAMP1_ST) == TRUE) && 00612 (kmo_check_lamp(main_header, INS_LAMP2_ST) == TRUE)) { 00613 lamp_config = ARGON_NEON; 00614 strcpy(tmpstr, "Argon + Neon"); 00615 } 00616 00617 cpl_msg_info(__func__, "Detected arc lamp configuration: %s", tmpstr); 00618 00619 /* assert that filter and grating match for each detector */ 00620 /* filter/grating can be different for each detector */ 00621 KMO_TRY_EXIT_IF_NULL( 00622 filter_ids = kmo_get_filter_setup(main_header, nr_devices, TRUE)); 00623 00624 /* scan for rotator angles */ 00625 #define ANGLE_DIM 360 00626 int rotang_found[ANGLE_DIM]; 00627 int rotang_cnt[ANGLE_DIM]; 00628 for (i = 0; i < ANGLE_DIM; i++) { 00629 rotang_found[i] = 0; 00630 rotang_cnt[i] = 0; 00631 } 00632 KMO_TRY_EXIT_IF_NULL( 00633 frame = kmo_dfs_get_frame(frameset, ARC_ON)); 00634 while (frame != NULL) { 00635 header = kmclipm_propertylist_load( 00636 cpl_frame_get_filename(frame), 0); 00637 if (cpl_propertylist_has(header, ROTANGLE)) { 00638 int rot_angle = (int)rint(cpl_propertylist_get_double( 00639 header, ROTANGLE)); 00640 if (rot_angle < 0) rot_angle += 360; 00641 if (rot_angle < 360 && rot_angle >= 0) rotang_cnt[rot_angle]++; 00642 } else { 00643 cpl_msg_warning(__func__,"File %s has no keyword \"ROTANGLE\"", 00644 cpl_frame_get_filename(frame)); 00645 } 00646 00647 cpl_propertylist_delete(header); header = NULL; 00648 frame = kmo_dfs_get_frame(frameset, NULL); 00649 KMO_TRY_CHECK_ERROR_STATE(); 00650 } 00651 for (ax = 0; ax < ANGLE_DIM; ax++) { 00652 if (rotang_cnt[ax] != 0) { 00653 if (rotang_cnt[ax] == 1 ) { 00654 cpl_msg_info(__func__, 00655 "Found %d frame with rotator angle %d", 00656 rotang_cnt[ax],ax); 00657 } else { 00658 cpl_msg_warning(__func__, 00659 "Found %d frames with rotator angle %d but only one will be used", 00660 rotang_cnt[ax],ax); 00661 } 00662 rotang_found[nr_angles] = ax; 00663 nr_angles++; 00664 } 00665 } 00666 00667 KMO_TRY_EXIT_IF_NULL ( 00668 angle_frameset = (cpl_frameset **)cpl_malloc( 00669 nr_angles * sizeof(cpl_frameset*))); 00670 for (i = 0; i < nr_angles; i++) { 00671 angle_frameset[i] = cpl_frameset_new(); 00672 } 00673 00674 KMO_TRY_EXIT_IF_NULL(frame = kmo_dfs_get_frame(frameset, ARC_ON)); 00675 while (frame != NULL) { 00676 header=kmclipm_propertylist_load(cpl_frame_get_filename(frame), 0); 00677 if (cpl_propertylist_has(header, ROTANGLE)) { 00678 int rot_angle = (int)rint(cpl_propertylist_get_double( 00679 header, ROTANGLE)); 00680 if (rot_angle < 0) rot_angle += 360; 00681 int ix = -1; 00682 for (ix = 0; ix<nr_angles; ix++) { 00683 if (rotang_found[ix] == rot_angle) { 00684 break; 00685 } 00686 } 00687 if (ix<nr_angles) { 00688 KMO_TRY_EXIT_IF_ERROR( 00689 cpl_frameset_insert(angle_frameset[ix], 00690 cpl_frame_duplicate(frame))); 00691 } 00692 } 00693 00694 cpl_propertylist_delete(header); header = NULL; 00695 frame = kmo_dfs_get_frame(frameset, NULL); 00696 KMO_TRY_CHECK_ERROR_STATE(); 00697 } 00698 00699 /* allocate temporary memory */ 00700 /* allocate here a edge table structure for all detectors */ 00701 KMO_TRY_EXIT_IF_NULL( 00702 edge_table = (cpl_table***)cpl_calloc(nr_devices, 00703 sizeof(cpl_table**))); 00704 for (i = 0; i < nr_devices; i++) { 00705 KMO_TRY_EXIT_IF_NULL( 00706 edge_table[i] = (cpl_table**)cpl_calloc(KMOS_IFUS_PER_DETECTOR, 00707 sizeof(cpl_table*))); 00708 } 00709 00710 /* the frames have to be stored temporarily because the QC params */ 00711 /* for the main header are calculated per detector. So they can be */ 00712 /* stored only when all detectors are processed */ 00713 KMO_TRY_EXIT_IF_NULL( 00714 stored_lcal = (cpl_image**)cpl_calloc(nr_devices * nr_angles, 00715 sizeof(cpl_image*))); 00716 KMO_TRY_EXIT_IF_NULL( 00717 stored_det_img = (cpl_image**)cpl_calloc(nr_devices * nr_angles, 00718 sizeof(cpl_image*))); 00719 KMO_TRY_EXIT_IF_NULL( 00720 stored_sub_headers_lcal = (cpl_propertylist**)cpl_calloc( 00721 nr_devices * nr_angles, sizeof(cpl_propertylist*))); 00722 KMO_TRY_EXIT_IF_NULL( 00723 stored_sub_headers_det_img = (cpl_propertylist**)cpl_calloc( 00724 nr_devices * nr_angles, sizeof(cpl_propertylist*))); 00725 KMO_TRY_EXIT_IF_NULL( 00726 stored_qc_arc_sat = (int*)cpl_calloc(nr_devices, 00727 nr_angles * sizeof(int))); 00728 KMO_TRY_EXIT_IF_NULL( 00729 stored_qc_ar_eff = (double*)cpl_calloc(nr_devices, 00730 nr_angles * sizeof(double))); 00731 KMO_TRY_EXIT_IF_NULL( 00732 stored_qc_ne_eff = (double*)cpl_calloc(nr_devices, 00733 nr_angles * sizeof(double))); 00734 00735 /* process data */ 00736 /* load arclines and reference lines */ 00737 KMO_TRY_EXIT_IF_NULL(frame = kmo_dfs_get_frame(frameset, ARC_LIST)); 00738 00739 /* check if ARC_LIST is the filter_id-one */ 00740 KMO_TRY_EXIT_IF_NULL(tmp_header = kmclipm_propertylist_load( 00741 cpl_frame_get_filename(frame), 0)); 00742 KMO_TRY_EXIT_IF_NULL( 00743 tmp_str = cpl_propertylist_get_string(tmp_header, FILT_ID)); 00744 KMO_TRY_ASSURE(strcmp(filter_ids[0], tmp_str) == 0, 00745 CPL_ERROR_ILLEGAL_INPUT, "ARC_LIST model must have primary " 00746 "keyword '%s' equal '%s'!!!", FILT_ID, filter_ids[0]); 00747 cpl_propertylist_delete(tmp_header); tmp_header = NULL; 00748 00749 desc2 = kmo_identify_fits_header(cpl_frame_get_filename(frame)); 00750 KMO_TRY_CHECK_ERROR_STATE(); 00751 00752 KMO_TRY_ASSURE((desc2.nr_ext == 1) && (desc2.fits_type == f2l_fits), 00753 CPL_ERROR_ILLEGAL_INPUT, "ARC_LIST has wrong format"); 00754 kmo_free_fits_desc(&desc2); 00755 kmo_init_fits_desc(&desc2); 00756 00757 KMO_TRY_EXIT_IF_NULL( 00758 arclines = kmo_dfs_load_table(frameset, ARC_LIST, 1, 0)); 00759 00760 KMO_TRY_EXIT_IF_NULL(lines = kmo_get_lines(arclines, lamp_config)); 00761 00762 cpl_msg_info(__func__, 00763 "Nr. of lines in arclist for this configuration: %lld", 00764 cpl_bivector_get_size(lines)); 00765 00766 if (line_estimate_method == 2) { 00767 KMO_TRY_EXIT_IF_NULL( 00768 reflines = kmo_dfs_load_table(frameset, REF_LINES, 1, 0)); 00769 } 00770 00771 /* check which IFUs are active for all FLAT frames */ 00772 KMO_TRY_EXIT_IF_NULL( 00773 unused_ifus_before = kmo_get_unused_ifus(frameset, 0, 0)); 00774 00775 KMO_TRY_EXIT_IF_NULL( 00776 unused_ifus_after = kmo_duplicate_unused_ifus(unused_ifus_before)); 00777 00778 kmo_print_unused_ifus(unused_ifus_before, FALSE); 00779 00780 /* make sure no reconstruction lookup table (LUT) is used */ 00781 if (getenv("KMCLIPM_PRIV_RECONSTRUCT_LUT_MODE") != NULL) { 00782 last_env = getenv("KMCLIPM_PRIV_RECONSTRUCT_LUT_MODE"); 00783 } 00784 setenv("KMCLIPM_PRIV_RECONSTRUCT_LUT_MODE","NONE",1); 00785 00786 /* loop all rotator angles and detectors */ 00787 for (a = 0; a < nr_angles; a++) { 00788 cpl_msg_info(__func__, 00789 "Processing rotator angle %d -> %d degree", 00790 a,rotang_found[a]); 00791 00792 for (i = 1; i <= nr_devices; i++) { 00793 // use loop below for line identification 00794 cpl_msg_info(__func__,"Processing detector No. %d", i); 00795 00796 int sx = a * nr_devices + (i - 1); 00797 00798 // load edge parameters 00799 KMO_TRY_EXIT_IF_NULL( 00800 frame = kmo_dfs_get_frame(frameset, FLAT_EDGE)); 00801 00802 for (j = 0; j < KMOS_IFUS_PER_DETECTOR; j++) { 00803 edge_table[i-1][j] = kmclipm_cal_table_load( 00804 cpl_frame_get_filename(frame), 00805 (i-1) * KMOS_IFUS_PER_DETECTOR + j + 1, 00806 rotang_found[a], 0, &angle_found); 00807 if (cpl_error_get_code() == CPL_ERROR_ILLEGAL_INPUT) { 00808 // IFU is inactive: proceed 00809 cpl_error_reset(); 00810 } 00811 } 00812 00813 if (fit_order_par == 0) { 00814 /* set default fit orders for the different bands */ 00815 if ((strcmp(filter_ids[i-1], "H") == 0) || 00816 (strcmp(filter_ids[i-1], "K") == 0) || 00817 (strcmp(filter_ids[i-1], "YJ") == 0)) 00818 { 00819 fit_order = 6; 00820 } else if (strcmp(filter_ids[i-1], "IZ") == 0) { 00821 fit_order = 4; 00822 } else if (strcmp(filter_ids[i-1], "HK") == 0) { 00823 fit_order = 5; 00824 } 00825 cpl_msg_info(__func__, 00826 "Order of wavelength spectrum fit for %s-band: %d", 00827 filter_ids[i-1], fit_order); 00828 } else { 00829 fit_order = fit_order_par; 00830 } 00831 00832 /* lamp_on */ 00833 KMO_TRY_EXIT_IF_NULL( 00834 frame = kmo_dfs_get_frame(angle_frameset[a], ARC_ON)); 00835 00836 /* if sat_mode is set to TRUE here, then the calc. of the */ 00837 /* saturated pixels has to be updated like in kmo_flat-recipe */ 00838 KMO_TRY_EXIT_IF_NULL( 00839 det_lamp_on = kmo_dfs_load_image_frame(frame, i, FALSE, 00840 TRUE, &nr_sat)); 00841 00842 /* count saturated pixels for each detector */ 00843 if (strcmp(cpl_propertylist_get_string(main_header, 00844 READMODE), "Nondest") == 0) { 00845 /* NDR: non-destructive readout mode */ 00846 stored_qc_arc_sat[sx] = nr_sat; 00847 } else { 00848 /* normal readout mode */ 00849 stored_qc_arc_sat[sx] = kmo_image_get_saturated( 00850 det_lamp_on, KMO_FLAT_SATURATED); 00851 } 00852 KMO_TRY_CHECK_ERROR_STATE(); 00853 00854 KMO_TRY_EXIT_IF_NULL( 00855 det_lamp_on_copy = cpl_image_duplicate(det_lamp_on)); 00856 00857 // lamp_off 00858 KMO_TRY_EXIT_IF_NULL( 00859 frame = kmo_dfs_get_frame(frameset, ARC_OFF)); 00860 00861 KMO_TRY_EXIT_IF_NULL( 00862 det_lamp_off = kmo_dfs_load_image_frame(frame, i, FALSE, 00863 FALSE, NULL)); 00864 00865 /* process imagelist */ 00866 KMO_TRY_CHECK_ERROR_STATE(); 00867 00868 /* subtract lamp_off from lamp_on */ 00869 KMO_TRY_EXIT_IF_ERROR( 00870 cpl_image_subtract(det_lamp_on, det_lamp_off)); 00871 00872 /* load flat calibration frames */ 00873 KMO_TRY_EXIT_IF_NULL( 00874 xcal = kmo_dfs_load_cal_image(frameset, XCAL, i, 0, 00875 (double)rotang_found[a], FALSE, NULL, &angle_found, -1, 00876 0, 0)); 00877 00878 KMO_TRY_EXIT_IF_NULL( 00879 ycal = kmo_dfs_load_cal_image(frameset, YCAL, i, 0, 00880 (double)rotang_found[a], FALSE, NULL, &angle_found, -1, 00881 0, 0)); 00882 00883 /* load bad pixel mask from XCAL and set NaNs to 0 */ 00884 /* and all other values to 1 */ 00885 KMO_TRY_EXIT_IF_NULL(bad_pix_mask = cpl_image_duplicate(xcal)); 00886 00887 KMO_TRY_EXIT_IF_NULL( 00888 pbad_pix_mask = cpl_image_get_data_float(bad_pix_mask)); 00889 for (x = 0; x < nx; x++) { 00890 for (y = 0; y < ny; y++) { 00891 if (isnan(pbad_pix_mask[x+nx*y])) { 00892 pbad_pix_mask[x+nx*y] = 0.; 00893 } else { 00894 pbad_pix_mask[x+nx*y] = 1.; 00895 } 00896 } 00897 } 00898 00899 /* calculate spectral curvature here */ 00900 err = kmo_calc_wave_calib(det_lamp_on, bad_pix_mask, xcal, 00901 ycal, filter_ids[i-1], lamp_config, i, 00902 unused_ifus_after[i-1], edge_table[i-1], lines, 00903 reflines, -1.0, &lcal, &(stored_qc_ar_eff[sx]), 00904 &(stored_qc_ne_eff[sx]), FALSE, fit_order, 00905 line_estimate_method); 00906 00907 if (err == CPL_ERROR_NONE) { 00908 // calculate QC parameters 00909 if (stored_qc_ar_eff[sx] != -1.0) { 00910 stored_qc_ar_eff[sx] /= exptime; 00911 } 00912 if (stored_qc_ne_eff[sx] != -1.0) { 00913 stored_qc_ne_eff[sx] /= exptime; 00914 } 00915 00916 /* apply the badpixel mask to the produced frame */ 00917 KMO_TRY_EXIT_IF_ERROR( 00918 cpl_image_multiply(lcal, bad_pix_mask)); 00919 00920 KMO_TRY_EXIT_IF_ERROR( 00921 kmo_image_reject_from_mask(lcal, bad_pix_mask)); 00922 00923 /* store flat frames, badpixel mask and calib frames */ 00924 stored_lcal[sx] = lcal; 00925 } else if (err == CPL_ERROR_UNSPECIFIED) { 00926 /* all IFUs seem to be deativated, continue processing */ 00927 /* just save empty frame */ 00928 cpl_error_reset(); 00929 stored_lcal[sx] = cpl_image_new(nx, ny, CPL_TYPE_FLOAT); 00930 kmo_image_fill(stored_lcal[sx], 0.0); 00931 } else { 00932 cpl_msg_warning(__func__, 00933 "Couldn't identify any line - Check the line list"); 00934 cpl_msg_warning(__func__, 00935 "Band defined in header of detector %d: %s", 00936 i, filter_ids[i-1]); 00937 cpl_msg_warning(__func__, "Arc line file defined: %s", 00938 cpl_frame_get_filename( 00939 kmo_dfs_get_frame(frameset, ARC_LIST))); 00940 cpl_error_reset(); 00941 } 00942 00943 /* create reconstructed and resampled arc frame */ 00944 stored_det_img[sx] = kmo_reconstructed_arc_image(frameset, 00945 det_lamp_on_copy, det_lamp_off, xcal, ycal, 00946 stored_lcal[sx], unused_ifus_after[i-1], FALSE, i, 00947 suffix, filter_ids[i-1], lamp_config, &qc_header); 00948 if (cpl_error_get_code() != CPL_ERROR_NONE) { 00949 /* couldn't reconstruct */ 00950 cpl_msg_error(__func__, 00951 "Couldn't reconstruct IFUs on detector %d", i); 00952 cpl_error_reset(); 00953 } 00954 00955 /* load and update sub_header with QC parameters */ 00956 KMO_TRY_EXIT_IF_NULL( 00957 stored_sub_headers_lcal[sx] = kmo_dfs_load_sub_header( 00958 frameset, ARC_ON, i, FALSE)); 00959 /* update EXTNAME */ 00960 KMO_TRY_EXIT_IF_NULL( 00961 extname = kmo_extname_creator(detector_frame, i, EXT_DATA)); 00962 KMO_TRY_EXIT_IF_ERROR( 00963 kmclipm_update_property_string(stored_sub_headers_lcal[sx], 00964 EXTNAME, extname, "FITS extension name")); 00965 cpl_free(extname); extname = NULL; 00966 00967 KMO_TRY_EXIT_IF_ERROR( 00968 kmclipm_update_property_int(stored_sub_headers_lcal[sx], 00969 EXTVER, sx+1, "FITS extension ver")); 00970 00971 // add first QC parameters 00972 KMO_TRY_EXIT_IF_ERROR( 00973 kmclipm_update_property_int(stored_sub_headers_lcal[sx], 00974 QC_ARC_SAT, stored_qc_arc_sat[sx], 00975 "[] nr. saturated pixels of arc exp.")); 00976 00977 gain = kmo_dfs_get_property_double(stored_sub_headers_lcal[sx], 00978 GAIN); 00979 KMO_TRY_CHECK_ERROR_STATE_MSG( 00980 "GAIN-keyword in fits-header is missing!"); 00981 00982 if (stored_qc_ar_eff[sx] != -1.0) { 00983 KMO_TRY_EXIT_IF_ERROR( 00984 kmclipm_update_property_double( 00985 stored_sub_headers_lcal[sx], QC_ARC_AR_EFF, 00986 stored_qc_ar_eff[sx]/gain, 00987 "[e-/s] Argon lamp efficiency")); 00988 } 00989 00990 if (stored_qc_ne_eff[sx] != -1.0) { 00991 KMO_TRY_EXIT_IF_ERROR( 00992 kmclipm_update_property_double( 00993 stored_sub_headers_lcal[sx], QC_ARC_NE_EFF, 00994 stored_qc_ne_eff[sx]/gain, 00995 "[e-/s] Neon lamp efficiency")); 00996 } 00997 00998 KMO_TRY_EXIT_IF_ERROR( 00999 kmclipm_update_property_double(stored_sub_headers_lcal[sx], 01000 CAL_ROTANGLE, ((double) rotang_found[a]), 01001 "[deg] Rotator relative to nasmyth")); 01002 01003 /* append QC parameters */ 01004 KMO_TRY_EXIT_IF_ERROR( 01005 cpl_propertylist_append(stored_sub_headers_lcal[sx], 01006 qc_header)); 01007 cpl_propertylist_delete(qc_header); qc_header = NULL; 01008 01009 KMO_TRY_EXIT_IF_NULL( 01010 stored_sub_headers_det_img[sx]=cpl_propertylist_duplicate( 01011 stored_sub_headers_lcal[sx])); 01012 01013 cpl_propertylist_erase(stored_sub_headers_lcal[sx], CRVAL1); 01014 cpl_propertylist_erase(stored_sub_headers_lcal[sx], CRVAL2); 01015 cpl_propertylist_erase(stored_sub_headers_lcal[sx], CTYPE1); 01016 cpl_propertylist_erase(stored_sub_headers_lcal[sx], CTYPE2); 01017 cpl_propertylist_erase(stored_sub_headers_lcal[sx], CDELT1); 01018 cpl_propertylist_erase(stored_sub_headers_lcal[sx], CDELT2); 01019 01020 /* free memory */ 01021 cpl_image_delete(det_lamp_on); det_lamp_on = NULL; 01022 cpl_image_delete(det_lamp_on_copy); det_lamp_on_copy = NULL; 01023 cpl_image_delete(det_lamp_off); det_lamp_off = NULL; 01024 cpl_image_delete(bad_pix_mask); bad_pix_mask = NULL; 01025 cpl_image_delete(xcal); xcal = NULL; 01026 cpl_image_delete(ycal); ycal = NULL; 01027 01028 for (j = 0; j < KMOS_IFUS_PER_DETECTOR; j++) { 01029 cpl_table_delete(edge_table[i-1][j]); 01030 edge_table[i-1][j] = NULL; 01031 } 01032 } // for i devices 01033 } // for a angles 01034 01035 if (line_estimate_method == 2) { 01036 cpl_table_delete(reflines); reflines = NULL; 01037 } 01038 01039 /* QC parameters & saving */ 01040 cpl_msg_info(__func__, "Saving data..."); 01041 01042 /* load, update & save primary header */ 01043 if (!suppress_extension) { 01044 KMO_TRY_EXIT_IF_NULL(fn_suffix = cpl_sprintf("%s", suffix)); 01045 } else { 01046 KMO_TRY_EXIT_IF_NULL(fn_suffix = cpl_sprintf("%s", "")); 01047 } 01048 01049 /* update which IFUs are not used */ 01050 KMO_TRY_EXIT_IF_ERROR( 01051 kmo_set_unused_ifus(unused_ifus_after, main_header, 01052 "kmo_wave_cal")); 01053 01054 KMO_TRY_EXIT_IF_NULL(frame = kmo_dfs_get_frame(frameset, ARC_ON)); 01055 01056 KMO_TRY_EXIT_IF_ERROR( 01057 kmo_dfs_save_main_header(frameset, filename_lcal, fn_suffix, frame, 01058 main_header, parlist, cpl_func)); 01059 01060 KMO_TRY_EXIT_IF_ERROR( 01061 kmo_dfs_save_main_header(frameset, filename_det_img, fn_suffix, 01062 frame, main_header, parlist, cpl_func)); 01063 01064 cpl_propertylist_delete(main_header); main_header = NULL; 01065 01066 /* save sub-frames */ 01067 for (a = 0; a < nr_angles; a++) { 01068 for (i = 1; i <= nr_devices; i++) { 01069 int sx = a * nr_devices + (i - 1); 01070 /* save lcal-frame */ 01071 KMO_TRY_EXIT_IF_ERROR( 01072 kmo_dfs_save_image(stored_lcal[sx], filename_lcal, 01073 fn_suffix, stored_sub_headers_lcal[sx], 0./0.)); 01074 01075 /* save detector image */ 01076 KMO_TRY_EXIT_IF_ERROR( 01077 kmo_dfs_save_image(stored_det_img[sx], filename_det_img, 01078 fn_suffix, stored_sub_headers_det_img[sx], 0./0.)); 01079 } // for i = nr_devices 01080 } // for a angles 01081 01082 /* print which IFUs are not used */ 01083 kmo_print_unused_ifus(unused_ifus_after, TRUE); 01084 } 01085 KMO_CATCH 01086 { 01087 KMO_CATCH_MSG(); 01088 ret_val = -1; 01089 } 01090 01091 if (last_env != NULL) { 01092 setenv("KMCLIPM_PRIV_RECONSTRUCT_LUT_MODE",last_env,1); 01093 } else { 01094 unsetenv("KMCLIPM_PRIV_RECONSTRUCT_LUT_MODE"); 01095 } 01096 01097 kmo_free_fits_desc(&desc1); 01098 kmo_free_fits_desc(&desc2); 01099 if (unused_ifus_before != NULL) { 01100 kmo_free_unused_ifus(unused_ifus_before); unused_ifus_before = NULL; 01101 } 01102 if (unused_ifus_after != NULL) { 01103 kmo_free_unused_ifus(unused_ifus_after); unused_ifus_after = NULL; 01104 } 01105 cpl_propertylist_delete(main_header); main_header = NULL; 01106 cpl_image_delete(det_lamp_on); det_lamp_on = NULL; 01107 cpl_image_delete(det_lamp_off); det_lamp_off = NULL; 01108 cpl_image_delete(bad_pix_mask); bad_pix_mask = NULL; 01109 cpl_table_delete(arclines); arclines = NULL; 01110 cpl_table_delete(reflines); reflines = NULL; 01111 cpl_free(stored_qc_arc_sat); stored_qc_arc_sat = NULL; 01112 cpl_free(stored_qc_ar_eff); stored_qc_ar_eff = NULL; 01113 cpl_free(stored_qc_ne_eff); stored_qc_ne_eff = NULL; 01114 for (i = 0; i < nr_devices * nr_angles; i++) { 01115 cpl_image_delete(stored_lcal[i]); stored_lcal[i] = NULL; 01116 cpl_image_delete(stored_det_img[i]); stored_det_img[i] = NULL; 01117 cpl_propertylist_delete(stored_sub_headers_lcal[i]); 01118 stored_sub_headers_lcal[i] = NULL; 01119 cpl_propertylist_delete(stored_sub_headers_det_img[i]); 01120 stored_sub_headers_det_img[i] = NULL; 01121 } 01122 for (i = 0; i < nr_angles; i++) { 01123 cpl_frameset_delete(angle_frameset[i]); angle_frameset[i] = NULL; 01124 } 01125 if (filter_ids != NULL) { 01126 for (i = 0; i < nr_devices; i++) { 01127 cpl_free(filter_ids[i]); filter_ids[i] = NULL; 01128 01129 } 01130 cpl_free(filter_ids); filter_ids = NULL; 01131 } 01132 if (edge_table != NULL) { 01133 for (i = 0; i < nr_devices; i++) { 01134 cpl_free(edge_table[i]); edge_table[i] = NULL; 01135 } 01136 cpl_free(edge_table); edge_table = NULL; 01137 } 01138 01139 cpl_free(angle_frameset); angle_frameset = NULL; 01140 cpl_free(stored_lcal); stored_lcal = NULL; 01141 cpl_free(stored_det_img); stored_det_img = NULL; 01142 cpl_free(stored_sub_headers_lcal); stored_sub_headers_lcal = NULL; 01143 cpl_free(stored_sub_headers_det_img); stored_sub_headers_det_img = NULL; 01144 cpl_free(readmode); readmode = NULL; 01145 cpl_bivector_delete(lines); lines = NULL; 01146 cpl_free(suffix); suffix = NULL; 01147 cpl_free(fn_suffix); fn_suffix = NULL; 01148 01149 return ret_val; 01150 } 01151