KMOS Pipeline Reference Manual
1.3.0
|
00001 /* 00002 * This file is part of the KMOS Pipeline 00003 * Copyright (C) 2002,2003 European Southern Observatory 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License as published by 00007 * the Free Software Foundation; either version 2 of the License, or 00008 * (at your option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 * GNU General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU General Public License 00016 * along with this program; if not, write to the Free Software 00017 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00018 */ 00019 00020 #ifdef HAVE_CONFIG_H 00021 #include <config.h> 00022 #endif 00023 00024 /*----------------------------------------------------------------------------- 00025 * Includes 00026 *----------------------------------------------------------------------------*/ 00027 00028 #include <string.h> 00029 #include <math.h> 00030 00031 #include <cpl.h> 00032 00033 #include "kmo_utils.h" 00034 #include "kmo_dfs.h" 00035 #include "kmo_error.h" 00036 #include "kmo_constants.h" 00037 #include "kmo_priv_dark.h" 00038 #include "kmo_priv_functions.h" 00039 #include "kmo_cpl_extensions.h" 00040 #include "kmo_debug.h" 00041 00042 /*----------------------------------------------------------------------------- 00043 * Functions prototypes 00044 *----------------------------------------------------------------------------*/ 00045 00046 static int kmo_dark_create(cpl_plugin *); 00047 static int kmo_dark_exec(cpl_plugin *); 00048 static int kmo_dark_destroy(cpl_plugin *); 00049 static int kmo_dark(cpl_parameterlist *, cpl_frameset *); 00050 00051 /*----------------------------------------------------------------------------- 00052 * Static variables 00053 *----------------------------------------------------------------------------*/ 00054 00055 static char kmo_dark_description[] = 00056 "This recipe calculates the master dark frame.\n" 00057 "\n" 00058 "It is recommended to provide three or more dark exposures to produce a\n" 00059 "reasonable master with associated noise.\n" 00060 "\n" 00061 "BASIC PARAMETERS\n" 00062 "----------------\n" 00063 "--pos_bad_pix_rej\n" 00064 "--neg_bad_pix_rej\n" 00065 "Bad pixels above and below defined positive/negative threshold levels will\n" 00066 "be flagged and output to the BADPIX_DARK frame.\n" 00067 "The number of bad pixels is returned as a QC1 parameter.\n" 00068 "The two parameters can be used to change these thresholds.\n" 00069 "\n" 00070 "--cmethod\n" 00071 "Following methods of frame combination are available:\n" 00072 " * 'ksigma' (Default)\n" 00073 " An iterative sigma clipping. For each position all pixels in the\n" 00074 " spectrum are examined. If they deviate significantly, they will be\n" 00075 " rejected according to the conditions:\n" 00076 " val > mean + stdev * cpos_rej\n" 00077 " and\n" 00078 " val < mean - stdev * cneg_rej\n" 00079 " where --cpos_rej, --cneg_rej and --citer are the wished parameters\n" 00080 " In the first iteration median and percentile level are used.\n" 00081 " * 'median'\n" 00082 " At each pixel position the median is calculated.\n" 00083 " * 'average'\n" 00084 " At each pixel position the average is calculated.\n" 00085 " * 'sum'\n" 00086 " At each pixel position the sum is calculated.\n" 00087 " * 'min_max'\n" 00088 " The specified number of min and max pixel values will be rejected.\n" 00089 " --cmax and --cmin apply to this method.\n" 00090 "\n" 00091 "--file_extension\n" 00092 "Set this parameter to TRUE if the EXPTIME keyword should be appended to\n" 00093 "the output filenames.\n" 00094 "\n" 00095 "ADVANCED PARAMETERS\n" 00096 "-------------------\n" 00097 "--cpos_rej\n" 00098 "--cneg_rej\n" 00099 "--citer\n" 00100 " see --cmethod='ksigma'\n" 00101 "--cmax\n" 00102 "--cmin\n" 00103 " see --cmethod='min_max'\n" 00104 "\n" 00105 "---------------------------------------------------------------------------\n" 00106 "Input files:\n" 00107 " DO CATG Type Explanation Required #Frames\n" 00108 " ------- ----- ----------- -------- -------\n" 00109 " DARK RAW Dark exposures Y 1-n \n" 00110 " (at least 3 frames recommended) \n" 00111 "\n" 00112 "Output files:\n" 00113 " DO CATG Type Explanation\n" 00114 " ------- ----- -----------\n" 00115 " MASTER_DARK F2D Calculated master dark frames\n" 00116 " BADPIXEL_DARK B2D Associated badpixel frames\n" 00117 "---------------------------------------------------------------------------" 00118 "\n"; 00119 00120 /*----------------------------------------------------------------------------- 00121 * Functions code 00122 *----------------------------------------------------------------------------*/ 00123 00130 /*----------------------------------------------------------------------------*/ 00139 /*----------------------------------------------------------------------------*/ 00140 int cpl_plugin_get_info(cpl_pluginlist *list) 00141 { 00142 cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe); 00143 cpl_plugin *plugin = &recipe->interface; 00144 00145 cpl_plugin_init(plugin, 00146 CPL_PLUGIN_API, 00147 KMOS_BINARY_VERSION, 00148 CPL_PLUGIN_TYPE_RECIPE, 00149 "kmo_dark", 00150 "Create master dark frame & bad pixel mask", 00151 kmo_dark_description, 00152 "Alex Agudo Berbel", 00153 "usd-help@eso.org", 00154 kmos_get_license(), 00155 kmo_dark_create, 00156 kmo_dark_exec, 00157 kmo_dark_destroy); 00158 00159 cpl_pluginlist_append(list, plugin); 00160 00161 return 0; 00162 } 00163 00164 /*----------------------------------------------------------------------------*/ 00172 /*----------------------------------------------------------------------------*/ 00173 static int kmo_dark_create(cpl_plugin *plugin) 00174 { 00175 cpl_recipe *recipe; 00176 cpl_parameter *p; 00177 00178 /* Check that the plugin is part of a valid recipe */ 00179 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00180 recipe = (cpl_recipe *)plugin; 00181 else 00182 return -1; 00183 00184 /* Create the parameters list in the cpl_recipe object */ 00185 recipe->parameters = cpl_parameterlist_new(); 00186 00187 /* Fill the parameters list */ 00188 00189 /* --pos_bad_pix_rej */ 00190 p = cpl_parameter_new_value("kmos.kmo_dark.pos_bad_pix_rej", 00191 CPL_TYPE_DOUBLE, "The positive rejection threshold for bad pixels", 00192 "kmos.kmo_dark", 50.0); 00193 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "pos_bad_pix_rej"); 00194 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00195 cpl_parameterlist_append(recipe->parameters, p); 00196 00197 /* --neg_bad_pix_rej */ 00198 p = cpl_parameter_new_value("kmos.kmo_dark.neg_bad_pix_rej", 00199 CPL_TYPE_DOUBLE, "The negative rejection threshold for bad pixels", 00200 "kmos.kmo_dark", 50.0); 00201 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "neg_bad_pix_rej"); 00202 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00203 cpl_parameterlist_append(recipe->parameters, p); 00204 00205 /* --file_extension */ 00206 p = cpl_parameter_new_value("kmos.kmo_dark.file_extension", CPL_TYPE_BOOL, 00207 "Controls if EXPTIME should be appended to product filenames", 00208 "kmos.kmo_dark", FALSE); 00209 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "file_extension"); 00210 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00211 cpl_parameterlist_append(recipe->parameters, p); 00212 00213 return kmo_combine_pars_create(recipe->parameters, "kmos.kmo_dark", 00214 DEF_REJ_METHOD, FALSE); 00215 } 00216 00217 /*----------------------------------------------------------------------------*/ 00223 /*----------------------------------------------------------------------------*/ 00224 static int kmo_dark_exec(cpl_plugin *plugin) 00225 { 00226 cpl_recipe *recipe; 00227 00228 /* Get the recipe out of the plugin */ 00229 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00230 recipe = (cpl_recipe *)plugin; 00231 else return -1; 00232 00233 return kmo_dark(recipe->parameters, recipe->frames); 00234 } 00235 00236 /*----------------------------------------------------------------------------*/ 00242 /*----------------------------------------------------------------------------*/ 00243 static int kmo_dark_destroy(cpl_plugin *plugin) 00244 { 00245 cpl_recipe *recipe; 00246 00247 /* Get the recipe out of the plugin */ 00248 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00249 recipe = (cpl_recipe *)plugin; 00250 else return -1 ; 00251 00252 cpl_parameterlist_delete(recipe->parameters); 00253 return 0 ; 00254 } 00255 00256 /*----------------------------------------------------------------------------*/ 00267 /*----------------------------------------------------------------------------*/ 00268 static int kmo_dark(cpl_parameterlist *parlist, cpl_frameset *frameset) 00269 { 00270 cpl_imagelist *detector_in_window = NULL; 00271 cpl_image *img_in_window = NULL, 00272 *combined_data = NULL, 00273 *combined_data_window = NULL, 00274 *combined_noise = NULL, 00275 *combined_noise_window = NULL, 00276 *bad_pix_mask = NULL, 00277 *bad_pix_mask_window = NULL; 00278 cpl_frame *frame = NULL; 00279 int ret_val = 0, 00280 nr_devices = 0, 00281 i = 0, 00282 cmax = 0, 00283 cmin = 0, 00284 citer = 0, 00285 nx = 0, 00286 ny = 0, 00287 nx_orig = 0, 00288 ny_orig = 0, 00289 nz = 0, 00290 ndit = 0, 00291 file_extension = FALSE; 00292 double cpos_rej = 0.0, 00293 cneg_rej = 0.0, 00294 exptime = 0.0, 00295 gain = 0.0, 00296 pos_bad_pix_rej = 0.0, 00297 neg_bad_pix_rej = 0.0, 00298 qc_dark = 0.0, 00299 qc_dark_median = 0.0, 00300 qc_readnoise = 0.0, 00301 qc_readnoise_median = 0.0, 00302 qc_bad_pix_num = 0.0; 00303 const char *cmethod = NULL, 00304 *my_method = NULL; 00305 00306 char *filename = NULL, 00307 *filename_bad = NULL, 00308 *extname = NULL; 00309 cpl_propertylist *main_header = NULL, 00310 *sub_header = NULL; 00311 main_fits_desc desc1, desc2; 00312 char do_mode[256]; 00313 00314 KMO_TRY 00315 { 00316 kmo_init_fits_desc(&desc1); 00317 kmo_init_fits_desc(&desc2); 00318 00319 // --- check inputs --- 00320 KMO_TRY_ASSURE((parlist != NULL) && (frameset != NULL), 00321 CPL_ERROR_NULL_INPUT, "Not all input data is provided!"); 00322 00323 if (cpl_frameset_count_tags(frameset, DARK) < 3) { 00324 cpl_msg_warning(cpl_func, 00325 "It is recommended to provide at least 3 DARK frames!"); 00326 } 00327 00328 if (cpl_frameset_count_tags(frameset, DARK) >= 1) { 00329 strcpy(do_mode, DARK); 00330 } else { 00331 strcpy(do_mode, "0"); 00332 } 00333 00334 KMO_TRY_ASSURE(kmo_dfs_set_groups(frameset, "kmo_dark") == 1, 00335 CPL_ERROR_ILLEGAL_INPUT, 00336 "Cannot identify RAW and CALIB frames!"); 00337 00338 // --- get parameters --- 00339 cpl_msg_info("", "--- Parameter setup for kmo_dark ----------"); 00340 00341 pos_bad_pix_rej = kmo_dfs_get_parameter_double(parlist, 00342 "kmos.kmo_dark.pos_bad_pix_rej"); 00343 KMO_TRY_CHECK_ERROR_STATE(); 00344 KMO_TRY_EXIT_IF_ERROR(kmo_dfs_print_parameter_help(parlist, 00345 "kmos.kmo_dark.pos_bad_pix_rej")); 00346 00347 neg_bad_pix_rej = kmo_dfs_get_parameter_double(parlist, 00348 "kmos.kmo_dark.neg_bad_pix_rej"); 00349 KMO_TRY_CHECK_ERROR_STATE(); 00350 KMO_TRY_EXIT_IF_ERROR(kmo_dfs_print_parameter_help(parlist, 00351 "kmos.kmo_dark.neg_bad_pix_rej")); 00352 00353 file_extension = kmo_dfs_get_parameter_bool(parlist, 00354 "kmos.kmo_dark.file_extension"); 00355 KMO_TRY_CHECK_ERROR_STATE(); 00356 KMO_TRY_EXIT_IF_ERROR(kmo_dfs_print_parameter_help(parlist, 00357 "kmos.kmo_dark.file_extension")); 00358 00359 KMO_TRY_ASSURE((file_extension == TRUE) || (file_extension == FALSE), 00360 CPL_ERROR_ILLEGAL_INPUT, "extension must be TRUE or FALSE!"); 00361 00362 KMO_TRY_EXIT_IF_ERROR(kmo_combine_pars_load(parlist, "kmos.kmo_dark", 00363 &cmethod, &cpos_rej, &cneg_rej, &citer, &cmin,&cmax,FALSE)); 00364 00365 cpl_msg_info("", "-------------------------------------------"); 00366 cpl_msg_info("", "Detected instrument setup:"); 00367 cpl_msg_info("", " not checked here"); 00368 cpl_msg_info("", "-------------------------------------------"); 00369 cpl_msg_info("", "IFU status before processing:"); 00370 cpl_msg_info("", " not checked here"); 00371 cpl_msg_info("", "-------------------------------------------"); 00372 00373 KMO_TRY_EXIT_IF_NULL(frame = kmo_dfs_get_frame(frameset, do_mode)); 00374 00375 i = 0; 00376 while (frame != NULL) { 00377 main_header = kmclipm_propertylist_load( 00378 cpl_frame_get_filename(frame), 0); 00379 if (cpl_error_get_code() != CPL_ERROR_NONE) { 00380 cpl_msg_error(cpl_func, "File '%s' not found", 00381 cpl_frame_get_filename(frame)); 00382 KMO_TRY_CHECK_ERROR_STATE(); 00383 } 00384 00385 if (i == 0) { 00386 exptime = cpl_propertylist_get_double(main_header, EXPTIME); 00387 KMO_TRY_CHECK_ERROR_STATE("EXPTIME missing in main header"); 00388 00389 ndit = cpl_propertylist_get_int(main_header, NDIT); 00390 KMO_TRY_CHECK_ERROR_STATE("NDIT missing in main header"); 00391 00392 if (file_extension) { 00393 /* Delete trailing zeros */ 00394 /* If zero right after decimal point,delete point as well */ 00395 char *exptimeStr = cpl_sprintf("%g", exptime); 00396 char *p = 0; 00397 for(p=exptimeStr; *p; ++p) { 00398 if('.' == *p) { 00399 while(*++p); 00400 while('0'==*--p) *p = '\0'; 00401 if(*p == '.') *p = '\0'; 00402 break; 00403 } 00404 } 00405 filename = cpl_sprintf("%s_%s", MASTER_DARK, exptimeStr); 00406 filename_bad = cpl_sprintf("%s_%s", BADPIXEL_DARK, 00407 exptimeStr); 00408 cpl_free(exptimeStr); exptimeStr = NULL; 00409 } else { 00410 filename = cpl_sprintf("%s", MASTER_DARK); 00411 filename_bad = cpl_sprintf("%s", BADPIXEL_DARK); 00412 } 00413 desc1 = kmo_identify_fits_header(cpl_frame_get_filename(frame)); 00414 KMO_TRY_CHECK_ERROR_STATE_MSG( 00415 "First fits file doesn't seem to be in KMOS-format!"); 00416 00417 KMO_TRY_ASSURE(desc1.fits_type == raw_fits, 00418 CPL_ERROR_ILLEGAL_INPUT, 00419 "First input file wrong data type - must be RAW"); 00420 } else { 00421 desc2 = kmo_identify_fits_header(cpl_frame_get_filename(frame)); 00422 KMO_TRY_CHECK_ERROR_STATE_MSG( 00423 "Fits file doesn't seem to be in KMOS-format!"); 00424 KMO_TRY_ASSURE(desc2.fits_type == raw_fits, 00425 CPL_ERROR_ILLEGAL_INPUT, 00426 "Input file wrong data type - must be a RAW)"); 00427 kmo_free_fits_desc(&desc2); 00428 } 00429 00430 // check if all lamps are off (flat and arc lamp) 00431 KMO_TRY_ASSURE(( 00432 (kmo_check_lamp(main_header, INS_LAMP1_ST) == FALSE) && 00433 (kmo_check_lamp(main_header, INS_LAMP2_ST) == FALSE) && 00434 (kmo_check_lamp(main_header, INS_LAMP3_ST) == FALSE) && 00435 (kmo_check_lamp(main_header, INS_LAMP4_ST) == FALSE)) || 00436 (((kmo_check_lamp(main_header, INS_LAMP1_ST) == TRUE) || 00437 (kmo_check_lamp(main_header, INS_LAMP2_ST) == TRUE) || 00438 (kmo_check_lamp(main_header, INS_LAMP3_ST) == TRUE) || 00439 (kmo_check_lamp(main_header, INS_LAMP4_ST) == TRUE)) && 00440 (strcmp(cpl_propertylist_get_string(main_header, "ESO INS FILT1 ID"), "Block") == 0) && 00441 (strcmp(cpl_propertylist_get_string(main_header, "ESO INS FILT2 ID"), "Block") == 0) && 00442 (strcmp(cpl_propertylist_get_string(main_header, "ESO INS FILT3 ID"), "Block") == 0)), 00443 CPL_ERROR_ILLEGAL_INPUT, 00444 "All lamps must be switched off for DARK frames!"); 00445 00446 // check if EXPTIME and NDIT are the same for all frames 00447 if (cpl_propertylist_get_double(main_header, EXPTIME) != exptime) { 00448 cpl_msg_warning(cpl_func, 00449 "EXPTIME isn't the same for all frames: (is %g and %g)", 00450 cpl_propertylist_get_double(main_header, EXPTIME), 00451 exptime); 00452 } 00453 00454 if (cpl_propertylist_get_int(main_header, NDIT) != ndit) { 00455 cpl_msg_warning(cpl_func, 00456 "NDIT isn't the same for all frames: (is %d and %d)", 00457 cpl_propertylist_get_int(main_header, NDIT), ndit); 00458 } 00459 00460 /* Get next DARK frame */ 00461 frame = kmo_dfs_get_frame(frameset, NULL); 00462 KMO_TRY_CHECK_ERROR_STATE(); 00463 00464 cpl_propertylist_delete(main_header); main_header = NULL; 00465 i++; 00466 } 00467 00468 /* --- load, update & save primary header --- */ 00469 KMO_TRY_EXIT_IF_NULL(frame = kmo_dfs_get_frame(frameset, do_mode)); 00470 KMO_TRY_EXIT_IF_ERROR(kmo_dfs_save_main_header(frameset, 00471 filename, "", frame, NULL, parlist, cpl_func)); 00472 KMO_TRY_EXIT_IF_ERROR(kmo_dfs_save_main_header(frameset, 00473 filename_bad, "", frame, NULL, parlist, cpl_func)); 00474 00475 /* --- load data --- */ 00476 nr_devices = desc1.nr_ext; 00477 00478 /* Use average method in case there is only 1 input */ 00479 my_method = cmethod; 00480 if ((cpl_frameset_count_tags(frameset, DARK) == 1) || 00481 (cpl_frameset_count_tags(frameset, COMMANDLINE) == 1)) { 00482 cpl_msg_warning(cpl_func, 00483 "cmethod is set to 'average' since there is only 1 input"); 00484 my_method = "average"; 00485 } 00486 00487 /* Get size of input frame */ 00488 KMO_TRY_EXIT_IF_NULL(img_in_window = kmo_dfs_load_image(frameset, 00489 do_mode, 1, FALSE, FALSE, NULL)); 00490 nx_orig = cpl_image_get_size_x(img_in_window); 00491 ny_orig = cpl_image_get_size_y(img_in_window); 00492 cpl_image_delete(img_in_window); img_in_window = NULL; 00493 KMO_TRY_ASSURE((nx_orig > 2*KMOS_BADPIX_BORDER) && 00494 (ny_orig > 2*KMOS_BADPIX_BORDER), CPL_ERROR_ILLEGAL_INPUT, 00495 "Input frames must have a height and width of at least 9 pix"); 00496 00497 /* --- loop through all detectors --- */ 00498 for (i = 1; i <= nr_devices; i++) { 00499 cpl_msg_info(cpl_func, "Processing detector No. %d", i); 00500 00501 KMO_TRY_EXIT_IF_NULL(detector_in_window = cpl_imagelist_new()); 00502 KMO_TRY_EXIT_IF_NULL(sub_header = 00503 kmo_dfs_load_sub_header(frameset, do_mode, i, FALSE)); 00504 00505 // load data of device i of all DARK frames into an imagelist 00506 KMO_TRY_EXIT_IF_NULL( 00507 img_in_window = kmo_dfs_load_image_window(frameset, do_mode, i, 00508 FALSE, KMOS_BADPIX_BORDER+1, KMOS_BADPIX_BORDER+1, 00509 nx_orig-KMOS_BADPIX_BORDER, ny_orig-KMOS_BADPIX_BORDER, 00510 FALSE, NULL)); 00511 00512 nx = cpl_image_get_size_x(img_in_window); 00513 ny = cpl_image_get_size_y(img_in_window); 00514 nz = 0; 00515 while (img_in_window != NULL) { 00516 cpl_imagelist_set(detector_in_window, img_in_window, nz); 00517 KMO_TRY_CHECK_ERROR_STATE(); 00518 00519 /* Load same extension of next DARK frame */ 00520 img_in_window = kmo_dfs_load_image_window(frameset, NULL, i, 00521 FALSE, KMOS_BADPIX_BORDER+1, KMOS_BADPIX_BORDER+1, 00522 nx_orig-KMOS_BADPIX_BORDER, ny_orig-KMOS_BADPIX_BORDER, 00523 FALSE, NULL); 00524 KMO_TRY_CHECK_ERROR_STATE(); 00525 00526 if (img_in_window != NULL) { 00527 KMO_TRY_ASSURE((nx==cpl_image_get_size_x(img_in_window)) && 00528 (ny == cpl_image_get_size_y(img_in_window)), 00529 CPL_ERROR_ILLEGAL_INPUT, 00530 "Not all input frames have the same dimensions"); 00531 } 00532 nz++; 00533 } 00534 00535 /* Combine imagelist (data only) and create noise */ 00536 KMO_TRY_EXIT_IF_ERROR( 00537 kmclipm_combine_frames(detector_in_window, NULL, NULL, 00538 my_method, cpos_rej, cneg_rej, citer, cmax, cmin, 00539 &combined_data_window, &combined_noise_window, -1.0)); 00540 00541 if (kmclipm_omit_warning_one_slice > 10) { 00542 kmclipm_omit_warning_one_slice = FALSE; 00543 } 00544 00545 /* Calculate preliminary mean and stdev to create the BPM */ 00546 qc_dark = cpl_image_get_mean(combined_data_window); 00547 KMO_TRY_CHECK_ERROR_STATE(); 00548 00549 /* Check the noise frame (NULL or ALL pixels are bad) */ 00550 if (combined_noise_window == NULL || 00551 cpl_image_count_rejected(combined_noise_window) == 00552 cpl_image_get_size_x(combined_noise_window)* 00553 cpl_image_get_size_y(combined_noise_window)) { 00554 qc_readnoise = cpl_image_get_stdev(combined_data_window); 00555 } else { 00556 if (nz > 2) qc_readnoise = 00557 cpl_image_get_mean(combined_noise_window); 00558 else if (nz == 2) qc_readnoise = 00559 cpl_image_get_stdev(combined_noise_window); 00560 else if (nz == 1) qc_readnoise = 00561 cpl_image_get_stdev(combined_data_window); 00562 else 00563 KMO_TRY_ASSURE(1 == 0, CPL_ERROR_ILLEGAL_INPUT, 00564 "Detector frame must have at least one frame"); 00565 } 00566 KMO_TRY_CHECK_ERROR_STATE(); 00567 00568 /* Create bad-pixel-mask */ 00569 qc_bad_pix_num = kmo_create_bad_pix_dark(combined_data_window, 00570 qc_dark, qc_readnoise, pos_bad_pix_rej, neg_bad_pix_rej, 00571 &bad_pix_mask_window); 00572 KMO_TRY_CHECK_ERROR_STATE(); 00573 00574 KMO_TRY_EXIT_IF_ERROR( 00575 kmclipm_update_property_int(sub_header, QC_NR_BAD_PIX, 00576 qc_bad_pix_num, "[] nr. of bad pixels")); 00577 00578 00579 /* Calculate QC.DARK, QC.READNOISE, QC.DARK.MEDIAN, */ 00580 /* QC.READNOISE.MEDIAN, QC.DARKCUR */ 00581 00582 /* Badpixels from combined_data_window are already rejected */ 00583 /* by kmo_create_bad_pix_dark() */ 00584 KMO_TRY_EXIT_IF_ERROR(kmo_image_reject_from_mask( 00585 combined_noise_window, bad_pix_mask_window)); 00586 qc_dark = cpl_image_get_mean(combined_data_window); 00587 qc_dark_median = cpl_image_get_median(combined_data_window); 00588 KMO_TRY_CHECK_ERROR_STATE(); 00589 00590 /* Check the noise frame (NULL or ALL pixels are bad) */ 00591 /* Calculate mean and stddev of combined frames (with rejection) */ 00592 if (combined_noise_window == NULL || 00593 cpl_image_count_rejected(combined_noise_window) == 00594 cpl_image_get_size_x(combined_noise_window)* 00595 cpl_image_get_size_y(combined_noise_window)) { 00596 qc_readnoise = cpl_image_get_stdev(combined_data_window); 00597 qc_readnoise_median = 00598 kmo_image_get_stdev_median(combined_data_window); 00599 } else { 00600 if (nz > 2) { 00601 qc_readnoise = 00602 cpl_image_get_mean(combined_noise_window) * sqrt(nz) ; 00603 qc_readnoise_median = 00604 cpl_image_get_median(combined_noise_window) * sqrt(nz); 00605 } else if (nz == 2) { 00606 qc_readnoise = 00607 cpl_image_get_stdev(combined_noise_window) * sqrt(nz) ; 00608 qc_readnoise_median = sqrt(nz) * 00609 kmo_image_get_stdev_median(combined_noise_window) ; 00610 } else if (nz == 1) { 00611 qc_readnoise = 00612 cpl_image_get_stdev(combined_data_window); 00613 qc_readnoise_median = 00614 kmo_image_get_stdev_median(combined_data_window); 00615 } else { 00616 KMO_TRY_ASSURE(1 == 0, CPL_ERROR_ILLEGAL_INPUT, 00617 "Detector frame must have at least one frame"); 00618 } 00619 } 00620 KMO_TRY_CHECK_ERROR_STATE(); 00621 00622 KMO_TRY_EXIT_IF_ERROR(kmclipm_update_property_double(sub_header, 00623 QC_DARK, qc_dark, "[adu] mean of master dark")); 00624 KMO_TRY_EXIT_IF_ERROR(kmclipm_update_property_double(sub_header, 00625 QC_READNOISE, qc_readnoise, 00626 "[adu] mean noise of master dark")); 00627 KMO_TRY_EXIT_IF_ERROR(kmclipm_update_property_double(sub_header, 00628 QC_DARK_MEDIAN, qc_dark_median, 00629 "[adu] median of master dark")); 00630 KMO_TRY_EXIT_IF_ERROR(kmclipm_update_property_double(sub_header, 00631 QC_READNOISE_MEDIAN, qc_readnoise_median, 00632 "[adu] median noise of master dark")); 00633 00634 /* Load gain */ 00635 gain = kmo_dfs_get_property_double(sub_header, GAIN); 00636 KMO_TRY_CHECK_ERROR_STATE_MSG( 00637 "GAIN-keyword in fits-header is missing!"); 00638 00639 KMO_TRY_EXIT_IF_ERROR(kmclipm_update_property_double(sub_header, 00640 QC_DARK_CURRENT, qc_dark / exptime / gain, 00641 "[e-/s] dark current")); 00642 00643 /* Save dark frame */ 00644 KMO_TRY_EXIT_IF_NULL(extname = kmo_extname_creator(detector_frame, 00645 i, EXT_DATA)); 00646 KMO_TRY_EXIT_IF_ERROR(kmclipm_update_property_string(sub_header, 00647 EXTNAME, extname, "FITS extension name")); 00648 cpl_free(extname); extname = NULL; 00649 00650 KMO_TRY_EXIT_IF_NULL(combined_data = 00651 kmo_add_bad_pix_border(combined_data_window, TRUE)); 00652 00653 KMO_TRY_EXIT_IF_ERROR(kmo_dfs_save_image(combined_data, 00654 filename, "", sub_header, 0./0.)); 00655 00656 /* Save noise frame */ 00657 KMO_TRY_EXIT_IF_NULL(extname = kmo_extname_creator(detector_frame, 00658 i, EXT_NOISE)); 00659 KMO_TRY_EXIT_IF_ERROR(kmclipm_update_property_string(sub_header, 00660 EXTNAME, extname, "FITS extension name")); 00661 cpl_free(extname); extname = NULL; 00662 00663 KMO_TRY_EXIT_IF_NULL(combined_noise = 00664 kmo_add_bad_pix_border(combined_noise_window, TRUE)); 00665 00666 KMO_TRY_EXIT_IF_ERROR(kmo_dfs_save_image(combined_noise, 00667 filename, "", sub_header, 0./0.)); 00668 00669 /* Save bad_pix frame */ 00670 KMO_TRY_EXIT_IF_NULL( 00671 extname = kmo_extname_creator(detector_frame, i, EXT_BADPIX)); 00672 KMO_TRY_EXIT_IF_ERROR(kmclipm_update_property_string(sub_header, 00673 EXTNAME, extname, "FITS extension name")); 00674 cpl_free(extname); extname = NULL; 00675 00676 KMO_TRY_EXIT_IF_NULL(bad_pix_mask = 00677 kmo_add_bad_pix_border(bad_pix_mask_window, FALSE)); 00678 KMO_TRY_EXIT_IF_ERROR(kmo_dfs_save_image(bad_pix_mask, 00679 filename_bad, "", sub_header, 0.)); 00680 00681 /* Free memory */ 00682 cpl_propertylist_delete(sub_header); sub_header = NULL; 00683 cpl_imagelist_delete(detector_in_window); detector_in_window = NULL; 00684 cpl_image_delete(combined_data); combined_data = NULL; 00685 cpl_image_delete(combined_data_window); combined_data_window = NULL; 00686 cpl_image_delete(combined_noise); combined_noise = NULL; 00687 cpl_image_delete(combined_noise_window); combined_noise_window=NULL; 00688 cpl_image_delete(bad_pix_mask); bad_pix_mask = NULL; 00689 cpl_image_delete(bad_pix_mask_window); bad_pix_mask_window = NULL; 00690 } // for i = [1, nr_devices] 00691 00692 cpl_msg_info("", "-------------------------------------------"); 00693 cpl_msg_info("", "IFU status after processing:"); 00694 cpl_msg_info("", " not checked here"); 00695 cpl_msg_info("", "-------------------------------------------"); 00696 } 00697 KMO_CATCH 00698 { 00699 KMO_CATCH_MSG(); 00700 kmo_free_fits_desc(&desc2); 00701 ret_val = -1; 00702 } 00703 00704 kmo_free_fits_desc(&desc1); 00705 cpl_free(filename); filename = NULL; 00706 cpl_free(filename_bad); filename_bad = NULL; 00707 cpl_propertylist_delete(main_header); main_header = NULL; 00708 cpl_propertylist_delete(sub_header); sub_header = NULL; 00709 cpl_imagelist_delete(detector_in_window); detector_in_window = NULL; 00710 cpl_image_delete(combined_data); combined_data = NULL; 00711 cpl_image_delete(combined_data_window); combined_data_window = NULL; 00712 cpl_image_delete(combined_noise); combined_noise = NULL; 00713 cpl_image_delete(combined_noise_window); combined_noise_window = NULL; 00714 cpl_image_delete(bad_pix_mask); bad_pix_mask = NULL; 00715 cpl_image_delete(bad_pix_mask_window); bad_pix_mask_window = NULL; 00716 00717 return ret_val; 00718 } 00719