|
KMOS Pipeline Reference Manual
1.2.0
|
00001 /* $Id: kmo_flat.c,v 1.43 2013/06/17 07:52:26 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/06/17 07:52:26 $ 00024 * $Revision: 1.43 $ 00025 * $Name: HEAD $ 00026 */ 00027 00028 #ifdef HAVE_CONFIG_H 00029 #include <config.h> 00030 #endif 00031 00032 /*----------------------------------------------------------------------------- 00033 * Includes 00034 *----------------------------------------------------------------------------*/ 00035 #include <string.h> 00036 #include <math.h> 00037 00038 #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, ii = 0, j = 0, ax = 0, a = 0; 00404 00405 double cpos_rej = 0.0, 00406 cneg_rej = 0.0, 00407 gain = 0.0, 00408 exptime = 0.0, 00409 *stored_qc_flat_eff = NULL, 00410 *stored_qc_flat_sn = NULL, 00411 mean_data = 0.0, 00412 mean_noise = 0.0, 00413 *stored_gapmean = NULL, 00414 *stored_gapsdv = NULL, 00415 *stored_gapmaxdev = NULL, 00416 *stored_slitmean = NULL, 00417 *stored_slitsdv = NULL, 00418 *stored_slitmaxdev = NULL; 00419 00420 const char *cmethod = NULL; 00421 00422 char *extname = NULL, 00423 filename_flat[256], 00424 filename_xcal[256], 00425 filename_ycal[256], 00426 filename_bad[256], 00427 filename_edge[256], 00428 *suffix = NULL, 00429 *fn_suffix = NULL, 00430 *tmpstr = NULL, 00431 *readmode = NULL; 00432 00433 cpl_propertylist *main_header = NULL, 00434 *main_header_xcal = NULL, 00435 *sub_header = NULL; 00436 00437 cpl_table ***edge_table = NULL; 00438 00439 main_fits_desc desc1, desc2; 00440 00441 cpl_array **unused_ifus_before = NULL, 00442 **unused_ifus_after = NULL; 00443 00444 cpl_error_code *spec_found = NULL; 00445 00446 char *fn_flat = "flat_tmp.fits", 00447 *fn_noise = "flat_noise_tmp.fits", 00448 *fn_badpix = "badpix_tmp.fits"; 00449 unsigned int save_mode = CPL_IO_CREATE; // at first files must be created 00450 00451 KMO_TRY 00452 { 00453 00454 kmo_init_fits_desc(&desc1); 00455 kmo_init_fits_desc(&desc2); 00456 00457 // ############################################################################# 00458 // ### check inputs 00459 // ############################################################################# 00460 KMO_TRY_ASSURE((parlist != NULL) && 00461 (frameset != NULL), 00462 CPL_ERROR_NULL_INPUT, 00463 "Not all input data is provided!"); 00464 00465 KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, FLAT_OFF) >= 1, 00466 CPL_ERROR_NULL_INPUT, 00467 "At least 1 FLAT_OFF frame must be provided (3 or more " 00468 "recommended)!"); 00469 00470 KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, FLAT_ON) >= 1, 00471 CPL_ERROR_NULL_INPUT, 00472 "At least 1 FLAT_ON frame must be provided (3 or more " 00473 "recommended)!"); 00474 00475 if (cpl_frameset_count_tags(frameset, FLAT_OFF) < 3) { 00476 cpl_msg_warning(cpl_func, "It is recommended to provide at least " 00477 "3 FLAT_OFF frames (Generated noise frames" 00478 " will not be very representative)!"); 00479 } 00480 00481 if (cpl_frameset_count_tags(frameset, FLAT_ON) < 3) { 00482 cpl_msg_warning(cpl_func, "It is recommended to provide at least " 00483 "3 FLAT_ON frames (Generated noise frames" 00484 " will not be very representative)!"); 00485 } 00486 00487 KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, BADPIXEL_DARK) == 1, 00488 CPL_ERROR_NULL_INPUT, 00489 "A BADPIXEL_DARK frame must be provided!"); 00490 00491 KMO_TRY_ASSURE(kmo_dfs_set_groups(frameset, "kmo_flat") == 1, 00492 CPL_ERROR_ILLEGAL_INPUT, 00493 "Cannot identify RAW and CALIB frames!"); 00494 00495 00496 // 00497 // ------------ get parameters ------------ 00498 // 00499 cpl_msg_info("", "--- Parameter setup for kmo_flat ----------"); 00500 00501 surrounding_pixels = kmo_dfs_get_parameter_int(parlist, 00502 "kmos.kmo_flat.surrounding_pixels"); 00503 KMO_TRY_CHECK_ERROR_STATE(); 00504 KMO_TRY_EXIT_IF_ERROR( 00505 kmo_dfs_print_parameter_help(parlist, 00506 "kmos.kmo_flat.surrounding_pixels")); 00507 00508 badpix_thresh = kmo_dfs_get_parameter_int(parlist, 00509 "kmos.kmo_flat.badpix_thresh"); 00510 KMO_TRY_CHECK_ERROR_STATE(); 00511 KMO_TRY_EXIT_IF_ERROR( 00512 kmo_dfs_print_parameter_help(parlist, 00513 "kmos.kmo_flat.badpix_thresh")); 00514 00515 suppress_extension = kmo_dfs_get_parameter_bool(parlist, 00516 "kmos.kmo_flat.suppress_extension"); 00517 KMO_TRY_CHECK_ERROR_STATE(); 00518 KMO_TRY_EXIT_IF_ERROR( 00519 kmo_dfs_print_parameter_help(parlist, "kmos.kmo_flat.suppress_extension")); 00520 00521 KMO_TRY_ASSURE((suppress_extension == TRUE) || (suppress_extension == FALSE), 00522 CPL_ERROR_ILLEGAL_INPUT, 00523 "suppress_extension must be TRUE or FALSE!"); 00524 00525 KMO_TRY_EXIT_IF_ERROR( 00526 kmo_combine_pars_load(parlist, "kmos.kmo_flat", &cmethod, &cpos_rej, 00527 &cneg_rej, &citer, &cmin, &cmax, 00528 FALSE)); 00529 00530 cpl_msg_info("", "-------------------------------------------"); 00531 00532 // check BADPIXEL_DARK 00533 KMO_TRY_EXIT_IF_NULL( 00534 frame = kmo_dfs_get_frame(frameset, BADPIXEL_DARK)); 00535 00536 desc2 = kmo_identify_fits_header( 00537 cpl_frame_get_filename(frame)); 00538 KMO_TRY_CHECK_ERROR_STATE(); 00539 00540 KMO_TRY_ASSURE((desc2.nr_ext == 3) && 00541 (desc2.ex_badpix == TRUE) && 00542 (desc2.fits_type == b2d_fits) && 00543 (desc2.frame_type == detector_frame), 00544 CPL_ERROR_ILLEGAL_INPUT, 00545 "BADPIXEL_DARK isn't in the correct format!!!"); 00546 00547 nx = desc2.naxis1; 00548 ny = desc2.naxis2; 00549 nz = desc2.naxis3; 00550 00551 KMO_TRY_ASSURE((surrounding_pixels >= 0) && (surrounding_pixels <= 8), 00552 CPL_ERROR_ILLEGAL_INPUT, 00553 "surrounding_pixels must be between 0 and 8!"); 00554 00555 KMO_TRY_ASSURE((badpix_thresh >= 0) && (badpix_thresh <= 100), 00556 CPL_ERROR_ILLEGAL_INPUT, 00557 "badpix_thresh must be between 0 and 100%%!"); 00558 00559 // 00560 // ------------ check EXPTIME, NDIT, READMODE and lamps ------------ 00561 // EXPTIME, NDIT, READMODE: the same for all frames 00562 // lamps: at least 3 lamp on and 3 lamp off frames 00563 // 00564 KMO_TRY_EXIT_IF_NULL( 00565 frame = kmo_dfs_get_frame(frameset, FLAT_OFF)); 00566 00567 KMO_TRY_EXIT_IF_NULL( 00568 main_header = kmclipm_propertylist_load( 00569 cpl_frame_get_filename(frame), 0)); 00570 00571 ndit = cpl_propertylist_get_int(main_header, NDIT); 00572 KMO_TRY_CHECK_ERROR_STATE("NDIT keyword in main header " 00573 "missing!"); 00574 00575 exptime = cpl_propertylist_get_double(main_header, EXPTIME); 00576 KMO_TRY_CHECK_ERROR_STATE("EXPTIME keyword in main header " 00577 "missing!"); 00578 00579 readmode = cpl_strdup(cpl_propertylist_get_string(main_header, READMODE)); 00580 KMO_TRY_CHECK_ERROR_STATE("ESO DET READ CURNAME keyword in main " 00581 "header missing!"); 00582 00583 cpl_propertylist_delete(main_header); main_header = NULL; 00584 00585 while (frame != NULL) { 00586 KMO_TRY_EXIT_IF_NULL( 00587 main_header = kmclipm_propertylist_load( 00588 cpl_frame_get_filename(frame), 0)); 00589 00590 KMO_TRY_ASSURE(cpl_propertylist_get_int(main_header, NDIT) == ndit, 00591 CPL_ERROR_ILLEGAL_INPUT, 00592 "NDIT isn't the same for all frames: (is %d and %d).", 00593 cpl_propertylist_get_int(main_header, NDIT), ndit); 00594 00595 KMO_TRY_ASSURE(cpl_propertylist_get_double(main_header, EXPTIME) == exptime, 00596 CPL_ERROR_ILLEGAL_INPUT, 00597 "EXPTIME isn't the same for all frames: (is %g and %g).", 00598 cpl_propertylist_get_double(main_header, EXPTIME), exptime); 00599 00600 KMO_TRY_ASSURE(strcmp(cpl_propertylist_get_string(main_header, READMODE), readmode) == 0, 00601 CPL_ERROR_ILLEGAL_INPUT, 00602 "ESO DET READ CURNAME isn't the same for all frames: (is %s and %s).", 00603 cpl_propertylist_get_string(main_header, READMODE), readmode); 00604 00605 desc1 = kmo_identify_fits_header( 00606 cpl_frame_get_filename(frame)); 00607 KMO_TRY_CHECK_ERROR_STATE_MSG( 00608 cpl_sprintf("File (%s) doesn't seem to be in KMOS-format!", 00609 cpl_frame_get_filename(frame))); 00610 00611 KMO_TRY_ASSURE(desc1.fits_type == raw_fits, 00612 CPL_ERROR_ILLEGAL_INPUT, 00613 "File hasn't correct data type " 00614 "(%s must be a raw, unprocessed file)!", 00615 cpl_frame_get_filename(frame)); 00616 00617 KMO_TRY_ASSURE((desc1.naxis1 == nx) && 00618 (desc1.naxis2 == ny) && 00619 (desc1.naxis3 == nz), 00620 CPL_ERROR_ILLEGAL_INPUT, 00621 "File (%s) hasn't correct dimensions! (x,y): " 00622 "(%d,%d) vs (%d,%d)", 00623 cpl_frame_get_filename(frame), 00624 desc1.naxis1, desc1.naxis2, nx, ny); 00625 00626 // assure that arc lamps are off 00627 KMO_TRY_ASSURE((kmo_check_lamp(main_header, INS_LAMP1_ST) == FALSE) && 00628 (kmo_check_lamp(main_header, INS_LAMP2_ST) == FALSE), 00629 CPL_ERROR_ILLEGAL_INPUT, 00630 "Arc lamps must be switched off (%s)!", 00631 cpl_frame_get_filename(frame)); 00632 00633 // check if flat lamps are off 00634 if ((kmo_check_lamp(main_header, INS_LAMP3_ST) == TRUE) || 00635 (kmo_check_lamp(main_header, INS_LAMP4_ST) == TRUE)) 00636 { 00637 if (!(strcmp(cpl_propertylist_get_string(main_header, "ESO INS FILT1 ID"), "Block") == 0) || 00638 !(strcmp(cpl_propertylist_get_string(main_header, "ESO INS FILT2 ID"), "Block") == 0) || 00639 !(strcmp(cpl_propertylist_get_string(main_header, "ESO INS FILT3 ID"), "Block") == 0)) 00640 { 00641 cpl_msg_warning("","At least one flat lamp is on! Check if the lamps are blocked!"); 00642 } 00643 } 00644 00645 kmo_free_fits_desc(&desc1); 00646 00647 // get next FLAT_OFF frame 00648 frame = kmo_dfs_get_frame(frameset, NULL); 00649 KMO_TRY_CHECK_ERROR_STATE(); 00650 00651 cpl_propertylist_delete(main_header); main_header = NULL; 00652 } 00653 00654 KMO_TRY_EXIT_IF_NULL( 00655 frame = kmo_dfs_get_frame(frameset, FLAT_ON)); 00656 00657 // uncomment this if these keywords can be different for FLAT_OFF and FLAT_ON 00658 // KMO_TRY_EXIT_IF_NULL( 00659 // main_header = kmclipm_propertylist_load( 00660 // cpl_frame_get_filename(frame), 0)); 00661 // ndit = cpl_propertylist_get_int(main_header, NDIT); 00662 // KMO_TRY_CHECK_ERROR_STATE("NDIT keyword in main header " 00663 // "missing!"); 00664 // exptime = cpl_propertylist_get_double(main_header, EXPTIME); 00665 // KMO_TRY_CHECK_ERROR_STATE("EXPTIME keyword in main header " 00666 // "missing!"); 00667 00668 // readmode = cpl_propertylist_get_string(main_header, READMODE); 00669 // KMO_TRY_CHECK_ERROR_STATE("ESO DET READ CURNAME keyword in main " 00670 // "header missing!"); 00671 00672 // cpl_propertylist_delete(main_header); main_header = NULL; 00673 00674 while (frame != NULL) { 00675 KMO_TRY_EXIT_IF_NULL( 00676 main_header = kmclipm_propertylist_load( 00677 cpl_frame_get_filename(frame), 0)); 00678 00679 KMO_TRY_ASSURE(cpl_propertylist_get_int(main_header, NDIT) == ndit, 00680 CPL_ERROR_ILLEGAL_INPUT, 00681 "NDIT isn't the same for all frames: (is %d and %d).", 00682 cpl_propertylist_get_int(main_header, NDIT), ndit); 00683 00684 KMO_TRY_ASSURE(cpl_propertylist_get_double(main_header, EXPTIME) == exptime, 00685 CPL_ERROR_ILLEGAL_INPUT, 00686 "EXPTIME isn't the same for all frames: (is %g and %g).", 00687 cpl_propertylist_get_double(main_header, EXPTIME), exptime); 00688 00689 KMO_TRY_ASSURE(strcmp(cpl_propertylist_get_string(main_header, READMODE), readmode) == 0, 00690 CPL_ERROR_ILLEGAL_INPUT, 00691 "ESO DET READ CURNAME isn't the same for all frames: (is %s and %s).", 00692 cpl_propertylist_get_string(main_header, READMODE), readmode); 00693 00694 desc1 = kmo_identify_fits_header( 00695 cpl_frame_get_filename(frame)); 00696 KMO_TRY_CHECK_ERROR_STATE_MSG( 00697 cpl_sprintf("File (%s) doesn't seem to be in KMOS-format!", 00698 cpl_frame_get_filename(frame))); 00699 00700 KMO_TRY_ASSURE(desc1.fits_type == raw_fits, 00701 CPL_ERROR_ILLEGAL_INPUT, 00702 "File hasn't correct data type " 00703 "(%s must be a raw, unprocessed file)!", 00704 cpl_frame_get_filename(frame)); 00705 00706 KMO_TRY_ASSURE((desc1.naxis1 == nx) && 00707 (desc1.naxis2 == ny) && 00708 (desc1.naxis3 == nz), 00709 CPL_ERROR_ILLEGAL_INPUT, 00710 "File (%s) hasn't correct dimensions! (x,y): " 00711 "(%d,%d) vs (%d,%d)", 00712 cpl_frame_get_filename(frame), 00713 desc1.naxis1, desc1.naxis2, nx, ny); 00714 00715 // assure that arc lamps are off 00716 KMO_TRY_ASSURE((kmo_check_lamp(main_header, INS_LAMP1_ST) == FALSE) && 00717 (kmo_check_lamp(main_header, INS_LAMP2_ST) == FALSE), 00718 CPL_ERROR_ILLEGAL_INPUT, 00719 "Arc lamps must be switched off (%s)!", 00720 cpl_frame_get_filename(frame)); 00721 00722 // assure that at least one flat lamp is on 00723 KMO_TRY_ASSURE((kmo_check_lamp(main_header, INS_LAMP3_ST) == TRUE) || 00724 (kmo_check_lamp(main_header, INS_LAMP4_ST) == TRUE), 00725 CPL_ERROR_ILLEGAL_INPUT, 00726 "At least one flat lamps must be switched on (%s)!", 00727 cpl_frame_get_filename(frame)); 00728 00729 kmo_free_fits_desc(&desc1); 00730 00731 // get next FLAT_ON frame 00732 frame = kmo_dfs_get_frame(frameset, NULL); 00733 KMO_TRY_CHECK_ERROR_STATE(); 00734 00735 cpl_propertylist_delete(main_header); main_header = NULL; 00736 } 00737 00738 // 00739 // ------------ check filter_id, grating_id and rotator offset --------- 00740 // must match for all detectors 00741 // 00742 KMO_TRY_EXIT_IF_ERROR( 00743 kmo_check_frameset_setup(frameset, FLAT_ON, 00744 TRUE, FALSE, FALSE)); 00745 00746 strcpy(filename_flat, MASTER_FLAT); 00747 strcpy(filename_bad, BADPIXEL_FLAT); 00748 strcpy(filename_xcal, XCAL); 00749 strcpy(filename_ycal, YCAL); 00750 strcpy(filename_edge, FLAT_EDGE); 00751 00752 KMO_TRY_EXIT_IF_NULL( 00753 frame = kmo_dfs_get_frame(frameset, FLAT_ON)); 00754 KMO_TRY_EXIT_IF_NULL( 00755 suffix = kmo_dfs_get_suffix(frame, TRUE, FALSE)); 00756 00757 cpl_msg_info("", "Detected instrument setup: %s", suffix+1); 00758 cpl_msg_info("", "(grating 1, 2 & 3)"); 00759 00760 // 00761 // ---- scan for rotator angles 00762 // 00763 #define ANGLE_DIM 360 00764 int rotang_found[ANGLE_DIM]; 00765 int rotang_cnt[ANGLE_DIM]; 00766 for (i = 0; i < ANGLE_DIM; i++) { 00767 rotang_found[i] = 0; 00768 rotang_cnt[i] = 0; 00769 } 00770 KMO_TRY_EXIT_IF_NULL( 00771 frame = kmo_dfs_get_frame(frameset, FLAT_ON)); 00772 while (frame != NULL) { 00773 main_header = kmclipm_propertylist_load(cpl_frame_get_filename(frame), 0); 00774 if (cpl_propertylist_has(main_header, ROTANGLE)) { 00775 int rot_angle = (int) rint(cpl_propertylist_get_double(main_header, ROTANGLE)); 00776 if (rot_angle < 0) { 00777 rot_angle += 360; 00778 } 00779 if (rot_angle < 360 && rot_angle >= 0) { 00780 rotang_cnt[rot_angle]++; 00781 // char * tag = cpl_sprintf("FLAT_ON_%3.3d",rot_angle); 00782 // KMO_TRY_EXIT_IF_ERROR( 00783 // cpl_frame_set_tag(frame, tag)); 00784 // cpl_free(tag); 00785 } 00786 } else { 00787 cpl_msg_warning("","File %s has no keyword \"ROTANGLE\"", 00788 cpl_frame_get_filename(frame)); 00789 } 00790 00791 cpl_propertylist_delete(main_header); main_header = NULL; 00792 frame = kmo_dfs_get_frame(frameset, NULL); 00793 KMO_TRY_CHECK_ERROR_STATE(); 00794 } 00795 nr_angles = 0; 00796 for (ax = 0; ax < ANGLE_DIM; ax++) { 00797 if (rotang_cnt[ax] != 0) { 00798 // if (rotang_cnt[ax] >=3) { 00799 cpl_msg_info("","Found %d frames with rotator angle %d",rotang_cnt[ax],ax); 00800 rotang_found[nr_angles] = ax; 00801 nr_angles++; 00802 // } else { 00803 // cpl_msg_warning("","Found %d frames with rotator angle %d but at least three are required", 00804 // rotang_cnt[ax],ax); 00805 // } 00806 } 00807 } 00808 00809 KMO_TRY_EXIT_IF_NULL ( 00810 angle_frameset = (cpl_frameset **) cpl_malloc(nr_angles * sizeof(cpl_frameset*))); 00811 for (i = 0; i < nr_angles; i++) { 00812 angle_frameset[i] = cpl_frameset_new(); 00813 } 00814 00815 KMO_TRY_EXIT_IF_NULL( 00816 frame = kmo_dfs_get_frame(frameset, FLAT_ON)); 00817 while (frame != NULL) { 00818 main_header = kmclipm_propertylist_load(cpl_frame_get_filename(frame), 0); 00819 if (cpl_propertylist_has(main_header, ROTANGLE)) { 00820 int rot_angle = (int) rint(cpl_propertylist_get_double(main_header, ROTANGLE)); 00821 if (rot_angle < 0) { 00822 rot_angle += 360; 00823 } 00824 int ix = -1; 00825 for (ix = 0; ix<nr_angles; ix++) { 00826 if (rotang_found[ix] == rot_angle) { 00827 break; 00828 } 00829 } 00830 if (ix<nr_angles) { 00831 KMO_TRY_EXIT_IF_ERROR( 00832 cpl_frameset_insert(angle_frameset[ix], cpl_frame_duplicate(frame))); 00833 } 00834 } 00835 00836 cpl_propertylist_delete(main_header); main_header = NULL; 00837 frame = kmo_dfs_get_frame(frameset, NULL); 00838 KMO_TRY_CHECK_ERROR_STATE(); 00839 } 00840 00841 00842 // ############################################################################# 00843 // ### allocate temporary memory 00844 // ############################################################################# 00845 // load descriptor and header of first operand 00846 KMO_TRY_EXIT_IF_NULL( 00847 frame = kmo_dfs_get_frame(frameset, FLAT_ON)); 00848 00849 desc1 = kmo_identify_fits_header(cpl_frame_get_filename(frame)); 00850 KMO_TRY_CHECK_ERROR_STATE(); 00851 00852 nr_devices = desc1.nr_ext; 00853 00854 // the frames have to be stored temporarily because the QC parameters 00855 // for the main header are calculated from each detector. So they can be 00856 // stored only when all detectors are processed 00857 KMO_TRY_EXIT_IF_NULL( 00858 stored_flat = (cpl_image**)cpl_calloc(nr_devices * nr_angles, 00859 sizeof(cpl_image*))); 00860 KMO_TRY_EXIT_IF_NULL( 00861 stored_noise = (cpl_image**)cpl_calloc(nr_devices * nr_angles, 00862 sizeof(cpl_image*))); 00863 KMO_TRY_EXIT_IF_NULL( 00864 stored_badpix = (cpl_image**)cpl_calloc(nr_devices * nr_angles, 00865 sizeof(cpl_image*))); 00866 KMO_TRY_EXIT_IF_NULL( 00867 stored_xcal = (cpl_image**)cpl_calloc(nr_devices * nr_angles, 00868 sizeof(cpl_image*))); 00869 KMO_TRY_EXIT_IF_NULL( 00870 stored_ycal = (cpl_image**)cpl_calloc(nr_devices * nr_angles, 00871 sizeof(cpl_image*))); 00872 KMO_TRY_EXIT_IF_NULL( 00873 stored_qc_flat_sat = (int*)cpl_malloc(nr_devices * nr_angles * 00874 sizeof(int))); 00875 KMO_TRY_EXIT_IF_NULL( 00876 stored_qc_flat_eff = (double*)cpl_malloc(nr_devices * nr_angles * 00877 sizeof(double))); 00878 KMO_TRY_EXIT_IF_NULL( 00879 stored_qc_flat_sn = (double*)cpl_malloc(nr_devices * nr_angles * 00880 sizeof(double))); 00881 KMO_TRY_EXIT_IF_NULL( 00882 stored_gapmean = (double*)cpl_malloc(nr_devices * nr_angles * 00883 sizeof(double))); 00884 KMO_TRY_EXIT_IF_NULL( 00885 stored_gapsdv = (double*)cpl_malloc(nr_devices * nr_angles * 00886 sizeof(double))); 00887 KMO_TRY_EXIT_IF_NULL( 00888 stored_gapmaxdev = (double*)cpl_malloc(nr_devices * nr_angles * 00889 sizeof(double))); 00890 KMO_TRY_EXIT_IF_NULL( 00891 stored_slitmean = (double*)cpl_malloc(nr_devices * nr_angles * 00892 sizeof(double))); 00893 KMO_TRY_EXIT_IF_NULL( 00894 stored_slitsdv = (double*)cpl_malloc(nr_devices * nr_angles * 00895 sizeof(double))); 00896 KMO_TRY_EXIT_IF_NULL( 00897 stored_slitmaxdev = (double*)cpl_malloc(nr_devices * nr_angles * 00898 sizeof(double))); 00899 KMO_TRY_EXIT_IF_NULL( 00900 spec_found = (cpl_error_code*)cpl_malloc(nr_devices * nr_angles * 00901 sizeof(cpl_error_code))); 00902 KMO_TRY_EXIT_IF_NULL( 00903 edge_table = (cpl_table***)cpl_malloc(KMOS_NR_DETECTORS * nr_angles * 00904 sizeof(cpl_table**))); 00905 00906 // initialize to NULL 00907 for (i = 0; i < nr_devices * nr_angles ; i++) { 00908 stored_qc_flat_sat[i] = 0.0; 00909 stored_qc_flat_eff[i] = 0.0; 00910 stored_qc_flat_sn[i] = 0.0; 00911 stored_gapmean[i] = 0.0; 00912 stored_gapsdv[i] = 0.0; 00913 stored_gapmaxdev[i] = 0.0; 00914 stored_slitmean[i] = 0.0; 00915 stored_slitsdv[i] = 0.0; 00916 stored_slitmaxdev[i] = 0.0; 00917 spec_found[i] = CPL_ERROR_NONE; 00918 } 00919 00920 for (i = 0; i < KMOS_NR_DETECTORS * nr_angles; i++) { 00921 edge_table[i] = NULL; 00922 } 00923 00924 // ############################################################################# 00925 // ### process data 00926 // ############################################################################# 00927 00928 // check which IFUs are active for all FLAT_ON frames 00929 KMO_TRY_EXIT_IF_NULL( 00930 unused_ifus_before = kmo_get_unused_ifus(frameset, 0, 0)); 00931 00932 KMO_TRY_EXIT_IF_NULL( 00933 unused_ifus_after = kmo_duplicate_unused_ifus(unused_ifus_before)); 00934 00935 kmo_print_unused_ifus(unused_ifus_before, FALSE); 00936 00937 cpl_msg_info("", "EXPTIME: %g seconds", exptime); 00938 cpl_msg_info("", "NDIT: %d", ndit); 00939 cpl_msg_info("", "Detector readout mode: %s", readmode); 00940 cpl_msg_info("", "-------------------------------------------"); 00941 00942 // 00943 // ------------ loop all rotator angles and detectors ------------ 00944 // 00945 00946 for (a = 0; a < nr_angles; a++) { 00947 cpl_msg_info("","Processing rotator angle %d -> %d degree", a,rotang_found[a]); 00948 for (i = 1; i <= nr_devices; i++) { 00949 cpl_msg_info("","Processing detector No. %d", i); 00950 00951 sx = a * nr_devices + (i - 1); 00952 00953 KMO_TRY_EXIT_IF_NULL( 00954 bad_pix_mask_dark = kmo_dfs_load_image(frameset, BADPIXEL_DARK, 00955 i, 2, FALSE, NULL)); 00956 00957 // 00958 // ------------ load all lamp_on and lamp_off images ------------ 00959 // 00960 KMO_TRY_EXIT_IF_NULL( 00961 det_lamp_on = cpl_imagelist_new()); 00962 KMO_TRY_EXIT_IF_NULL( 00963 det_lamp_off = cpl_imagelist_new()); 00964 00965 // load lamp-on images 00966 KMO_TRY_EXIT_IF_NULL( 00967 frame = kmo_dfs_get_frame(angle_frameset[a], FLAT_ON)); 00968 j = 0; 00969 while (frame != NULL) { 00970 KMO_TRY_EXIT_IF_NULL( 00971 img_in = kmo_dfs_load_image_frame(frame, i, FALSE, TRUE, &nr_sat)); 00972 00973 KMO_TRY_EXIT_IF_ERROR( 00974 kmo_image_reject_from_mask(img_in, bad_pix_mask_dark)); 00975 00976 cpl_imagelist_set(det_lamp_on, img_in, j++); 00977 KMO_TRY_CHECK_ERROR_STATE(); 00978 00979 frame = kmo_dfs_get_frame(angle_frameset[a], NULL); 00980 KMO_TRY_CHECK_ERROR_STATE(); 00981 } 00982 00983 // load lamp-off images 00984 KMO_TRY_EXIT_IF_NULL( 00985 frame = kmo_dfs_get_frame(frameset, FLAT_OFF)); 00986 j = 0; 00987 while (frame != NULL) { 00988 KMO_TRY_EXIT_IF_NULL( 00989 img_in = kmo_dfs_load_image_frame(frame, i, FALSE, FALSE, NULL)); 00990 00991 KMO_TRY_EXIT_IF_ERROR( 00992 kmo_image_reject_from_mask(img_in, bad_pix_mask_dark)); 00993 00994 cpl_imagelist_set(det_lamp_off, img_in, j++); 00995 KMO_TRY_CHECK_ERROR_STATE(); 00996 00997 // get next frame 00998 frame = kmo_dfs_get_frame(frameset, NULL); 00999 KMO_TRY_CHECK_ERROR_STATE(); 01000 } 01001 01002 // 01003 // ------------ process imagelist ------------ 01004 // 01005 01006 // count saturated pixels for each detector 01007 KMO_TRY_EXIT_IF_NULL( 01008 frame = kmo_dfs_get_frame(angle_frameset[a], FLAT_ON)); 01009 KMO_TRY_EXIT_IF_NULL( 01010 main_header = kmclipm_propertylist_load( 01011 cpl_frame_get_filename(frame), 0)); 01012 if (strcmp(cpl_propertylist_get_string(main_header, READMODE), "Nondest") == 0) { 01013 // NDR: non-destructive readout mode 01014 stored_qc_flat_sat[sx] = nr_sat; 01015 } else { 01016 // normal readout mode 01017 stored_qc_flat_sat[sx] = 01018 kmo_imagelist_get_saturated(det_lamp_on, 01019 KMO_FLAT_SATURATED, 01020 KMO_FLAT_SAT_MIN); 01021 } 01022 cpl_propertylist_delete(main_header); main_header = NULL; 01023 KMO_TRY_CHECK_ERROR_STATE(); 01024 01025 // combine imagelists and create noise 01026 KMO_TRY_EXIT_IF_ERROR( 01027 kmclipm_combine_frames(det_lamp_on, NULL, 01028 NULL, 01029 cmethod, cpos_rej, cneg_rej, citer, 01030 cmax, cmin, 01031 &combined_data_on, 01032 &combined_noise_on, 01033 -1.0)); 01034 01035 KMO_TRY_EXIT_IF_ERROR( 01036 kmclipm_combine_frames(det_lamp_off, NULL, 01037 NULL, 01038 cmethod, cpos_rej, cneg_rej, citer, 01039 cmax, cmin, 01040 &combined_data_off, 01041 &combined_noise_off, 01042 -1.0)); 01043 01044 if (kmclipm_omit_warning_one_slice > 10) { 01045 cpl_msg_warning(cpl_func, "Previous warning (number of " 01046 "identified slices) occured %d times.", 01047 kmclipm_omit_warning_one_slice); 01048 kmclipm_omit_warning_one_slice = FALSE; 01049 } 01050 01051 // subtract combined lamp_off from lamp_on 01052 // (for noise: sig_x = sqrt(sig_u^2 + sig_v^2) 01053 KMO_TRY_EXIT_IF_ERROR( 01054 cpl_image_subtract(combined_data_on, combined_data_off)); 01055 01056 KMO_TRY_EXIT_IF_ERROR( 01057 cpl_image_power(combined_noise_on, 2.0)); 01058 KMO_TRY_EXIT_IF_ERROR( 01059 cpl_image_power(combined_noise_off, 2.0)); 01060 KMO_TRY_EXIT_IF_ERROR( 01061 cpl_image_add(combined_noise_on, combined_noise_off)); 01062 KMO_TRY_EXIT_IF_ERROR( 01063 cpl_image_power(combined_noise_on, 0.5)); 01064 01065 // create bad-pixel-mask 01066 KMO_TRY_EXIT_IF_NULL( 01067 bad_pix_mask_flat = kmo_create_bad_pix_flat_thresh( 01068 combined_data_on, 01069 surrounding_pixels, 01070 badpix_thresh)); 01071 01072 // calculate spectral curvature here 01073 spec_found[sx] = kmo_calc_curvature(combined_data_on, 01074 combined_noise_on, 01075 unused_ifus_after[i-1], 01076 bad_pix_mask_flat, 01077 i, 01078 &xcal, 01079 &ycal, 01080 stored_gapmean+(sx), 01081 stored_gapsdv+(sx), 01082 stored_gapmaxdev+(sx), 01083 stored_slitmean+(sx), 01084 stored_slitsdv+(sx), 01085 stored_slitmaxdev+(sx), 01086 &edge_table[sx]); 01087 01088 if (spec_found[sx] == CPL_ERROR_NONE) { 01089 // all fine 01090 01091 // in kmo_calc_curvature() the spectral slope of each slitlet 01092 // has been normalised individually. Now the normalisation on 01093 // the whole frame is applied. (cpl_image_get_mean() 01094 // ignores bad pixels when calculating the mean) 01095 mean_data = cpl_image_get_mean(combined_data_on); 01096 KMO_TRY_CHECK_ERROR_STATE(); 01097 01098 stored_qc_flat_eff[sx] = mean_data / exptime; 01099 01100 mean_noise = cpl_image_get_mean(combined_noise_on); 01101 KMO_TRY_CHECK_ERROR_STATE(); 01102 01103 if ((cpl_frameset_count_tags(frameset, FLAT_OFF) > 1) || 01104 (cpl_frameset_count_tags(frameset, FLAT_ON) > 1)) 01105 { 01106 KMO_TRY_ASSURE(mean_noise != 0.0, 01107 CPL_ERROR_ILLEGAL_INPUT, 01108 "All frames of detector %i are exactly " 01109 "the same!", i); 01110 01111 stored_qc_flat_sn[sx] = mean_data / mean_noise; 01112 } 01113 01114 // normalize data & noise on the whole detector frame (the 01115 // spectral slope on each slitlet has already been normalised in 01116 // kmo_calc_curvature()) 01117 KMO_TRY_EXIT_IF_ERROR( 01118 cpl_image_divide_scalar(combined_data_on, mean_data)); 01119 01120 KMO_TRY_EXIT_IF_ERROR( 01121 cpl_image_divide_scalar(combined_noise_on, mean_data)); 01122 01123 // apply the badpixel mask to the produced frames 01124 KMO_TRY_EXIT_IF_ERROR( 01125 cpl_image_multiply(combined_data_on, bad_pix_mask_flat)); 01126 01127 KMO_TRY_EXIT_IF_ERROR( 01128 cpl_image_multiply(combined_noise_on, bad_pix_mask_flat)); 01129 01130 KMO_TRY_EXIT_IF_ERROR( 01131 cpl_image_multiply(xcal, bad_pix_mask_flat)); 01132 01133 KMO_TRY_EXIT_IF_ERROR( 01134 cpl_image_multiply(ycal, bad_pix_mask_flat)); 01135 01136 // 01137 // ------ store temporarily flat, badpixel and calibration ----- 01138 // 01139 stored_flat[sx] = combined_data_on; 01140 stored_noise[sx] = combined_noise_on; 01141 stored_badpix[sx] = bad_pix_mask_flat; 01142 stored_xcal[sx] = xcal; 01143 stored_ycal[sx] = ycal; 01144 } else if (spec_found[sx] == CPL_ERROR_DATA_NOT_FOUND) { 01145 // all IFUs seem to be deativated, continue processing 01146 // just save empty frames 01147 cpl_error_reset(); 01148 cpl_image_delete(combined_data_on); combined_data_on = NULL; 01149 cpl_image_delete(combined_noise_on); combined_noise_on = NULL; 01150 cpl_image_delete(bad_pix_mask_flat); bad_pix_mask_flat = NULL; 01151 stored_flat[sx] = cpl_image_new(nx, ny, CPL_TYPE_FLOAT); 01152 stored_noise[sx] = cpl_image_new(nx, ny, CPL_TYPE_FLOAT); 01153 stored_badpix[sx] = cpl_image_new(nx, ny, CPL_TYPE_FLOAT); 01154 } else { 01155 // another error occured 01156 KMO_TRY_CHECK_ERROR_STATE(); 01157 } 01158 01159 // store immediate results, free memory 01160 KMO_TRY_EXIT_IF_ERROR( 01161 kmclipm_image_save(stored_flat[sx], fn_flat, 01162 CPL_TYPE_FLOAT, NULL, save_mode, 0./0.)); 01163 KMO_TRY_EXIT_IF_ERROR( 01164 kmclipm_image_save(stored_noise[sx], fn_noise, 01165 CPL_TYPE_FLOAT, NULL, save_mode, 0./0.)); 01166 KMO_TRY_EXIT_IF_ERROR( 01167 kmclipm_image_save(stored_badpix[sx], fn_badpix, 01168 CPL_TYPE_FLOAT, NULL, save_mode, 0./0.)); 01169 save_mode = CPL_IO_EXTEND; //all other saves will create extensions 01170 cpl_image_delete(stored_flat[sx]); stored_flat[sx] = NULL; 01171 cpl_image_delete(stored_noise[sx]); stored_noise[sx] = NULL; 01172 cpl_image_delete(stored_badpix[sx]); stored_badpix[sx] = NULL; 01173 01174 01175 // free memory 01176 cpl_imagelist_delete(det_lamp_on); det_lamp_on = NULL; 01177 cpl_imagelist_delete(det_lamp_off); det_lamp_off = NULL; 01178 cpl_image_delete(combined_data_off); combined_data_off = NULL; 01179 cpl_image_delete(combined_noise_off); combined_noise_off = NULL; 01180 cpl_image_delete(bad_pix_mask_dark); bad_pix_mask_dark = NULL; 01181 } // for i = 1; i <= nr_devices 01182 } // for a = 0; a < nr_angles 01183 KMO_TRY_CHECK_ERROR_STATE(); 01184 01185 // ############################################################################# 01186 // ### QC parameters & saving 01187 // ############################################################################# 01188 // 01189 // ------------ load, update & save primary header ------------ 01190 // 01191 KMO_TRY_EXIT_IF_NULL( 01192 main_header = kmo_dfs_load_primary_header(frameset, FLAT_ON)); 01193 01194 // update which IFUs are not used 01195 kmo_print_unused_ifus(unused_ifus_after, TRUE); 01196 01197 KMO_TRY_EXIT_IF_ERROR( 01198 kmo_set_unused_ifus(unused_ifus_after, main_header, "kmo_flat")); 01199 01200 // write main_header for data-, noise-, ycal- and badpix-frame 01201 // xcal gets additionally the boundaries of the IFUs for reconstruction 01202 01203 // add here boundaries for reconstruction 01204 KMO_TRY_EXIT_IF_NULL( 01205 main_header_xcal = cpl_propertylist_new()); 01206 01207 KMO_TRY_EXIT_IF_NULL( 01208 total_bounds = (int**)cpl_malloc(nr_devices*sizeof(int*))); 01209 for (i = 0; i < nr_devices; i++) { 01210 KMO_TRY_EXIT_IF_NULL( 01211 total_bounds[i] = (int*) cpl_calloc(2*KMOS_IFUS_PER_DETECTOR,sizeof(int))); 01212 for (j = 0; j < KMOS_IFUS_PER_DETECTOR; j++) { 01213 total_bounds[i][2*j] = 2048; 01214 total_bounds[i][2*j+1] = 0; 01215 } 01216 } 01217 KMO_TRY_CHECK_ERROR_STATE(); 01218 01219 KMO_TRY_EXIT_IF_NULL( 01220 all_bounds = (int***) cpl_malloc(nr_angles*sizeof(int**))); 01221 for (a = 0; a < nr_angles; a++) { 01222 KMO_TRY_EXIT_IF_NULL( 01223 all_bounds[a] = (int**) cpl_malloc(nr_devices*sizeof(int*))); 01224 for (i = 0; i < nr_devices; i++) { 01225 KMO_TRY_EXIT_IF_NULL( 01226 all_bounds[a][i] = (int*) cpl_calloc(2*KMOS_IFUS_PER_DETECTOR,sizeof(int))); 01227 } 01228 } 01229 KMO_TRY_CHECK_ERROR_STATE(); 01230 01231 for (a = 0; a < nr_angles; a++) { 01232 for (i = 0; i < nr_devices; i++) { 01233 sx = a * nr_devices + i; 01234 if (stored_ycal[sx] != NULL) { 01235 KMO_TRY_EXIT_IF_NULL( 01236 bounds = kmo_split_frame(stored_ycal[sx])); 01237 for (j = 0; j < KMOS_IFUS_PER_DETECTOR; j++) { 01238 all_bounds[a][i][2*j] = bounds[2*j]; 01239 all_bounds[a][i][2*j+1] = bounds[2*j+1]; 01240 01241 if (total_bounds[i][2*j] >= 0 ) { 01242 if (bounds[2*j] < 0) { 01243 total_bounds[i][2*j] = bounds[2*j]; 01244 } else { 01245 if (total_bounds[i][2*j] > bounds[2*j]) { 01246 total_bounds[i][2*j] = bounds[2*j]; 01247 } 01248 } 01249 } 01250 if (total_bounds[i][2*j+1] >= 0 ) { 01251 if (bounds[2*j+1] < 0) { 01252 total_bounds[i][2*j+1] = bounds[2*j+1]; 01253 } else { 01254 if (total_bounds[i][2*j+1] < bounds[2*j+1]) { 01255 total_bounds[i][2*j+1] = bounds[2*j+1]; 01256 } 01257 } 01258 } 01259 } 01260 } else { 01261 // whole detector inactive 01262 for (j = 0; j < KMOS_IFUS_PER_DETECTOR; j++) { 01263 all_bounds[a][i][2*j] = -1; 01264 all_bounds[a][i][2*j+1] = -1; 01265 total_bounds[i][2*j] = -1; 01266 total_bounds[i][2*j+1] = -1; 01267 } 01268 } 01269 if (bounds != NULL) { 01270 cpl_free(bounds); bounds = NULL; 01271 } 01272 } // for (nr_devices) 01273 } // for (nr_angles) 01274 01275 for (i = 0; i < nr_devices; i++) { 01276 for (j = 0; j < KMOS_IFUS_PER_DETECTOR; j++) { 01277 if (total_bounds[i][2*j] > -1) { 01278 KMO_TRY_EXIT_IF_NULL( 01279 tmpstr= cpl_sprintf("%s%d%s", 01280 BOUNDS_PREFIX, 01281 i*KMOS_IFUS_PER_DETECTOR + j+1, 01282 "_L")); 01283 KMO_TRY_EXIT_IF_ERROR( 01284 kmclipm_update_property_int(main_header_xcal, 01285 tmpstr, total_bounds[i][2*j], 01286 "[pix] left boundary for reconstr.")); 01287 cpl_free(tmpstr); tmpstr = NULL; 01288 } 01289 01290 if (total_bounds[i][2*j+1] > -1) { 01291 KMO_TRY_EXIT_IF_NULL( 01292 tmpstr= cpl_sprintf("%s%d%s", 01293 BOUNDS_PREFIX, 01294 i*KMOS_IFUS_PER_DETECTOR + j+1, 01295 "_R")); 01296 KMO_TRY_EXIT_IF_ERROR( 01297 kmclipm_update_property_int(main_header_xcal, 01298 tmpstr, total_bounds[i][2*j+1], 01299 "[pix] right boundary for reconstr.")); 01300 cpl_free(tmpstr); tmpstr = NULL; 01301 } 01302 } 01303 } // for (nr_devices) 01304 01305 // 01306 // ------------ saving headers ------------ 01307 // 01308 if (!suppress_extension) { 01309 KMO_TRY_EXIT_IF_NULL( 01310 fn_suffix = cpl_sprintf("%s", suffix)); 01311 } else { 01312 KMO_TRY_EXIT_IF_NULL( 01313 fn_suffix = cpl_sprintf("%s", "")); 01314 } 01315 01316 cpl_msg_info("","Saving data..."); 01317 01318 KMO_TRY_EXIT_IF_NULL( 01319 frame = kmo_dfs_get_frame(frameset, FLAT_ON)); 01320 01321 KMO_TRY_EXIT_IF_ERROR( 01322 kmo_dfs_save_main_header(frameset, filename_flat, fn_suffix, frame, 01323 main_header, parlist, cpl_func)); 01324 KMO_TRY_EXIT_IF_ERROR( 01325 kmo_dfs_save_main_header(frameset, filename_xcal, fn_suffix, frame, 01326 main_header_xcal, parlist, cpl_func)); 01327 KMO_TRY_EXIT_IF_ERROR( 01328 kmo_dfs_save_main_header(frameset, filename_ycal, fn_suffix, frame, 01329 main_header, parlist, cpl_func)); 01330 KMO_TRY_EXIT_IF_ERROR( 01331 kmo_dfs_save_main_header(frameset, filename_bad, fn_suffix, frame, 01332 main_header, parlist, cpl_func)); 01333 KMO_TRY_EXIT_IF_ERROR( 01334 kmo_dfs_save_main_header(frameset, filename_edge, fn_suffix, frame, 01335 main_header, parlist, cpl_func)); 01336 01337 cpl_propertylist_delete(main_header); main_header = NULL; 01338 cpl_propertylist_delete(main_header_xcal); main_header_xcal = NULL; 01339 01340 // 01341 // ------------ saving sub frames ------------ 01342 // 01343 for (a = 0; a < nr_angles; a++) { 01344 for (i = 1; i <= nr_devices; i++) { 01345 sx = a * nr_devices + (i - 1); 01346 01347 // load stored data again 01348 KMO_TRY_EXIT_IF_NULL( 01349 stored_flat[sx] = kmclipm_image_load(fn_flat, 01350 CPL_TYPE_FLOAT, 0, sx)); 01351 KMO_TRY_EXIT_IF_NULL( 01352 stored_noise[sx] = kmclipm_image_load(fn_noise, 01353 CPL_TYPE_FLOAT, 0, sx)); 01354 KMO_TRY_EXIT_IF_NULL( 01355 stored_badpix[sx] = kmclipm_image_load(fn_badpix, 01356 CPL_TYPE_FLOAT, 0, sx)); 01357 01358 KMO_TRY_EXIT_IF_NULL( 01359 sub_header = kmo_dfs_load_sub_header(frameset, FLAT_ON, i, 01360 FALSE)); 01361 cpl_propertylist_erase(sub_header, CRPIX1); 01362 cpl_propertylist_erase(sub_header, CRPIX2); 01363 01364 KMO_TRY_EXIT_IF_ERROR( 01365 kmclipm_update_property_double(sub_header,CAL_ROTANGLE, 01366 ((double) rotang_found[a]), 01367 "[deg] Rotator relative to nasmyth")); 01368 01369 if (i == 1) { 01370 for (ii = 0; ii < nr_devices; ii++) { 01371 for (j = 0; j < KMOS_IFUS_PER_DETECTOR; j++) { 01372 if (all_bounds[a][ii][2*j] > -1) { 01373 KMO_TRY_EXIT_IF_NULL( 01374 tmpstr= cpl_sprintf("%s%d%s", 01375 BOUNDS_PREFIX, 01376 ii*KMOS_IFUS_PER_DETECTOR + j+1, 01377 "_L")); 01378 KMO_TRY_EXIT_IF_ERROR( 01379 kmclipm_update_property_int(sub_header, 01380 tmpstr, all_bounds[a][ii][2*j], 01381 "[pix] left boundary for reconstr.")); 01382 cpl_free(tmpstr); tmpstr = NULL; 01383 } 01384 01385 if (all_bounds[a][ii][2*j+1] > -1) { 01386 KMO_TRY_EXIT_IF_NULL( 01387 tmpstr= cpl_sprintf("%s%d%s", 01388 BOUNDS_PREFIX, 01389 ii-1*KMOS_IFUS_PER_DETECTOR + j+1, 01390 "_R")); 01391 KMO_TRY_EXIT_IF_ERROR( 01392 kmclipm_update_property_int(sub_header, 01393 tmpstr, all_bounds[a][ii][2*j+1], 01394 "[pix] right boundary for reconstr.")); 01395 cpl_free(tmpstr); tmpstr = NULL; 01396 } 01397 } 01398 } // for (nr_devices) 01399 01400 } 01401 01402 if (spec_found[sx] == CPL_ERROR_NONE) { 01403 KMO_TRY_EXIT_IF_ERROR( 01404 kmclipm_update_property_int(sub_header, 01405 QC_FLAT_SAT, 01406 stored_qc_flat_sat[sx], 01407 "[] nr. saturated pixels of master flat")); 01408 // load gain 01409 gain = kmo_dfs_get_property_double(sub_header, GAIN); 01410 KMO_TRY_CHECK_ERROR_STATE_MSG( 01411 "GAIN-keyword in fits-header is missing!"); 01412 01413 KMO_TRY_EXIT_IF_ERROR( 01414 kmclipm_update_property_double(sub_header, 01415 QC_FLAT_EFF, 01416 stored_qc_flat_eff[sx]/gain, 01417 "[e-/s] rel. brightness of flat lamp")); 01418 KMO_TRY_EXIT_IF_ERROR( 01419 kmclipm_update_property_double(sub_header, 01420 QC_FLAT_SN, 01421 stored_qc_flat_sn[sx], 01422 "[] S/N of master flat")); 01423 } 01424 01425 // store qc parameters only if any slitlet- and gap-width has been 01426 // detected (should be the case when at least one IFU is active) 01427 if (stored_xcal[sx] != NULL) { 01428 KMO_TRY_EXIT_IF_ERROR( 01429 kmclipm_update_property_double(sub_header, 01430 QC_GAP_MEAN, 01431 stored_gapmean[sx], 01432 "[pix] mean gap width between slitlets")); 01433 KMO_TRY_EXIT_IF_ERROR( 01434 kmclipm_update_property_double(sub_header, 01435 QC_GAP_SDV, 01436 stored_gapsdv[sx], 01437 "[pix] stdev of gap width between slitlets")); 01438 KMO_TRY_EXIT_IF_ERROR( 01439 kmclipm_update_property_double(sub_header, 01440 QC_GAP_MAXDEV, 01441 stored_gapmaxdev[sx], 01442 "[pix] max gap deviation between slitlets")); 01443 KMO_TRY_EXIT_IF_ERROR( 01444 kmclipm_update_property_double(sub_header, 01445 QC_SLIT_MEAN, 01446 stored_slitmean[sx], 01447 "[pix] mean slitlet width")); 01448 KMO_TRY_EXIT_IF_ERROR( 01449 kmclipm_update_property_double(sub_header, 01450 QC_SLIT_SDV, 01451 stored_slitsdv[sx], 01452 "[pix] stdev of slitlet widths")); 01453 KMO_TRY_EXIT_IF_ERROR( 01454 kmclipm_update_property_double(sub_header, 01455 QC_SLIT_MAXDEV, 01456 stored_slitmaxdev[sx], 01457 "[pix] max slitlet width deviation")); 01458 } 01459 01460 if (spec_found[sx] == CPL_ERROR_DATA_NOT_FOUND) { 01461 stored_xcal[sx] = cpl_image_new(nx, ny, CPL_TYPE_FLOAT); 01462 stored_ycal[sx] = cpl_image_new(nx, ny, CPL_TYPE_FLOAT); 01463 } 01464 01465 // calculate QC.BADPIX.NCOUNT 01466 nr_bad_pix = cpl_image_count_rejected(stored_badpix[sx]); 01467 KMO_TRY_CHECK_ERROR_STATE(); 01468 01469 // remove 4pixel-border as bad pixels 01470 nr_bad_pix -= 2*KMOS_BADPIX_BORDER*(nx-2*KMOS_BADPIX_BORDER) + 01471 2*KMOS_BADPIX_BORDER*ny; 01472 01473 KMO_TRY_EXIT_IF_ERROR( 01474 kmclipm_update_property_int(sub_header, 01475 QC_NR_BAD_PIX, 01476 nr_bad_pix, 01477 "[] nr. of bad pixels")); 01478 // save flat frame 01479 KMO_TRY_EXIT_IF_NULL( 01480 extname = kmo_extname_creator(detector_frame, i, EXT_DATA)); 01481 KMO_TRY_EXIT_IF_ERROR( 01482 kmclipm_update_property_string(sub_header, EXTNAME, 01483 extname, 01484 "FITS extension name")); 01485 cpl_free(extname); extname = NULL; 01486 01487 KMO_TRY_EXIT_IF_ERROR( 01488 kmclipm_update_property_int(sub_header, 01489 EXTVER, 01490 sx+1, 01491 "FITS extension ver")); 01492 01493 KMO_TRY_EXIT_IF_ERROR( 01494 kmo_dfs_save_image(stored_flat[sx], filename_flat, 01495 fn_suffix, sub_header, 0./0.)); 01496 01497 // save noise frame only when enough input frames were available 01498 KMO_TRY_EXIT_IF_NULL( 01499 extname = kmo_extname_creator(detector_frame, i, 01500 EXT_NOISE)); 01501 KMO_TRY_EXIT_IF_ERROR( 01502 kmclipm_update_property_string(sub_header, EXTNAME, 01503 extname, 01504 "FITS extension name")); 01505 cpl_free(extname); extname = NULL; 01506 01507 KMO_TRY_EXIT_IF_ERROR( 01508 kmo_dfs_save_image(stored_noise[sx], filename_flat, 01509 fn_suffix, sub_header, 0./0.)); 01510 01511 // save bad_pix frame 01512 KMO_TRY_EXIT_IF_NULL( 01513 extname = kmo_extname_creator(detector_frame, i, EXT_BADPIX)); 01514 KMO_TRY_EXIT_IF_ERROR( 01515 kmclipm_update_property_string(sub_header, EXTNAME, 01516 extname, 01517 "FITS extension name")); 01518 cpl_free(extname); extname = NULL; 01519 01520 KMO_TRY_EXIT_IF_ERROR( 01521 kmo_dfs_save_image(stored_badpix[sx], filename_bad, 01522 fn_suffix, sub_header, 0.)); 01523 01524 // save xcal and ycal-frame 01525 KMO_TRY_EXIT_IF_NULL( 01526 extname = kmo_extname_creator(detector_frame, i, EXT_DATA)); 01527 KMO_TRY_EXIT_IF_ERROR( 01528 kmclipm_update_property_string(sub_header, EXTNAME, 01529 extname, 01530 "FITS extension name")); 01531 cpl_free(extname); extname = NULL; 01532 01533 KMO_TRY_EXIT_IF_ERROR( 01534 kmo_dfs_save_image(stored_xcal[sx], filename_xcal, 01535 fn_suffix, sub_header, 0./0.)); 01536 01537 KMO_TRY_EXIT_IF_ERROR( 01538 kmo_dfs_save_image(stored_ycal[sx], filename_ycal, 01539 fn_suffix, sub_header, 0./0.)); 01540 01541 // save edge_pars-frame 01542 KMO_TRY_EXIT_IF_NULL( 01543 extname = kmo_extname_creator(list_frame, i, EXT_DATA)); 01544 KMO_TRY_EXIT_IF_ERROR( 01545 kmclipm_update_property_string(sub_header, EXTNAME, 01546 extname, 01547 "FITS extension name")); 01548 cpl_free(extname); extname = NULL; 01549 01550 for (j = 0; j < KMOS_IFUS_PER_DETECTOR; j++) { 01551 KMO_TRY_EXIT_IF_ERROR( 01552 kmclipm_update_property_int(sub_header, CAL_IFU_NR, 01553 j+1+(i-1)*KMOS_IFUS_PER_DETECTOR, 01554 "IFU Number {1..24}")); 01555 01556 // save edge-parameters as product 01557 if (spec_found[sx] != CPL_ERROR_DATA_NOT_FOUND) { 01558 if (edge_table[sx][j] != NULL) { 01559 KMO_TRY_EXIT_IF_ERROR( 01560 kmo_dfs_save_table(edge_table[sx][j], filename_edge, fn_suffix, sub_header)); 01561 } else { 01562 KMO_TRY_EXIT_IF_ERROR( 01563 kmo_dfs_save_table(NULL, filename_edge, fn_suffix, sub_header)); 01564 } 01565 } else { 01566 KMO_TRY_EXIT_IF_ERROR( 01567 kmo_dfs_save_table(NULL, filename_edge, fn_suffix, sub_header)); 01568 } 01569 } 01570 01571 cpl_propertylist_delete(sub_header); sub_header = NULL; 01572 01573 cpl_image_delete(stored_flat[sx]); stored_flat[sx] = NULL; 01574 cpl_image_delete(stored_noise[sx]); stored_noise[sx] = NULL; 01575 cpl_image_delete(stored_badpix[sx]); stored_badpix[sx] = NULL; 01576 } // for (i = nr_devices) 01577 } // for (a = nr_angles) 01578 } 01579 KMO_CATCH 01580 { 01581 KMO_CATCH_MSG(); 01582 ret_val = -1; 01583 } 01584 // delete temporary files 01585 unlink(fn_flat); 01586 unlink(fn_noise); 01587 unlink(fn_badpix); 01588 01589 kmo_free_fits_desc(&desc1); 01590 kmo_free_fits_desc(&desc2); 01591 kmo_free_unused_ifus(unused_ifus_before); unused_ifus_before = NULL; 01592 kmo_free_unused_ifus(unused_ifus_after); unused_ifus_after = NULL; 01593 cpl_propertylist_delete(main_header); main_header = NULL; 01594 cpl_propertylist_delete(main_header_xcal); main_header_xcal = NULL; 01595 cpl_propertylist_delete(sub_header); sub_header = NULL; 01596 cpl_imagelist_delete(det_lamp_on); det_lamp_on = NULL; 01597 cpl_imagelist_delete(det_lamp_off); det_lamp_off = NULL; 01598 cpl_image_delete(combined_data_off); combined_data_off = NULL; 01599 cpl_image_delete(combined_noise_off); combined_noise_off = NULL; 01600 cpl_image_delete(bad_pix_mask_dark); bad_pix_mask_dark = NULL; 01601 cpl_free(stored_qc_flat_sat); stored_qc_flat_sat = NULL; 01602 cpl_free(stored_qc_flat_eff); stored_qc_flat_eff = NULL; 01603 cpl_free(stored_qc_flat_sn); stored_qc_flat_sn = NULL; 01604 cpl_free(stored_gapmean); stored_gapmean = NULL; 01605 cpl_free(stored_gapsdv); stored_gapsdv = NULL; 01606 cpl_free(stored_gapmaxdev); stored_gapmaxdev = NULL; 01607 cpl_free(stored_slitmean); stored_slitmean = NULL; 01608 cpl_free(stored_slitsdv); stored_slitsdv = NULL; 01609 cpl_free(stored_slitmaxdev); stored_slitmaxdev = NULL; 01610 cpl_free(readmode); readmode = NULL; 01611 cpl_free(suffix); suffix = NULL; 01612 cpl_free(fn_suffix); fn_suffix = NULL; 01613 if (total_bounds != NULL) { 01614 for (i = 0; i < nr_devices; i++) { 01615 cpl_free(total_bounds[i]); total_bounds[i] = NULL; 01616 } 01617 } 01618 cpl_free(total_bounds); total_bounds = NULL; 01619 for (i = 0; i < nr_devices * nr_angles; i++) { 01620 cpl_image_delete(stored_flat[i]); stored_flat[i] = NULL; 01621 cpl_image_delete(stored_noise[i]); stored_noise[i] = NULL; 01622 cpl_image_delete(stored_badpix[i]); stored_badpix[i] = NULL; 01623 cpl_image_delete(stored_xcal[i]); stored_xcal[i] = NULL; 01624 cpl_image_delete(stored_ycal[i]); stored_ycal[i] = NULL; 01625 } 01626 cpl_free(stored_flat); stored_flat = NULL; 01627 cpl_free(stored_noise); stored_noise = NULL; 01628 cpl_free(stored_badpix); stored_badpix = NULL; 01629 cpl_free(stored_xcal); stored_xcal = NULL; 01630 cpl_free(stored_ycal); stored_ycal = NULL; 01631 for (a = 0; a < nr_angles; a++) { 01632 cpl_frameset_delete(angle_frameset[a]); angle_frameset[a] = NULL; 01633 if ((all_bounds != NULL) && (all_bounds[a] != NULL)) { 01634 for (i = 0; i < nr_devices; i++) { 01635 cpl_free(all_bounds[a][i]); all_bounds[a][i] = NULL; 01636 } 01637 cpl_free(all_bounds[a]); all_bounds[a] = NULL; 01638 } 01639 } 01640 cpl_free(angle_frameset); angle_frameset = NULL; 01641 cpl_free(all_bounds); all_bounds = NULL; 01642 if (edge_table != NULL) { 01643 for (i = 0; i < KMOS_NR_DETECTORS * nr_angles; i++) { 01644 if (edge_table[i] != NULL) { 01645 for (j = 0; j < KMOS_IFUS_PER_DETECTOR; j++) { 01646 cpl_table_delete(edge_table[i][j]); 01647 edge_table[i][j] = NULL; 01648 } 01649 cpl_free(edge_table[i]); edge_table[i] = NULL; 01650 } 01651 } 01652 cpl_free(edge_table); edge_table = NULL; 01653 } 01654 if (bounds != NULL) { 01655 cpl_free(bounds); bounds = NULL; 01656 } 01657 if (spec_found != NULL) { 01658 cpl_free(spec_found); spec_found = NULL; 01659 } 01660 01661 return ret_val; 01662 } 01663
1.7.6.1