|
KMOS Pipeline Reference Manual
1.2.7
|
00001 /* $Id: kmo_flat.c,v 1.49 2013-09-20 13:10:47 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-09-20 13:10:47 $ 00024 * $Revision: 1.49 $ 00025 * $Name: not supported by cvs2svn $ 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 #include <cpl.h> 00039 00040 #include "kmo_utils.h" 00041 #include "kmo_priv_flat.h" 00042 #include "kmo_priv_functions.h" 00043 #include "kmo_dfs.h" 00044 #include "kmo_error.h" 00045 #include "kmo_constants.h" 00046 #include "kmo_cpl_extensions.h" 00047 #include "kmo_debug.h" 00048 00049 /*----------------------------------------------------------------------------- 00050 * Functions prototypes 00051 *----------------------------------------------------------------------------*/ 00052 00053 static int kmo_flat_create(cpl_plugin *); 00054 static int kmo_flat_exec(cpl_plugin *); 00055 static int kmo_flat_destroy(cpl_plugin *); 00056 static int kmo_flat(cpl_parameterlist *, cpl_frameset *); 00057 00058 /*----------------------------------------------------------------------------- 00059 * Static variables 00060 *----------------------------------------------------------------------------*/ 00061 00062 static char kmo_flat_description[15000] = 00063 "This recipe creates the master flat field and calibration frames needed for \n" 00064 "spatial calibration for all three detectors. It must be called after the \n" 00065 "kmo_dark-recipe, which generates a bad pixel mask (badpixel_dark.fits). The \n" 00066 "bad pixel mask will be updated in this recipe (goes into badpixel_flat.fits).\n" 00067 "As input at least 3 dark frames, 3 frames with the flat lamp on are recommen-\n" 00068 "ded. Additionally a badpixel mask from kmo_dark is required.\n" 00069 "\n" 00070 "The badpixel mask contains 0 for bad pixels and 1 for good ones.\n" 00071 "\n" 00072 "The structure of the resulting xcal and ycal frames is quite complex since the\n" 00073 "arrangement of the IFUs isn't just linear on the detector. Basically the inte-\n" 00074 "ger part of the calibration data shows the offset of each pixels centre in mas\n" 00075 "(Milli arcsec) from the field centre. The viewing of an IFU is 2800mas \n" 00076 "(14pix*0.2arcsec/pix). So the values in these two frames will vary between \n" 00077 "+/-1500 (One would expect 1400, but since the slitlets aren't expected to be \n" 00078 "exactly vertical, the values can even go up to around 1500). Additionally in \n" 00079 "the calibration data in y-direction the decimal part of the data designates \n" 00080 "the IFU to which the slitlet corresponds to (for each detector from 1 to 8).\n" 00081 "Because of the irregular arrangement of the IFUs not all x-direction calibra-\n" 00082 "tion data is found in xcal and similarly not all y-direction calibration data\n" 00083 "is located in ycal. For certain IFUs they are switched and/or flipped in x- or\n" 00084 "y-direction:\n" 00085 "For IFUs 1,2,3,4,13,14,15,16: x- and y- data is switched\n" 00086 "For IFUs 17,18,19,20: y-data is flipped \n" 00087 "For IFUs 21,22,23,24: x-data is flipped \n" 00088 "For IFUs 5,6,7,8,9,10,11,12: x- and y- data is switched and x- and \n" 00089 " y- data is flipped\n" 00090 "\n" 00091 "Furthermore frames can be provided for several rotator angles. In this case\n" 00092 "the resulting calibration frames for each detector are repeatedly saved as \n" 00093 "extension for every angle.\n" 00094 "\n" 00095 "Advanced features:\n" 00096 "------------------\n" 00097 "To create the badpixel mask the edges of all slitlets are fitted to a polyno-\n" 00098 "mial. Since it can happen that some of these fits (3 detectors * 8 IFUs * \n" 00099 "14slitlets * 2 edges (left and right edge of slitlet)= 672 edges) fail, the\n" 00100 "fit parameters are themselves fitted again to detect any outliers. By default\n" 00101 "the parameters of all left and all right edges are grouped individually and \n" 00102 "then fitted using chebyshev polynomials. The advantage of a chebyshev polyno-\n" 00103 "mial is, that it consists in fact of a series of orthogonal polynomials. This\n" 00104 "implies that the parameters of the polynomials are independent. This fact pre-\n" 00105 "destines the use of chebyshev polynomials for our case. So each individual pa-\n" 00106 "rameter can be examined independently. The reason why the left and right edges\n" 00107 "are fitted individually is that there is a systematic pattern specific to \n" 00108 "these groups. The reason for this pattern is probably to be found in the opti-\n" 00109 "cal path the light is traversing.\n" 00110 "\n" 00111 "The behaviour of this fitting step can be influenced via environment parameters:\n" 00112 "* KF_ALLPARS (default: 1)\n" 00113 " When set to 1 all coefficients of the polynomial of an edge are to be cor-\n" 00114 " rected, also when just one of these coefficients is an outlier. When set to\n" 00115 " 0 only the outlier is to be corrected.\n" 00116 "* KF_CH (default: 1)\n" 00117 " When set to 1 chebyshev polynomials are used to fit the fitted parameters.\n" 00118 " When set to 0 normal polynomials are used.\n" 00119 "* KF_SIDES (default: 2)\n" 00120 " This variable can either be set to 1 or 2. When set to 2 the left and right\n" 00121 " edges are examined individually. When set to 1 all edges are examined as one\n" 00122 " group.\n" 00123 "* KF_FACTOR(default: 4)\n" 00124 " This factor defines the threshold factor. All parameters deviating \n" 00125 " KF_FACTOR*stddev are to be corrected\n" 00126 "\n" 00127 "BASIC PARAMETERS:\n" 00128 "-----------------\n" 00129 "--badpix_thresh\n" 00130 "The threshold level to mark pixels as bad on the dark subtracted frames [%]" 00131 "\n" 00132 "--surrounding_pixels\n" 00133 "The amount of bad pixels to surround a specific pixel, to let it be marked\n" 00134 "bad as well.\n" 00135 "\n" 00136 "--cmethod\n" 00137 "Following methods of frame combination are available:\n" 00138 " * 'ksigma' (Default)\n" 00139 " An iterative sigma clipping. For each position all pixels in the spectrum\n" 00140 " are examined. If they deviate significantly, they will be rejected according\n" 00141 " to the conditions:\n" 00142 " val > mean + stdev * cpos_rej\n" 00143 " and\n" 00144 " val < mean - stdev * cneg_rej\n" 00145 " where --cpos_rej, --cneg_rej and --citer are the corresponding configuration\n" 00146 " parameters. In the first iteration median and percentile level are used.\n" 00147 "\n" 00148 " * 'median'\n" 00149 " At each pixel position the median is calculated.\n" 00150 "\n" 00151 " * 'average'\n" 00152 " At each pixel position the average is calculated.\n" 00153 "\n" 00154 " * 'sum'\n" 00155 " At each pixel position the sum is calculated.\n" 00156 "\n" 00157 " * 'min_max'\n" 00158 " The specified number of minimum and maximum pixel values will be rejected.\n" 00159 " --cmax and --cmin apply to this method.\n" 00160 "\n" 00161 "ADVANCED PARAMETERS\n" 00162 "-------------------\n" 00163 "--cpos_rej\n" 00164 "--cneg_rej\n" 00165 "--citer\n" 00166 "see --cmethod='ksigma'\n" 00167 "\n" 00168 "--cmax\n" 00169 "--cmin\n" 00170 "see --cmethod='min_max'\n" 00171 "\n" 00172 "--suppress_extension\n" 00173 "If set to TRUE, the arbitrary filename extensions are supressed. If multiple\n" 00174 "products with the same category are produced, they will be numered consecutively\n" 00175 "starting from 0.\n" 00176 "\n" 00177 "-------------------------------------------------------------------------------\n" 00178 " Input files:\n" 00179 "\n" 00180 " DO KMOS \n" 00181 " category Type Explanation Required #Frames\n" 00182 " -------- ----- ----------- -------- -------\n" 00183 " FLAT_ON RAW Flatlamp-on exposures Y 1-n \n" 00184 " (at least 3 frames recommended) \n" 00185 " FLAT_OFF RAW Flatlamp-off exposures Y 1-n \n" 00186 " (at least 3 frames recommended) \n" 00187 " BADPIXEL_DARK B2D Bad pixel mask Y 1 \n" 00188 "\n" 00189 " Output files:\n" 00190 "\n" 00191 " DO KMOS\n" 00192 " category Type Explanation\n" 00193 " -------- ----- -----------\n" 00194 " MASTER_FLAT F2D Normalised flat field\n" 00195 " (6 extensions: alternating data & noise\n" 00196 " BADPIXEL_FLAT B2D Updated bad pixel mask (3 Extensions)\n" 00197 " XCAL F2D Calibration frame 1 (3 Extensions)\n" 00198 " YCAL F2D Calibration frame 2 (3 Extensions)\n" 00199 " FLAT_EDGE F2L Frame containing parameters of fitted \n" 00200 " slitlets of all IFUs of all detectors\n" 00201 "-------------------------------------------------------------------------------" 00202 "\n"; 00203 00204 /*----------------------------------------------------------------------------- 00205 * Functions code 00206 *----------------------------------------------------------------------------*/ 00224 int cpl_plugin_get_info(cpl_pluginlist *list) 00225 { 00226 cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe); 00227 cpl_plugin *plugin = &recipe->interface; 00228 00229 cpl_plugin_init(plugin, 00230 CPL_PLUGIN_API, 00231 KMOS_BINARY_VERSION, 00232 CPL_PLUGIN_TYPE_RECIPE, 00233 "kmo_flat", 00234 "Create master flatfield frame and badpixel map to be " 00235 "used during science reduction", 00236 kmo_flat_description, 00237 "Alex Agudo Berbel", 00238 "kmos-spark@mpe.mpg.de", 00239 kmos_get_license(), 00240 kmo_flat_create, 00241 kmo_flat_exec, 00242 kmo_flat_destroy); 00243 00244 cpl_pluginlist_append(list, plugin); 00245 00246 return 0; 00247 } 00248 00256 static int kmo_flat_create(cpl_plugin *plugin) 00257 { 00258 cpl_recipe *recipe; 00259 cpl_parameter *p; 00260 00261 // Check that the plugin is part of a valid recipe 00262 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00263 recipe = (cpl_recipe *)plugin; 00264 else 00265 return -1; 00266 00267 // Create the parameters list in the cpl_recipe object 00268 recipe->parameters = cpl_parameterlist_new(); 00269 00270 // Fill the parameters list 00271 // --badpix_thresh 00272 p = cpl_parameter_new_value("kmos.kmo_flat.badpix_thresh", 00273 CPL_TYPE_INT, 00274 "The threshold level to mark pixels as bad on " 00275 "the dark subtracted frames [%].", 00276 "kmos.kmo_flat", 00277 35); 00278 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "badpix_thresh"); 00279 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00280 cpl_parameterlist_append(recipe->parameters, p); 00281 00282 // --surrounding_pixels 00283 p = cpl_parameter_new_value("kmos.kmo_flat.surrounding_pixels", 00284 CPL_TYPE_INT, 00285 "The amount of bad pixels to surround a specific " 00286 "pixel, to let it be marked bad as well.", 00287 "kmos.kmo_flat", 00288 5); 00289 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "surrounding_pixels"); 00290 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00291 cpl_parameterlist_append(recipe->parameters, p); 00292 00293 /* --suppress_extension */ 00294 p = cpl_parameter_new_value("kmos.kmo_flat.suppress_extension", 00295 CPL_TYPE_BOOL, 00296 "Suppress arbitrary filename extension." 00297 "(TRUE (apply) or FALSE (don't apply)", 00298 "kmos.kmo_flat", 00299 FALSE); 00300 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "suppress_extension"); 00301 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00302 cpl_parameterlist_append(recipe->parameters, p); 00303 00304 return kmo_combine_pars_create(recipe->parameters, 00305 "kmos.kmo_flat", 00306 DEF_REJ_METHOD, 00307 FALSE); 00308 } 00309 00315 static int kmo_flat_exec(cpl_plugin *plugin) 00316 { 00317 cpl_recipe *recipe; 00318 00319 // Get the recipe out of the plugin 00320 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00321 recipe = (cpl_recipe *)plugin; 00322 else return -1; 00323 00324 return kmo_flat(recipe->parameters, recipe->frames); 00325 } 00326 00332 static int kmo_flat_destroy(cpl_plugin *plugin) 00333 { 00334 cpl_recipe *recipe; 00335 00336 // Get the recipe out of the plugin 00337 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00338 recipe = (cpl_recipe *)plugin; 00339 else return -1 ; 00340 00341 cpl_parameterlist_delete(recipe->parameters); 00342 return 0 ; 00343 } 00344 00359 static int kmo_flat(cpl_parameterlist *parlist, cpl_frameset *frameset) 00360 { 00361 cpl_imagelist *det_lamp_on = NULL, 00362 *det_lamp_off = NULL; 00363 00364 cpl_image *img_in = NULL, 00365 *combined_data_on = NULL, 00366 *combined_noise_on = NULL, 00367 *combined_data_off = NULL, 00368 *combined_noise_off = NULL, 00369 *bad_pix_mask_flat = NULL, 00370 *bad_pix_mask_dark = NULL, 00371 *xcal = NULL, 00372 *ycal = NULL; 00373 00374 cpl_image **stored_flat = NULL, 00375 **stored_noise = NULL, 00376 **stored_badpix = NULL, 00377 **stored_xcal = NULL, 00378 **stored_ycal = NULL; 00379 00380 cpl_frame *frame = NULL; 00381 cpl_frameset ** angle_frameset = NULL; 00382 00383 int ret_val = 0, 00384 nr_devices = 0, 00385 sx = 0, 00386 cmax = 0, 00387 cmin = 0, 00388 citer = 0, 00389 surrounding_pixels = 0, 00390 badpix_thresh = 0, 00391 nx = 0, 00392 ny = 0, 00393 nz = 0, 00394 *stored_qc_flat_sat = NULL, 00395 *bounds = NULL, 00396 **total_bounds = NULL, 00397 // ***all_bounds = NULL, 00398 nr_bad_pix = 0, 00399 ndit = 0, 00400 suppress_extension = FALSE, 00401 nr_sat = 0, 00402 nr_angles = 0, 00403 i = 0, j = 0, ax = 0, a = 0; 00404 cpl_size ix = 0, iy = 0; 00405 00406 double cpos_rej = 0.0, 00407 cneg_rej = 0.0, 00408 gain = 0.0, 00409 exptime = 0.0, 00410 *stored_qc_flat_eff = NULL, 00411 *stored_qc_flat_sn = NULL, 00412 mean_data = 0.0, 00413 mean_noise = 0.0, 00414 *stored_gapmean = NULL, 00415 *stored_gapsdv = NULL, 00416 *stored_gapmaxdev = NULL, 00417 *stored_slitmean = NULL, 00418 *stored_slitsdv = NULL, 00419 *stored_slitmaxdev = NULL; 00420 00421 const char *cmethod = NULL; 00422 00423 char *extname = NULL, 00424 filename_flat[256], 00425 filename_xcal[256], 00426 filename_ycal[256], 00427 filename_bad[256], 00428 filename_edge[256], 00429 *suffix = NULL, 00430 *fn_suffix = NULL, 00431 *tmpstr = NULL, 00432 *readmode = NULL; 00433 00434 cpl_propertylist *main_header = NULL, 00435 *main_header_xcal = NULL, 00436 *sub_header = NULL; 00437 00438 cpl_table ***edge_table = NULL; 00439 00440 main_fits_desc desc1, desc2; 00441 00442 cpl_array **unused_ifus_before = NULL, 00443 **unused_ifus_after = NULL; 00444 00445 cpl_error_code *spec_found = NULL; 00446 00447 char *fn_flat = "flat_tmp.fits", 00448 *fn_noise = "flat_noise_tmp.fits", 00449 *fn_badpix = "badpix_tmp.fits"; 00450 unsigned int save_mode = CPL_IO_CREATE; // at first files must be created 00451 00452 KMO_TRY 00453 { 00454 00455 kmo_init_fits_desc(&desc1); 00456 kmo_init_fits_desc(&desc2); 00457 00458 // ############################################################################# 00459 // ### check inputs 00460 // ############################################################################# 00461 KMO_TRY_ASSURE((parlist != NULL) && 00462 (frameset != NULL), 00463 CPL_ERROR_NULL_INPUT, 00464 "Not all input data is provided!"); 00465 00466 KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, FLAT_OFF) >= 1, 00467 CPL_ERROR_NULL_INPUT, 00468 "At least 1 FLAT_OFF frame must be provided (3 or more " 00469 "recommended)!"); 00470 00471 KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, FLAT_ON) >= 1, 00472 CPL_ERROR_NULL_INPUT, 00473 "At least 1 FLAT_ON frame must be provided (3 or more " 00474 "recommended)!"); 00475 00476 if (cpl_frameset_count_tags(frameset, FLAT_OFF) < 3) { 00477 cpl_msg_warning(cpl_func, "It is recommended to provide at least " 00478 "3 FLAT_OFF frames (Generated noise frames" 00479 " will not be very representative)!"); 00480 } 00481 00482 if (cpl_frameset_count_tags(frameset, FLAT_ON) < 3) { 00483 cpl_msg_warning(cpl_func, "It is recommended to provide at least " 00484 "3 FLAT_ON frames (Generated noise frames" 00485 " will not be very representative)!"); 00486 } 00487 00488 KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, BADPIXEL_DARK) == 1, 00489 CPL_ERROR_NULL_INPUT, 00490 "A BADPIXEL_DARK frame must be provided!"); 00491 00492 KMO_TRY_ASSURE(kmo_dfs_set_groups(frameset, "kmo_flat") == 1, 00493 CPL_ERROR_ILLEGAL_INPUT, 00494 "Cannot identify RAW and CALIB frames!"); 00495 00496 00497 // 00498 // ------------ get parameters ------------ 00499 // 00500 cpl_msg_info("", "--- Parameter setup for kmo_flat ----------"); 00501 00502 surrounding_pixels = kmo_dfs_get_parameter_int(parlist, 00503 "kmos.kmo_flat.surrounding_pixels"); 00504 KMO_TRY_CHECK_ERROR_STATE(); 00505 KMO_TRY_EXIT_IF_ERROR( 00506 kmo_dfs_print_parameter_help(parlist, 00507 "kmos.kmo_flat.surrounding_pixels")); 00508 00509 badpix_thresh = kmo_dfs_get_parameter_int(parlist, 00510 "kmos.kmo_flat.badpix_thresh"); 00511 KMO_TRY_CHECK_ERROR_STATE(); 00512 KMO_TRY_EXIT_IF_ERROR( 00513 kmo_dfs_print_parameter_help(parlist, 00514 "kmos.kmo_flat.badpix_thresh")); 00515 00516 suppress_extension = kmo_dfs_get_parameter_bool(parlist, 00517 "kmos.kmo_flat.suppress_extension"); 00518 KMO_TRY_CHECK_ERROR_STATE(); 00519 KMO_TRY_EXIT_IF_ERROR( 00520 kmo_dfs_print_parameter_help(parlist, "kmos.kmo_flat.suppress_extension")); 00521 00522 KMO_TRY_ASSURE((suppress_extension == TRUE) || (suppress_extension == FALSE), 00523 CPL_ERROR_ILLEGAL_INPUT, 00524 "suppress_extension must be TRUE or FALSE!"); 00525 00526 KMO_TRY_EXIT_IF_ERROR( 00527 kmo_combine_pars_load(parlist, "kmos.kmo_flat", &cmethod, &cpos_rej, 00528 &cneg_rej, &citer, &cmin, &cmax, 00529 FALSE)); 00530 00531 cpl_msg_info("", "-------------------------------------------"); 00532 00533 // check BADPIXEL_DARK 00534 KMO_TRY_EXIT_IF_NULL( 00535 frame = kmo_dfs_get_frame(frameset, BADPIXEL_DARK)); 00536 00537 desc2 = kmo_identify_fits_header( 00538 cpl_frame_get_filename(frame)); 00539 KMO_TRY_CHECK_ERROR_STATE(); 00540 00541 KMO_TRY_ASSURE((desc2.nr_ext == 3) && 00542 (desc2.ex_badpix == TRUE) && 00543 (desc2.fits_type == b2d_fits) && 00544 (desc2.frame_type == detector_frame), 00545 CPL_ERROR_ILLEGAL_INPUT, 00546 "BADPIXEL_DARK isn't in the correct format!!!"); 00547 00548 nx = desc2.naxis1; 00549 ny = desc2.naxis2; 00550 nz = desc2.naxis3; 00551 00552 KMO_TRY_ASSURE((surrounding_pixels >= 0) && (surrounding_pixels <= 8), 00553 CPL_ERROR_ILLEGAL_INPUT, 00554 "surrounding_pixels must be between 0 and 8!"); 00555 00556 KMO_TRY_ASSURE((badpix_thresh >= 0) && (badpix_thresh <= 100), 00557 CPL_ERROR_ILLEGAL_INPUT, 00558 "badpix_thresh must be between 0 and 100%%!"); 00559 00560 // 00561 // ------------ check EXPTIME, NDIT, READMODE and lamps ------------ 00562 // EXPTIME, NDIT, READMODE: the same for all frames 00563 // lamps: at least 3 lamp on and 3 lamp off frames 00564 // 00565 KMO_TRY_EXIT_IF_NULL( 00566 frame = kmo_dfs_get_frame(frameset, FLAT_OFF)); 00567 00568 KMO_TRY_EXIT_IF_NULL( 00569 main_header = kmclipm_propertylist_load( 00570 cpl_frame_get_filename(frame), 0)); 00571 00572 ndit = cpl_propertylist_get_int(main_header, NDIT); 00573 KMO_TRY_CHECK_ERROR_STATE("NDIT keyword in main header " 00574 "missing!"); 00575 00576 exptime = cpl_propertylist_get_double(main_header, EXPTIME); 00577 KMO_TRY_CHECK_ERROR_STATE("EXPTIME keyword in main header " 00578 "missing!"); 00579 00580 readmode = cpl_strdup(cpl_propertylist_get_string(main_header, READMODE)); 00581 KMO_TRY_CHECK_ERROR_STATE("ESO DET READ CURNAME keyword in main " 00582 "header missing!"); 00583 00584 cpl_propertylist_delete(main_header); main_header = NULL; 00585 00586 while (frame != NULL) { 00587 KMO_TRY_EXIT_IF_NULL( 00588 main_header = kmclipm_propertylist_load( 00589 cpl_frame_get_filename(frame), 0)); 00590 00591 KMO_TRY_ASSURE(cpl_propertylist_get_int(main_header, NDIT) == ndit, 00592 CPL_ERROR_ILLEGAL_INPUT, 00593 "NDIT isn't the same for all frames: (is %d and %d).", 00594 cpl_propertylist_get_int(main_header, NDIT), ndit); 00595 00596 KMO_TRY_ASSURE(cpl_propertylist_get_double(main_header, EXPTIME) == exptime, 00597 CPL_ERROR_ILLEGAL_INPUT, 00598 "EXPTIME isn't the same for all frames: (is %g and %g).", 00599 cpl_propertylist_get_double(main_header, EXPTIME), exptime); 00600 00601 KMO_TRY_ASSURE(strcmp(cpl_propertylist_get_string(main_header, READMODE), readmode) == 0, 00602 CPL_ERROR_ILLEGAL_INPUT, 00603 "ESO DET READ CURNAME isn't the same for all frames: (is %s and %s).", 00604 cpl_propertylist_get_string(main_header, READMODE), readmode); 00605 00606 desc1 = kmo_identify_fits_header( 00607 cpl_frame_get_filename(frame)); 00608 KMO_TRY_CHECK_ERROR_STATE_MSG( 00609 cpl_sprintf("File (%s) doesn't seem to be in KMOS-format!", 00610 cpl_frame_get_filename(frame))); 00611 00612 KMO_TRY_ASSURE(desc1.fits_type == raw_fits, 00613 CPL_ERROR_ILLEGAL_INPUT, 00614 "File hasn't correct data type " 00615 "(%s must be a raw, unprocessed file)!", 00616 cpl_frame_get_filename(frame)); 00617 00618 KMO_TRY_ASSURE((desc1.naxis1 == nx) && 00619 (desc1.naxis2 == ny) && 00620 (desc1.naxis3 == nz), 00621 CPL_ERROR_ILLEGAL_INPUT, 00622 "File (%s) hasn't correct dimensions! (x,y): " 00623 "(%d,%d) vs (%d,%d)", 00624 cpl_frame_get_filename(frame), 00625 desc1.naxis1, desc1.naxis2, nx, ny); 00626 00627 // assure that arc lamps are off 00628 KMO_TRY_ASSURE((kmo_check_lamp(main_header, INS_LAMP1_ST) == FALSE) && 00629 (kmo_check_lamp(main_header, INS_LAMP2_ST) == FALSE), 00630 CPL_ERROR_ILLEGAL_INPUT, 00631 "Arc lamps must be switched off (%s)!", 00632 cpl_frame_get_filename(frame)); 00633 00634 // check if flat lamps are off 00635 if ((kmo_check_lamp(main_header, INS_LAMP3_ST) == TRUE) || 00636 (kmo_check_lamp(main_header, INS_LAMP4_ST) == TRUE)) 00637 { 00638 if (!(strcmp(cpl_propertylist_get_string(main_header, "ESO INS FILT1 ID"), "Block") == 0) || 00639 !(strcmp(cpl_propertylist_get_string(main_header, "ESO INS FILT2 ID"), "Block") == 0) || 00640 !(strcmp(cpl_propertylist_get_string(main_header, "ESO INS FILT3 ID"), "Block") == 0)) 00641 { 00642 cpl_msg_warning("","At least one flat lamp is on! Check if the lamps are blocked!"); 00643 } 00644 } 00645 00646 kmo_free_fits_desc(&desc1); 00647 00648 // get next FLAT_OFF frame 00649 frame = kmo_dfs_get_frame(frameset, NULL); 00650 KMO_TRY_CHECK_ERROR_STATE(); 00651 00652 cpl_propertylist_delete(main_header); main_header = NULL; 00653 } 00654 00655 KMO_TRY_EXIT_IF_NULL( 00656 frame = kmo_dfs_get_frame(frameset, FLAT_ON)); 00657 00658 // uncomment this if these keywords can be different for FLAT_OFF and FLAT_ON 00659 // KMO_TRY_EXIT_IF_NULL( 00660 // main_header = kmclipm_propertylist_load( 00661 // cpl_frame_get_filename(frame), 0)); 00662 // ndit = cpl_propertylist_get_int(main_header, NDIT); 00663 // KMO_TRY_CHECK_ERROR_STATE("NDIT keyword in main header " 00664 // "missing!"); 00665 // exptime = cpl_propertylist_get_double(main_header, EXPTIME); 00666 // KMO_TRY_CHECK_ERROR_STATE("EXPTIME keyword in main header " 00667 // "missing!"); 00668 00669 // readmode = cpl_propertylist_get_string(main_header, READMODE); 00670 // KMO_TRY_CHECK_ERROR_STATE("ESO DET READ CURNAME keyword in main " 00671 // "header missing!"); 00672 00673 // cpl_propertylist_delete(main_header); main_header = NULL; 00674 00675 while (frame != NULL) { 00676 KMO_TRY_EXIT_IF_NULL( 00677 main_header = kmclipm_propertylist_load( 00678 cpl_frame_get_filename(frame), 0)); 00679 00680 KMO_TRY_ASSURE(cpl_propertylist_get_int(main_header, NDIT) == ndit, 00681 CPL_ERROR_ILLEGAL_INPUT, 00682 "NDIT isn't the same for all frames: (is %d and %d).", 00683 cpl_propertylist_get_int(main_header, NDIT), ndit); 00684 00685 KMO_TRY_ASSURE(cpl_propertylist_get_double(main_header, EXPTIME) == exptime, 00686 CPL_ERROR_ILLEGAL_INPUT, 00687 "EXPTIME isn't the same for all frames: (is %g and %g).", 00688 cpl_propertylist_get_double(main_header, EXPTIME), exptime); 00689 00690 KMO_TRY_ASSURE(strcmp(cpl_propertylist_get_string(main_header, READMODE), readmode) == 0, 00691 CPL_ERROR_ILLEGAL_INPUT, 00692 "ESO DET READ CURNAME isn't the same for all frames: (is %s and %s).", 00693 cpl_propertylist_get_string(main_header, READMODE), readmode); 00694 00695 desc1 = kmo_identify_fits_header( 00696 cpl_frame_get_filename(frame)); 00697 KMO_TRY_CHECK_ERROR_STATE_MSG( 00698 cpl_sprintf("File (%s) doesn't seem to be in KMOS-format!", 00699 cpl_frame_get_filename(frame))); 00700 00701 KMO_TRY_ASSURE(desc1.fits_type == raw_fits, 00702 CPL_ERROR_ILLEGAL_INPUT, 00703 "File hasn't correct data type " 00704 "(%s must be a raw, unprocessed file)!", 00705 cpl_frame_get_filename(frame)); 00706 00707 KMO_TRY_ASSURE((desc1.naxis1 == nx) && 00708 (desc1.naxis2 == ny) && 00709 (desc1.naxis3 == nz), 00710 CPL_ERROR_ILLEGAL_INPUT, 00711 "File (%s) hasn't correct dimensions! (x,y): " 00712 "(%d,%d) vs (%d,%d)", 00713 cpl_frame_get_filename(frame), 00714 desc1.naxis1, desc1.naxis2, nx, ny); 00715 00716 // assure that arc lamps are off 00717 KMO_TRY_ASSURE((kmo_check_lamp(main_header, INS_LAMP1_ST) == FALSE) && 00718 (kmo_check_lamp(main_header, INS_LAMP2_ST) == FALSE), 00719 CPL_ERROR_ILLEGAL_INPUT, 00720 "Arc lamps must be switched off (%s)!", 00721 cpl_frame_get_filename(frame)); 00722 00723 // assure that at least one flat lamp is on 00724 KMO_TRY_ASSURE((kmo_check_lamp(main_header, INS_LAMP3_ST) == TRUE) || 00725 (kmo_check_lamp(main_header, INS_LAMP4_ST) == TRUE), 00726 CPL_ERROR_ILLEGAL_INPUT, 00727 "At least one flat lamps must be switched on (%s)!", 00728 cpl_frame_get_filename(frame)); 00729 00730 kmo_free_fits_desc(&desc1); 00731 00732 // get next FLAT_ON frame 00733 frame = kmo_dfs_get_frame(frameset, NULL); 00734 KMO_TRY_CHECK_ERROR_STATE(); 00735 00736 cpl_propertylist_delete(main_header); main_header = NULL; 00737 } 00738 00739 // 00740 // ------------ check filter_id, grating_id and rotator offset --------- 00741 // must match for all detectors 00742 // 00743 KMO_TRY_EXIT_IF_ERROR( 00744 kmo_check_frameset_setup(frameset, FLAT_ON, 00745 TRUE, FALSE, FALSE)); 00746 00747 strcpy(filename_flat, MASTER_FLAT); 00748 strcpy(filename_bad, BADPIXEL_FLAT); 00749 strcpy(filename_xcal, XCAL); 00750 strcpy(filename_ycal, YCAL); 00751 strcpy(filename_edge, FLAT_EDGE); 00752 00753 KMO_TRY_EXIT_IF_NULL( 00754 frame = kmo_dfs_get_frame(frameset, FLAT_ON)); 00755 KMO_TRY_EXIT_IF_NULL( 00756 suffix = kmo_dfs_get_suffix(frame, TRUE, FALSE)); 00757 00758 cpl_msg_info("", "Detected instrument setup: %s", suffix+1); 00759 cpl_msg_info("", "(grating 1, 2 & 3)"); 00760 00761 // 00762 // ---- scan for rotator angles 00763 // 00764 #define ANGLE_DIM 360 00765 int rotang_found[ANGLE_DIM]; 00766 int rotang_cnt[ANGLE_DIM]; 00767 for (i = 0; i < ANGLE_DIM; i++) { 00768 rotang_found[i] = 0; 00769 rotang_cnt[i] = 0; 00770 } 00771 KMO_TRY_EXIT_IF_NULL( 00772 frame = kmo_dfs_get_frame(frameset, FLAT_ON)); 00773 while (frame != NULL) { 00774 main_header = kmclipm_propertylist_load(cpl_frame_get_filename(frame), 0); 00775 if (cpl_propertylist_has(main_header, ROTANGLE)) { 00776 int rot_angle = (int) rint(cpl_propertylist_get_double(main_header, ROTANGLE)); 00777 if (rot_angle < 0) { 00778 rot_angle += 360; 00779 } 00780 if (rot_angle < 360 && rot_angle >= 0) { 00781 rotang_cnt[rot_angle]++; 00782 // char * tag = cpl_sprintf("FLAT_ON_%3.3d",rot_angle); 00783 // KMO_TRY_EXIT_IF_ERROR( 00784 // cpl_frame_set_tag(frame, tag)); 00785 // cpl_free(tag); 00786 } 00787 } else { 00788 cpl_msg_warning("","File %s has no keyword \"ROTANGLE\"", 00789 cpl_frame_get_filename(frame)); 00790 } 00791 00792 cpl_propertylist_delete(main_header); main_header = NULL; 00793 frame = kmo_dfs_get_frame(frameset, NULL); 00794 KMO_TRY_CHECK_ERROR_STATE(); 00795 } 00796 nr_angles = 0; 00797 for (ax = 0; ax < ANGLE_DIM; ax++) { 00798 if (rotang_cnt[ax] != 0) { 00799 // if (rotang_cnt[ax] >=3) { 00800 cpl_msg_info("","Found %d frames with rotator angle %d",rotang_cnt[ax],ax); 00801 rotang_found[nr_angles] = ax; 00802 nr_angles++; 00803 // } else { 00804 // cpl_msg_warning("","Found %d frames with rotator angle %d but at least three are required", 00805 // rotang_cnt[ax],ax); 00806 // } 00807 } 00808 } 00809 00810 KMO_TRY_EXIT_IF_NULL ( 00811 angle_frameset = (cpl_frameset **) cpl_malloc(nr_angles * sizeof(cpl_frameset*))); 00812 for (i = 0; i < nr_angles; i++) { 00813 angle_frameset[i] = cpl_frameset_new(); 00814 } 00815 00816 KMO_TRY_EXIT_IF_NULL( 00817 frame = kmo_dfs_get_frame(frameset, FLAT_ON)); 00818 while (frame != NULL) { 00819 main_header = kmclipm_propertylist_load(cpl_frame_get_filename(frame), 0); 00820 if (cpl_propertylist_has(main_header, ROTANGLE)) { 00821 int rot_angle = (int) rint(cpl_propertylist_get_double(main_header, ROTANGLE)); 00822 if (rot_angle < 0) { 00823 rot_angle += 360; 00824 } 00825 int ix = -1; 00826 for (ix = 0; ix<nr_angles; ix++) { 00827 if (rotang_found[ix] == rot_angle) { 00828 break; 00829 } 00830 } 00831 if (ix<nr_angles) { 00832 KMO_TRY_EXIT_IF_ERROR( 00833 cpl_frameset_insert(angle_frameset[ix], cpl_frame_duplicate(frame))); 00834 } 00835 } 00836 00837 cpl_propertylist_delete(main_header); main_header = NULL; 00838 frame = kmo_dfs_get_frame(frameset, NULL); 00839 KMO_TRY_CHECK_ERROR_STATE(); 00840 } 00841 00842 00843 // ############################################################################# 00844 // ### allocate temporary memory 00845 // ############################################################################# 00846 // load descriptor and header of first operand 00847 KMO_TRY_EXIT_IF_NULL( 00848 frame = kmo_dfs_get_frame(frameset, FLAT_ON)); 00849 00850 desc1 = kmo_identify_fits_header(cpl_frame_get_filename(frame)); 00851 KMO_TRY_CHECK_ERROR_STATE(); 00852 00853 nr_devices = desc1.nr_ext; 00854 00855 // the frames have to be stored temporarily because the QC parameters 00856 // for the main header are calculated from each detector. So they can be 00857 // stored only when all detectors are processed 00858 KMO_TRY_EXIT_IF_NULL( 00859 stored_flat = (cpl_image**)cpl_calloc(nr_devices * nr_angles, 00860 sizeof(cpl_image*))); 00861 KMO_TRY_EXIT_IF_NULL( 00862 stored_noise = (cpl_image**)cpl_calloc(nr_devices * nr_angles, 00863 sizeof(cpl_image*))); 00864 KMO_TRY_EXIT_IF_NULL( 00865 stored_badpix = (cpl_image**)cpl_calloc(nr_devices * nr_angles, 00866 sizeof(cpl_image*))); 00867 KMO_TRY_EXIT_IF_NULL( 00868 stored_xcal = (cpl_image**)cpl_calloc(nr_devices * nr_angles, 00869 sizeof(cpl_image*))); 00870 KMO_TRY_EXIT_IF_NULL( 00871 stored_ycal = (cpl_image**)cpl_calloc(nr_devices * nr_angles, 00872 sizeof(cpl_image*))); 00873 KMO_TRY_EXIT_IF_NULL( 00874 stored_qc_flat_sat = (int*)cpl_malloc(nr_devices * nr_angles * 00875 sizeof(int))); 00876 KMO_TRY_EXIT_IF_NULL( 00877 stored_qc_flat_eff = (double*)cpl_malloc(nr_devices * nr_angles * 00878 sizeof(double))); 00879 KMO_TRY_EXIT_IF_NULL( 00880 stored_qc_flat_sn = (double*)cpl_malloc(nr_devices * nr_angles * 00881 sizeof(double))); 00882 KMO_TRY_EXIT_IF_NULL( 00883 stored_gapmean = (double*)cpl_malloc(nr_devices * nr_angles * 00884 sizeof(double))); 00885 KMO_TRY_EXIT_IF_NULL( 00886 stored_gapsdv = (double*)cpl_malloc(nr_devices * nr_angles * 00887 sizeof(double))); 00888 KMO_TRY_EXIT_IF_NULL( 00889 stored_gapmaxdev = (double*)cpl_malloc(nr_devices * nr_angles * 00890 sizeof(double))); 00891 KMO_TRY_EXIT_IF_NULL( 00892 stored_slitmean = (double*)cpl_malloc(nr_devices * nr_angles * 00893 sizeof(double))); 00894 KMO_TRY_EXIT_IF_NULL( 00895 stored_slitsdv = (double*)cpl_malloc(nr_devices * nr_angles * 00896 sizeof(double))); 00897 KMO_TRY_EXIT_IF_NULL( 00898 stored_slitmaxdev = (double*)cpl_malloc(nr_devices * nr_angles * 00899 sizeof(double))); 00900 KMO_TRY_EXIT_IF_NULL( 00901 spec_found = (cpl_error_code*)cpl_malloc(nr_devices * nr_angles * 00902 sizeof(cpl_error_code))); 00903 KMO_TRY_EXIT_IF_NULL( 00904 edge_table = (cpl_table***)cpl_malloc(KMOS_NR_DETECTORS * nr_angles * 00905 sizeof(cpl_table**))); 00906 00907 // initialize to NULL 00908 for (i = 0; i < nr_devices * nr_angles ; i++) { 00909 stored_qc_flat_sat[i] = 0.0; 00910 stored_qc_flat_eff[i] = 0.0; 00911 stored_qc_flat_sn[i] = 0.0; 00912 stored_gapmean[i] = 0.0; 00913 stored_gapsdv[i] = 0.0; 00914 stored_gapmaxdev[i] = 0.0; 00915 stored_slitmean[i] = 0.0; 00916 stored_slitsdv[i] = 0.0; 00917 stored_slitmaxdev[i] = 0.0; 00918 spec_found[i] = CPL_ERROR_NONE; 00919 } 00920 00921 for (i = 0; i < KMOS_NR_DETECTORS * nr_angles; i++) { 00922 edge_table[i] = NULL; 00923 } 00924 00925 // ############################################################################# 00926 // ### process data 00927 // ############################################################################# 00928 00929 // check which IFUs are active for all FLAT_ON frames 00930 KMO_TRY_EXIT_IF_NULL( 00931 unused_ifus_before = kmo_get_unused_ifus(frameset, 0, 0)); 00932 00933 KMO_TRY_EXIT_IF_NULL( 00934 unused_ifus_after = kmo_duplicate_unused_ifus(unused_ifus_before)); 00935 00936 kmo_print_unused_ifus(unused_ifus_before, FALSE); 00937 00938 cpl_msg_info("", "EXPTIME: %g seconds", exptime); 00939 cpl_msg_info("", "NDIT: %d", ndit); 00940 cpl_msg_info("", "Detector readout mode: %s", readmode); 00941 cpl_msg_info("", "-------------------------------------------"); 00942 00943 // 00944 // ------------ loop all rotator angles and detectors ------------ 00945 // 00946 00947 for (a = 0; a < nr_angles; a++) { 00948 cpl_msg_info("","Processing rotator angle %d -> %d degree", a, rotang_found[a]); 00949 for (i = 1; i <= nr_devices; i++) { 00950 cpl_msg_info("","Processing detector No. %d", i); 00951 00952 sx = a * nr_devices + (i - 1); 00953 00954 KMO_TRY_EXIT_IF_NULL( 00955 bad_pix_mask_dark = kmo_dfs_load_image(frameset, BADPIXEL_DARK, 00956 i, 2, FALSE, NULL)); 00957 00958 // 00959 // ------------ load all lamp_on and lamp_off images ------------ 00960 // 00961 KMO_TRY_EXIT_IF_NULL( 00962 det_lamp_on = cpl_imagelist_new()); 00963 KMO_TRY_EXIT_IF_NULL( 00964 det_lamp_off = cpl_imagelist_new()); 00965 00966 // load lamp-on images 00967 KMO_TRY_EXIT_IF_NULL( 00968 frame = kmo_dfs_get_frame(angle_frameset[a], FLAT_ON)); 00969 j = 0; 00970 while (frame != NULL) { 00971 KMO_TRY_EXIT_IF_NULL( 00972 img_in = kmo_dfs_load_image_frame(frame, i, FALSE, TRUE, &nr_sat)); 00973 00974 KMO_TRY_EXIT_IF_ERROR( 00975 kmo_image_reject_from_mask(img_in, bad_pix_mask_dark)); 00976 00977 cpl_imagelist_set(det_lamp_on, img_in, j++); 00978 KMO_TRY_CHECK_ERROR_STATE(); 00979 00980 frame = kmo_dfs_get_frame(angle_frameset[a], NULL); 00981 KMO_TRY_CHECK_ERROR_STATE(); 00982 } 00983 00984 // load lamp-off images 00985 KMO_TRY_EXIT_IF_NULL( 00986 frame = kmo_dfs_get_frame(frameset, FLAT_OFF)); 00987 j = 0; 00988 while (frame != NULL) { 00989 KMO_TRY_EXIT_IF_NULL( 00990 img_in = kmo_dfs_load_image_frame(frame, i, FALSE, FALSE, NULL)); 00991 00992 KMO_TRY_EXIT_IF_ERROR( 00993 kmo_image_reject_from_mask(img_in, bad_pix_mask_dark)); 00994 00995 cpl_imagelist_set(det_lamp_off, img_in, j++); 00996 KMO_TRY_CHECK_ERROR_STATE(); 00997 00998 // get next frame 00999 frame = kmo_dfs_get_frame(frameset, NULL); 01000 KMO_TRY_CHECK_ERROR_STATE(); 01001 } 01002 01003 // 01004 // ------------ process imagelist ------------ 01005 // 01006 01007 // count saturated pixels for each detector 01008 KMO_TRY_EXIT_IF_NULL( 01009 frame = kmo_dfs_get_frame(angle_frameset[a], FLAT_ON)); 01010 KMO_TRY_EXIT_IF_NULL( 01011 main_header = kmclipm_propertylist_load( 01012 cpl_frame_get_filename(frame), 0)); 01013 if (strcmp(cpl_propertylist_get_string(main_header, READMODE), "Nondest") == 0) { 01014 // NDR: non-destructive readout mode 01015 stored_qc_flat_sat[sx] = nr_sat; 01016 } else { 01017 // normal readout mode 01018 stored_qc_flat_sat[sx] = 01019 kmo_imagelist_get_saturated(det_lamp_on, 01020 KMO_FLAT_SATURATED, 01021 KMO_FLAT_SAT_MIN); 01022 } 01023 cpl_propertylist_delete(main_header); main_header = NULL; 01024 KMO_TRY_CHECK_ERROR_STATE(); 01025 01026 // combine imagelists and create noise 01027 KMO_TRY_EXIT_IF_ERROR( 01028 kmclipm_combine_frames(det_lamp_on, NULL, 01029 NULL, 01030 cmethod, cpos_rej, cneg_rej, citer, 01031 cmax, cmin, 01032 &combined_data_on, 01033 &combined_noise_on, 01034 -1.0)); 01035 01036 KMO_TRY_EXIT_IF_ERROR( 01037 kmclipm_combine_frames(det_lamp_off, NULL, 01038 NULL, 01039 cmethod, cpos_rej, cneg_rej, citer, 01040 cmax, cmin, 01041 &combined_data_off, 01042 &combined_noise_off, 01043 -1.0)); 01044 01045 if (kmclipm_omit_warning_one_slice > 10) { 01046 // AA: commmented this out: Too unclear for the user, no benefit to know about this number 01047 // cpl_msg_warning(cpl_func, "Previous warning (number of " 01048 // "identified slices) occured %d times.", 01049 // kmclipm_omit_warning_one_slice); 01050 kmclipm_omit_warning_one_slice = FALSE; 01051 } 01052 01053 // subtract combined lamp_off from lamp_on 01054 // (for noise: sig_x = sqrt(sig_u^2 + sig_v^2) 01055 KMO_TRY_EXIT_IF_ERROR( 01056 cpl_image_subtract(combined_data_on, combined_data_off)); 01057 01058 KMO_TRY_EXIT_IF_ERROR( 01059 cpl_image_power(combined_noise_on, 2.0)); 01060 KMO_TRY_EXIT_IF_ERROR( 01061 cpl_image_power(combined_noise_off, 2.0)); 01062 KMO_TRY_EXIT_IF_ERROR( 01063 cpl_image_add(combined_noise_on, combined_noise_off)); 01064 KMO_TRY_EXIT_IF_ERROR( 01065 cpl_image_power(combined_noise_on, 0.5)); 01066 01067 // create bad-pixel-mask 01068 KMO_TRY_EXIT_IF_NULL( 01069 bad_pix_mask_flat = kmo_create_bad_pix_flat_thresh( 01070 combined_data_on, 01071 surrounding_pixels, 01072 badpix_thresh)); 01073 01074 // calculate spectral curvature here 01075 spec_found[sx] = kmo_calc_curvature(combined_data_on, 01076 combined_noise_on, 01077 unused_ifus_after[i-1], 01078 bad_pix_mask_flat, 01079 i, 01080 &xcal, 01081 &ycal, 01082 stored_gapmean+(sx), 01083 stored_gapsdv+(sx), 01084 stored_gapmaxdev+(sx), 01085 stored_slitmean+(sx), 01086 stored_slitsdv+(sx), 01087 stored_slitmaxdev+(sx), 01088 &edge_table[sx]); 01089 01090 if (spec_found[sx] == CPL_ERROR_NONE) { 01091 // all fine 01092 01093 // in kmo_calc_curvature() the spectral slope of each slitlet 01094 // has been normalised individually. Now the normalisation on 01095 // the whole frame is applied. (cpl_image_get_mean() 01096 // ignores bad pixels when calculating the mean) 01097 mean_data = cpl_image_get_mean(combined_data_on); 01098 KMO_TRY_CHECK_ERROR_STATE(); 01099 01100 stored_qc_flat_eff[sx] = mean_data / exptime; 01101 01102 mean_noise = cpl_image_get_mean(combined_noise_on); 01103 KMO_TRY_CHECK_ERROR_STATE(); 01104 01105 if ((cpl_frameset_count_tags(frameset, FLAT_OFF) > 1) || 01106 (cpl_frameset_count_tags(frameset, FLAT_ON) > 1)) 01107 { 01108 KMO_TRY_ASSURE(mean_noise != 0.0, 01109 CPL_ERROR_ILLEGAL_INPUT, 01110 "All frames of detector %i are exactly " 01111 "the same!", i); 01112 01113 stored_qc_flat_sn[sx] = mean_data / mean_noise; 01114 } 01115 01116 // normalize data & noise on the whole detector frame (the 01117 // spectral slope on each slitlet has already been normalised in 01118 // kmo_calc_curvature()) 01119 KMO_TRY_EXIT_IF_ERROR( 01120 cpl_image_divide_scalar(combined_data_on, mean_data)); 01121 01122 KMO_TRY_EXIT_IF_ERROR( 01123 cpl_image_divide_scalar(combined_noise_on, mean_data)); 01124 01125 // apply the badpixel mask to the produced frames 01126 KMO_TRY_EXIT_IF_ERROR( 01127 cpl_image_multiply(combined_data_on, bad_pix_mask_flat)); 01128 01129 KMO_TRY_EXIT_IF_ERROR( 01130 cpl_image_multiply(combined_noise_on, bad_pix_mask_flat)); 01131 01132 KMO_TRY_EXIT_IF_ERROR( 01133 cpl_image_multiply(xcal, bad_pix_mask_flat)); 01134 01135 KMO_TRY_EXIT_IF_ERROR( 01136 cpl_image_multiply(ycal, bad_pix_mask_flat)); 01137 01138 // 01139 // ------ store temporarily flat, badpixel and calibration ----- 01140 // 01141 stored_flat[sx] = combined_data_on; 01142 stored_noise[sx] = combined_noise_on; 01143 stored_badpix[sx] = bad_pix_mask_flat; 01144 stored_xcal[sx] = xcal; 01145 stored_ycal[sx] = ycal; 01146 } else if (spec_found[sx] == CPL_ERROR_DATA_NOT_FOUND) { 01147 // all IFUs seem to be deativated, continue processing 01148 // just save empty frames 01149 cpl_error_reset(); 01150 01151 cpl_image_delete(combined_data_on); combined_data_on = NULL; 01152 cpl_image_delete(combined_noise_on); combined_noise_on = NULL; 01153 cpl_image_delete(bad_pix_mask_flat); bad_pix_mask_flat = NULL; 01154 01155 KMO_TRY_EXIT_IF_NULL( 01156 stored_flat[sx] = cpl_image_new(nx, ny, CPL_TYPE_FLOAT)); 01157 for(ix = 1; ix <= nx; ix++) { 01158 for(iy = 1; iy <= ny; iy++) { 01159 cpl_image_reject(stored_flat[sx], ix, iy); 01160 } 01161 } 01162 KMO_TRY_CHECK_ERROR_STATE(); 01163 01164 KMO_TRY_EXIT_IF_NULL( 01165 stored_noise[sx] = cpl_image_duplicate(stored_flat[sx])); 01166 KMO_TRY_EXIT_IF_NULL( 01167 stored_xcal[sx] = cpl_image_duplicate(stored_flat[sx])); 01168 KMO_TRY_EXIT_IF_NULL( 01169 stored_ycal[sx] = cpl_image_duplicate(stored_flat[sx])); 01170 KMO_TRY_EXIT_IF_NULL( 01171 stored_badpix[sx] = cpl_image_new(nx, ny, CPL_TYPE_FLOAT)); 01172 } else { 01173 // another error occured 01174 KMO_TRY_CHECK_ERROR_STATE(); 01175 } 01176 01177 // store immediate results, free memory 01178 KMO_TRY_EXIT_IF_ERROR( 01179 kmclipm_image_save(stored_flat[sx], fn_flat, 01180 CPL_TYPE_FLOAT, NULL, save_mode, 0./0.)); 01181 KMO_TRY_EXIT_IF_ERROR( 01182 kmclipm_image_save(stored_noise[sx], fn_noise, 01183 CPL_TYPE_FLOAT, NULL, save_mode, 0./0.)); 01184 KMO_TRY_EXIT_IF_ERROR( 01185 kmclipm_image_save(stored_badpix[sx], fn_badpix, 01186 CPL_TYPE_FLOAT, NULL, save_mode, 0./0.)); 01187 save_mode = CPL_IO_EXTEND; //all other saves will create extensions 01188 cpl_image_delete(stored_flat[sx]); stored_flat[sx] = NULL; 01189 cpl_image_delete(stored_noise[sx]); stored_noise[sx] = NULL; 01190 cpl_image_delete(stored_badpix[sx]); stored_badpix[sx] = NULL; 01191 01192 // free memory 01193 cpl_imagelist_delete(det_lamp_on); det_lamp_on = NULL; 01194 cpl_imagelist_delete(det_lamp_off); det_lamp_off = NULL; 01195 cpl_image_delete(combined_data_off); combined_data_off = NULL; 01196 cpl_image_delete(combined_noise_off); combined_noise_off = NULL; 01197 cpl_image_delete(bad_pix_mask_dark); bad_pix_mask_dark = NULL; 01198 } // for i = 1; i <= nr_devices 01199 } // for a = 0; a < nr_angles 01200 KMO_TRY_CHECK_ERROR_STATE(); 01201 01202 // ############################################################################# 01203 // ### QC parameters & saving 01204 // ############################################################################# 01205 // 01206 // ------------ load, update & save primary header ------------ 01207 // 01208 KMO_TRY_EXIT_IF_NULL( 01209 main_header = kmo_dfs_load_primary_header(frameset, FLAT_ON)); 01210 01211 // update which IFUs are not used 01212 kmo_print_unused_ifus(unused_ifus_after, TRUE); 01213 01214 KMO_TRY_EXIT_IF_ERROR( 01215 kmo_set_unused_ifus(unused_ifus_after, main_header, "kmo_flat")); 01216 01217 // write main_header for data-, noise-, ycal- and badpix-frame 01218 // xcal gets additionally the boundaries of the IFUs for reconstruction 01219 01220 // add here boundaries for reconstruction 01221 KMO_TRY_EXIT_IF_NULL( 01222 main_header_xcal = cpl_propertylist_new()); 01223 01224 KMO_TRY_EXIT_IF_NULL( 01225 total_bounds = (int**)cpl_malloc(nr_devices*sizeof(int*))); 01226 for (i = 0; i < nr_devices; i++) { 01227 KMO_TRY_EXIT_IF_NULL( 01228 total_bounds[i] = (int*) cpl_calloc(2*KMOS_IFUS_PER_DETECTOR,sizeof(int))); 01229 for (j = 0; j < KMOS_IFUS_PER_DETECTOR; j++) { 01230 total_bounds[i][2*j] = 2048; 01231 total_bounds[i][2*j+1] = 0; 01232 } 01233 } 01234 KMO_TRY_CHECK_ERROR_STATE(); 01235 01236 // KMO_TRY_EXIT_IF_NULL( 01237 // all_bounds = (int***) cpl_malloc(nr_angles*sizeof(int**))); 01238 // for (a = 0; a < nr_angles; a++) { 01239 // KMO_TRY_EXIT_IF_NULL( 01240 // all_bounds[a] = (int**) cpl_malloc(nr_devices*sizeof(int*))); 01241 // for (i = 0; i < nr_devices; i++) { 01242 // KMO_TRY_EXIT_IF_NULL( 01243 // all_bounds[a][i] = (int*) cpl_calloc(2*KMOS_IFUS_PER_DETECTOR,sizeof(int))); 01244 // } 01245 // } 01246 KMO_TRY_CHECK_ERROR_STATE(); 01247 01248 // 01249 // store the min left bound and max right bound for all angles 01250 // 01251 for (a = 0; a < nr_angles; a++) { 01252 for (i = 0; i < nr_devices; i++) { 01253 sx = a * nr_devices + i; 01254 if (stored_ycal[sx] != NULL) { 01255 KMO_TRY_EXIT_IF_NULL( 01256 bounds = kmo_split_frame(stored_ycal[sx])); 01257 01258 for (j = 0; j < KMOS_IFUS_PER_DETECTOR; j++) { 01259 // all_bounds[a][i][2*j] = bounds[2*j]; 01260 // all_bounds[a][i][2*j+1] = bounds[2*j+1]; 01261 01262 01263 if ((total_bounds[i][2*j] == -1) || (bounds[2*j] == -1)) { 01264 total_bounds[i][2*j] = -1; 01265 } else { 01266 if (total_bounds[i][2*j] > bounds[2*j]) { 01267 total_bounds[i][2*j] = bounds[2*j]; 01268 } 01269 } 01270 01271 if ((total_bounds[i][2*j+1] == -1) || (bounds[2*j+1] == -1)) { 01272 total_bounds[i][2*j+1] = -1; 01273 } else { 01274 if (total_bounds[i][2*j+1] < bounds[2*j+1]) { 01275 total_bounds[i][2*j+1] = bounds[2*j+1]; 01276 } 01277 } 01278 01279 // if (total_bounds[i][2*j] >= 0 ) { 01280 // if (bounds[2*j] < 0) { 01281 // total_bounds[i][2*j] = bounds[2*j]; 01282 // } else { 01283 // if (total_bounds[i][2*j] > bounds[2*j]) { 01284 // total_bounds[i][2*j] = bounds[2*j]; 01285 // } 01286 // } 01287 // } 01288 // if (total_bounds[i][2*j+1] >= 0 ) { 01289 // if (bounds[2*j+1] < 0) { 01290 // total_bounds[i][2*j+1] = bounds[2*j+1]; 01291 // } else { 01292 // if (total_bounds[i][2*j+1] < bounds[2*j+1]) { 01293 // total_bounds[i][2*j+1] = bounds[2*j+1]; 01294 // } 01295 // } 01296 // } 01297 } 01298 } else { 01299 // whole detector inactive 01300 for (j = 0; j < KMOS_IFUS_PER_DETECTOR; j++) { 01301 // all_bounds[a][i][2*j] = -1; 01302 // all_bounds[a][i][2*j+1] = -1; 01303 total_bounds[i][2*j] = -1; 01304 total_bounds[i][2*j+1] = -1; 01305 } 01306 } 01307 if (bounds != NULL) { 01308 cpl_free(bounds); bounds = NULL; 01309 } 01310 } // for (nr_devices) 01311 } // for (nr_angles) 01312 01313 // 01314 // write the min left bound and max right bound for all angles 01315 // into the main header 01316 // 01317 for (i = 0; i < nr_devices; i++) { 01318 for (j = 0; j < KMOS_IFUS_PER_DETECTOR; j++) { 01319 if (total_bounds[i][2*j] > -1) { 01320 KMO_TRY_EXIT_IF_NULL( 01321 tmpstr= cpl_sprintf("%s%d%s", 01322 BOUNDS_PREFIX, 01323 i*KMOS_IFUS_PER_DETECTOR + j+1, 01324 "_L")); 01325 KMO_TRY_EXIT_IF_ERROR( 01326 kmclipm_update_property_int(main_header_xcal, 01327 tmpstr, total_bounds[i][2*j], 01328 "[pix] left boundary for reconstr.")); 01329 cpl_free(tmpstr); tmpstr = NULL; 01330 } 01331 01332 if (total_bounds[i][2*j+1] > -1) { 01333 KMO_TRY_EXIT_IF_NULL( 01334 tmpstr= cpl_sprintf("%s%d%s", 01335 BOUNDS_PREFIX, 01336 i*KMOS_IFUS_PER_DETECTOR + j+1, 01337 "_R")); 01338 KMO_TRY_EXIT_IF_ERROR( 01339 kmclipm_update_property_int(main_header_xcal, 01340 tmpstr, total_bounds[i][2*j+1], 01341 "[pix] right boundary for reconstr.")); 01342 cpl_free(tmpstr); tmpstr = NULL; 01343 } 01344 } 01345 } // for (nr_devices) 01346 01347 // 01348 // ------------ saving headers ------------ 01349 // 01350 if (!suppress_extension) { 01351 KMO_TRY_EXIT_IF_NULL( 01352 fn_suffix = cpl_sprintf("%s", suffix)); 01353 } else { 01354 KMO_TRY_EXIT_IF_NULL( 01355 fn_suffix = cpl_sprintf("%s", "")); 01356 } 01357 01358 cpl_msg_info("","Saving data..."); 01359 01360 KMO_TRY_EXIT_IF_NULL( 01361 frame = kmo_dfs_get_frame(frameset, FLAT_ON)); 01362 01363 KMO_TRY_EXIT_IF_ERROR( 01364 kmo_dfs_save_main_header(frameset, filename_flat, fn_suffix, frame, 01365 main_header, parlist, cpl_func)); 01366 KMO_TRY_EXIT_IF_ERROR( 01367 kmo_dfs_save_main_header(frameset, filename_xcal, fn_suffix, frame, 01368 main_header_xcal, parlist, cpl_func)); 01369 KMO_TRY_EXIT_IF_ERROR( 01370 kmo_dfs_save_main_header(frameset, filename_ycal, fn_suffix, frame, 01371 main_header, parlist, cpl_func)); 01372 KMO_TRY_EXIT_IF_ERROR( 01373 kmo_dfs_save_main_header(frameset, filename_bad, fn_suffix, frame, 01374 main_header, parlist, cpl_func)); 01375 KMO_TRY_EXIT_IF_ERROR( 01376 kmo_dfs_save_main_header(frameset, filename_edge, fn_suffix, frame, 01377 main_header, parlist, cpl_func)); 01378 01379 cpl_propertylist_delete(main_header); main_header = NULL; 01380 cpl_propertylist_delete(main_header_xcal); main_header_xcal = NULL; 01381 01382 // 01383 // ------------ saving sub frames ------------ 01384 // 01385 for (a = 0; a < nr_angles; a++) { 01386 for (i = 1; i <= nr_devices; i++) { 01387 sx = a * nr_devices + (i - 1); 01388 01389 // load stored data again 01390 KMO_TRY_EXIT_IF_NULL( 01391 stored_flat[sx] = kmclipm_image_load(fn_flat, 01392 CPL_TYPE_FLOAT, 0, sx)); 01393 KMO_TRY_EXIT_IF_NULL( 01394 stored_noise[sx] = kmclipm_image_load(fn_noise, 01395 CPL_TYPE_FLOAT, 0, sx)); 01396 KMO_TRY_EXIT_IF_NULL( 01397 stored_badpix[sx] = kmclipm_image_load(fn_badpix, 01398 CPL_TYPE_FLOAT, 0, sx)); 01399 01400 KMO_TRY_EXIT_IF_NULL( 01401 sub_header = kmo_dfs_load_sub_header(frameset, FLAT_ON, i, 01402 FALSE)); 01403 // leave keywords in for proper fitsverify output 01404 // cpl_propertylist_erase(sub_header, CRPIX1); 01405 // cpl_propertylist_erase(sub_header, CRPIX2); 01406 01407 KMO_TRY_EXIT_IF_ERROR( 01408 kmclipm_update_property_double(sub_header,CAL_ROTANGLE, 01409 ((double) rotang_found[a]), 01410 "[deg] Rotator relative to nasmyth")); 01411 01412 // AA: commented this out: not needed for the moment. Additionally there were only 01413 // 34 values saved instead of 48?!? 01414 // And sometimes the keyword was named IFU-2_L instead of IFU2_L ?!? 01415 // // write BOUNDS as well into subheaders 01416 // if (i == 1) { 01417 // for (ii = 0; ii < nr_devices; ii++) { 01418 // for (j = 0; j < KMOS_IFUS_PER_DETECTOR; j++) { 01419 // if (all_bounds[a][ii][2*j] > -1) { 01420 // KMO_TRY_EXIT_IF_NULL( 01421 // tmpstr= cpl_sprintf("%s%d%s", 01422 // BOUNDS_PREFIX, 01423 // ii*KMOS_IFUS_PER_DETECTOR + j+1, 01424 // "_L")); 01425 // KMO_TRY_EXIT_IF_ERROR( 01426 // kmclipm_update_property_int(sub_header, 01427 // tmpstr, all_bounds[a][ii][2*j], 01428 // "[pix] left boundary for reconstr.")); 01429 // cpl_free(tmpstr); tmpstr = NULL; 01430 // } 01431 // 01432 // if (all_bounds[a][ii][2*j+1] > -1) { 01433 // KMO_TRY_EXIT_IF_NULL( 01434 // tmpstr= cpl_sprintf("%s%d%s", 01435 // BOUNDS_PREFIX, 01436 // ii-1*KMOS_IFUS_PER_DETECTOR + j+1, 01437 // "_R")); 01438 // KMO_TRY_EXIT_IF_ERROR( 01439 // kmclipm_update_property_int(sub_header, 01440 // tmpstr, all_bounds[a][ii][2*j+1], 01441 // "[pix] right boundary for reconstr.")); 01442 // cpl_free(tmpstr); tmpstr = NULL; 01443 // } 01444 // } 01445 // } // for (nr_devices) 01446 // } 01447 01448 if (spec_found[sx] == CPL_ERROR_NONE) { 01449 KMO_TRY_EXIT_IF_ERROR( 01450 kmclipm_update_property_int(sub_header, 01451 QC_FLAT_SAT, 01452 stored_qc_flat_sat[sx], 01453 "[] nr. saturated pixels of master flat")); 01454 // load gain 01455 gain = kmo_dfs_get_property_double(sub_header, GAIN); 01456 KMO_TRY_CHECK_ERROR_STATE_MSG( 01457 "GAIN-keyword in fits-header is missing!"); 01458 01459 KMO_TRY_EXIT_IF_ERROR( 01460 kmclipm_update_property_double(sub_header, 01461 QC_FLAT_EFF, 01462 stored_qc_flat_eff[sx]/gain, 01463 "[e-/s] rel. brightness of flat lamp")); 01464 KMO_TRY_EXIT_IF_ERROR( 01465 kmclipm_update_property_double(sub_header, 01466 QC_FLAT_SN, 01467 stored_qc_flat_sn[sx], 01468 "[] S/N of master flat")); 01469 } 01470 01471 // store qc parameters only if any slitlet- and gap-width has been 01472 // detected (should be the case when at least one IFU is active) 01473 if (stored_xcal[sx] != NULL) { 01474 KMO_TRY_EXIT_IF_ERROR( 01475 kmclipm_update_property_double(sub_header, 01476 QC_GAP_MEAN, 01477 stored_gapmean[sx], 01478 "[pix] mean gap width between slitlets")); 01479 KMO_TRY_EXIT_IF_ERROR( 01480 kmclipm_update_property_double(sub_header, 01481 QC_GAP_SDV, 01482 stored_gapsdv[sx], 01483 "[pix] stdev of gap width between slitlets")); 01484 KMO_TRY_EXIT_IF_ERROR( 01485 kmclipm_update_property_double(sub_header, 01486 QC_GAP_MAXDEV, 01487 stored_gapmaxdev[sx], 01488 "[pix] max gap deviation between slitlets")); 01489 KMO_TRY_EXIT_IF_ERROR( 01490 kmclipm_update_property_double(sub_header, 01491 QC_SLIT_MEAN, 01492 stored_slitmean[sx], 01493 "[pix] mean slitlet width")); 01494 KMO_TRY_EXIT_IF_ERROR( 01495 kmclipm_update_property_double(sub_header, 01496 QC_SLIT_SDV, 01497 stored_slitsdv[sx], 01498 "[pix] stdev of slitlet widths")); 01499 KMO_TRY_EXIT_IF_ERROR( 01500 kmclipm_update_property_double(sub_header, 01501 QC_SLIT_MAXDEV, 01502 stored_slitmaxdev[sx], 01503 "[pix] max slitlet width deviation")); 01504 } 01505 01506 // calculate QC.BADPIX.NCOUNT 01507 nr_bad_pix = cpl_image_count_rejected(stored_badpix[sx]); 01508 KMO_TRY_CHECK_ERROR_STATE(); 01509 01510 // remove 4pixel-border as bad pixels 01511 nr_bad_pix -= 2*KMOS_BADPIX_BORDER*(nx-2*KMOS_BADPIX_BORDER) + 01512 2*KMOS_BADPIX_BORDER*ny; 01513 01514 KMO_TRY_EXIT_IF_ERROR( 01515 kmclipm_update_property_int(sub_header, 01516 QC_NR_BAD_PIX, 01517 nr_bad_pix, 01518 "[] nr. of bad pixels")); 01519 // save flat frame 01520 KMO_TRY_EXIT_IF_NULL( 01521 extname = kmo_extname_creator(detector_frame, i, EXT_DATA)); 01522 KMO_TRY_EXIT_IF_ERROR( 01523 kmclipm_update_property_string(sub_header, EXTNAME, 01524 extname, 01525 "FITS extension name")); 01526 cpl_free(extname); extname = NULL; 01527 01528 KMO_TRY_EXIT_IF_ERROR( 01529 kmclipm_update_property_int(sub_header, 01530 EXTVER, 01531 sx+1, 01532 "FITS extension ver")); 01533 01534 KMO_TRY_EXIT_IF_ERROR( 01535 kmo_dfs_save_image(stored_flat[sx], filename_flat, 01536 fn_suffix, sub_header, 0./0.)); 01537 01538 // save noise frame only when enough input frames were available 01539 KMO_TRY_EXIT_IF_NULL( 01540 extname = kmo_extname_creator(detector_frame, i, 01541 EXT_NOISE)); 01542 KMO_TRY_EXIT_IF_ERROR( 01543 kmclipm_update_property_string(sub_header, EXTNAME, 01544 extname, 01545 "FITS extension name")); 01546 cpl_free(extname); extname = NULL; 01547 01548 KMO_TRY_EXIT_IF_ERROR( 01549 kmo_dfs_save_image(stored_noise[sx], filename_flat, 01550 fn_suffix, sub_header, 0./0.)); 01551 01552 // save bad_pix frame 01553 KMO_TRY_EXIT_IF_NULL( 01554 extname = kmo_extname_creator(detector_frame, i, EXT_BADPIX)); 01555 KMO_TRY_EXIT_IF_ERROR( 01556 kmclipm_update_property_string(sub_header, EXTNAME, 01557 extname, 01558 "FITS extension name")); 01559 cpl_free(extname); extname = NULL; 01560 01561 KMO_TRY_EXIT_IF_ERROR( 01562 kmo_dfs_save_image(stored_badpix[sx], filename_bad, 01563 fn_suffix, sub_header, 0.)); 01564 01565 // save xcal and ycal-frame 01566 KMO_TRY_EXIT_IF_NULL( 01567 extname = kmo_extname_creator(detector_frame, i, EXT_DATA)); 01568 KMO_TRY_EXIT_IF_ERROR( 01569 kmclipm_update_property_string(sub_header, EXTNAME, 01570 extname, 01571 "FITS extension name")); 01572 cpl_free(extname); extname = NULL; 01573 01574 KMO_TRY_EXIT_IF_ERROR( 01575 kmo_dfs_save_image(stored_xcal[sx], filename_xcal, 01576 fn_suffix, sub_header, 0./0.)); 01577 01578 KMO_TRY_EXIT_IF_ERROR( 01579 kmo_dfs_save_image(stored_ycal[sx], filename_ycal, 01580 fn_suffix, sub_header, 0./0.)); 01581 01582 // save edge_pars-frame 01583 cpl_free(extname); extname = NULL; 01584 01585 for (j = 0; j < KMOS_IFUS_PER_DETECTOR; j++) { 01586 KMO_TRY_EXIT_IF_NULL( 01587 extname = cpl_sprintf("%s_IFU.%d_ANGLE.%d", 01588 EXT_LIST, 01589 j+1+(i-1)*KMOS_IFUS_PER_DETECTOR, 01590 rotang_found[a])); 01591 KMO_TRY_EXIT_IF_ERROR( 01592 kmclipm_update_property_string(sub_header, EXTNAME, 01593 extname, 01594 "FITS extension name")); 01595 cpl_free(extname); extname = NULL; 01596 01597 KMO_TRY_EXIT_IF_ERROR( 01598 kmclipm_update_property_int(sub_header, CAL_IFU_NR, 01599 j+1+(i-1)*KMOS_IFUS_PER_DETECTOR, 01600 "IFU Number {1..24}")); 01601 01602 // save edge-parameters as product 01603 if ((spec_found[sx] != CPL_ERROR_DATA_NOT_FOUND) && (edge_table[sx][j] != NULL)) { 01604 KMO_TRY_EXIT_IF_ERROR( 01605 kmo_dfs_save_table(edge_table[sx][j], filename_edge, fn_suffix, sub_header)); 01606 } else { 01607 cpl_propertylist_erase(sub_header, CRVAL1); 01608 cpl_propertylist_erase(sub_header, CRVAL2); 01609 cpl_propertylist_erase(sub_header, CD1_1); 01610 cpl_propertylist_erase(sub_header, CD1_2); 01611 cpl_propertylist_erase(sub_header, CD2_1); 01612 cpl_propertylist_erase(sub_header, CD2_2); 01613 cpl_propertylist_erase(sub_header, CRPIX1); 01614 cpl_propertylist_erase(sub_header, CRPIX2); 01615 cpl_propertylist_erase(sub_header, CTYPE1); 01616 cpl_propertylist_erase(sub_header, CTYPE2); 01617 KMO_TRY_CHECK_ERROR_STATE(); 01618 01619 KMO_TRY_EXIT_IF_ERROR( 01620 kmo_dfs_save_table(NULL, filename_edge, fn_suffix, sub_header)); 01621 } 01622 } 01623 01624 cpl_propertylist_delete(sub_header); sub_header = NULL; 01625 01626 cpl_image_delete(stored_flat[sx]); stored_flat[sx] = NULL; 01627 cpl_image_delete(stored_noise[sx]); stored_noise[sx] = NULL; 01628 cpl_image_delete(stored_badpix[sx]); stored_badpix[sx] = NULL; 01629 } // for (i = nr_devices) 01630 } // for (a = nr_angles) 01631 } 01632 KMO_CATCH 01633 { 01634 KMO_CATCH_MSG(); 01635 ret_val = -1; 01636 } 01637 // delete temporary files 01638 unlink(fn_flat); 01639 unlink(fn_noise); 01640 unlink(fn_badpix); 01641 01642 kmo_free_fits_desc(&desc1); 01643 kmo_free_fits_desc(&desc2); 01644 kmo_free_unused_ifus(unused_ifus_before); unused_ifus_before = NULL; 01645 kmo_free_unused_ifus(unused_ifus_after); unused_ifus_after = NULL; 01646 cpl_propertylist_delete(main_header); main_header = NULL; 01647 cpl_propertylist_delete(main_header_xcal); main_header_xcal = NULL; 01648 cpl_propertylist_delete(sub_header); sub_header = NULL; 01649 cpl_imagelist_delete(det_lamp_on); det_lamp_on = NULL; 01650 cpl_imagelist_delete(det_lamp_off); det_lamp_off = NULL; 01651 cpl_image_delete(combined_data_off); combined_data_off = NULL; 01652 cpl_image_delete(combined_noise_off); combined_noise_off = NULL; 01653 cpl_image_delete(bad_pix_mask_dark); bad_pix_mask_dark = NULL; 01654 cpl_free(stored_qc_flat_sat); stored_qc_flat_sat = NULL; 01655 cpl_free(stored_qc_flat_eff); stored_qc_flat_eff = NULL; 01656 cpl_free(stored_qc_flat_sn); stored_qc_flat_sn = NULL; 01657 cpl_free(stored_gapmean); stored_gapmean = NULL; 01658 cpl_free(stored_gapsdv); stored_gapsdv = NULL; 01659 cpl_free(stored_gapmaxdev); stored_gapmaxdev = NULL; 01660 cpl_free(stored_slitmean); stored_slitmean = NULL; 01661 cpl_free(stored_slitsdv); stored_slitsdv = NULL; 01662 cpl_free(stored_slitmaxdev); stored_slitmaxdev = NULL; 01663 cpl_free(readmode); readmode = NULL; 01664 cpl_free(suffix); suffix = NULL; 01665 cpl_free(fn_suffix); fn_suffix = NULL; 01666 if (total_bounds != NULL) { 01667 for (i = 0; i < nr_devices; i++) { 01668 cpl_free(total_bounds[i]); total_bounds[i] = NULL; 01669 } 01670 } 01671 cpl_free(total_bounds); total_bounds = NULL; 01672 for (i = 0; i < nr_devices * nr_angles; i++) { 01673 cpl_image_delete(stored_flat[i]); stored_flat[i] = NULL; 01674 cpl_image_delete(stored_noise[i]); stored_noise[i] = NULL; 01675 cpl_image_delete(stored_badpix[i]); stored_badpix[i] = NULL; 01676 cpl_image_delete(stored_xcal[i]); stored_xcal[i] = NULL; 01677 cpl_image_delete(stored_ycal[i]); stored_ycal[i] = NULL; 01678 } 01679 cpl_free(stored_flat); stored_flat = NULL; 01680 cpl_free(stored_noise); stored_noise = NULL; 01681 cpl_free(stored_badpix); stored_badpix = NULL; 01682 cpl_free(stored_xcal); stored_xcal = NULL; 01683 cpl_free(stored_ycal); stored_ycal = NULL; 01684 for (a = 0; a < nr_angles; a++) { 01685 cpl_frameset_delete(angle_frameset[a]); angle_frameset[a] = NULL; 01686 // if ((all_bounds != NULL) && (all_bounds[a] != NULL)) { 01687 // for (i = 0; i < nr_devices; i++) { 01688 // cpl_free(all_bounds[a][i]); all_bounds[a][i] = NULL; 01689 // } 01690 // cpl_free(all_bounds[a]); all_bounds[a] = NULL; 01691 // } 01692 } 01693 cpl_free(angle_frameset); angle_frameset = NULL; 01694 // cpl_free(all_bounds); all_bounds = NULL; 01695 if (edge_table != NULL) { 01696 for (i = 0; i < KMOS_NR_DETECTORS * nr_angles; i++) { 01697 if (edge_table[i] != NULL) { 01698 for (j = 0; j < KMOS_IFUS_PER_DETECTOR; j++) { 01699 cpl_table_delete(edge_table[i][j]); 01700 edge_table[i][j] = NULL; 01701 } 01702 cpl_free(edge_table[i]); edge_table[i] = NULL; 01703 } 01704 } 01705 cpl_free(edge_table); edge_table = NULL; 01706 } 01707 if (bounds != NULL) { 01708 cpl_free(bounds); bounds = NULL; 01709 } 01710 if (spec_found != NULL) { 01711 cpl_free(spec_found); spec_found = NULL; 01712 } 01713 01714 return ret_val; 01715 } 01716
1.7.6.1