|
KMOS Pipeline Reference Manual
1.0.7
|
00001 /* $Id: kmo_illumination.c,v 1.36 2013/02/02 17:47:55 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/02/02 17:47:55 $ 00024 * $Revision: 1.36 $ 00025 * $Name: HEAD $ 00026 */ 00027 00028 #ifdef HAVE_CONFIG_H 00029 #include <config.h> 00030 #endif 00031 00032 /*----------------------------------------------------------------------------- 00033 * Includes 00034 *----------------------------------------------------------------------------*/ 00035 00036 #include <math.h> 00037 #include <string.h> 00038 00039 #include <cpl.h> 00040 00041 #include "kmo_priv_reconstruct.h" 00042 #include "kmo_priv_functions.h" 00043 #include "kmo_functions.h" 00044 #include "kmo_cpl_extensions.h" 00045 #include "kmo_dfs.h" 00046 #include "kmo_error.h" 00047 #include "kmo_constants.h" 00048 #include "kmo_debug.h" 00049 00050 /*----------------------------------------------------------------------------- 00051 * Functions prototypes 00052 *----------------------------------------------------------------------------*/ 00053 00054 static int kmo_illumination_create(cpl_plugin *); 00055 static int kmo_illumination_exec(cpl_plugin *); 00056 static int kmo_illumination_destroy(cpl_plugin *); 00057 static int kmo_illumination(cpl_parameterlist *, cpl_frameset *); 00058 00059 /*----------------------------------------------------------------------------- 00060 * Static variables 00061 *----------------------------------------------------------------------------*/ 00062 00063 static char kmo_illumination_description[] = 00064 "This recipe creates the spatial non-uniformity calibration frame needed for\n" 00065 "all three detectors. It must be called after the kmo_wave_cal-recipe, which\n" 00066 "generates the spectral calibration frame needed in this recipe. As input at\n" 00067 "least a sky, a master dark, a master flat and the spatial and spectral cali-\n" 00068 "bration frames are required.\n" 00069 "\n" 00070 "BASIC PARAMETERS:\n" 00071 "-----------------\n" 00072 "--imethod\n" 00073 "The interpolation method used for reconstruction.\n" 00074 "\n" 00075 "--range\n" 00076 "The spectral range [um] to combine when collapsing the reconstructed cubes.\n" 00077 "\n" 00078 "ADVANCED PARAMETERS\n" 00079 "-------------------\n" 00080 "--neighborhoodRange\n" 00081 "Defines the range to search for neighbors during reconstruction\n" 00082 "\n" 00083 "--b_samples\n" 00084 "The number of samples in spectral direction for the reconstructed cube.\n" 00085 "Ideally this number should be greater than 2048, the detector size.\n" 00086 "\n" 00087 "--b_start\n" 00088 "--b_end\n" 00089 "Used to define manually the start and end wavelength for the reconstructed\n" 00090 "cube. By default the internally defined values are used.\n" 00091 "\n" 00092 "--cmethod\n" 00093 "Following methods of frame combination are available:\n" 00094 " * 'ksigma' (Default)\n" 00095 " An iterative sigma clipping. For each position all pixels in the spectrum\n" 00096 " are examined. If they deviate significantly, they will be rejected according\n" 00097 " to the conditions:\n" 00098 " val > mean + stdev * cpos_rej\n" 00099 " and\n" 00100 " val < mean - stdev * cneg_rej\n" 00101 " where --cpos_rej, --cneg_rej and --citer are the corresponding configuration\n" 00102 " parameters. In the first iteration median and percentile level are used.\n" 00103 "\n" 00104 " * 'median'\n" 00105 " At each pixel position the median is calculated.\n" 00106 "\n" 00107 " * 'average'\n" 00108 " At each pixel position the average is calculated.\n" 00109 "\n" 00110 " * 'sum'\n" 00111 " At each pixel position the sum is calculated.\n" 00112 "\n" 00113 " * 'min_max'\n" 00114 " The specified number of minimum and maximum pixel values will be rejected.\n" 00115 " --cmax and --cmin apply to this method.\n" 00116 "\n" 00117 "--cpos_rej\n" 00118 "--cneg_rej\n" 00119 "--citer\n" 00120 "see --cmethod='ksigma'\n" 00121 "\n" 00122 "--cmax\n" 00123 "--cmin\n" 00124 "see --cmethod='min_max'\n" 00125 "\n" 00126 "-------------------------------------------------------------------------------\n" 00127 " Input files:\n" 00128 "\n" 00129 " DO KMOS \n" 00130 " category Type Explanation Required #Frames\n" 00131 " -------- ----- ----------- -------- -------\n" 00132 " FLAT_SKY F2D Sky exposures Y 1-n \n" 00133 " (at least 3 frames recommended) \n" 00134 " MASTER_DARK F2D Master dark Y 1 \n" 00135 " MASTER_FLAT F2D Master flat Y 1 \n" 00136 " XCAL F2D x calibration frame Y 1 \n" 00137 " YCAL F2D y calibration frame Y 1 \n" 00138 " LCAL F2D Wavelength calib. frame Y 1 \n" 00139 " WAVE_BAND F2L Table with start-/end-wavelengths Y 1 \n" 00140 "\n" 00141 " Output files:\n" 00142 "\n" 00143 " DO KMOS\n" 00144 " category Type Explanation\n" 00145 " -------- ----- -----------\n" 00146 " ILLUM_CORR F2I Illumination calibration frame \n" 00147 "-------------------------------------------------------------------------------\n" 00148 "\n"; 00149 00150 /*----------------------------------------------------------------------------- 00151 * Functions code 00152 *----------------------------------------------------------------------------*/ 00153 00170 int cpl_plugin_get_info(cpl_pluginlist *list) 00171 { 00172 cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe); 00173 cpl_plugin *plugin = &recipe->interface; 00174 00175 cpl_plugin_init(plugin, 00176 CPL_PLUGIN_API, 00177 KMOS_BINARY_VERSION, 00178 CPL_PLUGIN_TYPE_RECIPE, 00179 "kmo_illumination", 00180 "Create a calibration frame to correct spatial " 00181 "non-uniformity of flatfield.", 00182 kmo_illumination_description, 00183 "Alex Agudo Berbel", 00184 "agudo@mpe.mpg.de", 00185 kmos_get_license(), 00186 kmo_illumination_create, 00187 kmo_illumination_exec, 00188 kmo_illumination_destroy); 00189 00190 cpl_pluginlist_append(list, plugin); 00191 00192 return 0; 00193 } 00194 00202 static int kmo_illumination_create(cpl_plugin *plugin) 00203 { 00204 cpl_recipe *recipe; 00205 cpl_parameter *p; 00206 00207 /* Check that the plugin is part of a valid recipe */ 00208 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00209 recipe = (cpl_recipe *)plugin; 00210 else 00211 return -1; 00212 00213 /* Create the parameters list in the cpl_recipe object */ 00214 recipe->parameters = cpl_parameterlist_new(); 00215 00216 /* Fill the parameters list */ 00217 /* --imethod */ 00218 p = cpl_parameter_new_value("kmos.kmo_illumination.imethod", 00219 CPL_TYPE_STRING, 00220 "Method to use for interpolation: " 00221 "[\"NN\" (nearest neighbour), " 00222 "\"lwNN\" (linear weighted nearest neighbor)," 00223 "\"swNN\" (square weighted nearest neighbor)" 00224 "\"MS\" (Modified Shepard's method)" 00225 "\"CS\" (Cubic spline)]", 00226 "kmos.kmo_illumination", 00227 "CS"); 00228 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "imethod"); 00229 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00230 cpl_parameterlist_append(recipe->parameters, p); 00231 00232 /* --neighborhoodRange */ 00233 p = cpl_parameter_new_value("kmos.kmo_illumination.neighborhoodRange", 00234 CPL_TYPE_DOUBLE, 00235 "Defines the range to search for neighbors." 00236 "in pixels", 00237 "kmos.kmo_illumination", 00238 1.001); 00239 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "neighborhoodRange"); 00240 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00241 cpl_parameterlist_append(recipe->parameters, p); 00242 00243 /* --range */ 00244 p = cpl_parameter_new_value("kmos.kmo_illumination.range", 00245 CPL_TYPE_STRING, 00246 "The spectral ranges to combine when collapsing" 00247 "the reconstructed cubes. e.g." 00248 "\"x1_start,x1_end;x2_start,x2_end\" (microns)", 00249 "kmos.kmo_illumination", 00250 ""); 00251 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "range"); 00252 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00253 cpl_parameterlist_append(recipe->parameters, p); 00254 00255 /* --flux */ 00256 p = cpl_parameter_new_value("kmos.kmo_illumination.flux", 00257 CPL_TYPE_BOOL, 00258 "TRUE: Apply flux conservation. FALSE: otherwise", 00259 "kmos.kmo_illumination", 00260 FALSE); 00261 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "flux"); 00262 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00263 cpl_parameterlist_append(recipe->parameters, p); 00264 00265 // add parameters for band-definition 00266 kmo_band_pars_create(recipe->parameters, 00267 "kmos.kmo_illumination"); 00268 00269 // add parameters for combining 00270 return kmo_combine_pars_create(recipe->parameters, 00271 "kmos.kmo_illumination", 00272 DEF_REJ_METHOD, 00273 FALSE); 00274 } 00275 00281 static int kmo_illumination_exec(cpl_plugin *plugin) 00282 { 00283 cpl_recipe *recipe; 00284 00285 /* Get the recipe out of the plugin */ 00286 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00287 recipe = (cpl_recipe *)plugin; 00288 else return -1; 00289 00290 return kmo_illumination(recipe->parameters, recipe->frames); 00291 } 00292 00298 static int kmo_illumination_destroy(cpl_plugin *plugin) 00299 { 00300 cpl_recipe *recipe; 00301 00302 /* Get the recipe out of the plugin */ 00303 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00304 recipe = (cpl_recipe *)plugin; 00305 else return -1 ; 00306 00307 cpl_parameterlist_delete(recipe->parameters); 00308 return 0 ; 00309 } 00310 00325 static int kmo_illumination(cpl_parameterlist *parlist, cpl_frameset *frameset) 00326 { 00327 cpl_table *band_table = NULL; 00328 00329 cpl_vector *ranges = NULL, 00330 *identified_slices = NULL; 00331 00332 cpl_image *img_in = NULL, 00333 *img_dark = NULL, 00334 *img_dark_noise = NULL, 00335 *img_flat = NULL, 00336 *img_flat_noise = NULL, 00337 *combined_data = NULL, 00338 *combined_noise = NULL, 00339 *xcal = NULL, 00340 *ycal = NULL, 00341 *lcal = NULL, 00342 *data_ifu = NULL, 00343 *noise_ifu = NULL, 00344 **stored_data_images = NULL, 00345 **stored_noise_images = NULL; 00346 00347 cpl_frame *frame = NULL, 00348 *xcalFrame = NULL, 00349 *ycalFrame = NULL, 00350 *lcalFrame = NULL; 00351 00352 cpl_array *calTimestamp = NULL, 00353 **unused_ifus_before = NULL, 00354 **unused_ifus_after = NULL; 00355 00356 int ret_val = 0, 00357 nr_devices = 0, 00358 i = 0, 00359 j = 0, 00360 ifu_nr = 0, 00361 nx = 0, 00362 ny = 0, 00363 process_noise = FALSE, 00364 cmax = 0, 00365 cmin = 0, 00366 citer = 0, 00367 det_nr = 0, 00368 *bounds = NULL, 00369 count = 0, 00370 qc_max_dev_id = 0, 00371 qc_max_nonunif_id = 0, 00372 flux = FALSE; 00373 00374 const int *punused_ifus = NULL; 00375 00376 cpl_propertylist *main_header = NULL, 00377 *tmp_header = NULL, 00378 *sub_header = NULL, 00379 **stored_sub_data_headers = NULL, 00380 **stored_sub_noise_headers = NULL; 00381 00382 cpl_imagelist *cube_data = NULL, 00383 *cube_noise = NULL, 00384 *detector_in = NULL, 00385 **stored_data_cubes = NULL, 00386 **stored_noise_cubes = NULL; 00387 00388 main_fits_desc desc_sky, 00389 desc_dark, 00390 desc_flat, 00391 desc_xcal, 00392 desc_ycal, 00393 desc_lcal; 00394 00395 const char *method = NULL, 00396 *cmethod = NULL, 00397 *filter_id = NULL, 00398 *filter_id_l = NULL, 00399 *ranges_txt = NULL; 00400 00401 char *keyword = NULL, 00402 *fn_lut = NULL, 00403 *suffix = NULL, 00404 *extname = NULL; 00405 00406 00407 double cpos_rej = 0.0, 00408 cneg_rej = 0.0, 00409 neighborhoodRange = 1.001, 00410 mean_data = 0.0, 00411 ifu_crpix = 0.0, 00412 ifu_crval = 0.0, 00413 ifu_cdelt = 0.0, 00414 qc_spat_unif = 0.0, 00415 qc_max_dev = 0.0, 00416 qc_max_nonunif = 0.0, 00417 tmp_stdev = 0.0, 00418 tmp_mean = 0.0, 00419 rotangle = 0.0, 00420 tmp_rotangle = 0.0, 00421 rotangle_found = 0.0; 00422 00423 gridDefinition gd; 00424 00425 KMO_TRY 00426 { 00427 kmo_init_fits_desc(&desc_sky); 00428 kmo_init_fits_desc(&desc_dark); 00429 kmo_init_fits_desc(&desc_flat); 00430 kmo_init_fits_desc(&desc_xcal); 00431 kmo_init_fits_desc(&desc_ycal); 00432 kmo_init_fits_desc(&desc_lcal); 00433 00434 /* --- check input --- */ 00435 KMO_TRY_ASSURE((parlist != NULL) && 00436 (frameset != NULL), 00437 CPL_ERROR_NULL_INPUT, 00438 "Not all input data is provided!"); 00439 00440 KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, FLAT_SKY) >= 1, 00441 CPL_ERROR_ILLEGAL_INPUT, 00442 "One or more FLAT_SKY frames are required!"); 00443 00444 if (cpl_frameset_count_tags(frameset, FLAT_SKY) < 3) { 00445 cpl_msg_warning(cpl_func, "It is recommended to provide at least " 00446 "3 FLAT_SKY frames!"); 00447 } 00448 00449 KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, MASTER_DARK) == 1, 00450 CPL_ERROR_ILLEGAL_INPUT, 00451 "Exactly one MASTER_DARK frame is required!"); 00452 00453 KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, MASTER_FLAT) == 1, 00454 CPL_ERROR_ILLEGAL_INPUT, 00455 "Exactly one MASTER_FLAT frame is required!"); 00456 00457 KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, XCAL) == 1, 00458 CPL_ERROR_ILLEGAL_INPUT, 00459 "Exactly one XCAL frame is required!"); 00460 00461 KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, YCAL) == 1, 00462 CPL_ERROR_ILLEGAL_INPUT, 00463 "Exactly one YCAL frame is required!"); 00464 00465 KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, LCAL) == 1, 00466 CPL_ERROR_ILLEGAL_INPUT, 00467 "Exactly one LCAL frame is required!"); 00468 00469 KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, WAVE_BAND) == 1, 00470 CPL_ERROR_ILLEGAL_INPUT, 00471 "Exactly one WAVE_BAND frame is required!"); 00472 00473 KMO_TRY_ASSURE(kmo_dfs_set_groups(frameset, "kmo_illumination") == 1, 00474 CPL_ERROR_ILLEGAL_INPUT, 00475 "Cannot identify RAW and CALIB frames!"); 00476 00477 /* --- get parameters --- */ 00478 cpl_msg_info("", "--- Parameter setup for kmo_illumination ---"); 00479 00480 KMO_TRY_EXIT_IF_NULL( 00481 method = kmo_dfs_get_parameter_string(parlist, 00482 "kmos.kmo_illumination.imethod")); 00483 00484 KMO_TRY_ASSURE((strcmp(method, "NN") == 0) || 00485 (strcmp(method, "lwNN") == 0) || 00486 (strcmp(method, "swNN") == 0) || 00487 (strcmp(method, "MS") == 0) || 00488 (strcmp(method, "CS") == 0), 00489 CPL_ERROR_ILLEGAL_INPUT, 00490 "method must be either \"NN\", \"lwNN\", " 00491 "\"swNN\", \"MS\" or \"CS\"!"); 00492 00493 KMO_TRY_EXIT_IF_ERROR( 00494 kmo_dfs_print_parameter_help(parlist, 00495 "kmos.kmo_illumination.imethod")); 00496 00497 neighborhoodRange = kmo_dfs_get_parameter_double(parlist, 00498 "kmos.kmo_illumination.neighborhoodRange"); 00499 KMO_TRY_CHECK_ERROR_STATE(); 00500 00501 KMO_TRY_ASSURE(neighborhoodRange > 0.0, 00502 CPL_ERROR_ILLEGAL_INPUT, 00503 "neighborhoodRange must be greater than 0.0"); 00504 00505 KMO_TRY_EXIT_IF_ERROR( 00506 kmo_dfs_print_parameter_help(parlist, 00507 "kmos.kmo_illumination.neighborhoodRange")); 00508 00509 ranges_txt = kmo_dfs_get_parameter_string(parlist, 00510 "kmos.kmo_illumination.range"); 00511 KMO_TRY_CHECK_ERROR_STATE(); 00512 00513 KMO_TRY_EXIT_IF_ERROR( 00514 kmo_dfs_print_parameter_help(parlist, "kmos.kmo_illumination.range")); 00515 00516 ranges = kmo_identify_ranges(ranges_txt); 00517 KMO_TRY_CHECK_ERROR_STATE(); 00518 00519 flux = kmo_dfs_get_parameter_bool(parlist, 00520 "kmos.kmo_illumination.flux"); 00521 00522 KMO_TRY_ASSURE((flux == 0) || 00523 (flux == 1), 00524 CPL_ERROR_ILLEGAL_INPUT, 00525 "flux must be either FALSE or TRUE!"); 00526 00527 KMO_TRY_EXIT_IF_ERROR( 00528 kmo_dfs_print_parameter_help(parlist, "kmos.kmo_illumination.flux")); 00529 00530 kmo_band_pars_load(parlist, "kmos.kmo_illumination"); 00531 00532 KMO_TRY_EXIT_IF_ERROR( 00533 kmo_combine_pars_load(parlist, 00534 "kmos.kmo_illumination", 00535 &cmethod, 00536 &cpos_rej, 00537 &cneg_rej, 00538 &citer, 00539 &cmin, 00540 &cmax, 00541 FALSE)); 00542 cpl_msg_info("", "-------------------------------------------"); 00543 00544 // check if filter_id, grating_id and rotator offset match for all 00545 // detectors 00546 KMO_TRY_EXIT_IF_ERROR( 00547 kmo_check_frameset_setup(frameset, FLAT_SKY, 00548 TRUE, FALSE, TRUE)); 00549 KMO_TRY_EXIT_IF_ERROR( 00550 kmo_check_frame_setup(frameset, FLAT_SKY, XCAL, 00551 TRUE, FALSE, TRUE)); 00552 KMO_TRY_EXIT_IF_ERROR( 00553 kmo_check_frame_setup(frameset, XCAL, YCAL, 00554 TRUE, FALSE, TRUE)); 00555 KMO_TRY_EXIT_IF_ERROR( 00556 kmo_check_frame_setup(frameset, XCAL, LCAL, 00557 TRUE, FALSE, TRUE)); 00558 00559 // KMO_TRY_EXIT_IF_ERROR( 00560 // kmo_check_cal_frames_rotangle(frameset, XCAL, YCAL)); 00561 // KMO_TRY_EXIT_IF_ERROR( 00562 // kmo_check_cal_frames_rotangle(frameset, XCAL, LCAL)); 00563 // not tested, since MASTER_DARK needn't any particaular filter/grating 00564 // KMO_TRY_EXIT_IF_ERROR( 00565 // kmo_priv_check_frame_setup(frameset, XCAL, MASTER_DARK, 00566 // TRUE, TRUE, TRUE, 00567 // NULL)); 00568 KMO_TRY_EXIT_IF_ERROR( 00569 kmo_check_frame_setup(frameset, XCAL, MASTER_FLAT, 00570 TRUE, FALSE, TRUE)); 00571 KMO_TRY_EXIT_IF_ERROR( 00572 kmo_check_frame_setup(frameset, XCAL, BADPIXEL_FLAT, 00573 TRUE, FALSE, TRUE)); 00574 00575 KMO_TRY_EXIT_IF_NULL( 00576 frame = kmo_dfs_get_frame(frameset, XCAL)); 00577 KMO_TRY_EXIT_IF_NULL( 00578 suffix = kmo_dfs_get_suffix(frame, TRUE, FALSE)); 00579 00580 cpl_msg_info("", "Detected instrument setup: %s", suffix+1); 00581 cpl_msg_info("", "(grating 1, 2 & 3)"); 00582 00583 // check which IFUs are active for all frames 00584 KMO_TRY_EXIT_IF_NULL( 00585 unused_ifus_before = kmo_get_unused_ifus(frameset, 0, 0)); 00586 00587 KMO_TRY_EXIT_IF_NULL( 00588 unused_ifus_after = kmo_duplicate_unused_ifus(unused_ifus_before)); 00589 00590 kmo_print_unused_ifus(unused_ifus_before, FALSE); 00591 00592 // load desc for MASTER_DARK and check 00593 KMO_TRY_EXIT_IF_NULL( 00594 frame = kmo_dfs_get_frame(frameset, MASTER_DARK)); 00595 desc_dark = kmo_identify_fits_header( 00596 cpl_frame_get_filename(frame)); 00597 KMO_TRY_CHECK_ERROR_STATE_MSG("MASTER_DARK frame doesn't seem to " 00598 "be in KMOS-format!"); 00599 KMO_TRY_ASSURE((desc_dark.nr_ext == 6) && 00600 (desc_dark.ex_badpix == FALSE) && 00601 (desc_dark.fits_type == f2d_fits) && 00602 (desc_dark.frame_type == detector_frame), 00603 CPL_ERROR_ILLEGAL_INPUT, 00604 "MASTER_DARK isn't in the correct format!!!"); 00605 nx = desc_dark.naxis1; 00606 ny = desc_dark.naxis2; 00607 00608 // load desc for MASTER_FLAT and check 00609 KMO_TRY_EXIT_IF_NULL( 00610 frame = kmo_dfs_get_frame(frameset, MASTER_FLAT)); 00611 desc_flat = kmo_identify_fits_header(cpl_frame_get_filename(frame)); 00612 KMO_TRY_CHECK_ERROR_STATE_MSG("MASTER_FLAT frame doesn't seem to " 00613 "be in KMOS-format!"); 00614 KMO_TRY_ASSURE((desc_flat.nr_ext % 6 == 0) && 00615 (desc_flat.ex_badpix == FALSE) && 00616 (desc_flat.fits_type == f2d_fits) && 00617 (desc_flat.frame_type == detector_frame), 00618 CPL_ERROR_ILLEGAL_INPUT, 00619 "MASTER_FLAT isn't in the correct format!!!"); 00620 00621 // load desc for XCAL and check 00622 KMO_TRY_EXIT_IF_NULL( 00623 xcalFrame = kmo_dfs_get_frame(frameset, XCAL)); 00624 desc_xcal = kmo_identify_fits_header(cpl_frame_get_filename(xcalFrame)); 00625 KMO_TRY_CHECK_ERROR_STATE_MSG("XCAL frame doesn't seem to " 00626 "be in KMOS-format!"); 00627 KMO_TRY_ASSURE((desc_xcal.nr_ext % 3 == 0) && 00628 (desc_xcal.ex_badpix == FALSE) && 00629 (desc_xcal.fits_type == f2d_fits) && 00630 (desc_xcal.frame_type == detector_frame), 00631 CPL_ERROR_ILLEGAL_INPUT, 00632 "XCAL isn't in the correct format!!!"); 00633 KMO_TRY_ASSURE((desc_xcal.naxis1 == nx) && 00634 (desc_xcal.naxis2 == ny), 00635 CPL_ERROR_ILLEGAL_INPUT, 00636 "MASTER_DARK and XCAL frame haven't same dimensions! " 00637 "(x,y): (%d,%d) vs (%d,%d)", 00638 nx, ny, desc_xcal.naxis1, desc_xcal.naxis2); 00639 00640 nr_devices = desc_xcal.nr_ext; 00641 00642 // load desc for YCAL and check 00643 KMO_TRY_EXIT_IF_NULL( 00644 ycalFrame = kmo_dfs_get_frame(frameset, YCAL)); 00645 desc_ycal = kmo_identify_fits_header(cpl_frame_get_filename(ycalFrame)); 00646 KMO_TRY_CHECK_ERROR_STATE_MSG("YCAL frame doesn't seem to " 00647 "be in KMOS-format!"); 00648 KMO_TRY_ASSURE((desc_ycal.nr_ext % 3 == 0) && 00649 (desc_ycal.ex_badpix == FALSE) && 00650 (desc_ycal.fits_type == f2d_fits) && 00651 (desc_ycal.frame_type == detector_frame), 00652 CPL_ERROR_ILLEGAL_INPUT, 00653 "YCAL isn't in the correct format!!!"); 00654 KMO_TRY_ASSURE((desc_ycal.naxis1 == nx) && 00655 (desc_ycal.naxis2 == ny) && 00656 (desc_ycal.nr_ext == nr_devices), 00657 CPL_ERROR_ILLEGAL_INPUT, 00658 "MASTER_DARK and YCAL frame haven't same dimensions! " 00659 "(x,y): (%d,%d) vs (%d,%d)", 00660 nx, ny, desc_ycal.naxis1, desc_ycal.naxis2); 00661 00662 // load desc for LCAL and check 00663 KMO_TRY_EXIT_IF_NULL( 00664 lcalFrame = kmo_dfs_get_frame(frameset, LCAL)); 00665 desc_lcal = kmo_identify_fits_header(cpl_frame_get_filename(lcalFrame)); 00666 KMO_TRY_CHECK_ERROR_STATE_MSG("LCAL frame doesn't seem to " 00667 "be in KMOS-format!"); 00668 KMO_TRY_ASSURE((desc_lcal.nr_ext % 3 == 0) && 00669 (desc_lcal.ex_badpix == FALSE) && 00670 (desc_lcal.fits_type == f2d_fits) && 00671 (desc_lcal.frame_type == detector_frame), 00672 CPL_ERROR_ILLEGAL_INPUT, 00673 "LCAL isn't in the correct format!!!"); 00674 KMO_TRY_ASSURE((desc_lcal.naxis1 == nx) && 00675 (desc_lcal.naxis2 == ny) && 00676 (desc_lcal.nr_ext == nr_devices), 00677 CPL_ERROR_ILLEGAL_INPUT, 00678 "MASTER_DARK and LCAL frame haven't same dimensions! " 00679 "(x,y): (%d,%d) vs (%d,%d)", 00680 nx, ny, desc_lcal.naxis1, desc_lcal.naxis2); 00681 KMO_TRY_EXIT_IF_NULL( 00682 tmp_header = kmo_dfs_load_primary_header(frameset, LCAL)); 00683 00684 // load desc for FLAT_SKY and check 00685 i = 1; 00686 nr_devices = KMOS_NR_DETECTORS; 00687 KMO_TRY_EXIT_IF_NULL( 00688 frame = kmo_dfs_get_frame(frameset, FLAT_SKY)); 00689 00690 KMO_TRY_EXIT_IF_NULL( 00691 main_header = kmclipm_propertylist_load( 00692 cpl_frame_get_filename(frame), 0)); 00693 rotangle = cpl_propertylist_get_double(main_header, ROTANGLE); 00694 KMO_TRY_CHECK_ERROR_STATE_MSG("Cannot retrieve ROTANGLE FITS keyword from sky frame!"); 00695 kmclipm_strip_angle(&rotangle); 00696 cpl_propertylist_delete(main_header); main_header = NULL; 00697 00698 while (frame != NULL) { 00699 KMO_TRY_EXIT_IF_NULL( 00700 main_header = kmclipm_propertylist_load( 00701 cpl_frame_get_filename(frame), 0)); 00702 00703 desc_sky = kmo_identify_fits_header( 00704 cpl_frame_get_filename(frame)); 00705 KMO_TRY_CHECK_ERROR_STATE_MSG("FLAT_SKY frame doesn't seem to " 00706 "be in KMOS-format!"); 00707 KMO_TRY_ASSURE((desc_sky.nr_ext == 3) && 00708 (desc_sky.ex_badpix == FALSE) && 00709 (desc_sky.fits_type == raw_fits) && 00710 (desc_sky.frame_type == detector_frame), 00711 CPL_ERROR_ILLEGAL_INPUT, 00712 "FLAT_SKY isn't in the correct format!!!"); 00713 KMO_TRY_ASSURE((desc_sky.naxis1 == nx) && 00714 (desc_sky.naxis2 == ny) && 00715 (desc_sky.nr_ext == nr_devices), 00716 CPL_ERROR_ILLEGAL_INPUT, 00717 "MASTER_DARK and FLAT_SKY (no. %d) frame haven't " 00718 "same dimensions! (x,y): (%d,%d) vs (%d,%d)", 00719 i, nx, ny, desc_flat.naxis1, desc_flat.naxis2); 00720 kmo_free_fits_desc(&desc_sky); 00721 kmo_init_fits_desc(&desc_sky); 00722 00723 KMO_TRY_ASSURE( 00724 (kmo_check_lamp(main_header, INS_LAMP1_ST) == FALSE) && 00725 (kmo_check_lamp(main_header, INS_LAMP2_ST) == FALSE) && 00726 (kmo_check_lamp(main_header, INS_LAMP3_ST) == FALSE) && 00727 (kmo_check_lamp(main_header, INS_LAMP4_ST) == FALSE), 00728 CPL_ERROR_ILLEGAL_INPUT, 00729 "All lamps must be switched off for the FLAT_SKY frames!"); 00730 00731 // assert that filters have correct IDs and that all detectors of 00732 // all input frames have the same filter set 00733 for (i = 1; i <= 3; i++) { 00734 // ESO INS FILTi ID 00735 KMO_TRY_EXIT_IF_NULL( 00736 keyword = cpl_sprintf("%s%d%s", IFU_FILTID_PREFIX, i, 00737 IFU_FILTID_POSTFIX)); 00738 KMO_TRY_EXIT_IF_NULL( 00739 filter_id = cpl_propertylist_get_string(main_header, 00740 keyword)); 00741 00742 KMO_TRY_EXIT_IF_NULL( 00743 filter_id_l = cpl_propertylist_get_string(tmp_header, 00744 keyword)); 00745 cpl_free(keyword); keyword = NULL; 00746 00747 KMO_TRY_ASSURE((strcmp(filter_id, "IZ") == 0) || 00748 (strcmp(filter_id, "YJ") == 0) || 00749 (strcmp(filter_id, "H") == 0) || 00750 (strcmp(filter_id, "K") == 0) || 00751 (strcmp(filter_id, "HK") == 0), 00752 CPL_ERROR_ILLEGAL_INPUT, 00753 "Filter ID in primary header must be either 'IZ', " 00754 "'YJ', 'H', 'K' or " "'HK' !"); 00755 00756 KMO_TRY_ASSURE(strcmp(filter_id, filter_id_l) == 0, 00757 CPL_ERROR_ILLEGAL_INPUT, 00758 "Filter IDs must be the same for FLAT_SKY frame" 00759 " and lcal frame!" 00760 "Detector No.: %d\n%s: %s\nLCAL: %s\n", 00761 i, cpl_frame_get_filename(frame), 00762 filter_id, filter_id_l); 00763 00764 // ESO INS GRATi ID 00765 KMO_TRY_EXIT_IF_NULL( 00766 keyword = cpl_sprintf("%s%d%s", IFU_GRATID_PREFIX, i, 00767 IFU_GRATID_POSTFIX)); 00768 KMO_TRY_EXIT_IF_NULL( 00769 filter_id = cpl_propertylist_get_string(main_header, 00770 keyword)); 00771 00772 KMO_TRY_EXIT_IF_NULL( 00773 filter_id_l = cpl_propertylist_get_string(tmp_header, 00774 keyword)); 00775 cpl_free(keyword); keyword = NULL; 00776 00777 KMO_TRY_ASSURE((strcmp(filter_id, "IZ") == 0) || 00778 (strcmp(filter_id, "YJ") == 0) || 00779 (strcmp(filter_id, "H") == 0) || 00780 (strcmp(filter_id, "K") == 0) || 00781 (strcmp(filter_id, "HK") == 0), 00782 CPL_ERROR_ILLEGAL_INPUT, 00783 "Grating ID in primary header must be either " 00784 "'IZ', 'YJ', 'H', 'K' or " "'HK' !"); 00785 00786 KMO_TRY_ASSURE(strcmp(filter_id, filter_id_l) == 0, 00787 CPL_ERROR_ILLEGAL_INPUT, 00788 "Grating IDs must be the same for FLAT_SKY frame" 00789 " and lcal frame!" 00790 "Detector No.: %d\n%s: %s\nLCAL: %s\n", 00791 i, cpl_frame_get_filename(frame), 00792 filter_id, filter_id_l); 00793 00794 tmp_rotangle = cpl_propertylist_get_double(main_header, ROTANGLE); 00795 KMO_TRY_CHECK_ERROR_STATE_MSG("Cannot retrieve ROTANGLE FITS keyword from sky frame!"); 00796 kmclipm_strip_angle(&tmp_rotangle); 00797 KMO_TRY_ASSURE((abs(rotangle - tmp_rotangle) < 10.0) || 00798 (abs(rotangle - tmp_rotangle) > 360.-10.) , 00799 CPL_ERROR_ILLEGAL_INPUT, 00800 "OCS ROT NAANGLE of sky flat frames differ to much: %f %f", 00801 rotangle, tmp_rotangle); 00802 } 00803 cpl_propertylist_delete(main_header); main_header = NULL; 00804 00805 // get next FLAT_SKY frame 00806 frame = kmo_dfs_get_frame(frameset, NULL); 00807 KMO_TRY_CHECK_ERROR_STATE(); 00808 i++; 00809 } 00810 00811 cpl_propertylist_delete(tmp_header); tmp_header = NULL; 00812 00813 KMO_TRY_EXIT_IF_NULL( 00814 frame = kmo_dfs_get_frame(frameset, FLAT_SKY)); 00815 KMO_TRY_EXIT_IF_NULL( 00816 main_header = kmo_dfs_load_primary_header(frameset, FLAT_SKY)); 00817 00818 // 00819 // noise will be propagated when: 00820 // MASTER_DARK and MASTER_FLAT have noise extensions and if at least 00821 // 2 FLAT_SKY frames are provided. 00822 // Otherwise noise will be ignored. 00823 // 00824 if (desc_dark.ex_noise && 00825 desc_flat.ex_noise && 00826 (cpl_frameset_count_tags(frameset, FLAT_SKY) >= 2)) { 00827 process_noise = TRUE; 00828 } 00829 00830 if (cpl_frameset_count_tags(frameset, FLAT_SKY) == 1) { 00831 cpl_msg_warning(cpl_func, "cmethod is changed to 'average' " 00832 "since there is only one input frame! (The output " 00833 "file won't have any noise extensions)"); 00834 00835 cmethod = "average"; 00836 } 00837 00838 // setup grid definition, wavekength start and end points will be set 00839 // in the detector loop 00840 KMO_TRY_EXIT_IF_ERROR( 00841 kmclipm_setup_grid(&gd, method, neighborhoodRange)); 00842 00843 // create filename for LUT 00844 KMO_TRY_EXIT_IF_NULL( 00845 fn_lut = cpl_sprintf("%s%s", "lut", suffix)); 00846 00847 // extract bounds 00848 KMO_TRY_EXIT_IF_NULL( 00849 tmp_header = kmclipm_propertylist_load( 00850 cpl_frame_get_filename(xcalFrame), 0)); 00851 KMO_TRY_EXIT_IF_NULL( 00852 bounds = kmclipm_extract_bounds(tmp_header)); 00853 cpl_propertylist_delete(tmp_header); tmp_header = NULL; 00854 00855 // get timestamps of xcal, ycal & lcal 00856 KMO_TRY_EXIT_IF_NULL( 00857 calTimestamp = kmo_get_timestamps(xcalFrame, ycalFrame, lcalFrame)); 00858 00859 // create arrays to hold reconstructed data and noise cubes and 00860 // their headers 00861 KMO_TRY_EXIT_IF_NULL( 00862 stored_data_cubes = 00863 (cpl_imagelist**)cpl_malloc(nr_devices * 00864 KMOS_IFUS_PER_DETECTOR * 00865 sizeof(cpl_imagelist*))); 00866 KMO_TRY_EXIT_IF_NULL( 00867 stored_noise_cubes = 00868 (cpl_imagelist**)cpl_malloc(nr_devices * 00869 KMOS_IFUS_PER_DETECTOR * 00870 sizeof(cpl_imagelist*))); 00871 KMO_TRY_EXIT_IF_NULL( 00872 stored_data_images = 00873 (cpl_image**)cpl_malloc(nr_devices * 00874 KMOS_IFUS_PER_DETECTOR * 00875 sizeof(cpl_image*))); 00876 KMO_TRY_EXIT_IF_NULL( 00877 stored_noise_images = 00878 (cpl_image**)cpl_malloc(nr_devices * 00879 KMOS_IFUS_PER_DETECTOR * 00880 sizeof(cpl_image*))); 00881 KMO_TRY_EXIT_IF_NULL( 00882 stored_sub_data_headers = 00883 (cpl_propertylist**)cpl_malloc(nr_devices * 00884 KMOS_IFUS_PER_DETECTOR * 00885 sizeof(cpl_propertylist*))); 00886 KMO_TRY_EXIT_IF_NULL( 00887 stored_sub_noise_headers = 00888 (cpl_propertylist**)cpl_malloc(nr_devices * 00889 KMOS_IFUS_PER_DETECTOR * 00890 sizeof(cpl_propertylist*))); 00891 00892 for (i = 0; i < nr_devices * KMOS_IFUS_PER_DETECTOR; i++) { 00893 stored_data_cubes[i] = NULL; 00894 stored_noise_cubes[i] = NULL; 00895 stored_data_images[i] = NULL; 00896 stored_noise_images[i] = NULL; 00897 stored_sub_data_headers[i] = NULL; 00898 stored_sub_noise_headers[i] = NULL; 00899 } 00900 00901 // 00902 // loop through all detectors 00903 // 00904 for (det_nr = 1; det_nr <= nr_devices; det_nr++) { 00905 cpl_msg_info("","Processing detector No. %d", det_nr); 00906 00907 KMO_TRY_EXIT_IF_NULL( 00908 detector_in = cpl_imagelist_new()); 00909 00910 // load data of device i of all FLAT_SKY frames into an imagelist 00911 KMO_TRY_EXIT_IF_NULL( 00912 img_in = kmo_dfs_load_image(frameset, FLAT_SKY, det_nr, FALSE, TRUE, NULL)); 00913 00914 i = 0; 00915 while (img_in != NULL) { 00916 cpl_imagelist_set(detector_in, img_in, i); 00917 KMO_TRY_CHECK_ERROR_STATE(); 00918 00919 /* load same extension of next FLAT_SKY frame*/ 00920 img_in = kmo_dfs_load_image(frameset, NULL, det_nr, FALSE, TRUE, NULL); 00921 KMO_TRY_CHECK_ERROR_STATE(); 00922 00923 i++; 00924 } 00925 00926 // 00927 // process imagelist 00928 // 00929 00930 // combine imagelist (data only) and create noise (stdev of data) 00931 cpl_msg_info("","Combining frames..."); 00932 if (process_noise) { 00933 KMO_TRY_EXIT_IF_ERROR( 00934 kmclipm_combine_frames(detector_in, 00935 NULL, 00936 NULL, 00937 cmethod, 00938 cpos_rej, 00939 cneg_rej, 00940 citer, 00941 cmax, 00942 cmin, 00943 &combined_data, 00944 &combined_noise, 00945 -1.0)); 00946 } else { 00947 KMO_TRY_EXIT_IF_ERROR( 00948 kmclipm_combine_frames(detector_in, 00949 NULL, 00950 NULL, 00951 cmethod, 00952 cpos_rej, 00953 cneg_rej, 00954 citer, 00955 cmax, 00956 cmin, 00957 &combined_data, 00958 NULL, 00959 -1.0)); 00960 } 00961 00962 if (kmclipm_omit_warning_one_slice > 10) { 00963 cpl_msg_warning(cpl_func, "Previous warning (number of " 00964 "identified slices) occured %d times.", 00965 kmclipm_omit_warning_one_slice); 00966 kmclipm_omit_warning_one_slice = FALSE; 00967 } 00968 00969 cpl_imagelist_delete(detector_in); detector_in = NULL; 00970 00971 // 00972 // reconstruct 00973 // 00974 00975 // load MASTER_DARK and MASTER_FLAT 00976 KMO_TRY_EXIT_IF_NULL( 00977 img_dark = kmo_dfs_load_image(frameset, MASTER_DARK, 00978 det_nr, FALSE, FALSE, NULL)); 00979 00980 if (process_noise) { 00981 KMO_TRY_EXIT_IF_NULL( 00982 img_dark_noise = kmo_dfs_load_image(frameset, MASTER_DARK, 00983 det_nr, TRUE, FALSE, NULL)); 00984 } 00985 00986 KMO_TRY_EXIT_IF_NULL( 00987 img_flat = kmo_dfs_load_cal_image(frameset, MASTER_FLAT, 00988 det_nr, FALSE, rotangle, FALSE, NULL, &rotangle_found)); 00989 00990 if (process_noise) { 00991 KMO_TRY_EXIT_IF_NULL( 00992 img_flat_noise = kmo_dfs_load_cal_image(frameset, MASTER_FLAT, 00993 det_nr, TRUE, rotangle, FALSE, NULL, &rotangle_found)); 00994 } 00995 00996 // load calibration files 00997 KMO_TRY_EXIT_IF_NULL( 00998 xcal = kmo_dfs_load_cal_image(frameset, XCAL, det_nr, FALSE, rotangle, 00999 FALSE, NULL, &rotangle_found)); 01000 KMO_TRY_EXIT_IF_NULL( 01001 ycal = kmo_dfs_load_cal_image(frameset, YCAL, det_nr, FALSE, rotangle, 01002 FALSE, NULL, &rotangle_found)); 01003 KMO_TRY_EXIT_IF_NULL( 01004 lcal = kmo_dfs_load_cal_image(frameset, LCAL, det_nr, FALSE, rotangle, 01005 FALSE, NULL, &rotangle_found)); 01006 01007 char *tmp_band_method = getenv("KMO_BAND_METHOD"); 01008 int band_method = 0; 01009 if (tmp_band_method != NULL) { 01010 band_method = atoi(tmp_band_method); 01011 } 01012 01013 // ESO INS FILTi ID 01014 KMO_TRY_EXIT_IF_NULL( 01015 keyword = cpl_sprintf("%s%d%s", IFU_FILTID_PREFIX, det_nr, 01016 IFU_FILTID_POSTFIX)); 01017 KMO_TRY_EXIT_IF_NULL( 01018 filter_id = cpl_propertylist_get_string(main_header, keyword)); 01019 cpl_free(keyword); keyword = NULL; 01020 01021 KMO_TRY_EXIT_IF_NULL( 01022 band_table = kmo_dfs_load_table(frameset, WAVE_BAND, 1, 0)); 01023 KMO_TRY_EXIT_IF_ERROR( 01024 kmclipm_setup_grid_band_lcal(&gd, lcal, filter_id, band_method, 01025 band_table)); 01026 cpl_table_delete(band_table); band_table = NULL; 01027 01028 cpl_msg_info("","Reconstructing cubes..."); 01029 for (j = 0; j < KMOS_IFUS_PER_DETECTOR; j++) { 01030 // update sub-header 01031 ifu_nr = (det_nr-1)*KMOS_IFUS_PER_DETECTOR + j + 1; 01032 01033 // load raw image and sub-header 01034 KMO_TRY_EXIT_IF_NULL( 01035 sub_header = kmo_dfs_load_sub_header(frameset, FLAT_SKY, 01036 det_nr, FALSE)); 01037 01038 KMO_TRY_EXIT_IF_NULL( 01039 punused_ifus = cpl_array_get_data_int_const( 01040 unused_ifus_after[det_nr-1])); 01041 01042 // check if IFU is valid according to main header keywords & 01043 // calibration files 01044 KMO_TRY_EXIT_IF_NULL( 01045 keyword = cpl_sprintf("%s%d%s", IFU_VALID_PREFIX, ifu_nr, 01046 IFU_VALID_POSTFIX)); 01047 KMO_TRY_CHECK_ERROR_STATE(); 01048 ranges_txt = cpl_propertylist_get_string(main_header, keyword); 01049 cpl_free(keyword); keyword = NULL; 01050 01051 if ((cpl_error_get_code() == CPL_ERROR_DATA_NOT_FOUND) && 01052 (bounds[2*(ifu_nr-1)] != -1) && 01053 (bounds[2*(ifu_nr-1)+1] != -1) && 01054 (punused_ifus[j] == 0)) 01055 { 01056 // IFU is valid 01057 cpl_error_reset(); 01058 01059 // calculate WCS 01060 KMO_TRY_EXIT_IF_ERROR( 01061 kmo_calc_wcs(main_header, sub_header, ifu_nr, 01062 gd.l.start, gd.l.delta)); 01063 01064 // reconstruct data 01065 KMO_TRY_EXIT_IF_ERROR( 01066 kmo_reconstruct_sci_image(ifu_nr, 01067 bounds[2*(ifu_nr-1)], 01068 bounds[2*(ifu_nr-1)+1], 01069 combined_data, 01070 combined_noise, 01071 img_dark, 01072 img_dark_noise, 01073 img_flat, 01074 img_flat_noise, 01075 xcal, 01076 ycal, 01077 lcal, 01078 &gd, 01079 calTimestamp, 01080 fn_lut, 01081 &cube_data, 01082 &cube_noise, 01083 flux)); 01084 KMO_TRY_CHECK_ERROR_STATE(); 01085 } else { 01086 // IFU is invalid 01087 cpl_error_reset(); 01088 } // if ((cpl_error_get_code() == CPL_ERROR_DATA_NOT_FOUND) ... 01089 01090 // save output 01091 KMO_TRY_EXIT_IF_NULL( 01092 extname = kmo_extname_creator(ifu_frame, ifu_nr, EXT_DATA)); 01093 01094 KMO_TRY_EXIT_IF_ERROR( 01095 kmclipm_update_property_string(sub_header, EXTNAME, 01096 extname, 01097 "FITS extension name")); 01098 01099 cpl_free(extname); extname = NULL; 01100 01101 // store cube and sub header into array for later 01102 stored_data_cubes[ifu_nr - 1] = cube_data; 01103 stored_sub_data_headers[ifu_nr - 1] = sub_header; 01104 01105 if (process_noise) { 01106 KMO_TRY_EXIT_IF_NULL( 01107 sub_header = cpl_propertylist_duplicate( 01108 stored_sub_data_headers[ifu_nr - 1])); 01109 KMO_TRY_EXIT_IF_NULL( 01110 extname = kmo_extname_creator(ifu_frame, ifu_nr, 01111 EXT_NOISE)); 01112 01113 KMO_TRY_EXIT_IF_ERROR( 01114 kmclipm_update_property_string(sub_header, 01115 EXTNAME, 01116 extname, 01117 "FITS extension name")); 01118 01119 cpl_free(extname); extname = NULL; 01120 01121 stored_noise_cubes[ifu_nr - 1] = cube_noise; 01122 stored_sub_noise_headers[ifu_nr - 1] = sub_header; 01123 } 01124 cpl_image_delete(data_ifu); data_ifu = NULL; 01125 cpl_image_delete(noise_ifu); noise_ifu = NULL; 01126 cube_data = NULL; 01127 cube_noise = NULL; 01128 } // for j IFUs 01129 01130 // free memory 01131 cpl_image_delete(combined_data); combined_data = NULL; 01132 cpl_image_delete(combined_noise); combined_noise = NULL; 01133 01134 cpl_image_delete(xcal); xcal = NULL; 01135 cpl_image_delete(ycal); ycal = NULL; 01136 cpl_image_delete(lcal); lcal = NULL; 01137 01138 cpl_image_delete(img_dark); img_dark = NULL; 01139 cpl_image_delete(img_flat); img_flat = NULL; 01140 if (process_noise) { 01141 cpl_image_delete(img_dark_noise); img_dark_noise = NULL; 01142 cpl_image_delete(img_flat_noise); img_flat_noise = NULL; 01143 } 01144 01145 } // for nr_devices 01146 01147 // collapse cubes using rejection 01148 cpl_msg_info("","Collapsing cubes..."); 01149 for (i = 0; i < nr_devices * KMOS_IFUS_PER_DETECTOR; i++) { 01150 if (ranges != NULL) { 01151 ifu_crpix = cpl_propertylist_get_double(stored_sub_data_headers[i], 01152 CRPIX3); 01153 KMO_TRY_CHECK_ERROR_STATE_MSG( 01154 "CRPIX3 keyword in FITS-header is missing!"); 01155 01156 ifu_crval = cpl_propertylist_get_double(stored_sub_data_headers[i], 01157 CRVAL3); 01158 KMO_TRY_CHECK_ERROR_STATE_MSG( 01159 "CRVAL3 keyword in FITS-header is missing!"); 01160 01161 ifu_cdelt = cpl_propertylist_get_double(stored_sub_data_headers[i], 01162 CDELT3); 01163 KMO_TRY_CHECK_ERROR_STATE_MSG( 01164 "CDELT3 keyword in FITS-header is missing!"); 01165 } 01166 01167 KMO_TRY_EXIT_IF_NULL( 01168 identified_slices = kmo_identify_slices(ranges, 01169 ifu_crpix, 01170 ifu_crval, 01171 ifu_cdelt, 01172 gd.l.dim)); 01173 01174 if (stored_data_cubes[i] != NULL) { 01175 KMO_TRY_EXIT_IF_ERROR( 01176 kmclipm_make_image(stored_data_cubes[i], 01177 stored_noise_cubes[i], 01178 &stored_data_images[i], 01179 &stored_noise_images[i], 01180 identified_slices, 01181 cmethod, cpos_rej, cneg_rej, 01182 citer, cmax, cmin)); 01183 } 01184 cpl_vector_delete(identified_slices); identified_slices = NULL; 01185 } 01186 01187 // normalise all IFUs as a group. 01188 // Calculate mean of each IFU, add up and divide by number of successful 01189 // averaged IFUs. 01190 // Then divide all valid IFUs with mean value 01191 // 01192 count = 0; 01193 for (i = 0; i < nr_devices * KMOS_IFUS_PER_DETECTOR; i++) { 01194 if (stored_data_images[i] != NULL) { 01195 KMO_TRY_ASSURE(cpl_image_count_rejected(stored_data_images[i]) < 01196 cpl_image_get_size_x(stored_data_images[i])* 01197 cpl_image_get_size_y(stored_data_images[i]), 01198 CPL_ERROR_ILLEGAL_INPUT, 01199 "The collapsed, dark-subtracted image contains " 01200 "only invalid values! Probably the provided " 01201 "FLAT_SKY frames are exactly the same as the " 01202 "frames used for MASTER_DARK calculation."); 01203 01204 mean_data += cpl_image_get_mean(stored_data_images[i]); 01205 KMO_TRY_CHECK_ERROR_STATE(); 01206 count++; 01207 } 01208 01209 } 01210 mean_data /= count; 01211 01212 if (mean_data != 0.0) { 01213 for (i = 0; i < nr_devices * KMOS_IFUS_PER_DETECTOR; i++) { 01214 if (stored_data_images[i] != NULL) { 01215 KMO_TRY_EXIT_IF_ERROR( 01216 cpl_image_divide_scalar(stored_data_images[i], 01217 mean_data)); 01218 } 01219 } 01220 } else { 01221 cpl_msg_warning(cpl_func, "Data couldn't be normalised " 01222 "(mean = 0.0)!"); 01223 } 01224 01225 if (process_noise) { 01226 // count = 0; 01227 // for (i = 0; i < nr_devices * KMOS_IFUS_PER_DETECTOR; i++) { 01228 // if (stored_noise_images[i] != NULL) { 01229 // mean_noise += cpl_image_get_mean(stored_noise_images[i]); 01230 // KMO_TRY_CHECK_ERROR_STATE(); 01231 // count++; 01232 // } 01233 // } 01234 // mean_noise /= count; 01235 01236 if (mean_data != 0.0) { 01237 for (i = 0; i < nr_devices * KMOS_IFUS_PER_DETECTOR; i++) { 01238 if (stored_noise_images[i] != NULL) { 01239 KMO_TRY_EXIT_IF_ERROR( 01240 cpl_image_divide_scalar(stored_noise_images[i], 01241 mean_data)); 01242 } 01243 } 01244 } else { 01245 cpl_msg_warning(cpl_func, "Noise couldn't be normalised " 01246 "(mean = 0.0)!"); 01247 } 01248 } 01249 01250 // calculate qc parameters on normalised data 01251 qc_spat_unif = 0.0; 01252 count = 0; 01253 for (i = 0; i < nr_devices * KMOS_IFUS_PER_DETECTOR; i++) { 01254 if (stored_data_images[i] != NULL) { 01255 tmp_mean = cpl_image_get_mean(stored_data_images[i]); 01256 tmp_stdev = cpl_image_get_stdev (stored_data_images[i]); 01257 01258 qc_spat_unif += pow(tmp_mean-1, 2); 01259 if (fabs(tmp_mean) > qc_max_dev) { 01260 qc_max_dev = tmp_mean-1; 01261 qc_max_dev_id = i+1; 01262 } 01263 if (fabs(tmp_stdev) > qc_max_nonunif) { 01264 qc_max_nonunif = tmp_stdev; 01265 qc_max_nonunif_id = i+1; 01266 } 01267 KMO_TRY_CHECK_ERROR_STATE(); 01268 count++; 01269 } 01270 } 01271 qc_spat_unif = sqrt(qc_spat_unif / count); 01272 01273 // 01274 // save data 01275 // 01276 01277 // update which IFUs are not used 01278 kmo_print_unused_ifus(unused_ifus_after, TRUE); 01279 01280 KMO_TRY_EXIT_IF_ERROR( 01281 kmo_set_unused_ifus(unused_ifus_after, main_header, 01282 "kmo_illumination")); 01283 01284 cpl_msg_info("","Saving data..."); 01285 01286 KMO_TRY_EXIT_IF_ERROR( 01287 kmclipm_update_property_double(main_header, 01288 QC_SPAT_UNIF, 01289 qc_spat_unif, 01290 "[adu] uniformity of illumination correction")); 01291 KMO_TRY_EXIT_IF_ERROR( 01292 kmclipm_update_property_double(main_header, 01293 QC_SPAT_MAX_DEV, 01294 qc_max_dev, 01295 "[adu] max. deviation from unity")); 01296 KMO_TRY_EXIT_IF_ERROR( 01297 kmclipm_update_property_int(main_header, 01298 QC_SPAT_MAX_DEV_ID, 01299 qc_max_dev_id, 01300 "[] IFU ID with max. dev. from unity")); 01301 KMO_TRY_EXIT_IF_ERROR( 01302 kmclipm_update_property_double(main_header, 01303 QC_SPAT_MAX_NONUNIF, 01304 qc_max_nonunif, 01305 "[adu] max. stdev of illumination corr.")); 01306 KMO_TRY_EXIT_IF_ERROR( 01307 kmclipm_update_property_int(main_header, 01308 QC_SPAT_MAX_NONUNIF_ID, 01309 qc_max_nonunif_id, 01310 "[] IFU ID with max. stdev in illum. corr.")); 01311 01312 KMO_TRY_EXIT_IF_ERROR( 01313 kmo_dfs_save_main_header(frameset, ILLUM_CORR, suffix, frame, 01314 main_header, parlist, cpl_func)); 01315 01316 for (i = 0; i < nr_devices * KMOS_IFUS_PER_DETECTOR; i++) { 01317 KMO_TRY_EXIT_IF_ERROR( 01318 kmo_dfs_save_image(stored_data_images[i], ILLUM_CORR, suffix, 01319 stored_sub_data_headers[i], 0./0.)); 01320 01321 if (process_noise) { 01322 KMO_TRY_EXIT_IF_ERROR( 01323 kmo_dfs_save_image(stored_noise_images[i], ILLUM_CORR, 01324 suffix, stored_sub_noise_headers[i], 0./0.)); 01325 } 01326 } 01327 } 01328 KMO_CATCH 01329 { 01330 KMO_CATCH_MSG(); 01331 ret_val = -1; 01332 } 01333 kmo_free_fits_desc(&desc_sky); 01334 kmo_free_fits_desc(&desc_dark); 01335 kmo_free_fits_desc(&desc_flat); 01336 kmo_free_fits_desc(&desc_xcal); 01337 kmo_free_fits_desc(&desc_ycal); 01338 kmo_free_fits_desc(&desc_lcal); 01339 cpl_image_delete(combined_data); combined_data = NULL; 01340 cpl_image_delete(combined_noise); combined_noise = NULL; 01341 cpl_image_delete(xcal); xcal = NULL; 01342 cpl_image_delete(ycal); ycal = NULL; 01343 cpl_image_delete(lcal); lcal = NULL; 01344 cpl_image_delete(img_dark); img_dark = NULL; 01345 cpl_image_delete(img_dark_noise); img_dark_noise = NULL; 01346 cpl_image_delete(img_flat); img_flat = NULL; 01347 cpl_image_delete(img_flat_noise); img_flat_noise = NULL; 01348 cpl_array_delete(calTimestamp); calTimestamp = NULL; 01349 cpl_propertylist_delete(main_header); main_header = NULL; 01350 cpl_free(bounds); bounds = NULL; 01351 01352 for (i = 0; i < nr_devices * KMOS_IFUS_PER_DETECTOR; i++) { 01353 if (stored_data_cubes != NULL) { 01354 cpl_imagelist_delete(stored_data_cubes[i]); 01355 stored_data_cubes[i] = NULL; 01356 } 01357 01358 if (stored_noise_cubes != NULL) { 01359 cpl_imagelist_delete(stored_noise_cubes[i]); 01360 stored_noise_cubes[i] = NULL; 01361 } 01362 01363 if (stored_data_images != NULL) { 01364 cpl_image_delete(stored_data_images[i]); 01365 stored_data_images[i] = NULL; 01366 } 01367 01368 if (stored_noise_images != NULL) { 01369 cpl_image_delete(stored_noise_images[i]); 01370 stored_noise_images[i] = NULL; 01371 } 01372 01373 if (stored_sub_data_headers != NULL) { 01374 cpl_propertylist_delete(stored_sub_data_headers[i]); 01375 stored_sub_data_headers[i] = NULL; 01376 } 01377 01378 if (stored_sub_noise_headers != NULL) { 01379 cpl_propertylist_delete(stored_sub_noise_headers[i]); 01380 stored_sub_noise_headers[i] = NULL; 01381 } 01382 } 01383 01384 kmo_free_unused_ifus(unused_ifus_before); unused_ifus_before = NULL; 01385 kmo_free_unused_ifus(unused_ifus_after); unused_ifus_after = NULL; 01386 cpl_free(stored_data_cubes); stored_data_cubes = NULL; 01387 cpl_free(stored_noise_cubes); stored_noise_cubes = NULL; 01388 cpl_free(stored_data_images); stored_data_images = NULL; 01389 cpl_free(stored_noise_images); stored_noise_images = NULL; 01390 cpl_free(stored_sub_data_headers); stored_sub_data_headers = NULL; 01391 cpl_free(stored_sub_noise_headers); stored_sub_noise_headers = NULL; 01392 cpl_free(fn_lut); fn_lut = NULL; 01393 cpl_free(suffix); suffix = NULL; 01394 01395 return ret_val; 01396 } 01397
1.7.6.1