|
KMOS Pipeline Reference Manual
1.1.0
|
00001 /* $Id: kmo_reconstruct.c,v 1.38 2013/03/18 11:52:13 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 11:52:13 $ 00024 * $Revision: 1.38 $ 00025 * $Name: HEAD $ 00026 */ 00027 00028 #ifdef HAVE_CONFIG_H 00029 #include <config.h> 00030 #endif 00031 00032 /*----------------------------------------------------------------------------- 00033 * Includes 00034 *----------------------------------------------------------------------------*/ 00035 00036 #include <string.h> 00037 #include <math.h> 00038 00039 #include <cpl.h> 00040 00041 #include "kmo_utils.h" 00042 #include "kmo_functions.h" 00043 #include "kmo_priv_reconstruct.h" 00044 #include "kmo_priv_functions.h" 00045 #include "kmo_cpl_extensions.h" 00046 #include "kmo_dfs.h" 00047 #include "kmo_error.h" 00048 #include "kmo_utils.h" 00049 #include "kmo_constants.h" 00050 #include "kmo_debug.h" 00051 00052 /*----------------------------------------------------------------------------- 00053 * Functions prototypes 00054 *----------------------------------------------------------------------------*/ 00055 00056 static int kmo_reconstruct_create(cpl_plugin *); 00057 static int kmo_reconstruct_exec(cpl_plugin *); 00058 static int kmo_reconstruct_destroy(cpl_plugin *); 00059 static int kmo_reconstruct(cpl_parameterlist *, cpl_frameset *); 00060 00061 /*----------------------------------------------------------------------------- 00062 * Static variables 00063 *----------------------------------------------------------------------------*/ 00064 00065 static char kmo_reconstruct_description[] = 00066 "Data with or without noise is reconstructed into a cube using the calibration\n" 00067 "frames XCAL, YCAL and LCAL. XCAL and YCAL are generated using recipe kmo_flat,\n" 00068 "LCAL is generated using recipe kmo_wave_cal.\n" 00069 "The input data can contain noise extensions and will be reconstructed into\n" 00070 "additional extensions.\n" 00071 "\n" 00072 "BASIC PARAMETERS:\n" 00073 "-----------------\n" 00074 "--imethod\n" 00075 "The interpolation method used for reconstruction.\n" 00076 "\n" 00077 "--detimg\n" 00078 "Specify if the resampled image of the input frame should be generated. There-\n" 00079 "fore all slitlets of all IFUs are aligned one next to the other. This frame\n" 00080 "serves for quality control. One can immediately see if the reconstruction was\n" 00081 "successful.\n" 00082 "\n" 00083 "--file_extension" 00084 "Set this parameter to TRUE if the EXPTIME keyword should be appended to\n" 00085 "the output filenames.\n" 00086 "\n" 00087 "ADVANCED PARAMETERS\n" 00088 "-------------------\n" 00089 "--flux\n" 00090 "Specify if flux conservation should be applied.\n" 00091 "\n" 00092 "--neighborhoodRange\n" 00093 "Defines the range to search for neighbors during reconstruction\n" 00094 "\n" 00095 "--b_samples\n" 00096 "The number of samples in spectral direction for the reconstructed cube. Ideal-\n" 00097 "ly this number should be greater than 2048, the detector size.\n" 00098 "\n" 00099 "--b_start\n" 00100 "--b_end\n" 00101 "Used to define manually the start and end wavelength for the reconstructed\n" 00102 "cube. By default the internally defined values are used.\n" 00103 "\n" 00104 "--file_extension" 00105 "Set to TRUE if OBS_ID (from input frame header) should be appended to the\n" 00106 "output frame.\n" 00107 "\n" 00108 "-------------------------------------------------------------------------------\n" 00109 " Input files:\n" 00110 "\n" 00111 " DO KMOS \n" 00112 " category Type Explanation Required #Frames\n" 00113 " -------- ----- ----------- -------- -------\n" 00114 " DARK or RAW/F2D data with Y 1 \n" 00115 " FLAT_ON or RAW/F2D or without noise \n" 00116 " ARC_ON or RAW/F2D \n" 00117 " OBJECT or RAW \n" 00118 " STD or RAW \n" 00119 " SCIENCE RAW \n" 00120 " XCAL F2D x-direction calib. frame Y 1 \n" 00121 " YCAL F2D y-direction calib. frame Y 1 \n" 00122 " LCAL F2D Wavelength calib. frame Y 1 \n" 00123 " WAVE_BAND F2L Table with start-/end-wavelengths Y 1 \n" 00124 "\n" 00125 " Output files:\n" 00126 "\n" 00127 " DO KMOS\n" 00128 " category Type Explanation\n" 00129 " -------- ----- -----------\n" 00130 " CUBE_DARK or F3I Reconstructed cube \n" 00131 " CUBE_FLAT or RAW/F2D with or without noise\n" 00132 " CUBE_ARC or \n" 00133 " CUBE_OBJECT or \n" 00134 " CUBE_STD or \n" 00135 " CUBE_SCIENCE \n" 00136 "-------------------------------------------------------------------------------\n" 00137 "\n"; 00138 00139 /*----------------------------------------------------------------------------- 00140 * Functions code 00141 *----------------------------------------------------------------------------*/ 00142 00159 int cpl_plugin_get_info(cpl_pluginlist *list) 00160 { 00161 cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe); 00162 cpl_plugin *plugin = &recipe->interface; 00163 00164 cpl_plugin_init(plugin, 00165 CPL_PLUGIN_API, 00166 KMOS_BINARY_VERSION, 00167 CPL_PLUGIN_TYPE_RECIPE, 00168 "kmo_reconstruct", 00169 "Performs the cube reconstruction " 00170 "using different interpolation methods.", 00171 kmo_reconstruct_description, 00172 "Alex Agudo Berbel", 00173 "agudo@mpe.mpg.de", 00174 kmos_get_license(), 00175 kmo_reconstruct_create, 00176 kmo_reconstruct_exec, 00177 kmo_reconstruct_destroy); 00178 00179 cpl_pluginlist_append(list, plugin); 00180 00181 return 0; 00182 } 00183 00191 static int kmo_reconstruct_create(cpl_plugin *plugin) 00192 { 00193 cpl_recipe *recipe; 00194 cpl_parameter *p; 00195 00196 /* Check that the plugin is part of a valid recipe */ 00197 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00198 recipe = (cpl_recipe *)plugin; 00199 else 00200 return -1; 00201 00202 /* Create the parameters list in the cpl_recipe object */ 00203 recipe->parameters = cpl_parameterlist_new(); 00204 00205 /* Fill the parameters list */ 00206 /* --imethod */ 00207 p = cpl_parameter_new_value("kmos.kmo_reconstruct.imethod", 00208 CPL_TYPE_STRING, 00209 "Method to use for interpolation. " 00210 "[\"NN\" (nearest neighbour), " 00211 "\"lwNN\" (linear weighted nearest neighbor), " 00212 "\"swNN\" (square weighted nearest neighbor), " 00213 "\"MS\" (Modified Shepard's method)" 00214 "\"CS\" (Cubic spline)]", 00215 "kmos.kmo_reconstruct", 00216 "CS"); 00217 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "imethod"); 00218 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00219 cpl_parameterlist_append(recipe->parameters, p); 00220 00221 /* --neighborhoodRange */ 00222 p = cpl_parameter_new_value("kmos.kmo_reconstruct.neighborhoodRange", 00223 CPL_TYPE_DOUBLE, 00224 "Defines the range to search for neighbors. " 00225 "in pixels", 00226 "kmos.kmo_reconstruct", 00227 1.001); 00228 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "neighborhoodRange"); 00229 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00230 cpl_parameterlist_append(recipe->parameters, p); 00231 00232 /* --flux */ 00233 p = cpl_parameter_new_value("kmos.kmo_reconstruct.flux", 00234 CPL_TYPE_BOOL, 00235 "TRUE: Apply flux conservation. FALSE: otherwise", 00236 "kmos.kmo_reconstruct", 00237 FALSE); 00238 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "flux"); 00239 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00240 cpl_parameterlist_append(recipe->parameters, p); 00241 00242 /* --detectorimage */ 00243 p = cpl_parameter_new_value("kmos.kmo_reconstruct.detectorimage", 00244 CPL_TYPE_BOOL, 00245 "TRUE: if resampled detector frame should be " 00246 "created, FALSE: otherwise", 00247 "kmos.kmo_reconstruct", 00248 FALSE); 00249 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "detimg"); 00250 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00251 cpl_parameterlist_append(recipe->parameters, p); 00252 00253 /* --file_extension */ 00254 p = cpl_parameter_new_value("kmos.kmo_reconstruct.file_extension", 00255 CPL_TYPE_BOOL, 00256 "TRUE: if OBS_ID keyword should be appended to " 00257 "output frames, FALSE: otherwise", 00258 "kmos.kmo_reconstruct", 00259 FALSE); 00260 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "file_extension"); 00261 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00262 cpl_parameterlist_append(recipe->parameters, p); 00263 00264 /* --dev_flip */ 00265 p = cpl_parameter_new_value("kmos.kmo_reconstruct.dev_flip", 00266 CPL_TYPE_BOOL, 00267 "INTENDED FOR PIPELINE DEVELOPERS ONLY: " 00268 "Set this parameter to TRUE if the wavelengths " 00269 "are ascending on the detector from bottom to " 00270 "top (only for old simulation data).", 00271 "kmos.kmo_reconstruct", 00272 FALSE); 00273 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "dev_flip"); 00274 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00275 cpl_parameterlist_append(recipe->parameters, p); 00276 00277 // add parameters for band-definition 00278 kmo_band_pars_create(recipe->parameters, 00279 "kmos.kmo_reconstruct"); 00280 00281 return 0; 00282 } 00283 00289 static int kmo_reconstruct_exec(cpl_plugin *plugin) 00290 { 00291 cpl_recipe *recipe; 00292 00293 /* Get the recipe out of the plugin */ 00294 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00295 recipe = (cpl_recipe *)plugin; 00296 else return -1; 00297 00298 return kmo_reconstruct(recipe->parameters, recipe->frames); 00299 } 00300 00306 static int kmo_reconstruct_destroy(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 cpl_parameterlist_delete(recipe->parameters); 00316 return 0 ; 00317 } 00318 00333 static int kmo_reconstruct(cpl_parameterlist *parlist, cpl_frameset *frameset) 00334 { 00335 int ret_val = 0, 00336 nr_devices = 0, 00337 i = 0, 00338 j = 0, 00339 flux = 0, 00340 index = 0, 00341 detectorimage = 0, 00342 *bounds = NULL, 00343 ifu_nr = 0, 00344 obs_id = 0, 00345 file_extension = FALSE, 00346 dev_flip = FALSE, 00347 detImgCube = FALSE; 00348 float *pdet_img_data = NULL, 00349 *pdet_img_noise = NULL, 00350 *slice = NULL; 00351 double neighborhoodRange = 1.001; 00352 00353 const char *imethod = NULL, 00354 *input_frame_name = NULL, 00355 *output_frame_name = NULL, 00356 *filter_id = NULL, 00357 *filter_id_tmp = NULL; 00358 char *keyword = NULL, 00359 *filename_cube = NULL, 00360 *filename_img = NULL, 00361 // *fn_lut = NULL, 00362 *suffix = NULL, 00363 *obs_suffix = NULL, 00364 *my_filter_id = NULL, 00365 *extname = NULL; 00366 cpl_image *lcal = NULL, 00367 *det_img_data[KMOS_NR_DETECTORS], 00368 *det_img_noise[KMOS_NR_DETECTORS]; 00369 cpl_imagelist *cube_data = NULL, 00370 *cube_noise = NULL; 00371 cpl_frame *rec_frame = NULL, 00372 *xcal_frame = NULL, 00373 *ycal_frame = NULL, 00374 *lcal_frame = NULL; 00375 cpl_propertylist *main_header = NULL, 00376 *sub_header = NULL, 00377 *sub_header_orig = NULL, 00378 *actual_sub_header = NULL, 00379 *tmp_header = NULL; 00380 cpl_table *band_table = NULL; 00381 gridDefinition gd; 00382 main_fits_desc desc1, 00383 desc2; 00384 00385 for (int i=0; i<KMOS_NR_DETECTORS; i++) { 00386 det_img_data[i] = NULL; 00387 det_img_noise[i] = NULL; 00388 } 00389 00390 KMO_TRY 00391 { 00392 kmo_init_fits_desc(&desc1); 00393 kmo_init_fits_desc(&desc2); 00394 00395 // --- check input --- 00396 KMO_TRY_ASSURE((parlist != NULL) && 00397 (frameset != NULL), 00398 CPL_ERROR_NULL_INPUT, 00399 "Not all input data is provided!"); 00400 00401 KMO_TRY_ASSURE((cpl_frameset_count_tags(frameset, DARK) == 1) || 00402 (cpl_frameset_count_tags(frameset, FLAT_ON) == 1) || 00403 (cpl_frameset_count_tags(frameset, ARC_ON) == 1) || 00404 (cpl_frameset_count_tags(frameset, OBJECT) == 1) || 00405 (cpl_frameset_count_tags(frameset, STD) == 1) || 00406 (cpl_frameset_count_tags(frameset, SCIENCE) == 1), 00407 CPL_ERROR_NULL_INPUT, 00408 "A data frame (DARK, FLAT_ON, ARC_ON, OBJECT, STD or SCIENCE) must " 00409 "be provided!"); 00410 00411 KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, XCAL) == 1, 00412 CPL_ERROR_FILE_NOT_FOUND, 00413 "XCAL frame missing in frameset!!"); 00414 00415 KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, YCAL) == 1, 00416 CPL_ERROR_FILE_NOT_FOUND, 00417 "YCAL frame missing in frameset!!"); 00418 00419 KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, LCAL) == 1, 00420 CPL_ERROR_FILE_NOT_FOUND, 00421 "LCAL frame missing in frameset!!"); 00422 00423 KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, WAVE_BAND) == 1, 00424 CPL_ERROR_FILE_NOT_FOUND, 00425 "WAVE_BAND frame missing in frameset!!"); 00426 00427 KMO_TRY_ASSURE(kmo_dfs_set_groups(frameset, "kmo_reconstruct") == 1, 00428 CPL_ERROR_ILLEGAL_INPUT, 00429 "Cannot identify RAW and CALIB frames!"); 00430 00431 // --- get parameters --- 00432 cpl_msg_info("", "--- Parameter setup for kmo_reconstruct ---"); 00433 00434 KMO_TRY_EXIT_IF_NULL( 00435 imethod = kmo_dfs_get_parameter_string(parlist, 00436 "kmos.kmo_reconstruct.imethod")); 00437 00438 KMO_TRY_ASSURE((strcmp(imethod, "NN") == 0) || 00439 (strcmp(imethod, "lwNN") == 0) || 00440 (strcmp(imethod, "swNN") == 0) || 00441 (strcmp(imethod, "MS") == 0) || 00442 (strcmp(imethod, "CS") == 0), 00443 CPL_ERROR_ILLEGAL_INPUT, 00444 "imethod must be either \"NN\", \"lwNN\", " 00445 "\"swNN\", \"MS\" or \"CS\"!"); 00446 00447 KMO_TRY_EXIT_IF_ERROR( 00448 kmo_dfs_print_parameter_help(parlist, 00449 "kmos.kmo_reconstruct.imethod")); 00450 00451 flux = kmo_dfs_get_parameter_bool(parlist, 00452 "kmos.kmo_reconstruct.flux"); 00453 00454 KMO_TRY_ASSURE((flux == 0) || 00455 (flux == 1), 00456 CPL_ERROR_ILLEGAL_INPUT, 00457 "flux must be either FALSE or TRUE!"); 00458 00459 KMO_TRY_EXIT_IF_ERROR( 00460 kmo_dfs_print_parameter_help(parlist, "kmos.kmo_reconstruct.flux")); 00461 00462 detectorimage = kmo_dfs_get_parameter_bool(parlist, 00463 "kmos.kmo_reconstruct.detectorimage"); 00464 00465 KMO_TRY_ASSURE((detectorimage == 0) || 00466 (detectorimage == 1), 00467 CPL_ERROR_ILLEGAL_INPUT, 00468 "detectorimage must be either 0 or 1 !"); 00469 00470 KMO_TRY_EXIT_IF_ERROR( 00471 kmo_dfs_print_parameter_help(parlist, "kmos.kmo_reconstruct.detectorimage")); 00472 00473 neighborhoodRange = kmo_dfs_get_parameter_double(parlist, 00474 "kmos.kmo_reconstruct.neighborhoodRange"); 00475 KMO_TRY_CHECK_ERROR_STATE(); 00476 00477 KMO_TRY_ASSURE(neighborhoodRange > 0.0, 00478 CPL_ERROR_ILLEGAL_INPUT, 00479 "neighborhoodRange must be greater than 0.0"); 00480 00481 KMO_TRY_EXIT_IF_ERROR( 00482 kmo_dfs_print_parameter_help(parlist, 00483 "kmos.kmo_reconstruct.neighborhoodRange")); 00484 00485 kmo_band_pars_load(parlist, "kmos.kmo_reconstruct"); 00486 00487 file_extension = kmo_dfs_get_parameter_bool(parlist, 00488 "kmos.kmo_reconstruct.file_extension"); 00489 KMO_TRY_CHECK_ERROR_STATE(); 00490 00491 KMO_TRY_EXIT_IF_ERROR( 00492 kmo_dfs_print_parameter_help(parlist, 00493 "kmos.kmo_reconstruct.file_extension")); 00494 00495 dev_flip = kmo_dfs_get_parameter_bool(parlist, 00496 "kmos.kmo_reconstruct.dev_flip"); 00497 KMO_TRY_CHECK_ERROR_STATE(); 00498 KMO_TRY_EXIT_IF_ERROR( 00499 kmo_dfs_print_parameter_help(parlist, "kmos.kmo_reconstruct.dev_flip")); 00500 KMO_TRY_ASSURE((dev_flip == TRUE) || 00501 (dev_flip == FALSE), 00502 CPL_ERROR_ILLEGAL_INPUT, 00503 "dev_flip must be TRUE or FALSE!"); 00504 00505 00506 cpl_msg_info("", "-------------------------------------------"); 00507 00508 // load descriptor and header of data frame to reconstruct 00509 if (cpl_frameset_count_tags(frameset, DARK) == 1) { 00510 input_frame_name = DARK; 00511 output_frame_name = CUBE_DARK; 00512 } else if (cpl_frameset_count_tags(frameset, FLAT_ON) == 1) { 00513 input_frame_name = FLAT_ON; 00514 output_frame_name = CUBE_FLAT; 00515 } else if (cpl_frameset_count_tags(frameset, ARC_ON) == 1) { 00516 input_frame_name = ARC_ON; 00517 output_frame_name = CUBE_ARC; 00518 } else if (cpl_frameset_count_tags(frameset, OBJECT) == 1) { 00519 input_frame_name = OBJECT; 00520 output_frame_name = CUBE_OBJECT; 00521 } else if (cpl_frameset_count_tags(frameset, STD) == 1) { 00522 input_frame_name = STD; 00523 output_frame_name = CUBE_STD; 00524 } else if (cpl_frameset_count_tags(frameset, SCIENCE) == 1) { 00525 input_frame_name = SCIENCE; 00526 output_frame_name = CUBE_SCIENCE; 00527 } 00528 00529 // assure that filters, grating and rotation offsets match for 00530 // XCAL, YCAL, LCAL and for data frame to reconstruct (except DARK 00531 // frames) 00532 // check if filter_id and grating_id match for all detectors 00533 KMO_TRY_EXIT_IF_ERROR( 00534 kmo_check_frame_setup(frameset, XCAL, YCAL, 00535 TRUE, FALSE, TRUE)); 00536 KMO_TRY_EXIT_IF_ERROR( 00537 kmo_check_frame_setup(frameset, XCAL, LCAL, 00538 TRUE, FALSE, TRUE)); 00539 00540 // This check doesn't make sense here since OCS.ROT.NAANGLE is compared. 00541 // When creating the calibration files the RAW exposures needn't have been 00542 // provided in the same order 00543 // KMO_TRY_EXIT_IF_ERROR( 00544 // kmo_check_cal_frames_rotangle(frameset, XCAL, YCAL)); 00545 // KMO_TRY_EXIT_IF_ERROR( 00546 // kmo_check_cal_frames_rotangle(frameset, XCAL, LCAL)); 00547 00548 if (cpl_frameset_count_tags(frameset, DARK) != 1) { 00549 00550 // check if filters, gratings and rotator offset match 00551 // (except for DARK frames) 00552 KMO_TRY_EXIT_IF_ERROR( 00553 kmo_check_frame_setup(frameset, XCAL, input_frame_name, 00554 TRUE, FALSE, FALSE)); 00555 /* 00556 // check if rotator offset don't differ to much 00557 cpl_frame *f1 = NULL, *f2 = NULL; 00558 cpl_propertylist *h1 = NULL, *h2 = NULL; 00559 char *kw = NULL; 00560 double tmp_dbl1 = 0.0, tmp_dbl2 = 0.0; 00561 00562 KMO_TRY_EXIT_IF_NULL( 00563 f1 = kmo_dfs_get_frame(frameset, XCAL)); 00564 00565 KMO_TRY_EXIT_IF_NULL( 00566 f2 = kmo_dfs_get_frame(frameset, input_frame_name)); 00567 h1 = kmclipm_propertylist_load(cpl_frame_get_filename(f1), 0); 00568 if (cpl_error_get_code() != CPL_ERROR_NONE) { 00569 cpl_msg_error("","File not found: %s!", 00570 cpl_frame_get_filename(f1)); 00571 KMO_TRY_CHECK_ERROR_STATE(); 00572 } 00573 00574 h2 = kmclipm_propertylist_load(cpl_frame_get_filename(f2), 0); 00575 if (cpl_error_get_code() != CPL_ERROR_NONE) { 00576 cpl_msg_error("","File not found: %s!", 00577 cpl_frame_get_filename(f2)); 00578 KMO_TRY_CHECK_ERROR_STATE(); 00579 } 00580 KMO_TRY_EXIT_IF_NULL( 00581 kw = cpl_sprintf("%s", ROTANGLE)); 00582 tmp_dbl1 = cpl_propertylist_get_double(h1, kw); 00583 if (cpl_error_get_code() != CPL_ERROR_NONE) { 00584 KMO_TRY_ASSURE(1 == 0, 00585 CPL_ERROR_ILLEGAL_INPUT, 00586 "keyword \n%s\n of frame %s is missing!", 00587 keyword, XCAL); 00588 } 00589 00590 tmp_dbl2 = cpl_propertylist_get_double(h2, kw); 00591 if (cpl_error_get_code() != CPL_ERROR_NONE) { 00592 KMO_TRY_ASSURE(1 == 0, 00593 CPL_ERROR_ILLEGAL_INPUT, 00594 "keyword \n%s\n of frame %s is missing!", 00595 keyword, input_frame_name); 00596 } 00597 00598 // strip angles below 0 deg and above 360 deg 00599 kmclipm_strip_angle(&tmp_dbl1); 00600 kmclipm_strip_angle(&tmp_dbl2); 00601 00602 if (fabs(tmp_dbl1 - tmp_dbl2) > 30.) { 00603 if ((fabs(tmp_dbl1) < 0.001) && (tmp_dbl2>330) && (tmp_dbl2<360)) { 00604 // singularity! 00605 // we have rot=0 for XCAL and rot>330 | rot<360 for input frame 00606 } else { 00607 cpl_msg_warning("","The angle of the calibration files (%g deg) " 00608 "and the angle of the frame to reconstruct" 00609 " (%g deg) differ by %g deg! Think about using " 00610 "calibration files matching better the actual " 00611 "rotator offset (ESO OCS ROT NAANGLE)", 00612 tmp_dbl1, tmp_dbl2, 00613 fabs(tmp_dbl1 - tmp_dbl2)); 00614 } 00615 } 00616 00617 cpl_propertylist_delete(h1); h1 = NULL; 00618 cpl_propertylist_delete(h2); h2 = NULL; 00619 cpl_free(kw); kw = NULL; 00620 */ 00621 } 00622 00623 KMO_TRY_EXIT_IF_NULL( 00624 xcal_frame = kmo_dfs_get_frame(frameset, XCAL)); 00625 KMO_TRY_EXIT_IF_NULL( 00626 rec_frame = kmo_dfs_get_frame(frameset, input_frame_name)); 00627 KMO_TRY_EXIT_IF_NULL( 00628 suffix = kmo_dfs_get_suffix(rec_frame, TRUE, TRUE)); 00629 00630 KMO_TRY_EXIT_IF_ERROR( 00631 kmo_check_frame_setup_md5(frameset)); 00632 00633 cpl_msg_info("", "Detected instrument setup: %s", suffix+1); 00634 cpl_msg_info("", "(grating 1, 2 & 3, rotation angle)"); 00635 cpl_msg_info("", "-------------------------------------------"); 00636 00637 00638 desc1 = kmo_identify_fits_header(cpl_frame_get_filename(rec_frame)); 00639 KMO_TRY_CHECK_ERROR_STATE(); 00640 00641 KMO_TRY_ASSURE(((desc1.nr_ext == KMOS_NR_DETECTORS) || 00642 ((desc1.nr_ext == 2*KMOS_NR_DETECTORS))) && 00643 (desc1.ex_badpix == FALSE) && 00644 ((desc1.fits_type == raw_fits) || 00645 (desc1.fits_type == f2d_fits)) && 00646 (desc1.frame_type == detector_frame), 00647 CPL_ERROR_ILLEGAL_INPUT, 00648 "The frame to reconstruct isn't in the correct format!!!" 00649 "Exactly 3 frames, or 6 with noise are expected!"); 00650 00651 if (!desc1.ex_noise) { 00652 nr_devices = desc1.nr_ext; 00653 } else { 00654 nr_devices = desc1.nr_ext / 2; 00655 } 00656 00657 // compare descriptor of XCAL and data frame to reconstruct 00658 desc2 = kmo_identify_fits_header(cpl_frame_get_filename(xcal_frame)); 00659 KMO_TRY_CHECK_ERROR_STATE(); 00660 00661 KMO_TRY_ASSURE((desc2.nr_ext % 3 == 0) && 00662 (desc1.ex_badpix == desc2.ex_badpix) && 00663 (desc1.frame_type == desc2.frame_type), 00664 CPL_ERROR_ILLEGAL_INPUT, 00665 "XCAL isn't in the correct format!!!"); 00666 00667 kmo_free_fits_desc(&desc2); 00668 00669 // compare descriptor of YCAL and data frame to reconstruct 00670 kmo_init_fits_desc(&desc2); 00671 00672 KMO_TRY_EXIT_IF_NULL( 00673 ycal_frame = kmo_dfs_get_frame(frameset, YCAL)); 00674 00675 desc2 = kmo_identify_fits_header(cpl_frame_get_filename(ycal_frame)); 00676 KMO_TRY_CHECK_ERROR_STATE(); 00677 00678 KMO_TRY_ASSURE((desc2.nr_ext % 3 == 0) && 00679 (desc1.ex_badpix == desc2.ex_badpix) && 00680 (desc1.frame_type == desc2.frame_type), 00681 CPL_ERROR_ILLEGAL_INPUT, 00682 "YCAL isn't in the correct format!!!"); 00683 00684 kmo_free_fits_desc(&desc2); 00685 00686 // compare descriptor of LCAL and data frame to reconstruct 00687 kmo_init_fits_desc(&desc2); 00688 00689 KMO_TRY_EXIT_IF_NULL( 00690 lcal_frame = kmo_dfs_get_frame(frameset, LCAL)); 00691 00692 desc2 = kmo_identify_fits_header(cpl_frame_get_filename(lcal_frame)); 00693 KMO_TRY_CHECK_ERROR_STATE(); 00694 00695 KMO_TRY_ASSURE((desc2.nr_ext % 3 == 0) && 00696 (desc1.ex_badpix == desc2.ex_badpix) && 00697 (desc1.frame_type == desc2.frame_type), 00698 CPL_ERROR_ILLEGAL_INPUT, 00699 "LCAL isn't in the correct format!!!"); 00700 00701 kmo_free_fits_desc(&desc2); 00702 00703 // 00704 // --- load, update & save primary header --- 00705 // 00706 KMO_TRY_EXIT_IF_NULL( 00707 main_header = kmo_dfs_load_primary_header(frameset, 00708 input_frame_name)); 00709 00710 KMO_TRY_EXIT_IF_NULL( 00711 tmp_header = kmo_dfs_load_primary_header(frameset, LCAL)); 00712 00713 // assert that filters have correct IDs and that all detectors of all 00714 // input frames have the same filter set 00715 for (i = 1; i <= nr_devices; i++) { 00716 // ESO INS FILTi ID 00717 KMO_TRY_EXIT_IF_NULL( 00718 keyword = cpl_sprintf("%s%d%s", IFU_FILTID_PREFIX, i, 00719 IFU_FILTID_POSTFIX)); 00720 00721 KMO_TRY_EXIT_IF_NULL( 00722 filter_id = cpl_propertylist_get_string(tmp_header, keyword)); 00723 00724 KMO_TRY_ASSURE((strcmp(filter_id, "IZ") == 0) || 00725 (strcmp(filter_id, "YJ") == 0) || 00726 (strcmp(filter_id, "H") == 0) || 00727 (strcmp(filter_id, "K") == 0) || 00728 (strcmp(filter_id, "HK") == 0), 00729 CPL_ERROR_ILLEGAL_INPUT, 00730 "Filter ID in primary header of LCAL frame must " 00731 "be either \"IZ\", \"YJ\", \"H\", \"K\" or " 00732 "\"HK\" !"); 00733 00734 if (strcmp(input_frame_name, DARK) != 0) { 00735 // dark needn't to be taken with filter! 00736 00737 KMO_TRY_EXIT_IF_NULL( 00738 filter_id_tmp = cpl_propertylist_get_string(main_header, 00739 keyword)); 00740 KMO_TRY_ASSURE(strcmp(filter_id, filter_id_tmp) == 0, 00741 CPL_ERROR_ILLEGAL_INPUT, 00742 "Filter IDs must be the same for LCAL frame and " 00743 "the frame to reconstruct!" 00744 "Detector No.: %d\nLCAL: %s\n%s: %s\n", 00745 i, filter_id, input_frame_name, filter_id_tmp); 00746 } 00747 cpl_free(keyword); keyword = NULL; 00748 } 00749 KMO_TRY_EXIT_IF_NULL( 00750 my_filter_id = cpl_strdup(filter_id)); 00751 cpl_propertylist_delete(tmp_header); tmp_header = NULL; 00752 00753 obs_id = cpl_propertylist_get_int(main_header, OBS_ID); 00754 KMO_TRY_CHECK_ERROR_STATE(); 00755 00756 KMO_TRY_EXIT_IF_NULL( 00757 filename_cube = cpl_sprintf("%s", output_frame_name)); 00758 KMO_TRY_EXIT_IF_NULL( 00759 filename_img = cpl_sprintf("%s", DET_IMG_REC)); 00760 if (file_extension) { 00761 KMO_TRY_EXIT_IF_NULL( 00762 obs_suffix = cpl_sprintf("%s%d", "_", obs_id)); 00763 } else { 00764 KMO_TRY_EXIT_IF_NULL( 00765 obs_suffix = cpl_sprintf("%s", "")); 00766 } 00767 00768 KMO_TRY_EXIT_IF_ERROR( 00769 kmo_dfs_save_main_header(frameset, filename_cube, obs_suffix, 00770 rec_frame, NULL, parlist, cpl_func)); 00771 00772 // setup grid definition, wavelength start and end points will be set 00773 // in the detector loop 00774 KMO_TRY_EXIT_IF_ERROR( 00775 kmclipm_setup_grid(&gd, imethod, neighborhoodRange)); 00776 00777 KMO_TRY_EXIT_IF_NULL( 00778 tmp_header = kmo_dfs_load_primary_header(frameset, XCAL)); 00779 00780 KMO_TRY_EXIT_IF_NULL( 00781 bounds = kmclipm_extract_bounds(tmp_header)); 00782 cpl_propertylist_delete(tmp_header); tmp_header = NULL; 00783 00784 if (detectorimage == TRUE) { 00785 KMO_TRY_EXIT_IF_ERROR( 00786 kmo_dfs_save_main_header(frameset, filename_img, obs_suffix, 00787 rec_frame, NULL, parlist, cpl_func)); 00788 } 00789 00790 /* loop through all detectors */ 00791 for (i = 1; i <= nr_devices; i++) { 00792 cpl_msg_info("","Processing detector No. %d", i); 00793 00794 // load lcal 00795 // extract LCAL image close to ROTANGLE 0. assuming that the wavelength range 00796 // doesn't differ too much with different ROTANGLEs. 00797 double rotangle_found; 00798 KMO_TRY_EXIT_IF_NULL( 00799 lcal = kmo_dfs_load_cal_image(frameset, LCAL, i, FALSE, 0., 00800 FALSE, NULL, &rotangle_found)); 00801 00802 char *tmp_band_method = getenv("KMO_BAND_METHOD"); 00803 int band_method = 0; 00804 if (tmp_band_method != NULL) { 00805 band_method = atoi(tmp_band_method); 00806 } 00807 00808 KMO_TRY_EXIT_IF_NULL( 00809 band_table = kmo_dfs_load_table(frameset, WAVE_BAND, 1, FALSE)); 00810 00811 KMO_TRY_EXIT_IF_ERROR( 00812 kmclipm_setup_grid_band_lcal(&gd, lcal, my_filter_id, 00813 band_method, band_table)); 00814 cpl_table_delete(band_table); band_table = NULL; 00815 00816 cpl_image_delete(lcal); lcal = NULL; 00817 00818 if (detectorimage == TRUE) { 00819 KMO_TRY_EXIT_IF_NULL( 00820 det_img_data[i-1] = cpl_image_new(gd.x.dim*gd.y.dim*KMOS_IFUS_PER_DETECTOR, 00821 gd.l.dim, CPL_TYPE_FLOAT)); 00822 KMO_TRY_EXIT_IF_NULL( 00823 pdet_img_data = cpl_image_get_data_float(det_img_data[i-1])); 00824 00825 KMO_TRY_EXIT_IF_NULL( 00826 det_img_noise[i-1] = cpl_image_new(gd.x.dim*gd.y.dim*KMOS_IFUS_PER_DETECTOR, 00827 gd.l.dim, CPL_TYPE_FLOAT)); 00828 KMO_TRY_EXIT_IF_NULL( 00829 pdet_img_noise = cpl_image_get_data_float(det_img_noise[i-1])); 00830 } 00831 00832 00833 for (j = 0; j < KMOS_IFUS_PER_DETECTOR; j++) { 00834 /* update sub-header */ 00835 ifu_nr = (i-1)*KMOS_IFUS_PER_DETECTOR + j + 1; 00836 00837 /* load raw image and sub-header*/ 00838 KMO_TRY_EXIT_IF_NULL( 00839 sub_header = kmo_dfs_load_sub_header(frameset, input_frame_name, 00840 i, FALSE)); 00841 KMO_TRY_EXIT_IF_NULL( 00842 sub_header_orig = cpl_propertylist_duplicate(sub_header)); 00843 00844 // check if IFU is valid according to main header keywords & 00845 // calibration files 00846 00847 if (getenv("KMOS_RECONSTRUCT_ALL") == NULL) { 00848 KMO_TRY_EXIT_IF_NULL( 00849 keyword = cpl_sprintf("%s%d%s", IFU_VALID_PREFIX, ifu_nr, 00850 IFU_VALID_POSTFIX)); 00851 KMO_TRY_CHECK_ERROR_STATE(); 00852 cpl_propertylist_get_string(main_header, keyword); 00853 cpl_free(keyword); keyword = NULL; 00854 } else { 00855 // if KMOS_RECONSTRUCT_ALL is set all IFUs should be 00856 // reconstructed 00857 cpl_propertylist_get_string(main_header, "ggg"); 00858 } 00859 00860 if ((cpl_error_get_code() == CPL_ERROR_DATA_NOT_FOUND) && 00861 (bounds[2*(ifu_nr-1)] != -1) && 00862 (bounds[2*(ifu_nr-1)+1] != -1)) 00863 { 00864 cpl_error_reset(); 00865 // IFU is valid 00866 actual_sub_header = sub_header; 00867 00868 // calculate WCS 00869 KMO_TRY_EXIT_IF_ERROR( 00870 kmo_calc_wcs(main_header, actual_sub_header, ifu_nr, 00871 gd.l.start, gd.l.delta)); 00872 00873 // reconstruct data and noise (if available) 00874 if (j == 0) { 00875 sat_mode_msg = FALSE; 00876 } else { 00877 sat_mode_msg = TRUE; 00878 } 00879 KMO_TRY_EXIT_IF_ERROR( 00880 kmo_reconstruct_sci(ifu_nr, 00881 bounds[2*(ifu_nr-1)], 00882 bounds[2*(ifu_nr-1)+1], 00883 rec_frame, 00884 input_frame_name, 00885 NULL, 00886 NULL, 00887 NULL, 00888 xcal_frame, 00889 ycal_frame, 00890 lcal_frame, 00891 &gd, 00892 &cube_data, 00893 &cube_noise, 00894 flux)); 00895 } else { 00896 // IFU is invalid 00897 actual_sub_header = sub_header_orig; 00898 cpl_error_reset(); 00899 } // if ((cpl_error_get_code() == CPL_ERROR_DATA_NOT_FOUND) .. 00900 00901 if (detectorimage) { 00902 if (cube_data != NULL) { 00903 for (int l=0; l<gd.l.dim; l++) { 00904 KMO_TRY_EXIT_IF_NULL( 00905 slice = cpl_image_get_data_float(cpl_imagelist_get(cube_data, l))); 00906 for (int y=0; y<gd.y.dim; y++) { 00907 for (int x=0; x<gd.x.dim; x++) { 00908 int ix = x + 00909 y * gd.x.dim + 00910 j * gd.x.dim*gd.y.dim + //IFU offset 00911 l * gd.x.dim*gd.y.dim*KMOS_IFUS_PER_DETECTOR; 00912 pdet_img_data[ix] = slice[x + y*gd.x.dim]; 00913 } 00914 } 00915 } 00916 } 00917 if (cube_noise != NULL) { 00918 if (detectorimage) { 00919 detImgCube = TRUE; 00920 } 00921 for (int l=0; l<gd.l.dim; l++) { 00922 KMO_TRY_EXIT_IF_NULL( 00923 slice = cpl_image_get_data_float(cpl_imagelist_get(cube_noise, l))); 00924 for (int y=0; y<gd.y.dim; y++) { 00925 for (int x=0; x<gd.x.dim; x++) { 00926 int ix = x + 00927 y * gd.x.dim + 00928 j * gd.x.dim*gd.y.dim + //IFU offset 00929 l * gd.x.dim*gd.y.dim*KMOS_IFUS_PER_DETECTOR; 00930 pdet_img_noise[ix] = slice[x + y*gd.x.dim]; 00931 } 00932 } 00933 } 00934 } 00935 } 00936 00937 // save output 00938 KMO_TRY_EXIT_IF_NULL( 00939 extname = kmo_extname_creator(ifu_frame, ifu_nr, 00940 EXT_DATA)); 00941 00942 KMO_TRY_EXIT_IF_ERROR( 00943 kmclipm_update_property_string(actual_sub_header, 00944 EXTNAME, 00945 extname, 00946 "FITS extension name")); 00947 00948 cpl_free(extname); extname = NULL; 00949 00950 KMO_TRY_EXIT_IF_ERROR( 00951 kmo_dfs_save_cube(cube_data, filename_cube, obs_suffix, 00952 actual_sub_header, 0./0.)); 00953 00954 if (cube_noise != NULL) { 00955 KMO_TRY_EXIT_IF_NULL( 00956 extname = kmo_extname_creator(ifu_frame, ifu_nr, 00957 EXT_NOISE)); 00958 00959 KMO_TRY_EXIT_IF_ERROR( 00960 kmclipm_update_property_string(actual_sub_header, 00961 EXTNAME, 00962 extname, 00963 "FITS extension name")); 00964 00965 cpl_free(extname); extname = NULL; 00966 00967 KMO_TRY_EXIT_IF_ERROR( 00968 kmo_dfs_save_cube(cube_noise, filename_cube, obs_suffix, 00969 actual_sub_header, 0./0.)); 00970 } 00971 00972 cpl_imagelist_delete(cube_data); cube_data = NULL; 00973 cpl_imagelist_delete(cube_noise); cube_noise = NULL; 00974 cpl_propertylist_delete(sub_header); sub_header = NULL; 00975 cpl_propertylist_delete(sub_header_orig); sub_header_orig = NULL; 00976 } // for j IFUs 00977 00978 if (detectorimage) { 00979 index = kmo_identify_index(cpl_frame_get_filename(rec_frame), 00980 i, FALSE); 00981 KMO_TRY_CHECK_ERROR_STATE(); 00982 00983 KMO_TRY_EXIT_IF_NULL( 00984 tmp_header = kmclipm_propertylist_load( 00985 cpl_frame_get_filename(rec_frame), index)); 00986 KMO_TRY_EXIT_IF_ERROR( 00987 kmo_save_det_img_ext(det_img_data[i-1], gd, i, filename_img, 00988 obs_suffix, tmp_header, dev_flip, FALSE)); 00989 cpl_propertylist_delete(tmp_header); tmp_header = NULL; 00990 00991 if (detImgCube) { 00992 if (desc1.ex_noise) { 00993 index = kmo_identify_index(cpl_frame_get_filename(rec_frame), 00994 i, TRUE); 00995 KMO_TRY_CHECK_ERROR_STATE(); 00996 } else { 00997 // use same index as for data frame, since input frame 00998 // has just 3 extensions 00999 } 01000 KMO_TRY_EXIT_IF_NULL( 01001 tmp_header = kmclipm_propertylist_load( 01002 cpl_frame_get_filename(rec_frame), index)); 01003 KMO_TRY_EXIT_IF_ERROR( 01004 kmo_save_det_img_ext(det_img_noise[i-1], gd, i, filename_img, 01005 obs_suffix, tmp_header, dev_flip, TRUE)); 01006 cpl_propertylist_delete(tmp_header); tmp_header = NULL; 01007 } 01008 } 01009 01010 // free memory 01011 cpl_imagelist_delete(cube_data); cube_data = NULL; 01012 cpl_imagelist_delete(cube_noise); cube_noise = NULL; 01013 cpl_propertylist_delete(sub_header); sub_header = NULL; 01014 cpl_propertylist_delete(sub_header_orig); sub_header_orig = NULL; 01015 } // for i devices 01016 } 01017 KMO_CATCH 01018 { 01019 KMO_CATCH_MSG(); 01020 ret_val = -1; 01021 } 01022 01023 kmo_free_fits_desc(&desc1); 01024 kmo_free_fits_desc(&desc2); 01025 for (int i=0; i<KMOS_NR_DETECTORS; i++) { 01026 cpl_image_delete(det_img_data[i]); det_img_data[i] = NULL; 01027 cpl_image_delete(det_img_noise[i]); det_img_noise[i] = NULL; 01028 } 01029 cpl_free(my_filter_id); my_filter_id = NULL; 01030 cpl_free(bounds); bounds = NULL; 01031 cpl_propertylist_delete(main_header); main_header = NULL; 01032 cpl_propertylist_delete(sub_header); sub_header = NULL; 01033 cpl_propertylist_delete(sub_header_orig); sub_header_orig = NULL; 01034 cpl_imagelist_delete(cube_data); cube_data = NULL; 01035 cpl_imagelist_delete(cube_noise); cube_noise = NULL; 01036 cpl_free(obs_suffix); obs_suffix = NULL; 01037 cpl_free(suffix); suffix = NULL; 01038 cpl_free(filename_img); filename_img = NULL; 01039 cpl_free(filename_cube); filename_cube = NULL; 01040 sat_mode_msg = FALSE; 01041 01042 return ret_val; 01043 } 01044
1.7.6.1