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