|
KMOS Pipeline Reference Manual
1.1.0
|
00001 /* $Id: kmo_illumination.c,v 1.43 2013/03/18 14:02:30 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/03/18 14:02:30 $ 00024 * $Revision: 1.43 $ 00025 * $Name: HEAD $ 00026 */ 00027 00028 #ifdef HAVE_CONFIG_H 00029 #include <config.h> 00030 #endif 00031 00032 /*----------------------------------------------------------------------------- 00033 * Includes 00034 *----------------------------------------------------------------------------*/ 00035 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_priv_flat.h" 00044 #include "kmo_priv_wave_cal.h" 00045 #include "kmclipm_priv_splines.h" 00046 #include "kmo_functions.h" 00047 #include "kmo_cpl_extensions.h" 00048 #include "kmo_dfs.h" 00049 #include "kmo_error.h" 00050 #include "kmo_constants.h" 00051 #include "kmo_debug.h" 00052 00053 /*----------------------------------------------------------------------------- 00054 * Functions prototypes 00055 *----------------------------------------------------------------------------*/ 00056 00057 static int kmo_illumination_create(cpl_plugin *); 00058 static int kmo_illumination_exec(cpl_plugin *); 00059 static int kmo_illumination_destroy(cpl_plugin *); 00060 static int kmo_illumination(cpl_parameterlist *, cpl_frameset *); 00061 00062 /*----------------------------------------------------------------------------- 00063 * Static variables 00064 *----------------------------------------------------------------------------*/ 00065 00066 static char kmo_illumination_description[] = 00067 "This recipe creates the spatial non-uniformity calibration frame needed for\n" 00068 "all three detectors. It must be called after the kmo_wave_cal-recipe, which\n" 00069 "generates the spectral calibration frame needed in this recipe. As input at\n" 00070 "least a sky, a master dark, a master flat and the spatial and spectral cali-\n" 00071 "bration frames are required.\n" 00072 "\n" 00073 "BASIC PARAMETERS:\n" 00074 "-----------------\n" 00075 "--imethod\n" 00076 "The interpolation method used for reconstruction.\n" 00077 "\n" 00078 "--range\n" 00079 "The spectral ranges to combine when collapsing the reconstructed cubes. e.g.\n" 00080 "\"x1_start,x1_end;x2_start,x2_end\" (microns)\n" 00081 "\n" 00082 "ADVANCED PARAMETERS\n" 00083 "-------------------\n" 00084 "--add-all\n" 00085 "By default the first FLAT_SKY frame is omitted, since in the\n" 00086 "KMOS_spec_cal_skyflat template this is an acquisition frame to estimate the\n" 00087 "needed exposure time for the subsequent FLAT_SKY frames. If anyway all frames\n" 00088 "should be considered, set this parameter to TRUE.\n" 00089 "\n" 00090 "--neighborhoodRange\n" 00091 "Defines the range to search for neighbors during reconstruction\n" 00092 "\n" 00093 "--b_samples\n" 00094 "The number of samples in spectral direction for the reconstructed cube.\n" 00095 "Ideally this number should be greater than 2048, the detector size.\n" 00096 "\n" 00097 "--b_start\n" 00098 "--b_end\n" 00099 "Used to define manually the start and end wavelength for the reconstructed\n" 00100 "cube. By default the internally defined values are used.\n" 00101 "\n" 00102 "--cmethod\n" 00103 "Following methods of frame combination are available:\n" 00104 " * 'ksigma' (Default)\n" 00105 " An iterative sigma clipping. For each position all pixels in the spectrum\n" 00106 " are examined. If they deviate significantly, they will be rejected according\n" 00107 " to the conditions:\n" 00108 " val > mean + stdev * cpos_rej\n" 00109 " and\n" 00110 " val < mean - stdev * cneg_rej\n" 00111 " where --cpos_rej, --cneg_rej and --citer are the corresponding configuration\n" 00112 " parameters. In the first iteration median and percentile level are used.\n" 00113 "\n" 00114 " * 'median'\n" 00115 " At each pixel position the median is calculated.\n" 00116 "\n" 00117 " * 'average'\n" 00118 " At each pixel position the average is calculated.\n" 00119 "\n" 00120 " * 'sum'\n" 00121 " At each pixel position the sum is calculated.\n" 00122 "\n" 00123 " * 'min_max'\n" 00124 " The specified number of minimum and maximum pixel values will be rejected.\n" 00125 " --cmax and --cmin apply to this method.\n" 00126 "\n" 00127 "--cpos_rej\n" 00128 "--cneg_rej\n" 00129 "--citer\n" 00130 "see --cmethod='ksigma'\n" 00131 "\n" 00132 "--cmax\n" 00133 "--cmin\n" 00134 "see --cmethod='min_max'\n" 00135 "\n" 00136 "-------------------------------------------------------------------------------\n" 00137 " Input files:\n" 00138 "\n" 00139 " DO KMOS \n" 00140 " category Type Explanation Required #Frames\n" 00141 " -------- ----- ----------- -------- -------\n" 00142 " FLAT_SKY F2D Sky exposures Y 1-n \n" 00143 " (at least 3 frames recommended) \n" 00144 " MASTER_DARK F2D Master dark Y 1 \n" 00145 " MASTER_FLAT F2D Master flat Y 1 \n" 00146 " XCAL F2D x calibration frame Y 1 \n" 00147 " YCAL F2D y calibration frame Y 1 \n" 00148 " LCAL F2D Wavelength calib. frame Y 1 \n" 00149 " WAVE_BAND F2L Table with start-/end-wavelengths Y 1 \n" 00150 " FLAT_EDGE F2L Table with fitted slitlet edges N 0,1 \n" 00151 "\n" 00152 " Output files:\n" 00153 "\n" 00154 " DO KMOS\n" 00155 " category Type Explanation\n" 00156 " -------- ----- -----------\n" 00157 " ILLUM_CORR F2I Illumination calibration frame \n" 00158 " If FLAT_EDGE is provided: \n" 00159 " SKYFLAT_EDGE F2L Frame containing parameters of fitted \n" 00160 " slitlets of all IFUs of all detectors\n" 00161 "-------------------------------------------------------------------------------\n" 00162 "\n"; 00163 00164 /*----------------------------------------------------------------------------- 00165 * Functions code 00166 *----------------------------------------------------------------------------*/ 00167 00184 int cpl_plugin_get_info(cpl_pluginlist *list) 00185 { 00186 cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe); 00187 cpl_plugin *plugin = &recipe->interface; 00188 00189 cpl_plugin_init(plugin, 00190 CPL_PLUGIN_API, 00191 KMOS_BINARY_VERSION, 00192 CPL_PLUGIN_TYPE_RECIPE, 00193 "kmo_illumination", 00194 "Create a calibration frame to correct spatial " 00195 "non-uniformity of flatfield.", 00196 kmo_illumination_description, 00197 "Alex Agudo Berbel", 00198 "agudo@mpe.mpg.de", 00199 kmos_get_license(), 00200 kmo_illumination_create, 00201 kmo_illumination_exec, 00202 kmo_illumination_destroy); 00203 00204 cpl_pluginlist_append(list, plugin); 00205 00206 return 0; 00207 } 00208 00216 static int kmo_illumination_create(cpl_plugin *plugin) 00217 { 00218 cpl_recipe *recipe; 00219 cpl_parameter *p; 00220 00221 /* Check that the plugin is part of a valid recipe */ 00222 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00223 recipe = (cpl_recipe *)plugin; 00224 else 00225 return -1; 00226 00227 /* Create the parameters list in the cpl_recipe object */ 00228 recipe->parameters = cpl_parameterlist_new(); 00229 00230 /* Fill the parameters list */ 00231 /* --imethod */ 00232 p = cpl_parameter_new_value("kmos.kmo_illumination.imethod", 00233 CPL_TYPE_STRING, 00234 "Method to use for interpolation: " 00235 "[\"NN\" (nearest neighbour), " 00236 "\"lwNN\" (linear weighted nearest neighbor)," 00237 "\"swNN\" (square weighted nearest neighbor)" 00238 "\"MS\" (Modified Shepard's method)" 00239 "\"CS\" (Cubic spline)]", 00240 "kmos.kmo_illumination", 00241 "CS"); 00242 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "imethod"); 00243 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00244 cpl_parameterlist_append(recipe->parameters, p); 00245 00246 /* --neighborhoodRange */ 00247 p = cpl_parameter_new_value("kmos.kmo_illumination.neighborhoodRange", 00248 CPL_TYPE_DOUBLE, 00249 "Defines the range to search for neighbors." 00250 "in pixels", 00251 "kmos.kmo_illumination", 00252 1.001); 00253 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "neighborhoodRange"); 00254 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00255 cpl_parameterlist_append(recipe->parameters, p); 00256 00257 /* --range */ 00258 p = cpl_parameter_new_value("kmos.kmo_illumination.range", 00259 CPL_TYPE_STRING, 00260 "The spectral ranges to combine when collapsing" 00261 "the reconstructed cubes. e.g." 00262 "\"x1_start,x1_end;x2_start,x2_end\" (microns)", 00263 "kmos.kmo_illumination", 00264 ""); 00265 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "range"); 00266 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00267 cpl_parameterlist_append(recipe->parameters, p); 00268 00269 /* --flux */ 00270 p = cpl_parameter_new_value("kmos.kmo_illumination.flux", 00271 CPL_TYPE_BOOL, 00272 "TRUE: Apply flux conservation. FALSE: otherwise", 00273 "kmos.kmo_illumination", 00274 FALSE); 00275 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "flux"); 00276 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00277 cpl_parameterlist_append(recipe->parameters, p); 00278 00279 /* --add-all */ 00280 p = cpl_parameter_new_value("kmos.kmo_illumination.add-all", 00281 CPL_TYPE_BOOL, 00282 "FALSE: omit 1st FLAT_SKY frame (acquisition), " 00283 "TRUE: don't perform any checks, add them all", 00284 "kmos.kmo_illumination", 00285 FALSE); 00286 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "add-all"); 00287 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00288 cpl_parameterlist_append(recipe->parameters, p); 00289 00290 // add parameters for band-definition 00291 kmo_band_pars_create(recipe->parameters, 00292 "kmos.kmo_illumination"); 00293 00294 // add parameters for combining 00295 return kmo_combine_pars_create(recipe->parameters, 00296 "kmos.kmo_illumination", 00297 DEF_REJ_METHOD, 00298 FALSE); 00299 } 00300 00306 static int kmo_illumination_exec(cpl_plugin *plugin) 00307 { 00308 cpl_recipe *recipe; 00309 00310 /* Get the recipe out of the plugin */ 00311 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00312 recipe = (cpl_recipe *)plugin; 00313 else return -1; 00314 00315 return kmo_illumination(recipe->parameters, recipe->frames); 00316 } 00317 00323 static int kmo_illumination_destroy(cpl_plugin *plugin) 00324 { 00325 cpl_recipe *recipe; 00326 00327 /* Get the recipe out of the plugin */ 00328 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00329 recipe = (cpl_recipe *)plugin; 00330 else return -1 ; 00331 00332 cpl_parameterlist_delete(recipe->parameters); 00333 return 0 ; 00334 } 00335 00350 static int kmo_illumination(cpl_parameterlist *parlist, cpl_frameset *frameset) 00351 { 00352 int ret_val = 0, 00353 nr_devices = 0, 00354 ifu_nr = 0, 00355 nx = 0, 00356 ny = 0, 00357 process_noise = FALSE, 00358 cmax = 0, 00359 cmin = 0, 00360 citer = 0, 00361 *bounds = NULL, 00362 cnt = 0, 00363 qc_max_dev_id = 0, 00364 qc_max_nonunif_id = 0, 00365 flux = FALSE, 00366 add_all_sky = FALSE, 00367 same_exptime = TRUE, 00368 has_flat_edge = FALSE; 00369 const int *punused_ifus = NULL; 00370 float *pbad_pix_mask = NULL; 00371 double exptime = 0., 00372 exptime1 = 0., 00373 exptime2 = 0., 00374 cpos_rej = 0.0, 00375 cneg_rej = 0.0, 00376 neighborhoodRange = 1.001, 00377 mean_data = 0.0, 00378 ifu_crpix = 0.0, 00379 ifu_crval = 0.0, 00380 ifu_cdelt = 0.0, 00381 qc_spat_unif = 0.0, 00382 qc_max_dev = 0.0, 00383 qc_max_nonunif = 0.0, 00384 tmp_stdev = 0.0, 00385 tmp_mean = 0.0, 00386 rotangle = 0.0, 00387 tmp_rotangle = 0.0, 00388 rotangle_found = 0.0; 00389 char *keyword = NULL, 00390 *fn_lut = NULL, 00391 *suffix = NULL, 00392 *extname = NULL, 00393 *filter = NULL; 00394 const char *method = NULL, 00395 *cmethod = NULL, 00396 *filter_id_l = NULL, 00397 *filter_id = NULL, 00398 *ranges_txt = NULL; 00399 cpl_array *calTimestamp = NULL, 00400 **unused_ifus_before = NULL, 00401 **unused_ifus_after = NULL; 00402 cpl_frame *frame = NULL, 00403 *xcalFrame = NULL, 00404 *ycalFrame = NULL, 00405 *lcalFrame = NULL; 00406 cpl_frameset *frameset_sky = NULL; 00407 cpl_image *img_in = NULL, 00408 *img_dark = NULL, 00409 *img_dark_noise = NULL, 00410 *img_flat = NULL, 00411 *img_flat_noise = NULL, 00412 *combined_data = NULL, 00413 *combined_noise = NULL, 00414 *xcal = NULL, 00415 *ycal = NULL, 00416 *lcal = NULL, 00417 *bad_pix_mask = NULL, 00418 *data_ifu = NULL, 00419 *noise_ifu = NULL, 00420 **stored_data_images = NULL, 00421 **stored_noise_images = NULL; 00422 cpl_imagelist *cube_data = NULL, 00423 *cube_noise = NULL, 00424 *detector_in = NULL, 00425 **stored_data_cubes = NULL, 00426 **stored_noise_cubes = NULL; 00427 cpl_matrix **edgepars = NULL; 00428 cpl_propertylist *main_header = NULL, 00429 *tmp_header = NULL, 00430 *sub_header = NULL, 00431 **stored_sub_data_headers = NULL, 00432 **stored_sub_noise_headers = NULL; 00433 cpl_table *band_table = NULL, 00434 ***edge_table_sky = NULL, 00435 **edge_table_flat = NULL; 00436 cpl_vector *ranges = NULL, 00437 *identified_slices = NULL, 00438 *calAngles = NULL, 00439 **slitlet_ids = NULL, 00440 *shift_vec = NULL, 00441 *edge_vec = NULL; 00442 main_fits_desc desc_sky, 00443 desc_dark, 00444 desc_flat, 00445 desc_xcal, 00446 desc_ycal, 00447 desc_lcal; 00448 gridDefinition gd; 00449 00450 KMO_TRY 00451 { 00452 kmo_init_fits_desc(&desc_sky); 00453 kmo_init_fits_desc(&desc_dark); 00454 kmo_init_fits_desc(&desc_flat); 00455 kmo_init_fits_desc(&desc_xcal); 00456 kmo_init_fits_desc(&desc_ycal); 00457 kmo_init_fits_desc(&desc_lcal); 00458 00459 /* --- check input --- */ 00460 KMO_TRY_ASSURE((parlist != NULL) && 00461 (frameset != NULL), 00462 CPL_ERROR_NULL_INPUT, 00463 "Not all input data is provided!"); 00464 00465 KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, FLAT_SKY) >= 1, 00466 CPL_ERROR_ILLEGAL_INPUT, 00467 "One or more FLAT_SKY frames are required!"); 00468 00469 if (cpl_frameset_count_tags(frameset, FLAT_SKY) < 3) { 00470 cpl_msg_warning(cpl_func, "It is recommended to provide at least " 00471 "3 FLAT_SKY frames!"); 00472 } 00473 00474 KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, MASTER_DARK) == 1, 00475 CPL_ERROR_ILLEGAL_INPUT, 00476 "Exactly one MASTER_DARK frame is required!"); 00477 00478 KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, MASTER_FLAT) == 1, 00479 CPL_ERROR_ILLEGAL_INPUT, 00480 "Exactly one MASTER_FLAT frame is required!"); 00481 00482 KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, XCAL) == 1, 00483 CPL_ERROR_ILLEGAL_INPUT, 00484 "Exactly one XCAL frame is required!"); 00485 00486 KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, YCAL) == 1, 00487 CPL_ERROR_ILLEGAL_INPUT, 00488 "Exactly one YCAL frame is required!"); 00489 00490 KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, LCAL) == 1, 00491 CPL_ERROR_ILLEGAL_INPUT, 00492 "Exactly one LCAL frame is required!"); 00493 00494 KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, WAVE_BAND) == 1, 00495 CPL_ERROR_ILLEGAL_INPUT, 00496 "Exactly one WAVE_BAND frame is required!"); 00497 00498 KMO_TRY_ASSURE((cpl_frameset_count_tags(frameset, FLAT_EDGE) == 1) || 00499 (cpl_frameset_count_tags(frameset, FLAT_EDGE) == 0), 00500 CPL_ERROR_ILLEGAL_INPUT, 00501 "Exactly one FLAT_EDGE frame is required!"); 00502 00503 has_flat_edge = cpl_frameset_count_tags(frameset, FLAT_EDGE); 00504 00505 KMO_TRY_ASSURE(kmo_dfs_set_groups(frameset, "kmo_illumination") == 1, 00506 CPL_ERROR_ILLEGAL_INPUT, 00507 "Cannot identify RAW and CALIB frames!"); 00508 00509 /* --- get parameters --- */ 00510 cpl_msg_info("", "--- Parameter setup for kmo_illumination ---"); 00511 00512 KMO_TRY_EXIT_IF_NULL( 00513 method = kmo_dfs_get_parameter_string(parlist, 00514 "kmos.kmo_illumination.imethod")); 00515 00516 KMO_TRY_ASSURE((strcmp(method, "NN") == 0) || 00517 (strcmp(method, "lwNN") == 0) || 00518 (strcmp(method, "swNN") == 0) || 00519 (strcmp(method, "MS") == 0) || 00520 (strcmp(method, "CS") == 0), 00521 CPL_ERROR_ILLEGAL_INPUT, 00522 "method must be either \"NN\", \"lwNN\", " 00523 "\"swNN\", \"MS\" or \"CS\"!"); 00524 00525 KMO_TRY_EXIT_IF_ERROR( 00526 kmo_dfs_print_parameter_help(parlist, 00527 "kmos.kmo_illumination.imethod")); 00528 00529 neighborhoodRange = kmo_dfs_get_parameter_double(parlist, 00530 "kmos.kmo_illumination.neighborhoodRange"); 00531 KMO_TRY_CHECK_ERROR_STATE(); 00532 00533 KMO_TRY_ASSURE(neighborhoodRange > 0.0, 00534 CPL_ERROR_ILLEGAL_INPUT, 00535 "neighborhoodRange must be greater than 0.0"); 00536 00537 KMO_TRY_EXIT_IF_ERROR( 00538 kmo_dfs_print_parameter_help(parlist, 00539 "kmos.kmo_illumination.neighborhoodRange")); 00540 00541 ranges_txt = kmo_dfs_get_parameter_string(parlist, 00542 "kmos.kmo_illumination.range"); 00543 KMO_TRY_CHECK_ERROR_STATE(); 00544 00545 KMO_TRY_EXIT_IF_ERROR( 00546 kmo_dfs_print_parameter_help(parlist, "kmos.kmo_illumination.range")); 00547 00548 ranges = kmo_identify_ranges(ranges_txt); 00549 KMO_TRY_CHECK_ERROR_STATE(); 00550 00551 flux = kmo_dfs_get_parameter_bool(parlist, 00552 "kmos.kmo_illumination.flux"); 00553 00554 KMO_TRY_ASSURE((flux == 0) || 00555 (flux == 1), 00556 CPL_ERROR_ILLEGAL_INPUT, 00557 "flux must be either FALSE or TRUE!"); 00558 00559 KMO_TRY_EXIT_IF_ERROR( 00560 kmo_dfs_print_parameter_help(parlist, "kmos.kmo_illumination.flux")); 00561 00562 add_all_sky = kmo_dfs_get_parameter_bool(parlist, 00563 "kmos.kmo_illumination.add-all"); 00564 00565 KMO_TRY_ASSURE((add_all_sky == 0) || 00566 (add_all_sky == 1), 00567 CPL_ERROR_ILLEGAL_INPUT, 00568 "add_all must be either FALSE or TRUE!"); 00569 00570 KMO_TRY_EXIT_IF_ERROR( 00571 kmo_dfs_print_parameter_help(parlist, "kmos.kmo_illumination.add-all")); 00572 00573 kmo_band_pars_load(parlist, "kmos.kmo_illumination"); 00574 00575 KMO_TRY_EXIT_IF_ERROR( 00576 kmo_combine_pars_load(parlist, 00577 "kmos.kmo_illumination", 00578 &cmethod, 00579 &cpos_rej, 00580 &cneg_rej, 00581 &citer, 00582 &cmin, 00583 &cmax, 00584 FALSE)); 00585 cpl_msg_info("", "-------------------------------------------"); 00586 00587 // check if filter_id, grating_id and rotator offset match for all 00588 // detectors 00589 KMO_TRY_EXIT_IF_ERROR( 00590 kmo_check_frameset_setup(frameset, FLAT_SKY, 00591 TRUE, FALSE, TRUE)); 00592 KMO_TRY_EXIT_IF_ERROR( 00593 kmo_check_frame_setup(frameset, FLAT_SKY, XCAL, 00594 TRUE, FALSE, TRUE)); 00595 KMO_TRY_EXIT_IF_ERROR( 00596 kmo_check_frame_setup(frameset, XCAL, YCAL, 00597 TRUE, FALSE, TRUE)); 00598 KMO_TRY_EXIT_IF_ERROR( 00599 kmo_check_frame_setup(frameset, XCAL, LCAL, 00600 TRUE, FALSE, TRUE)); 00601 KMO_TRY_EXIT_IF_ERROR( 00602 kmo_check_frame_setup(frameset, XCAL, MASTER_FLAT, 00603 TRUE, FALSE, TRUE)); 00604 00605 KMO_TRY_EXIT_IF_NULL( 00606 frame = kmo_dfs_get_frame(frameset, XCAL)); 00607 KMO_TRY_EXIT_IF_NULL( 00608 suffix = kmo_dfs_get_suffix(frame, TRUE, FALSE)); 00609 00610 KMO_TRY_EXIT_IF_ERROR( 00611 kmo_check_frame_setup_md5(frameset)); 00612 00613 cpl_msg_info("", "Detected instrument setup: %s", suffix+1); 00614 cpl_msg_info("", "(grating 1, 2 & 3)"); 00615 00616 // check which IFUs are active for all frames 00617 KMO_TRY_EXIT_IF_NULL( 00618 unused_ifus_before = kmo_get_unused_ifus(frameset, 0, 0)); 00619 00620 KMO_TRY_EXIT_IF_NULL( 00621 unused_ifus_after = kmo_duplicate_unused_ifus(unused_ifus_before)); 00622 00623 kmo_print_unused_ifus(unused_ifus_before, FALSE); 00624 00625 // load desc for MASTER_DARK and check 00626 KMO_TRY_EXIT_IF_NULL( 00627 frame = kmo_dfs_get_frame(frameset, MASTER_DARK)); 00628 desc_dark = kmo_identify_fits_header( 00629 cpl_frame_get_filename(frame)); 00630 KMO_TRY_CHECK_ERROR_STATE_MSG("MASTER_DARK frame doesn't seem to " 00631 "be in KMOS-format!"); 00632 KMO_TRY_ASSURE((desc_dark.nr_ext == 6) && 00633 (desc_dark.ex_badpix == FALSE) && 00634 (desc_dark.fits_type == f2d_fits) && 00635 (desc_dark.frame_type == detector_frame), 00636 CPL_ERROR_ILLEGAL_INPUT, 00637 "MASTER_DARK isn't in the correct format!!!"); 00638 nx = desc_dark.naxis1; 00639 ny = desc_dark.naxis2; 00640 00641 // load desc for MASTER_FLAT and check 00642 KMO_TRY_EXIT_IF_NULL( 00643 frame = kmo_dfs_get_frame(frameset, MASTER_FLAT)); 00644 desc_flat = kmo_identify_fits_header(cpl_frame_get_filename(frame)); 00645 KMO_TRY_CHECK_ERROR_STATE_MSG("MASTER_FLAT frame doesn't seem to " 00646 "be in KMOS-format!"); 00647 KMO_TRY_ASSURE((desc_flat.nr_ext % 6 == 0) && 00648 (desc_flat.ex_badpix == FALSE) && 00649 (desc_flat.fits_type == f2d_fits) && 00650 (desc_flat.frame_type == detector_frame), 00651 CPL_ERROR_ILLEGAL_INPUT, 00652 "MASTER_FLAT isn't in the correct format!!!"); 00653 00654 // load desc for XCAL and check 00655 KMO_TRY_EXIT_IF_NULL( 00656 xcalFrame = kmo_dfs_get_frame(frameset, XCAL)); 00657 desc_xcal = kmo_identify_fits_header(cpl_frame_get_filename(xcalFrame)); 00658 KMO_TRY_CHECK_ERROR_STATE_MSG("XCAL frame doesn't seem to " 00659 "be in KMOS-format!"); 00660 KMO_TRY_ASSURE((desc_xcal.nr_ext % 3 == 0) && 00661 (desc_xcal.ex_badpix == FALSE) && 00662 (desc_xcal.fits_type == f2d_fits) && 00663 (desc_xcal.frame_type == detector_frame), 00664 CPL_ERROR_ILLEGAL_INPUT, 00665 "XCAL isn't in the correct format!!!"); 00666 KMO_TRY_ASSURE((desc_xcal.naxis1 == nx) && 00667 (desc_xcal.naxis2 == ny), 00668 CPL_ERROR_ILLEGAL_INPUT, 00669 "MASTER_DARK and XCAL frame haven't same dimensions! " 00670 "(x,y): (%d,%d) vs (%d,%d)", 00671 nx, ny, desc_xcal.naxis1, desc_xcal.naxis2); 00672 00673 nr_devices = desc_xcal.nr_ext; 00674 00675 // load desc for YCAL and check 00676 KMO_TRY_EXIT_IF_NULL( 00677 ycalFrame = kmo_dfs_get_frame(frameset, YCAL)); 00678 desc_ycal = kmo_identify_fits_header(cpl_frame_get_filename(ycalFrame)); 00679 KMO_TRY_CHECK_ERROR_STATE_MSG("YCAL frame doesn't seem to " 00680 "be in KMOS-format!"); 00681 KMO_TRY_ASSURE((desc_ycal.nr_ext % 3 == 0) && 00682 (desc_ycal.ex_badpix == FALSE) && 00683 (desc_ycal.fits_type == f2d_fits) && 00684 (desc_ycal.frame_type == detector_frame), 00685 CPL_ERROR_ILLEGAL_INPUT, 00686 "YCAL isn't in the correct format!!!"); 00687 KMO_TRY_ASSURE((desc_ycal.naxis1 == nx) && 00688 (desc_ycal.naxis2 == ny) && 00689 (desc_ycal.nr_ext == nr_devices), 00690 CPL_ERROR_ILLEGAL_INPUT, 00691 "MASTER_DARK and YCAL frame haven't same dimensions! " 00692 "(x,y): (%d,%d) vs (%d,%d)", 00693 nx, ny, desc_ycal.naxis1, desc_ycal.naxis2); 00694 00695 // load desc for LCAL and check 00696 KMO_TRY_EXIT_IF_NULL( 00697 lcalFrame = kmo_dfs_get_frame(frameset, LCAL)); 00698 desc_lcal = kmo_identify_fits_header(cpl_frame_get_filename(lcalFrame)); 00699 KMO_TRY_CHECK_ERROR_STATE_MSG("LCAL frame doesn't seem to " 00700 "be in KMOS-format!"); 00701 KMO_TRY_ASSURE((desc_lcal.nr_ext % 3 == 0) && 00702 (desc_lcal.ex_badpix == FALSE) && 00703 (desc_lcal.fits_type == f2d_fits) && 00704 (desc_lcal.frame_type == detector_frame), 00705 CPL_ERROR_ILLEGAL_INPUT, 00706 "LCAL isn't in the correct format!!!"); 00707 KMO_TRY_ASSURE((desc_lcal.naxis1 == nx) && 00708 (desc_lcal.naxis2 == ny) && 00709 (desc_lcal.nr_ext == nr_devices), 00710 CPL_ERROR_ILLEGAL_INPUT, 00711 "MASTER_DARK and LCAL frame haven't same dimensions! " 00712 "(x,y): (%d,%d) vs (%d,%d)", 00713 nx, ny, desc_lcal.naxis1, desc_lcal.naxis2); 00714 KMO_TRY_EXIT_IF_NULL( 00715 tmp_header = kmo_dfs_load_primary_header(frameset, LCAL)); 00716 00717 // load desc for FLAT_SKY and check 00718 nr_devices = KMOS_NR_DETECTORS; 00719 KMO_TRY_EXIT_IF_NULL( 00720 frame = kmo_dfs_get_frame(frameset, FLAT_SKY)); 00721 00722 KMO_TRY_EXIT_IF_NULL( 00723 main_header = kmclipm_propertylist_load( 00724 cpl_frame_get_filename(frame), 0)); 00725 rotangle = cpl_propertylist_get_double(main_header, ROTANGLE); 00726 KMO_TRY_CHECK_ERROR_STATE_MSG("Cannot retrieve ROTANGLE FITS keyword from sky frame!"); 00727 kmclipm_strip_angle(&rotangle); 00728 cpl_propertylist_delete(main_header); main_header = NULL; 00729 00730 cnt = 1; 00731 while (frame != NULL) { 00732 KMO_TRY_EXIT_IF_NULL( 00733 main_header = kmclipm_propertylist_load( 00734 cpl_frame_get_filename(frame), 0)); 00735 00736 desc_sky = kmo_identify_fits_header( 00737 cpl_frame_get_filename(frame)); 00738 KMO_TRY_CHECK_ERROR_STATE_MSG("FLAT_SKY frame doesn't seem to " 00739 "be in KMOS-format!"); 00740 KMO_TRY_ASSURE((desc_sky.nr_ext == 3) && 00741 (desc_sky.ex_badpix == FALSE) && 00742 (desc_sky.fits_type == raw_fits) && 00743 (desc_sky.frame_type == detector_frame), 00744 CPL_ERROR_ILLEGAL_INPUT, 00745 "FLAT_SKY isn't in the correct format!!!"); 00746 KMO_TRY_ASSURE((desc_sky.naxis1 == nx) && 00747 (desc_sky.naxis2 == ny) && 00748 (desc_sky.nr_ext == nr_devices), 00749 CPL_ERROR_ILLEGAL_INPUT, 00750 "MASTER_DARK and FLAT_SKY (no. %d) frame haven't " 00751 "same dimensions! (x,y): (%d,%d) vs (%d,%d)", 00752 cnt, nx, ny, desc_flat.naxis1, desc_flat.naxis2); 00753 kmo_free_fits_desc(&desc_sky); 00754 kmo_init_fits_desc(&desc_sky); 00755 00756 KMO_TRY_ASSURE( 00757 (kmo_check_lamp(main_header, INS_LAMP1_ST) == FALSE) && 00758 (kmo_check_lamp(main_header, INS_LAMP2_ST) == FALSE) && 00759 (kmo_check_lamp(main_header, INS_LAMP3_ST) == FALSE) && 00760 (kmo_check_lamp(main_header, INS_LAMP4_ST) == FALSE), 00761 CPL_ERROR_ILLEGAL_INPUT, 00762 "All lamps must be switched off for the FLAT_SKY frames!"); 00763 00764 // assert that filters have correct IDs and that all detectors of 00765 // all input frames have the same filter set 00766 for (int i = 1; i <= KMOS_NR_DETECTORS; i++) { 00767 // ESO INS FILTi ID 00768 KMO_TRY_EXIT_IF_NULL( 00769 keyword = cpl_sprintf("%s%d%s", IFU_FILTID_PREFIX, i, IFU_FILTID_POSTFIX)); 00770 KMO_TRY_EXIT_IF_NULL( 00771 filter_id = cpl_propertylist_get_string(main_header, keyword)); 00772 00773 KMO_TRY_EXIT_IF_NULL( 00774 filter_id_l = cpl_propertylist_get_string(tmp_header, 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 "Filter ID in primary header must be either 'IZ', " 00784 "'YJ', 'H', 'K' or " "'HK' !"); 00785 00786 KMO_TRY_ASSURE(strcmp(filter_id, filter_id_l) == 0, 00787 CPL_ERROR_ILLEGAL_INPUT, 00788 "Filter 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 // ESO INS GRATi ID 00795 KMO_TRY_EXIT_IF_NULL( 00796 keyword = cpl_sprintf("%s%d%s", IFU_GRATID_PREFIX, i, IFU_GRATID_POSTFIX)); 00797 KMO_TRY_EXIT_IF_NULL( 00798 filter_id = cpl_propertylist_get_string(main_header, keyword)); 00799 00800 KMO_TRY_EXIT_IF_NULL( 00801 filter_id_l = cpl_propertylist_get_string(tmp_header, keyword)); 00802 cpl_free(keyword); keyword = NULL; 00803 00804 KMO_TRY_ASSURE((strcmp(filter_id, "IZ") == 0) || 00805 (strcmp(filter_id, "YJ") == 0) || 00806 (strcmp(filter_id, "H") == 0) || 00807 (strcmp(filter_id, "K") == 0) || 00808 (strcmp(filter_id, "HK") == 0), 00809 CPL_ERROR_ILLEGAL_INPUT, 00810 "Grating ID in primary header must be either " 00811 "'IZ', 'YJ', 'H', 'K' or " "'HK' !"); 00812 00813 KMO_TRY_ASSURE(strcmp(filter_id, filter_id_l) == 0, 00814 CPL_ERROR_ILLEGAL_INPUT, 00815 "Grating IDs must be the same for FLAT_SKY frame" 00816 " and lcal frame!" 00817 "Detector No.: %d\n%s: %s\nLCAL: %s\n", 00818 i, cpl_frame_get_filename(frame), 00819 filter_id, filter_id_l); 00820 00821 tmp_rotangle = cpl_propertylist_get_double(main_header, ROTANGLE); 00822 KMO_TRY_CHECK_ERROR_STATE_MSG("Cannot retrieve ROTANGLE FITS keyword from sky frame!"); 00823 kmclipm_strip_angle(&tmp_rotangle); 00824 KMO_TRY_ASSURE((abs(rotangle - tmp_rotangle) < 10.0) || 00825 (abs(rotangle - tmp_rotangle) > 360.-10.) , 00826 CPL_ERROR_ILLEGAL_INPUT, 00827 "OCS ROT NAANGLE of sky flat frames differ to much: %f %f", 00828 rotangle, tmp_rotangle); 00829 } 00830 cpl_propertylist_delete(main_header); main_header = NULL; 00831 00832 // get next FLAT_SKY frame 00833 frame = kmo_dfs_get_frame(frameset, NULL); 00834 KMO_TRY_CHECK_ERROR_STATE(); 00835 cnt++; 00836 } 00837 00838 cpl_propertylist_delete(tmp_header); tmp_header = NULL; 00839 00840 // 00841 // noise will be propagated when: 00842 // MASTER_DARK and MASTER_FLAT have noise extensions and if at least 00843 // 2 FLAT_SKY frames are provided. 00844 // Otherwise noise will be ignored. 00845 // 00846 if (desc_dark.ex_noise && 00847 desc_flat.ex_noise && 00848 (cpl_frameset_count_tags(frameset, FLAT_SKY) >= 2)) { 00849 process_noise = TRUE; 00850 } 00851 00852 if (cpl_frameset_count_tags(frameset, FLAT_SKY) == 1) { 00853 cpl_msg_warning(cpl_func, "cmethod is changed to 'average' " 00854 "since there is only one input frame! (The output " 00855 "file won't have any noise extensions)"); 00856 00857 cmethod = "average"; 00858 } 00859 00860 // 00861 // Check whether 1st FLAT_SKY should be omitted 00862 // 00863 KMO_TRY_EXIT_IF_NULL( 00864 frameset_sky = cpl_frameset_new()); 00865 00866 if (add_all_sky) { 00867 // just add all FLAT_SKY frames without check 00868 frame = kmo_dfs_get_frame(frameset, FLAT_SKY); 00869 while (frame != NULL) { 00870 KMO_TRY_EXIT_IF_ERROR( 00871 cpl_frameset_insert(frameset_sky, cpl_frame_duplicate(frame))); 00872 frame = kmo_dfs_get_frame(frameset, NULL); 00873 } 00874 cpl_msg_info("", "Add all FLAT_SKY without checking for acquisition frame."); 00875 } else { 00876 // check if 1st FLAT_SKY has different exposure time and whether to omit it 00877 KMO_TRY_EXIT_IF_NULL( 00878 frame = kmo_dfs_get_frame(frameset, FLAT_SKY)); 00879 00880 if (cpl_frameset_count_tags(frameset, FLAT_SKY) == 1) { 00881 // just one FLAT_SKY, always add 00882 KMO_TRY_EXIT_IF_ERROR( 00883 cpl_frameset_insert(frameset_sky, cpl_frame_duplicate(frame))); 00884 KMO_TRY_CHECK_ERROR_STATE(); 00885 } else { 00886 // several FLAT_SKY frames, check exptime 00887 00888 // get exptime 1 00889 KMO_TRY_EXIT_IF_NULL( 00890 main_header = kmclipm_propertylist_load(cpl_frame_get_filename(frame), 0)); 00891 exptime1 = cpl_propertylist_get_double(main_header, EXPTIME); 00892 KMO_TRY_CHECK_ERROR_STATE(); 00893 cpl_propertylist_delete(main_header); main_header = NULL; 00894 00895 // get exptime 2 00896 frame = kmo_dfs_get_frame(frameset, NULL); 00897 KMO_TRY_EXIT_IF_NULL( 00898 main_header = kmclipm_propertylist_load(cpl_frame_get_filename(frame), 0)); 00899 exptime2 = cpl_propertylist_get_double(main_header, EXPTIME); 00900 KMO_TRY_CHECK_ERROR_STATE(); 00901 cpl_propertylist_delete(main_header); main_header = NULL; 00902 00903 // loop remaining frames 00904 same_exptime = TRUE; 00905 frame = kmo_dfs_get_frame(frameset, NULL); 00906 while (same_exptime && (frame != NULL)) { 00907 KMO_TRY_EXIT_IF_NULL( 00908 main_header = kmclipm_propertylist_load(cpl_frame_get_filename(frame), 0)); 00909 exptime = cpl_propertylist_get_double(main_header, EXPTIME); 00910 KMO_TRY_CHECK_ERROR_STATE(); 00911 cpl_propertylist_delete(main_header); main_header = NULL; 00912 if (fabs(exptime-exptime2) > 0.01) { 00913 // not same 00914 same_exptime = FALSE; 00915 } 00916 frame = kmo_dfs_get_frame(frameset, NULL); 00917 } 00918 00919 if (same_exptime) { 00920 // frame [2,n] have same exptime, add them 00921 frame = kmo_dfs_get_frame(frameset, FLAT_SKY); 00922 KMO_TRY_EXIT_IF_NULL( 00923 main_header = kmclipm_propertylist_load(cpl_frame_get_filename(frame), 0)); 00924 exptime = cpl_propertylist_get_double(main_header, EXPTIME); 00925 KMO_TRY_CHECK_ERROR_STATE(); 00926 cpl_propertylist_delete(main_header); main_header = NULL; 00927 cpl_msg_info("", "Omit FLAT_SKY: %s with EXPTIME of %g sec (acquisition), other frame(s) have EXPTIME of %g sec", cpl_frame_get_filename(frame), exptime, exptime2); 00928 frame = kmo_dfs_get_frame(frameset, NULL); 00929 while (frame != NULL) { 00930 KMO_TRY_EXIT_IF_ERROR( 00931 cpl_frameset_insert(frameset_sky, cpl_frame_duplicate(frame))); 00932 frame = kmo_dfs_get_frame(frameset, NULL); 00933 } 00934 if (fabs(exptime1-exptime2) < 0.01) { 00935 cpl_msg_warning("", "The 1st FLAT_SKY has the same exposure time as the following ones. " 00936 "It has anyway been omitted since we assume it is an acquisition frame. " 00937 "If you want to add it anyway call this recipe with the --add-all parameter"); 00938 } 00939 } else { 00940 cpl_msg_error("", "The exposure times of the FLAT_SKY frames don't match!"); 00941 cpl_msg_error("", "We assume that the 1st frame is an acquisition frame and would be omitted."); 00942 cpl_msg_error("", "The following frames should have the same exposure time if they originate from the same template."); 00943 cpl_msg_error("", "If you want to reduce them anyway call this recipe with the --add-all parameter"); 00944 frame = kmo_dfs_get_frame(frameset, FLAT_SKY); 00945 while (frame != NULL) { 00946 KMO_TRY_EXIT_IF_NULL( 00947 main_header = kmclipm_propertylist_load(cpl_frame_get_filename(frame), 0)); 00948 exptime = cpl_propertylist_get_double(main_header, EXPTIME); 00949 KMO_TRY_CHECK_ERROR_STATE(); 00950 cpl_propertylist_delete(main_header); main_header = NULL; 00951 cpl_msg_error("", "FLAT_SKY: %s, EXPTIME: %g", cpl_frame_get_filename(frame), exptime); 00952 frame = kmo_dfs_get_frame(frameset, NULL); 00953 } 00954 cpl_error_set(cpl_func, CPL_ERROR_ILLEGAL_INPUT); 00955 KMO_TRY_CHECK_ERROR_STATE(); 00956 } 00957 } 00958 } 00959 00960 KMO_TRY_EXIT_IF_NULL( 00961 frame = kmo_dfs_get_frame(frameset_sky, FLAT_SKY)); 00962 KMO_TRY_EXIT_IF_NULL( 00963 main_header = kmo_dfs_load_primary_header(frameset_sky, FLAT_SKY)); 00964 KMO_TRY_EXIT_IF_NULL( 00965 keyword = cpl_sprintf("%s%d%s", IFU_GRATID_PREFIX, 1, IFU_GRATID_POSTFIX)); 00966 KMO_TRY_EXIT_IF_NULL( 00967 filter = cpl_sprintf("%s", cpl_propertylist_get_string(main_header, keyword))); 00968 cpl_free(keyword); keyword = NULL; 00969 00970 // 00971 // set default band-specific ranges for collapsing 00972 // 00973 if (ranges == NULL) { 00974 if (strcmp(filter, "IZ") == 0) { 00975 ranges_txt = "0.81,1.05"; 00976 } else if (strcmp(filter, "YJ") == 0) { 00977 ranges_txt = "1.025,1.3"; 00978 } else if (strcmp(filter, "H") == 0) { 00979 ranges_txt = "1.5,1.7"; 00980 } else if (strcmp(filter, "K") == 0) { 00981 ranges_txt = "2.1,2.35"; 00982 } else if (strcmp(filter, "HK") == 0) { 00983 ranges_txt = "1.5,1.7;2.1,2.35"; 00984 // ranges_txt = "1.5,1.7"; 00985 } else { 00986 KMO_TRY_ASSURE(1 == 0, 00987 CPL_ERROR_ILLEGAL_INPUT, 00988 "We really shouldn't get here..."); 00989 } 00990 cpl_msg_info("", "Spectral range to collapse has been set to %s um for this band.", ranges_txt); 00991 ranges = kmo_identify_ranges(ranges_txt); 00992 KMO_TRY_CHECK_ERROR_STATE(); 00993 } 00994 00995 // setup grid definition, wavelength start and end points will be set 00996 // in the detector loop 00997 KMO_TRY_EXIT_IF_ERROR( 00998 kmclipm_setup_grid(&gd, method, neighborhoodRange)); 00999 01000 // create filename for LUT 01001 KMO_TRY_EXIT_IF_NULL( 01002 fn_lut = cpl_sprintf("%s%s", "lut", suffix)); 01003 01004 // extract bounds 01005 KMO_TRY_EXIT_IF_NULL( 01006 tmp_header = kmclipm_propertylist_load( 01007 cpl_frame_get_filename(xcalFrame), 0)); 01008 KMO_TRY_EXIT_IF_NULL( 01009 bounds = kmclipm_extract_bounds(tmp_header)); 01010 cpl_propertylist_delete(tmp_header); tmp_header = NULL; 01011 01012 // get timestamps of xcal, ycal & lcal 01013 KMO_TRY_EXIT_IF_NULL( 01014 calTimestamp = kmo_get_timestamps(xcalFrame, ycalFrame, lcalFrame)); 01015 01016 // create arrays to hold reconstructed data and noise cubes and 01017 // their headers 01018 KMO_TRY_EXIT_IF_NULL( 01019 stored_data_cubes = (cpl_imagelist**)cpl_calloc(nr_devices * KMOS_IFUS_PER_DETECTOR, 01020 sizeof(cpl_imagelist*))); 01021 KMO_TRY_EXIT_IF_NULL( 01022 stored_noise_cubes = (cpl_imagelist**)cpl_calloc(nr_devices * KMOS_IFUS_PER_DETECTOR, 01023 sizeof(cpl_imagelist*))); 01024 KMO_TRY_EXIT_IF_NULL( 01025 stored_data_images = (cpl_image**)cpl_calloc(nr_devices * KMOS_IFUS_PER_DETECTOR, 01026 sizeof(cpl_image*))); 01027 KMO_TRY_EXIT_IF_NULL( 01028 stored_noise_images = (cpl_image**)cpl_calloc(nr_devices * KMOS_IFUS_PER_DETECTOR, 01029 sizeof(cpl_image*))); 01030 KMO_TRY_EXIT_IF_NULL( 01031 stored_sub_data_headers = (cpl_propertylist**)cpl_calloc(nr_devices * KMOS_IFUS_PER_DETECTOR, 01032 sizeof(cpl_propertylist*))); 01033 KMO_TRY_EXIT_IF_NULL( 01034 stored_sub_noise_headers = (cpl_propertylist**)cpl_calloc(nr_devices * KMOS_IFUS_PER_DETECTOR, 01035 sizeof(cpl_propertylist*))); 01036 KMO_TRY_EXIT_IF_NULL( 01037 edge_table_sky = (cpl_table***)cpl_calloc(KMOS_NR_DETECTORS, 01038 sizeof(cpl_table**))); 01039 KMO_TRY_EXIT_IF_NULL( 01040 edge_table_flat = (cpl_table**)cpl_calloc(KMOS_IFUS_PER_DETECTOR, 01041 sizeof(cpl_table*))); 01042 KMO_TRY_EXIT_IF_NULL( 01043 calAngles = cpl_vector_new(3)); 01044 01045 // 01046 // loop through all detectors 01047 // 01048 for (int det_nr = 1; det_nr <= nr_devices; det_nr++) { 01049 cpl_msg_info("","Processing detector No. %d", det_nr); 01050 01051 KMO_TRY_EXIT_IF_NULL( 01052 detector_in = cpl_imagelist_new()); 01053 01054 // load data of det_nr of all FLAT_SKY frames into an imagelist 01055 KMO_TRY_EXIT_IF_NULL( 01056 img_in = kmo_dfs_load_image(frameset_sky, FLAT_SKY, det_nr, FALSE, TRUE, NULL)); 01057 01058 cnt = 0; 01059 while (img_in != NULL) { 01060 cpl_imagelist_set(detector_in, img_in, cnt); 01061 KMO_TRY_CHECK_ERROR_STATE(); 01062 01063 /* load same extension of next FLAT_SKY frame*/ 01064 img_in = kmo_dfs_load_image(frameset_sky, NULL, det_nr, FALSE, TRUE, NULL); 01065 KMO_TRY_CHECK_ERROR_STATE(); 01066 01067 cnt++; 01068 } 01069 01070 // 01071 // process imagelist 01072 // 01073 01074 // combine imagelist (data only) and create noise (stdev of data) 01075 cpl_msg_info("","Combining frames..."); 01076 if (process_noise) { 01077 KMO_TRY_EXIT_IF_ERROR( 01078 kmclipm_combine_frames(detector_in, 01079 NULL, 01080 NULL, 01081 cmethod, 01082 cpos_rej, 01083 cneg_rej, 01084 citer, 01085 cmax, 01086 cmin, 01087 &combined_data, 01088 &combined_noise, 01089 -1.0)); 01090 } else { 01091 KMO_TRY_EXIT_IF_ERROR( 01092 kmclipm_combine_frames(detector_in, 01093 NULL, 01094 NULL, 01095 cmethod, 01096 cpos_rej, 01097 cneg_rej, 01098 citer, 01099 cmax, 01100 cmin, 01101 &combined_data, 01102 NULL, 01103 -1.0)); 01104 } 01105 01106 if (kmclipm_omit_warning_one_slice > 10) { 01107 cpl_msg_warning(cpl_func, "Previous warning (number of " 01108 "identified slices) occured %d times.", 01109 kmclipm_omit_warning_one_slice); 01110 kmclipm_omit_warning_one_slice = FALSE; 01111 } 01112 01113 cpl_imagelist_delete(detector_in); detector_in = NULL; 01114 01115 // load calibration files 01116 KMO_TRY_EXIT_IF_NULL( 01117 xcal = kmo_dfs_load_cal_image(frameset, XCAL, det_nr, FALSE, rotangle, 01118 FALSE, NULL, &rotangle_found)); 01119 01120 KMO_TRY_EXIT_IF_ERROR( 01121 cpl_vector_set(calAngles, 0, rotangle_found)); 01122 KMO_TRY_EXIT_IF_NULL( 01123 ycal = kmo_dfs_load_cal_image(frameset, YCAL, det_nr, FALSE, rotangle, 01124 FALSE, NULL, &rotangle_found)); 01125 KMO_TRY_EXIT_IF_ERROR( 01126 cpl_vector_set(calAngles, 1, rotangle_found)); 01127 KMO_TRY_EXIT_IF_NULL( 01128 lcal = kmo_dfs_load_cal_image(frameset, LCAL, det_nr, FALSE, rotangle, 01129 FALSE, NULL, &rotangle_found)); 01130 KMO_TRY_EXIT_IF_ERROR( 01131 cpl_vector_set(calAngles, 2, rotangle_found)); 01132 01133 // load bad pixel mask from XCAL and set NaNs to 0 and all other values to 1 01134 KMO_TRY_EXIT_IF_NULL( 01135 bad_pix_mask = cpl_image_duplicate(xcal)); 01136 01137 KMO_TRY_EXIT_IF_NULL( 01138 pbad_pix_mask = cpl_image_get_data_float(bad_pix_mask)); 01139 for (int x = 0; x < nx; x++) { 01140 for (int y = 0; y < ny; y++) { 01141 if (isnan(pbad_pix_mask[x+nx*y])) { 01142 pbad_pix_mask[x+nx*y] = 0.; 01143 } else { 01144 pbad_pix_mask[x+nx*y] = 1.; 01145 } 01146 } 01147 } 01148 KMO_TRY_CHECK_ERROR_STATE(); 01149 01150 // 01151 // calculate SKYFLAT_EDGE 01152 // 01153 if (has_flat_edge) { 01154 // get edge-edgepars from FLAT_SKY 01155 KMO_TRY_EXIT_IF_ERROR( 01156 kmo_calc_edgepars(combined_data, 01157 unused_ifus_after[det_nr-1], 01158 bad_pix_mask, 01159 det_nr, 01160 &slitlet_ids, 01161 &edgepars)); 01162 KMO_TRY_CHECK_ERROR_STATE(); 01163 01164 // copy edgepars to table for saving later on 01165 KMO_TRY_EXIT_IF_NULL( 01166 edge_table_sky[det_nr-1] = kmo_edgepars_to_table(slitlet_ids, edgepars)); 01167 01168 if (edgepars != NULL) { 01169 for (int i = 0; i < KMOS_IFUS_PER_DETECTOR; i++) { 01170 cpl_matrix_delete(edgepars[i]); edgepars[i] = NULL; 01171 } 01172 cpl_free(edgepars); edgepars = NULL; 01173 } 01174 if (slitlet_ids != NULL) { 01175 for (int i = 0; i < KMOS_IFUS_PER_DETECTOR; i++) { 01176 cpl_vector_delete(slitlet_ids[i]); slitlet_ids[i] = NULL; 01177 } 01178 cpl_free(slitlet_ids); slitlet_ids = NULL; 01179 } 01180 KMO_TRY_CHECK_ERROR_STATE(); 01181 01182 // 01183 // correlate FLAT_EDGE and SKYFLAT_EDGE 01184 // 01185 01186 // load flat_edge from MASTER_FLAT 01187 KMO_TRY_EXIT_IF_NULL( 01188 frame = kmo_dfs_get_frame(frameset, FLAT_EDGE)); 01189 for (int j = 0; j < KMOS_IFUS_PER_DETECTOR; j++) { 01190 ifu_nr = (det_nr-1)*KMOS_IFUS_PER_DETECTOR + j + 1; 01191 KMO_TRY_EXIT_IF_NULL( 01192 edge_table_flat[j] = kmclipm_cal_table_load(cpl_frame_get_filename(frame), 01193 ifu_nr, rotangle, 0, &tmp_rotangle)); 01194 } 01195 01196 // 01197 // calculate shift value 01198 // 01199 01200 KMO_TRY_EXIT_IF_NULL( 01201 shift_vec = cpl_vector_new(KMOS_IFUS_PER_DETECTOR)); 01202 KMO_TRY_EXIT_IF_NULL( 01203 edge_vec = cpl_vector_new(2*KMOS_SLITLET_X)); 01204 01205 // get shift values for each IFU by comparing all edge parameters, 01206 // rejecting and applying median 01207 int row = 1024; // middle of frame 01208 for (int j = 0; j < KMOS_IFUS_PER_DETECTOR; j++) { 01209 ifu_nr = (det_nr-1)*KMOS_IFUS_PER_DETECTOR + j + 1; 01210 for (int edgeNr = 0; edgeNr < 2*KMOS_SLITLET_X; edgeNr++) { 01211 double flatval = kmo_calc_fitted_slitlet_edge(edge_table_flat[j], edgeNr, row); 01212 double skyval = kmo_calc_fitted_slitlet_edge(edge_table_sky[det_nr-1][j], edgeNr, row); 01213 cpl_vector_set(edge_vec, edgeNr, flatval-skyval); 01214 } 01215 01216 // reject deviating edge-differences 01217 kmclipm_vector *kv = NULL; 01218 KMO_TRY_EXIT_IF_NULL( 01219 kv = kmclipm_vector_create(cpl_vector_duplicate(edge_vec))); 01220 kmclipm_reject_deviant(kv, 3, 3, NULL, NULL); 01221 01222 // set shift value for each IFU 01223 cpl_vector_set(shift_vec, j, kmclipm_vector_get_median(kv, KMCLIPM_ARITHMETIC)); 01224 kmclipm_vector_delete(kv); kv = NULL; 01225 } 01226 cpl_vector_delete(edge_vec); edge_vec = NULL; 01227 KMO_TRY_CHECK_ERROR_STATE(); 01228 01229 for (int j = 0; j < KMOS_IFUS_PER_DETECTOR; j++) { 01230 cpl_table_delete(edge_table_flat[j]); 01231 edge_table_flat[j] = NULL; 01232 } 01233 01234 // take median of all IFU-shift-values 01235 double shift_val = -cpl_vector_get_median(shift_vec); 01236 cpl_vector_delete(shift_vec); shift_vec = NULL; 01237 01238 cpl_msg_info("", "Shift detector %d by %g pixels.", det_nr, shift_val); 01239 01240 int xdim = cpl_image_get_size_x(combined_data), 01241 ydim = cpl_image_get_size_y(combined_data); 01242 double *array_in = cpl_calloc(xdim, sizeof(double)), 01243 *array_out = NULL; 01244 float *pcombined_data = cpl_image_get_data_float(combined_data), 01245 *pcombined_noise = NULL; 01246 // float *tmpArray = cpl_calloc(xdim, sizeof(float)); 01247 if (process_noise) { 01248 pcombined_noise = cpl_image_get_data_float(combined_noise); 01249 } 01250 01251 for (int iy = 0; iy < ydim; iy++) { 01252 // cubic spline 01253 for (int ix = 0; ix < xdim; ix++) { 01254 array_in[ix] = pcombined_data[ix+iy*xdim]; 01255 } 01256 array_out = cubicspline_reg_reg(xdim, 0., 1., array_in, 01257 xdim, shift_val, 1.0, 01258 NATURAL); 01259 for (int ix = 0; ix < xdim; ix++) { 01260 pcombined_data[ix+iy*xdim] = array_out[ix]; 01261 } 01262 cpl_free(array_out); 01263 01264 // // linear 01265 // for (int ix = 1; ix < xdim; ix++) { 01266 // tmpArray[ix-1] = (pcombined_data[ix+iy*xdim]-pcombined_data[(ix-1)+iy*xdim])*shift_val + 01267 // pcombined_data[(ix-1)+iy*xdim]; 01268 // } 01269 // for (int ix = 1; ix < xdim; ix++) { 01270 // pcombined_data[ix+iy*xdim] = tmpArray[ix]; 01271 // } 01272 01273 if (process_noise) { 01274 // cubic spline 01275 for (int ix = 0; ix < xdim; ix++) { 01276 array_in[ix] = pcombined_noise[ix+iy*xdim]; 01277 } 01278 array_out = cubicspline_reg_reg(xdim, 0., 1., array_in, 01279 xdim, shift_val, 1.0, 01280 NATURAL); 01281 for (int ix = 0; ix < xdim; ix++) { 01282 pcombined_noise[ix+iy*xdim] = array_out[ix]; 01283 } 01284 cpl_free(array_out); 01285 01286 // // linear 01287 // for (int ix = 1; ix < xdim; ix++) { 01288 // tmpArray[ix-1] = (pcombined_noise[ix+iy*xdim]-pcombined_noise[(ix-1)+iy*xdim])*shift_val + 01289 // pcombined_noise[(ix-1)+iy*xdim]; 01290 // } 01291 // for (int ix = 1; ix < xdim; ix++) { 01292 // pcombined_noise[ix+iy*xdim] = tmpArray[ix]; 01293 // } 01294 } 01295 } 01296 cpl_free(array_in); array_in = NULL; 01297 } 01298 // 01299 // reconstruct 01300 // 01301 // load MASTER_DARK and MASTER_FLAT 01302 KMO_TRY_EXIT_IF_NULL( 01303 img_dark = kmo_dfs_load_image(frameset, MASTER_DARK, 01304 det_nr, FALSE, FALSE, NULL)); 01305 01306 if (process_noise) { 01307 KMO_TRY_EXIT_IF_NULL( 01308 img_dark_noise = kmo_dfs_load_image(frameset, MASTER_DARK, 01309 det_nr, TRUE, FALSE, NULL)); 01310 } 01311 01312 KMO_TRY_EXIT_IF_NULL( 01313 img_flat = kmo_dfs_load_cal_image(frameset, MASTER_FLAT, det_nr, FALSE, 01314 rotangle, FALSE, NULL, &rotangle_found)); 01315 01316 if (process_noise) { 01317 KMO_TRY_EXIT_IF_NULL( 01318 img_flat_noise = kmo_dfs_load_cal_image(frameset, MASTER_FLAT, det_nr, TRUE, 01319 rotangle, FALSE, NULL, &rotangle_found)); 01320 } 01321 01322 char *tmp_band_method = getenv("KMO_BAND_METHOD"); 01323 int band_method = 0; 01324 if (tmp_band_method != NULL) { 01325 band_method = atoi(tmp_band_method); 01326 } 01327 01328 // ESO INS FILTi ID 01329 KMO_TRY_EXIT_IF_NULL( 01330 keyword = cpl_sprintf("%s%d%s", IFU_FILTID_PREFIX, det_nr, 01331 IFU_FILTID_POSTFIX)); 01332 KMO_TRY_EXIT_IF_NULL( 01333 filter_id = cpl_propertylist_get_string(main_header, keyword)); 01334 cpl_free(keyword); keyword = NULL; 01335 01336 KMO_TRY_EXIT_IF_NULL( 01337 band_table = kmo_dfs_load_table(frameset, WAVE_BAND, 1, 0)); 01338 KMO_TRY_EXIT_IF_ERROR( 01339 kmclipm_setup_grid_band_lcal(&gd, lcal, filter_id, band_method, 01340 band_table)); 01341 cpl_table_delete(band_table); band_table = NULL; 01342 01343 cpl_msg_info("","Reconstructing cubes..."); 01344 for (int j = 0; j < KMOS_IFUS_PER_DETECTOR; j++) { 01345 // update sub-header 01346 ifu_nr = (det_nr-1)*KMOS_IFUS_PER_DETECTOR + j + 1; 01347 01348 // load raw image and sub-header 01349 KMO_TRY_EXIT_IF_NULL( 01350 sub_header = kmo_dfs_load_sub_header(frameset_sky, FLAT_SKY, 01351 det_nr, FALSE)); 01352 01353 KMO_TRY_EXIT_IF_NULL( 01354 punused_ifus = cpl_array_get_data_int_const( 01355 unused_ifus_after[det_nr-1])); 01356 01357 // check if IFU is valid according to main header keywords & 01358 // calibration files 01359 KMO_TRY_EXIT_IF_NULL( 01360 keyword = cpl_sprintf("%s%d%s", IFU_VALID_PREFIX, ifu_nr, 01361 IFU_VALID_POSTFIX)); 01362 KMO_TRY_CHECK_ERROR_STATE(); 01363 ranges_txt = cpl_propertylist_get_string(main_header, keyword); 01364 cpl_free(keyword); keyword = NULL; 01365 01366 if ((cpl_error_get_code() == CPL_ERROR_DATA_NOT_FOUND) && 01367 (bounds[2*(ifu_nr-1)] != -1) && 01368 (bounds[2*(ifu_nr-1)+1] != -1) && 01369 (punused_ifus[j] == 0)) 01370 { 01371 // IFU is valid 01372 cpl_error_reset(); 01373 01374 // calculate WCS 01375 KMO_TRY_EXIT_IF_ERROR( 01376 kmo_calc_wcs(main_header, sub_header, ifu_nr, 01377 gd.l.start, gd.l.delta)); 01378 01379 // reconstruct data 01380 KMO_TRY_EXIT_IF_ERROR( 01381 kmo_reconstruct_sci_image(ifu_nr, 01382 bounds[2*(ifu_nr-1)], 01383 bounds[2*(ifu_nr-1)+1], 01384 combined_data, 01385 combined_noise, 01386 img_dark, 01387 img_dark_noise, 01388 img_flat, 01389 img_flat_noise, 01390 xcal, 01391 ycal, 01392 lcal, 01393 &gd, 01394 calTimestamp, 01395 calAngles, 01396 fn_lut, 01397 &cube_data, 01398 &cube_noise, 01399 flux)); 01400 KMO_TRY_CHECK_ERROR_STATE(); 01401 } else { 01402 // IFU is invalid 01403 cpl_error_reset(); 01404 } // if ((cpl_error_get_code() == CPL_ERROR_DATA_NOT_FOUND) ... 01405 01406 // save output 01407 KMO_TRY_EXIT_IF_NULL( 01408 extname = kmo_extname_creator(ifu_frame, ifu_nr, EXT_DATA)); 01409 01410 KMO_TRY_EXIT_IF_ERROR( 01411 kmclipm_update_property_string(sub_header, EXTNAME, 01412 extname, 01413 "FITS extension name")); 01414 01415 cpl_free(extname); extname = NULL; 01416 01417 // store cube and sub header into array for later 01418 stored_data_cubes[ifu_nr - 1] = cube_data; 01419 stored_sub_data_headers[ifu_nr - 1] = sub_header; 01420 01421 if (process_noise) { 01422 KMO_TRY_EXIT_IF_NULL( 01423 sub_header = cpl_propertylist_duplicate( 01424 stored_sub_data_headers[ifu_nr - 1])); 01425 KMO_TRY_EXIT_IF_NULL( 01426 extname = kmo_extname_creator(ifu_frame, ifu_nr, 01427 EXT_NOISE)); 01428 01429 KMO_TRY_EXIT_IF_ERROR( 01430 kmclipm_update_property_string(sub_header, 01431 EXTNAME, 01432 extname, 01433 "FITS extension name")); 01434 01435 cpl_free(extname); extname = NULL; 01436 01437 stored_noise_cubes[ifu_nr - 1] = cube_noise; 01438 stored_sub_noise_headers[ifu_nr - 1] = sub_header; 01439 } 01440 cpl_image_delete(data_ifu); data_ifu = NULL; 01441 cpl_image_delete(noise_ifu); noise_ifu = NULL; 01442 cube_data = NULL; 01443 cube_noise = NULL; 01444 } // for j IFUs 01445 01446 // free memory 01447 cpl_image_delete(combined_data); combined_data = NULL; 01448 cpl_image_delete(combined_noise); combined_noise = NULL; 01449 cpl_image_delete(xcal); xcal = NULL; 01450 cpl_image_delete(ycal); ycal = NULL; 01451 cpl_image_delete(lcal); lcal = NULL; 01452 cpl_image_delete(img_dark); img_dark = NULL; 01453 cpl_image_delete(img_flat); img_flat = NULL; 01454 cpl_image_delete(bad_pix_mask); bad_pix_mask = NULL; 01455 if (process_noise) { 01456 cpl_image_delete(img_dark_noise); img_dark_noise = NULL; 01457 cpl_image_delete(img_flat_noise); img_flat_noise = NULL; 01458 } 01459 } // for nr_devices 01460 01461 cpl_free(edge_table_flat); edge_table_flat = NULL; 01462 01463 // collapse cubes using rejection 01464 cpl_msg_info("","Collapsing cubes..."); 01465 for (int det_nr = 1; det_nr <= nr_devices; det_nr++) { 01466 for (int j = 0; j < KMOS_IFUS_PER_DETECTOR; j++) { 01467 ifu_nr = (det_nr-1)*KMOS_IFUS_PER_DETECTOR + j + 1; 01468 01469 KMO_TRY_EXIT_IF_NULL( 01470 punused_ifus = cpl_array_get_data_int_const( 01471 unused_ifus_after[det_nr-1])); 01472 if (punused_ifus[j] == 0) { 01473 if (stored_sub_data_headers[ifu_nr-1] != NULL) { 01474 // IFU is valid 01475 ifu_crpix = cpl_propertylist_get_double(stored_sub_data_headers[ifu_nr-1], 01476 CRPIX3); 01477 KMO_TRY_CHECK_ERROR_STATE_MSG( 01478 "CRPIX3 keyword in FITS-header is missing!"); 01479 01480 ifu_crval = cpl_propertylist_get_double(stored_sub_data_headers[ifu_nr-1], 01481 CRVAL3); 01482 KMO_TRY_CHECK_ERROR_STATE_MSG( 01483 "CRVAL3 keyword in FITS-header is missing!"); 01484 01485 ifu_cdelt = cpl_propertylist_get_double(stored_sub_data_headers[ifu_nr-1], 01486 CDELT3); 01487 KMO_TRY_CHECK_ERROR_STATE_MSG( 01488 "CDELT3 keyword in FITS-header is missing!"); 01489 01490 KMO_TRY_EXIT_IF_NULL( 01491 identified_slices = kmo_identify_slices(ranges, 01492 ifu_crpix, 01493 ifu_crval, 01494 ifu_cdelt, 01495 gd.l.dim)); 01496 }/* else { 01497 KMO_TRY_EXIT_IF_NULL( 01498 identified_slices = cpl_vector_new(gd.l.dim)); 01499 cpl_vector_fill(identified_slices, 1.); 01500 }*/ 01501 01502 if (stored_data_cubes[ifu_nr-1] != NULL) { 01503 KMO_TRY_EXIT_IF_ERROR( 01504 kmclipm_make_image(stored_data_cubes[ifu_nr-1], 01505 stored_noise_cubes[ifu_nr-1], 01506 &stored_data_images[ifu_nr-1], 01507 &stored_noise_images[ifu_nr-1], 01508 identified_slices, 01509 cmethod, cpos_rej, cneg_rej, 01510 citer, cmax, cmin)); 01511 } 01512 cpl_vector_delete(identified_slices); identified_slices = NULL; 01513 } else { 01514 // IFU is invalid 01515 } 01516 } 01517 } 01518 01519 // normalise all IFUs as a group. 01520 // Calculate mean of each IFU, add up and divide by number of successful 01521 // averaged IFUs. 01522 // Then divide all valid IFUs with mean value 01523 cnt = 0; 01524 for (int i = 0; i < nr_devices * KMOS_IFUS_PER_DETECTOR; i++) { 01525 if (stored_data_images[i] != NULL) { 01526 KMO_TRY_ASSURE(cpl_image_count_rejected(stored_data_images[i]) < 01527 cpl_image_get_size_x(stored_data_images[i])* 01528 cpl_image_get_size_y(stored_data_images[i]), 01529 CPL_ERROR_ILLEGAL_INPUT, 01530 "The collapsed, dark-subtracted image contains " 01531 "only invalid values! Probably the provided " 01532 "FLAT_SKY frames are exactly the same as the " 01533 "frames used for MASTER_DARK calculation."); 01534 01535 mean_data += cpl_image_get_mean(stored_data_images[i]); 01536 KMO_TRY_CHECK_ERROR_STATE(); 01537 cnt++; 01538 } 01539 01540 } 01541 mean_data /= cnt; 01542 01543 if (mean_data != 0.0) { 01544 for (int i = 0; i < nr_devices * KMOS_IFUS_PER_DETECTOR; i++) { 01545 if (stored_data_images[i] != NULL) { 01546 KMO_TRY_EXIT_IF_ERROR( 01547 cpl_image_divide_scalar(stored_data_images[i], 01548 mean_data)); 01549 } 01550 } 01551 } else { 01552 cpl_msg_warning(cpl_func, "Data couldn't be normalised " 01553 "(mean = 0.0)!"); 01554 } 01555 01556 if (process_noise) { 01557 if (mean_data != 0.0) { 01558 for (int i = 0; i < nr_devices * KMOS_IFUS_PER_DETECTOR; i++) { 01559 if (stored_noise_images[i] != NULL) { 01560 KMO_TRY_EXIT_IF_ERROR( 01561 cpl_image_divide_scalar(stored_noise_images[i], 01562 mean_data)); 01563 } 01564 } 01565 } else { 01566 cpl_msg_warning(cpl_func, "Noise couldn't be normalised " 01567 "(mean = 0.0)!"); 01568 } 01569 } 01570 01571 // calculate qc parameters on normalised data 01572 qc_spat_unif = 0.0; 01573 cnt = 0; 01574 for (int i = 0; i < nr_devices * KMOS_IFUS_PER_DETECTOR; i++) { 01575 if (stored_data_images[i] != NULL) { 01576 tmp_mean = cpl_image_get_mean(stored_data_images[i]); 01577 tmp_stdev = cpl_image_get_stdev (stored_data_images[i]); 01578 01579 qc_spat_unif += pow(tmp_mean-1, 2); 01580 if (fabs(tmp_mean) > qc_max_dev) { 01581 qc_max_dev = tmp_mean-1; 01582 qc_max_dev_id = i+1; 01583 } 01584 if (fabs(tmp_stdev) > qc_max_nonunif) { 01585 qc_max_nonunif = tmp_stdev; 01586 qc_max_nonunif_id = i+1; 01587 } 01588 KMO_TRY_CHECK_ERROR_STATE(); 01589 cnt++; 01590 } 01591 } 01592 qc_spat_unif = sqrt(qc_spat_unif / cnt); 01593 01594 // 01595 // save data 01596 // 01597 01598 // update which IFUs are not used 01599 kmo_print_unused_ifus(unused_ifus_after, TRUE); 01600 01601 KMO_TRY_EXIT_IF_ERROR( 01602 kmo_set_unused_ifus(unused_ifus_after, main_header, 01603 "kmo_illumination")); 01604 01605 cpl_msg_info("","Saving data..."); 01606 01607 KMO_TRY_EXIT_IF_ERROR( 01608 kmclipm_update_property_double(main_header, QC_SPAT_UNIF, qc_spat_unif, 01609 "[adu] uniformity of illumination correction")); 01610 KMO_TRY_EXIT_IF_ERROR( 01611 kmclipm_update_property_double(main_header, QC_SPAT_MAX_DEV, qc_max_dev, 01612 "[adu] max. deviation from unity")); 01613 KMO_TRY_EXIT_IF_ERROR( 01614 kmclipm_update_property_int(main_header, QC_SPAT_MAX_DEV_ID, qc_max_dev_id, 01615 "[] IFU ID with max. dev. from unity")); 01616 KMO_TRY_EXIT_IF_ERROR( 01617 kmclipm_update_property_double(main_header, QC_SPAT_MAX_NONUNIF, qc_max_nonunif, 01618 "[adu] max. stdev of illumination corr.")); 01619 KMO_TRY_EXIT_IF_ERROR( 01620 kmclipm_update_property_int(main_header, QC_SPAT_MAX_NONUNIF_ID, qc_max_nonunif_id, 01621 "[] IFU ID with max. stdev in illum. corr.")); 01622 01623 KMO_TRY_EXIT_IF_ERROR( 01624 kmo_dfs_save_main_header(frameset, ILLUM_CORR, suffix, frame, 01625 main_header, parlist, cpl_func)); 01626 01627 KMO_TRY_EXIT_IF_ERROR( 01628 kmo_dfs_save_main_header(frameset, SKYFLAT_EDGE, suffix, frame, 01629 main_header, parlist, cpl_func)); 01630 01631 for (int i = 0; i < nr_devices * KMOS_IFUS_PER_DETECTOR; i++) { 01632 KMO_TRY_EXIT_IF_ERROR( 01633 kmo_dfs_save_image(stored_data_images[i], ILLUM_CORR, suffix, 01634 stored_sub_data_headers[i], 0./0.)); 01635 01636 if (process_noise) { 01637 KMO_TRY_EXIT_IF_ERROR( 01638 kmo_dfs_save_image(stored_noise_images[i], ILLUM_CORR, 01639 suffix, stored_sub_noise_headers[i], 0./0.)); 01640 } 01641 } 01642 01643 for (int det_nr = 1; det_nr <= nr_devices; det_nr++) { 01644 for (int ifu_nr = 0; ifu_nr < KMOS_IFUS_PER_DETECTOR; ifu_nr++) { 01645 KMO_TRY_EXIT_IF_ERROR( 01646 kmclipm_update_property_int(stored_sub_data_headers[(det_nr-1)*KMOS_IFUS_PER_DETECTOR+ifu_nr], 01647 CAL_IFU_NR, 01648 ifu_nr+1+(det_nr-1)*KMOS_IFUS_PER_DETECTOR, 01649 "IFU Number {1..24}")); 01650 KMO_TRY_EXIT_IF_ERROR( 01651 kmclipm_update_property_double( 01652 stored_sub_data_headers[(det_nr-1)*KMOS_IFUS_PER_DETECTOR+ifu_nr], 01653 CAL_ROTANGLE, 01654 rotangle_found, 01655 "[deg] Rotator relative to nasmyth")); 01656 if (has_flat_edge) { 01657 // save edge-parameters as product 01658 KMO_TRY_EXIT_IF_ERROR( 01659 kmo_dfs_save_table(edge_table_sky[det_nr-1][ifu_nr], SKYFLAT_EDGE, suffix, 01660 stored_sub_data_headers[(det_nr-1)*KMOS_IFUS_PER_DETECTOR+ifu_nr])); 01661 } 01662 } 01663 } 01664 } 01665 KMO_CATCH 01666 { 01667 KMO_CATCH_MSG(); 01668 ret_val = -1; 01669 } 01670 kmo_free_fits_desc(&desc_sky); 01671 kmo_free_fits_desc(&desc_dark); 01672 kmo_free_fits_desc(&desc_flat); 01673 kmo_free_fits_desc(&desc_xcal); 01674 kmo_free_fits_desc(&desc_ycal); 01675 kmo_free_fits_desc(&desc_lcal); 01676 cpl_image_delete(combined_data); combined_data = NULL; 01677 cpl_image_delete(combined_noise); combined_noise = NULL; 01678 cpl_image_delete(xcal); xcal = NULL; 01679 cpl_image_delete(ycal); ycal = NULL; 01680 cpl_image_delete(lcal); lcal = NULL; 01681 cpl_image_delete(img_dark); img_dark = NULL; 01682 cpl_image_delete(img_dark_noise); img_dark_noise = NULL; 01683 cpl_image_delete(img_flat); img_flat = NULL; 01684 cpl_image_delete(img_flat_noise); img_flat_noise = NULL; 01685 cpl_array_delete(calTimestamp); calTimestamp = NULL; 01686 cpl_free(bounds); bounds = NULL; 01687 kmo_free_unused_ifus(unused_ifus_before); unused_ifus_before = NULL; 01688 kmo_free_unused_ifus(unused_ifus_after); unused_ifus_after = NULL; 01689 cpl_free(fn_lut); fn_lut = NULL; 01690 cpl_free(suffix); suffix = NULL; 01691 cpl_frameset_delete(frameset_sky); frameset_sky = NULL; 01692 cpl_vector_delete(ranges); ranges = NULL; 01693 cpl_free(filter); filter = NULL; 01694 if (calAngles != NULL) { 01695 cpl_vector_delete(calAngles); calAngles = NULL; 01696 } 01697 cpl_propertylist_delete(main_header); main_header = NULL; 01698 for (int i = 0; i < nr_devices * KMOS_IFUS_PER_DETECTOR; i++) { 01699 if (stored_data_cubes != NULL) { 01700 cpl_imagelist_delete(stored_data_cubes[i]); 01701 stored_data_cubes[i] = NULL; 01702 } 01703 if (stored_noise_cubes != NULL) { 01704 cpl_imagelist_delete(stored_noise_cubes[i]); 01705 stored_noise_cubes[i] = NULL; 01706 } 01707 if (stored_data_images != NULL) { 01708 cpl_image_delete(stored_data_images[i]); 01709 stored_data_images[i] = NULL; 01710 } 01711 if (stored_noise_images != NULL) { 01712 cpl_image_delete(stored_noise_images[i]); 01713 stored_noise_images[i] = NULL; 01714 } 01715 if (stored_sub_data_headers != NULL) { 01716 cpl_propertylist_delete(stored_sub_data_headers[i]); 01717 stored_sub_data_headers[i] = NULL; 01718 } 01719 if (stored_sub_noise_headers != NULL) { 01720 cpl_propertylist_delete(stored_sub_noise_headers[i]); 01721 stored_sub_noise_headers[i] = NULL; 01722 } 01723 } 01724 cpl_free(stored_data_cubes); stored_data_cubes = NULL; 01725 cpl_free(stored_noise_cubes); stored_noise_cubes = NULL; 01726 cpl_free(stored_data_images); stored_data_images = NULL; 01727 cpl_free(stored_noise_images); stored_noise_images = NULL; 01728 cpl_free(stored_sub_data_headers); stored_sub_data_headers = NULL; 01729 cpl_free(stored_sub_noise_headers); stored_sub_noise_headers = NULL; 01730 if (edge_table_sky != NULL) { 01731 for (int i = 0; i < KMOS_NR_DETECTORS; i++) { 01732 if (edge_table_sky[i] != NULL) { 01733 for (int j = 0; j < KMOS_IFUS_PER_DETECTOR; j++) { 01734 cpl_table_delete(edge_table_sky[i][j]); 01735 edge_table_sky[i][j] = NULL; 01736 } 01737 cpl_free(edge_table_sky[i]); edge_table_sky[i] = NULL; 01738 } 01739 } 01740 cpl_free(edge_table_sky); edge_table_sky = NULL; 01741 } 01742 if (edge_table_flat != NULL) { 01743 for (int j = 0; j < KMOS_IFUS_PER_DETECTOR; j++) { 01744 cpl_table_delete(edge_table_flat[j]); 01745 edge_table_flat[j] = NULL; 01746 } 01747 cpl_free(edge_table_flat); edge_table_flat = NULL; 01748 } 01749 01750 return ret_val; 01751 } 01752
1.7.6.1