KMOS Pipeline Reference Manual
1.3.0
|
00001 /* 00002 * This file is part of the KMOS Pipeline 00003 * Copyright (C) 2002,2003 European Southern Observatory 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License as published by 00007 * the Free Software Foundation; either version 2 of the License, or 00008 * (at your option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 * GNU General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU General Public License 00016 * along with this program; if not, write to the Free Software 00017 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00018 */ 00019 00020 #ifdef HAVE_CONFIG_H 00021 #include <config.h> 00022 #endif 00023 00024 /*----------------------------------------------------------------------------- 00025 * Includes 00026 *----------------------------------------------------------------------------*/ 00027 00028 #include <string.h> 00029 #include <math.h> 00030 00031 #include <cpl.h> 00032 00033 #include "kmo_utils.h" 00034 #include "kmo_functions.h" 00035 #include "kmo_priv_reconstruct.h" 00036 #include "kmo_priv_functions.h" 00037 #include "kmo_priv_lcorr.h" 00038 #include "kmo_cpl_extensions.h" 00039 #include "kmo_dfs.h" 00040 #include "kmo_error.h" 00041 #include "kmo_utils.h" 00042 #include "kmo_constants.h" 00043 #include "kmo_debug.h" 00044 00045 /*----------------------------------------------------------------------------- 00046 * Functions prototypes 00047 *----------------------------------------------------------------------------*/ 00048 00049 static int kmo_reconstruct_create(cpl_plugin *); 00050 static int kmo_reconstruct_exec(cpl_plugin *); 00051 static int kmo_reconstruct_destroy(cpl_plugin *); 00052 static int kmo_reconstruct(cpl_parameterlist *, cpl_frameset *); 00053 00054 /*----------------------------------------------------------------------------- 00055 * Static variables 00056 *----------------------------------------------------------------------------*/ 00057 00058 static char kmo_reconstruct_description[] = 00059 "Data with or without noise is reconstructed into a cube using the\n" 00060 "calibration frames XCAL, YCAL and LCAL. XCAL and YCAL are generated using\n" 00061 "recipe kmo_flat, LCAL is generated using recipe kmo_wave_cal.\n" 00062 "The input data can contain noise extensions and will be reconstructed into\n" 00063 "additional extensions.\n" 00064 "If an OH spectrum is given in the SOF file the lambda axis will be corrected\n" 00065 "using the OH lines as reference.\n" 00066 "\n" 00067 "BASIC PARAMETERS:\n" 00068 "-----------------\n" 00069 "--imethod\n" 00070 "The interpolation method used for reconstruction.\n" 00071 "\n" 00072 "--detectorimage\n" 00073 "Specify if the resampled image of the input frame should be generated.\n" 00074 "Therefore all slitlets of all IFUs are aligned one next to the other. This\n" 00075 "frame serves for quality control. One can immediately see if the\n" 00076 "reconstruction was successful.\n" 00077 "\n" 00078 "--file_extension" 00079 "Set to TRUE if OBS_ID (from input frame header) should be appended to the\n" 00080 "output frame.\n" 00081 "\n" 00082 "ADVANCED PARAMETERS\n" 00083 "-------------------\n" 00084 "--flux\n" 00085 "Specify if flux conservation should be applied.\n" 00086 "\n" 00087 "--neighborhoodRange\n" 00088 "Defines the range to search for neighbors during reconstruction\n" 00089 "\n" 00090 "--b_samples\n" 00091 "The number of samples in spectral direction for the reconstructed cube." 00092 "Ideally this number should be greater than 2048, the detector size.\n" 00093 "\n" 00094 "--b_start\n" 00095 "--b_end\n" 00096 "Used to define manually the start and end wavelength for the reconstructed\n" 00097 "cube. By default the internally defined values are used.\n" 00098 "\n" 00099 "--pix_scale\n" 00100 "Change the pixel scale [arcsec]. Default of 0.2\" results into cubes of\n" 00101 "14x14pix, a scale of 0.1\" results into cubes of 28x28pix, etc.\n" 00102 "\n" 00103 "--xcal_interpolation\n" 00104 "If TRUE interpolate the pixel position in the slitlet (xcal) using the two\n" 00105 "closest rotator angles in the calibration file. Otherwise take the values\n" 00106 "of the closest rotator angle\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 " OH_SPEC F1S Vector holding OH lines N 1 \n" 00125 "\n" 00126 " Output files:\n" 00127 "\n" 00128 " DO KMOS\n" 00129 " category Type Explanation\n" 00130 " -------- ----- -----------\n" 00131 " CUBE_DARK or F3I Reconstructed cube \n" 00132 " CUBE_FLAT or RAW/F2D with or without noise\n" 00133 " CUBE_ARC or \n" 00134 " CUBE_OBJECT or \n" 00135 " CUBE_STD or \n" 00136 " CUBE_SCIENCE \n" 00137 "---------------------------------------------------------------------------\n" 00138 "\n"; 00139 00140 /*----------------------------------------------------------------------------- 00141 * Functions code 00142 *----------------------------------------------------------------------------*/ 00143 00144 /*----------------------------------------------------------------------------*/ 00148 /*----------------------------------------------------------------------------*/ 00149 00152 /*----------------------------------------------------------------------------*/ 00161 /*----------------------------------------------------------------------------*/ 00162 int cpl_plugin_get_info(cpl_pluginlist *list) 00163 { 00164 cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe); 00165 cpl_plugin *plugin = &recipe->interface; 00166 00167 cpl_plugin_init(plugin, 00168 CPL_PLUGIN_API, 00169 KMOS_BINARY_VERSION, 00170 CPL_PLUGIN_TYPE_RECIPE, 00171 "kmo_reconstruct", 00172 "Performs the cube reconstruction " 00173 "using different interpolation methods.", 00174 kmo_reconstruct_description, 00175 "Alex Agudo Berbel", 00176 "usd-help@eso.org", 00177 kmos_get_license(), 00178 kmo_reconstruct_create, 00179 kmo_reconstruct_exec, 00180 kmo_reconstruct_destroy); 00181 00182 cpl_pluginlist_append(list, plugin); 00183 00184 return 0; 00185 } 00186 00187 /*----------------------------------------------------------------------------*/ 00195 /*----------------------------------------------------------------------------*/ 00196 static int kmo_reconstruct_create(cpl_plugin *plugin) 00197 { 00198 cpl_recipe *recipe; 00199 cpl_parameter *p; 00200 00201 /* Check that the plugin is part of a valid recipe */ 00202 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00203 recipe = (cpl_recipe *)plugin; 00204 else 00205 return -1; 00206 00207 /* Create the parameters list in the cpl_recipe object */ 00208 recipe->parameters = cpl_parameterlist_new(); 00209 00210 /* Fill the parameters list */ 00211 /* --imethod */ 00212 p = cpl_parameter_new_value("kmos.kmo_reconstruct.imethod", CPL_TYPE_STRING, 00213 "Method to use for interpolation. [\"NN\" (nearest neighbour), " 00214 "\"lwNN\" (linear weighted nearest neighbor), " 00215 "\"swNN\" (square weighted nearest neighbor), " 00216 "\"MS\" (Modified Shepard's method)" 00217 "\"CS\" (Cubic spline)]", 00218 "kmos.kmo_reconstruct", "CS"); 00219 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "imethod"); 00220 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00221 cpl_parameterlist_append(recipe->parameters, p); 00222 00223 /* --neighborhoodRange */ 00224 p = cpl_parameter_new_value("kmos.kmo_reconstruct.neighborhoodRange", 00225 CPL_TYPE_DOUBLE, 00226 "Defines the range to search for neighbors. in pixels", 00227 "kmos.kmo_reconstruct", 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", CPL_TYPE_BOOL, 00234 "TRUE: Apply flux conservation. FALSE: otherwise", 00235 "kmos.kmo_reconstruct", FALSE); 00236 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "flux"); 00237 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00238 cpl_parameterlist_append(recipe->parameters, p); 00239 00240 /* --detectorimage */ 00241 p = cpl_parameter_new_value("kmos.kmo_reconstruct.detectorimage", 00242 CPL_TYPE_BOOL, 00243 "TRUE: if resampled detector frame should be " 00244 "created, FALSE: otherwise", 00245 "kmos.kmo_reconstruct", FALSE); 00246 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "detimg"); 00247 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00248 cpl_parameterlist_append(recipe->parameters, p); 00249 00250 /* --file_extension */ 00251 p = cpl_parameter_new_value("kmos.kmo_reconstruct.file_extension", 00252 CPL_TYPE_BOOL, 00253 "TRUE: if OBS_ID keyword should be appended to " 00254 "output frames, FALSE: otherwise", 00255 "kmos.kmo_reconstruct", FALSE); 00256 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "file_extension"); 00257 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00258 cpl_parameterlist_append(recipe->parameters, p); 00259 00260 /* --pix_scale */ 00261 p = cpl_parameter_new_value("kmos.kmo_reconstruct.pix_scale", 00262 CPL_TYPE_DOUBLE, 00263 "Change the pixel scale [arcsec]. " 00264 "Default of 0.2\" results into cubes of 14x14pix, " 00265 "a scale of 0.1\" results into cubes of 28x28pix, etc.", 00266 "kmos.kmo_reconstruct", KMOS_PIX_RESOLUTION); 00267 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "pix_scale"); 00268 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00269 cpl_parameterlist_append(recipe->parameters, p); 00270 00271 /* --xcal_interpolation */ 00272 p = cpl_parameter_new_value("kmos.kmo_reconstruct.xcal_interpolation", 00273 CPL_TYPE_BOOL, 00274 "TRUE: Interpolate xcal between rotator angles. FALSE: otherwise", 00275 "kmos.kmo_reconstruct", TRUE); 00276 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "xcal_interpolation"); 00277 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00278 cpl_parameterlist_append(recipe->parameters, p); 00279 00280 /* Add parameters for band-definition */ 00281 kmo_band_pars_create(recipe->parameters, "kmos.kmo_reconstruct"); 00282 return 0; 00283 } 00284 00285 /*----------------------------------------------------------------------------*/ 00291 /*----------------------------------------------------------------------------*/ 00292 static int kmo_reconstruct_exec(cpl_plugin *plugin) 00293 { 00294 cpl_recipe *recipe; 00295 00296 /* Get the recipe out of the plugin */ 00297 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00298 recipe = (cpl_recipe *)plugin; 00299 else return -1; 00300 00301 return kmo_reconstruct(recipe->parameters, recipe->frames); 00302 } 00303 00304 /*----------------------------------------------------------------------------*/ 00310 /*----------------------------------------------------------------------------*/ 00311 static int kmo_reconstruct_destroy(cpl_plugin *plugin) 00312 { 00313 cpl_recipe *recipe; 00314 00315 /* Get the recipe out of the plugin */ 00316 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00317 recipe = (cpl_recipe *)plugin; 00318 else return -1 ; 00319 00320 cpl_parameterlist_delete(recipe->parameters); 00321 return 0 ; 00322 } 00323 00324 /*----------------------------------------------------------------------------*/ 00339 /*----------------------------------------------------------------------------*/ 00340 static int kmo_reconstruct(cpl_parameterlist *parlist, cpl_frameset *frameset) 00341 { 00342 int ret_val = 0, 00343 nr_devices = 0, 00344 i = 0, 00345 j = 0, 00346 flux = FALSE, 00347 background = FALSE, 00348 index = 0, 00349 detectorimage = 0, 00350 *bounds = NULL, 00351 ifu_nr = 0, 00352 obs_id = 0, 00353 file_extension = FALSE, 00354 xcal_interpolation = FALSE, 00355 detImgCube = FALSE, 00356 l = 0, x = 0, y = 0; 00357 float *pdet_img_data = NULL, 00358 *pdet_img_noise = NULL, 00359 *slice = NULL; 00360 double neighborhoodRange = 1.001, 00361 pix_scale = 0.0; 00362 00363 const char *imethod = NULL, 00364 *input_frame_name = NULL, 00365 *output_frame_name = NULL, 00366 *filter_id = NULL, 00367 *filter_id_tmp = NULL, 00368 *tmp_str = NULL; 00369 char *keyword = NULL, 00370 *filename_cube = NULL, 00371 *filename_img = NULL, 00372 // *fn_lut = NULL, 00373 *suffix = NULL, 00374 *obs_suffix = NULL, 00375 *my_filter_id = NULL, 00376 *extname = NULL; 00377 cpl_image *lcal = NULL, 00378 *det_img_data[KMOS_NR_DETECTORS], 00379 *det_img_noise[KMOS_NR_DETECTORS], 00380 *tmp_img = NULL; 00381 cpl_imagelist *cube_data = NULL, 00382 *cube_noise = NULL; 00383 cpl_frame *rec_frame = NULL, 00384 *xcal_frame = NULL, 00385 *ycal_frame = NULL, 00386 *lcal_frame = NULL, 00387 *ref_spectrum_frame = NULL; 00388 cpl_propertylist *main_header = NULL, 00389 *sub_header = NULL, 00390 *sub_header_orig = NULL, 00391 *actual_sub_header = NULL, 00392 *tmp_header = NULL; 00393 cpl_table *band_table = NULL; 00394 gridDefinition gd; 00395 main_fits_desc desc1, 00396 desc2; 00397 cpl_polynomial *lcorr_coeffs = NULL; 00398 00399 for (i = 0; i < KMOS_NR_DETECTORS; i++) { 00400 det_img_data[i] = NULL; 00401 det_img_noise[i] = NULL; 00402 } 00403 00404 KMO_TRY 00405 { 00406 kmo_init_fits_desc(&desc1); 00407 kmo_init_fits_desc(&desc2); 00408 00409 // --- check input --- 00410 KMO_TRY_ASSURE((parlist != NULL) && 00411 (frameset != NULL), 00412 CPL_ERROR_NULL_INPUT, 00413 "Not all input data is provided!"); 00414 00415 KMO_TRY_ASSURE((cpl_frameset_count_tags(frameset, DARK) == 1) || 00416 (cpl_frameset_count_tags(frameset, FLAT_ON) == 1) || 00417 (cpl_frameset_count_tags(frameset, ARC_ON) == 1) || 00418 (cpl_frameset_count_tags(frameset, OBJECT) == 1) || 00419 (cpl_frameset_count_tags(frameset, STD) == 1) || 00420 (cpl_frameset_count_tags(frameset, SCIENCE) == 1), 00421 CPL_ERROR_NULL_INPUT, 00422 "A data frame (DARK, FLAT_ON, ARC_ON, OBJECT, STD or SCIENCE) must " 00423 "be provided!"); 00424 00425 KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, XCAL) == 1, 00426 CPL_ERROR_FILE_NOT_FOUND, 00427 "XCAL frame missing in frameset!!"); 00428 00429 KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, YCAL) == 1, 00430 CPL_ERROR_FILE_NOT_FOUND, 00431 "YCAL frame missing in frameset!!"); 00432 00433 KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, LCAL) == 1, 00434 CPL_ERROR_FILE_NOT_FOUND, 00435 "LCAL frame missing in frameset!!"); 00436 00437 KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, WAVE_BAND) == 1, 00438 CPL_ERROR_FILE_NOT_FOUND, 00439 "WAVE_BAND frame missing in frameset!!"); 00440 00441 KMO_TRY_ASSURE(kmo_dfs_set_groups(frameset, "kmo_reconstruct") == 1, 00442 CPL_ERROR_ILLEGAL_INPUT, 00443 "Cannot identify RAW and CALIB frames!"); 00444 00445 KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, OH_SPEC) == 0 || 00446 cpl_frameset_count_tags(frameset, OH_SPEC) == 1, 00447 CPL_ERROR_ILLEGAL_INPUT, 00448 "Only a single reference spectrum can be provided!"); 00449 00450 // --- get parameters --- 00451 cpl_msg_info("", "--- Parameter setup for kmo_reconstruct ---"); 00452 00453 KMO_TRY_EXIT_IF_NULL( 00454 imethod = kmo_dfs_get_parameter_string(parlist, 00455 "kmos.kmo_reconstruct.imethod")); 00456 00457 KMO_TRY_ASSURE((strcmp(imethod, "NN") == 0) || 00458 (strcmp(imethod, "lwNN") == 0) || 00459 (strcmp(imethod, "swNN") == 0) || 00460 (strcmp(imethod, "MS") == 0) || 00461 (strcmp(imethod, "CS") == 0), 00462 CPL_ERROR_ILLEGAL_INPUT, 00463 "imethod must be either \"NN\", \"lwNN\", " 00464 "\"swNN\", \"MS\" or \"CS\"!"); 00465 00466 KMO_TRY_EXIT_IF_ERROR( 00467 kmo_dfs_print_parameter_help(parlist, 00468 "kmos.kmo_reconstruct.imethod")); 00469 00470 flux = kmo_dfs_get_parameter_bool(parlist, 00471 "kmos.kmo_reconstruct.flux"); 00472 00473 KMO_TRY_ASSURE((flux == 0) || 00474 (flux == 1), 00475 CPL_ERROR_ILLEGAL_INPUT, 00476 "flux must be either FALSE or TRUE!"); 00477 00478 KMO_TRY_EXIT_IF_ERROR( 00479 kmo_dfs_print_parameter_help(parlist, "kmos.kmo_reconstruct.flux")); 00480 00481 detectorimage = kmo_dfs_get_parameter_bool(parlist, 00482 "kmos.kmo_reconstruct.detectorimage"); 00483 00484 KMO_TRY_ASSURE((detectorimage == 0) || 00485 (detectorimage == 1), 00486 CPL_ERROR_ILLEGAL_INPUT, 00487 "detectorimage must be either 0 or 1 !"); 00488 00489 KMO_TRY_EXIT_IF_ERROR( 00490 kmo_dfs_print_parameter_help(parlist, "kmos.kmo_reconstruct.detectorimage")); 00491 00492 neighborhoodRange = kmo_dfs_get_parameter_double(parlist, 00493 "kmos.kmo_reconstruct.neighborhoodRange"); 00494 KMO_TRY_CHECK_ERROR_STATE(); 00495 KMO_TRY_ASSURE(neighborhoodRange > 0.0, 00496 CPL_ERROR_ILLEGAL_INPUT, 00497 "neighborhoodRange must be greater than 0.0"); 00498 KMO_TRY_EXIT_IF_ERROR( 00499 kmo_dfs_print_parameter_help(parlist, 00500 "kmos.kmo_reconstruct.neighborhoodRange")); 00501 00502 kmo_band_pars_load(parlist, "kmos.kmo_reconstruct"); 00503 00504 file_extension = kmo_dfs_get_parameter_bool(parlist, 00505 "kmos.kmo_reconstruct.file_extension"); 00506 KMO_TRY_CHECK_ERROR_STATE(); 00507 KMO_TRY_EXIT_IF_ERROR( 00508 kmo_dfs_print_parameter_help(parlist, 00509 "kmos.kmo_reconstruct.file_extension")); 00510 00511 pix_scale = kmo_dfs_get_parameter_double(parlist, 00512 "kmos.kmo_reconstruct.pix_scale"); 00513 KMO_TRY_CHECK_ERROR_STATE(); 00514 KMO_TRY_EXIT_IF_ERROR( 00515 kmo_dfs_print_parameter_help(parlist, 00516 "kmos.kmo_reconstruct.pix_scale")); 00517 KMO_TRY_ASSURE((pix_scale >= 0.01) && 00518 (pix_scale <= 0.4), 00519 CPL_ERROR_ILLEGAL_INPUT, 00520 "pix_scale must be between 0.01 and 0.4 (results in cubes " 00521 "with 7x7 to 280x280 pixels)!"); 00522 00523 xcal_interpolation = kmo_dfs_get_parameter_bool(parlist, 00524 "kmos.kmo_reconstruct.xcal_interpolation"); 00525 KMO_TRY_CHECK_ERROR_STATE(); 00526 KMO_TRY_EXIT_IF_ERROR( 00527 kmo_dfs_print_parameter_help(parlist, "kmos.kmo_reconstruct.xcal_interpolation")); 00528 KMO_TRY_ASSURE((xcal_interpolation == TRUE) || 00529 (xcal_interpolation == FALSE), 00530 CPL_ERROR_ILLEGAL_INPUT, 00531 "xcal_interpolation must be TRUE or FALSE!"); 00532 00533 00534 cpl_msg_info("", "-------------------------------------------"); 00535 00536 // load descriptor and header of data frame to reconstruct 00537 if (cpl_frameset_count_tags(frameset, DARK) == 1) { 00538 input_frame_name = DARK; 00539 output_frame_name = CUBE_DARK; 00540 } else if (cpl_frameset_count_tags(frameset, FLAT_ON) == 1) { 00541 input_frame_name = FLAT_ON; 00542 output_frame_name = CUBE_FLAT; 00543 } else if (cpl_frameset_count_tags(frameset, ARC_ON) == 1) { 00544 input_frame_name = ARC_ON; 00545 output_frame_name = CUBE_ARC; 00546 } else if (cpl_frameset_count_tags(frameset, OBJECT) == 1) { 00547 input_frame_name = OBJECT; 00548 output_frame_name = CUBE_OBJECT; 00549 } else if (cpl_frameset_count_tags(frameset, STD) == 1) { 00550 input_frame_name = STD; 00551 output_frame_name = CUBE_STD; 00552 } else if (cpl_frameset_count_tags(frameset, SCIENCE) == 1) { 00553 input_frame_name = SCIENCE; 00554 output_frame_name = CUBE_SCIENCE; 00555 } 00556 00557 // assure that filters, grating and rotation offsets match for 00558 // XCAL, YCAL, LCAL and for data frame to reconstruct (except DARK 00559 // frames) 00560 // check if filter_id and grating_id match for all detectors 00561 KMO_TRY_EXIT_IF_ERROR( 00562 kmo_check_frame_setup(frameset, XCAL, YCAL, 00563 TRUE, FALSE, TRUE)); 00564 KMO_TRY_EXIT_IF_ERROR( 00565 kmo_check_frame_setup(frameset, XCAL, LCAL, 00566 TRUE, FALSE, TRUE)); 00567 00568 if (cpl_frameset_count_tags(frameset, OH_SPEC) > 0) { 00569 KMO_TRY_EXIT_IF_ERROR(kmo_check_oh_spec_setup(frameset, XCAL)); 00570 } 00571 00572 if (cpl_frameset_count_tags(frameset, DARK) != 1) { 00573 // check if filters, gratings and rotator offset match 00574 // (except for DARK frames) 00575 KMO_TRY_EXIT_IF_ERROR( 00576 kmo_check_frame_setup(frameset, XCAL, input_frame_name, 00577 TRUE, FALSE, FALSE)); 00578 } 00579 00580 KMO_TRY_EXIT_IF_NULL( 00581 xcal_frame = kmo_dfs_get_frame(frameset, XCAL)); 00582 KMO_TRY_EXIT_IF_NULL( 00583 rec_frame = kmo_dfs_get_frame(frameset, input_frame_name)); 00584 KMO_TRY_EXIT_IF_NULL( 00585 suffix = kmo_dfs_get_suffix(rec_frame, TRUE, TRUE)); 00586 00587 KMO_TRY_EXIT_IF_ERROR( 00588 kmo_check_frame_setup_md5_xycal(frameset)); 00589 KMO_TRY_EXIT_IF_ERROR( 00590 kmo_check_frame_setup_md5(frameset)); 00591 00592 cpl_msg_info("", "Detected instrument setup: %s", suffix+1); 00593 cpl_msg_info("", "(grating 1, 2 & 3, rotation angle)"); 00594 cpl_msg_info("", "-------------------------------------------"); 00595 00596 KMO_TRY_EXIT_IF_NULL( 00597 main_header = kmo_dfs_load_primary_header(frameset, 00598 input_frame_name)); 00599 00600 if (cpl_frameset_count_tags(frameset, OH_SPEC) != 0) { 00601 if (cpl_propertylist_has(main_header, ORIGFILE)) { 00602 KMO_TRY_EXIT_IF_NULL( 00603 tmp_str = cpl_propertylist_get_string(main_header, ORIGFILE)); 00604 if (strstr(tmp_str, "OBS") != NULL) { 00605 // we are reconstructing an OBS-frame, allow OH_SPEC correction 00606 KMO_TRY_EXIT_IF_NULL( 00607 ref_spectrum_frame = kmo_dfs_get_frame(frameset, OH_SPEC)); 00608 } else { 00609 cpl_msg_warning("", "Supplied OH_SPEC is ignored since a calibration frame is being reconstructed."); 00610 } 00611 } else { 00612 cpl_msg_warning("", "The supplied frame %s is assumed to be a science frame. If it is a calibration frame, omit OH_SPEC from sof-file", input_frame_name); 00613 KMO_TRY_EXIT_IF_NULL( 00614 ref_spectrum_frame = kmo_dfs_get_frame(frameset, OH_SPEC)); 00615 } 00616 } 00617 00618 desc1 = kmo_identify_fits_header(cpl_frame_get_filename(rec_frame)); 00619 KMO_TRY_CHECK_ERROR_STATE(); 00620 00621 KMO_TRY_ASSURE(((desc1.nr_ext == KMOS_NR_DETECTORS) || 00622 ((desc1.nr_ext == 2*KMOS_NR_DETECTORS))) && 00623 (desc1.ex_badpix == FALSE) && 00624 ((desc1.fits_type == raw_fits) || 00625 (desc1.fits_type == f2d_fits)) && 00626 (desc1.frame_type == detector_frame), 00627 CPL_ERROR_ILLEGAL_INPUT, 00628 "The frame to reconstruct isn't in the correct format!!!" 00629 "Exactly 3 frames, or 6 with noise are expected!"); 00630 00631 if (!desc1.ex_noise) { 00632 nr_devices = desc1.nr_ext; 00633 } else { 00634 nr_devices = desc1.nr_ext / 2; 00635 } 00636 00637 // compare descriptor of XCAL and data frame to reconstruct 00638 desc2 = kmo_identify_fits_header(cpl_frame_get_filename(xcal_frame)); 00639 KMO_TRY_CHECK_ERROR_STATE(); 00640 00641 KMO_TRY_ASSURE((desc2.nr_ext % 3 == 0) && 00642 (desc1.ex_badpix == desc2.ex_badpix) && 00643 (desc1.frame_type == desc2.frame_type), 00644 CPL_ERROR_ILLEGAL_INPUT, 00645 "XCAL isn't in the correct format!!!"); 00646 00647 kmo_free_fits_desc(&desc2); 00648 00649 // compare descriptor of YCAL and data frame to reconstruct 00650 kmo_init_fits_desc(&desc2); 00651 00652 KMO_TRY_EXIT_IF_NULL( 00653 ycal_frame = kmo_dfs_get_frame(frameset, YCAL)); 00654 00655 desc2 = kmo_identify_fits_header(cpl_frame_get_filename(ycal_frame)); 00656 KMO_TRY_CHECK_ERROR_STATE(); 00657 00658 KMO_TRY_ASSURE((desc2.nr_ext % 3 == 0) && 00659 (desc1.ex_badpix == desc2.ex_badpix) && 00660 (desc1.frame_type == desc2.frame_type), 00661 CPL_ERROR_ILLEGAL_INPUT, 00662 "YCAL isn't in the correct format!!!"); 00663 00664 kmo_free_fits_desc(&desc2); 00665 00666 // compare descriptor of LCAL and data frame to reconstruct 00667 kmo_init_fits_desc(&desc2); 00668 00669 KMO_TRY_EXIT_IF_NULL( 00670 lcal_frame = kmo_dfs_get_frame(frameset, LCAL)); 00671 00672 desc2 = kmo_identify_fits_header(cpl_frame_get_filename(lcal_frame)); 00673 KMO_TRY_CHECK_ERROR_STATE(); 00674 00675 KMO_TRY_ASSURE((desc2.nr_ext % 3 == 0) && 00676 (desc1.ex_badpix == desc2.ex_badpix) && 00677 (desc1.frame_type == desc2.frame_type), 00678 CPL_ERROR_ILLEGAL_INPUT, 00679 "LCAL isn't in the correct format!!!"); 00680 00681 kmo_free_fits_desc(&desc2); 00682 00683 // 00684 // --- update & save primary header --- 00685 // 00686 KMO_TRY_EXIT_IF_NULL( 00687 tmp_header = kmo_dfs_load_primary_header(frameset, LCAL)); 00688 00689 // assert that filters have correct IDs and that all detectors of all 00690 // input frames have the same filter set 00691 for (i = 1; i <= nr_devices; i++) { 00692 // ESO INS FILTi ID 00693 KMO_TRY_EXIT_IF_NULL( 00694 keyword = cpl_sprintf("%s%d%s", IFU_FILTID_PREFIX, i, 00695 IFU_FILTID_POSTFIX)); 00696 00697 KMO_TRY_EXIT_IF_NULL( 00698 filter_id = cpl_propertylist_get_string(tmp_header, keyword)); 00699 00700 KMO_TRY_ASSURE((strcmp(filter_id, "IZ") == 0) || 00701 (strcmp(filter_id, "YJ") == 0) || 00702 (strcmp(filter_id, "H") == 0) || 00703 (strcmp(filter_id, "K") == 0) || 00704 (strcmp(filter_id, "HK") == 0), 00705 CPL_ERROR_ILLEGAL_INPUT, 00706 "Filter ID in primary header of LCAL frame must " 00707 "be either \"IZ\", \"YJ\", \"H\", \"K\" or " 00708 "\"HK\" !"); 00709 00710 if (strcmp(input_frame_name, DARK) != 0) { 00711 // dark needn't to be taken with filter! 00712 00713 KMO_TRY_EXIT_IF_NULL( 00714 filter_id_tmp = cpl_propertylist_get_string(main_header, 00715 keyword)); 00716 KMO_TRY_ASSURE(strcmp(filter_id, filter_id_tmp) == 0, 00717 CPL_ERROR_ILLEGAL_INPUT, 00718 "Filter IDs must be the same for LCAL frame and " 00719 "the frame to reconstruct!" 00720 "Detector No.: %d\nLCAL: %s\n%s: %s\n", 00721 i, filter_id, input_frame_name, filter_id_tmp); 00722 } 00723 cpl_free(keyword); keyword = NULL; 00724 } 00725 KMO_TRY_EXIT_IF_NULL( 00726 my_filter_id = cpl_strdup(filter_id)); 00727 cpl_propertylist_delete(tmp_header); tmp_header = NULL; 00728 00729 obs_id = cpl_propertylist_get_int(main_header, OBS_ID); 00730 KMO_TRY_CHECK_ERROR_STATE(); 00731 00732 KMO_TRY_EXIT_IF_NULL( 00733 filename_cube = cpl_sprintf("%s", output_frame_name)); 00734 KMO_TRY_EXIT_IF_NULL( 00735 filename_img = cpl_sprintf("%s", DET_IMG_REC)); 00736 if (file_extension) { 00737 KMO_TRY_EXIT_IF_NULL( 00738 obs_suffix = cpl_sprintf("%s%d", "_", obs_id)); 00739 } else { 00740 KMO_TRY_EXIT_IF_NULL( 00741 obs_suffix = cpl_sprintf("%s", "")); 00742 } 00743 00744 KMO_TRY_EXIT_IF_ERROR( 00745 kmo_dfs_save_main_header(frameset, filename_cube, obs_suffix, 00746 rec_frame, NULL, parlist, cpl_func)); 00747 00748 // setup grid definition, wavelength start and end points will be set 00749 // in the detector loop 00750 KMO_TRY_EXIT_IF_ERROR( 00751 kmclipm_setup_grid(&gd, imethod, neighborhoodRange, pix_scale, 0.)); 00752 00753 KMO_TRY_EXIT_IF_NULL( 00754 tmp_header = kmo_dfs_load_primary_header(frameset, XCAL)); 00755 00756 KMO_TRY_EXIT_IF_NULL( 00757 bounds = kmclipm_extract_bounds(tmp_header)); 00758 cpl_propertylist_delete(tmp_header); tmp_header = NULL; 00759 00760 if (detectorimage == TRUE) { 00761 KMO_TRY_EXIT_IF_ERROR( 00762 kmo_dfs_save_main_header(frameset, filename_img, obs_suffix, 00763 rec_frame, NULL, parlist, cpl_func)); 00764 } 00765 00766 /* loop through all detectors */ 00767 for (i = 1; i <= nr_devices; i++) { 00768 cpl_msg_info("","Processing detector No. %d", i); 00769 00770 // load lcal 00771 // extract LCAL image close to ROTANGLE 0. assuming that the wavelength range 00772 // doesn't differ too much with different ROTANGLEs. 00773 double rotangle_found; 00774 print_cal_angle_msg_once = FALSE; 00775 print_xcal_angle_msg_once = FALSE; 00776 KMO_TRY_EXIT_IF_NULL( 00777 lcal = kmo_dfs_load_cal_image(frameset, LCAL, i, FALSE, 0., 00778 FALSE, NULL, &rotangle_found, -1, 0, 0)); 00779 if (i==1) { 00780 print_cal_angle_msg_once = TRUE; 00781 print_xcal_angle_msg_once = TRUE; 00782 } 00783 00784 KMO_TRY_EXIT_IF_NULL( 00785 band_table = kmo_dfs_load_table(frameset, WAVE_BAND, 1, FALSE)); 00786 00787 KMO_TRY_EXIT_IF_ERROR( 00788 kmclipm_setup_grid_band_lcal(&gd, my_filter_id, 00789 band_table)); 00790 cpl_table_delete(band_table); band_table = NULL; 00791 00792 cpl_image_delete(lcal); lcal = NULL; 00793 00794 if (detectorimage == TRUE) { 00795 KMO_TRY_EXIT_IF_NULL( 00796 det_img_data[i-1] = cpl_image_new(gd.x.dim*gd.y.dim*KMOS_IFUS_PER_DETECTOR, 00797 gd.l.dim, CPL_TYPE_FLOAT)); 00798 KMO_TRY_EXIT_IF_NULL( 00799 pdet_img_data = cpl_image_get_data_float(det_img_data[i-1])); 00800 00801 KMO_TRY_EXIT_IF_NULL( 00802 det_img_noise[i-1] = cpl_image_new(gd.x.dim*gd.y.dim*KMOS_IFUS_PER_DETECTOR, 00803 gd.l.dim, CPL_TYPE_FLOAT)); 00804 KMO_TRY_EXIT_IF_NULL( 00805 pdet_img_noise = cpl_image_get_data_float(det_img_noise[i-1])); 00806 } 00807 00808 00809 for (j = 0; j < KMOS_IFUS_PER_DETECTOR; j++) { 00810 /* update sub-header */ 00811 ifu_nr = (i-1)*KMOS_IFUS_PER_DETECTOR + j + 1; 00812 00813 /* load raw image and sub-header*/ 00814 KMO_TRY_EXIT_IF_NULL( 00815 sub_header = kmo_dfs_load_sub_header(frameset, input_frame_name, 00816 i, FALSE)); 00817 KMO_TRY_EXIT_IF_NULL( 00818 sub_header_orig = cpl_propertylist_duplicate(sub_header)); 00819 00820 // check if IFU is valid according to main header keywords & 00821 // calibration files 00822 00823 if (getenv("KMOS_RECONSTRUCT_ALL") == NULL) { 00824 KMO_TRY_EXIT_IF_NULL( 00825 keyword = cpl_sprintf("%s%d%s", IFU_VALID_PREFIX, ifu_nr, 00826 IFU_VALID_POSTFIX)); 00827 KMO_TRY_CHECK_ERROR_STATE(); 00828 cpl_propertylist_get_string(main_header, keyword); 00829 cpl_free(keyword); keyword = NULL; 00830 } else { 00831 // if KMOS_RECONSTRUCT_ALL is set all IFUs should be 00832 // reconstructed 00833 cpl_propertylist_get_string(main_header, "ggg"); 00834 } 00835 00836 if ((cpl_error_get_code() == CPL_ERROR_DATA_NOT_FOUND) && 00837 (bounds[2*(ifu_nr-1)] != -1) && 00838 (bounds[2*(ifu_nr-1)+1] != -1)) 00839 { 00840 cpl_error_reset(); 00841 // IFU is valid 00842 actual_sub_header = sub_header; 00843 00844 // 00845 // calc WCS & update subheader 00846 // 00847 KMO_TRY_EXIT_IF_ERROR( 00848 kmo_calc_wcs_gd(main_header, actual_sub_header, ifu_nr, gd)); 00849 00850 KMO_TRY_EXIT_IF_ERROR( 00851 kmclipm_update_property_int(actual_sub_header, 00852 NAXIS, 3, 00853 "number of data axes")); 00854 KMO_TRY_EXIT_IF_ERROR( 00855 kmclipm_update_property_int(actual_sub_header, 00856 NAXIS1, gd.x.dim, 00857 "length of data axis 1")); 00858 KMO_TRY_EXIT_IF_ERROR( 00859 kmclipm_update_property_int(actual_sub_header, 00860 NAXIS2, gd.y.dim, 00861 "length of data axis 2")); 00862 KMO_TRY_EXIT_IF_ERROR( 00863 kmclipm_update_property_int(actual_sub_header, 00864 NAXIS3, gd.l.dim, 00865 "length of data axis 3")); 00866 00867 // reconstruct data and noise (if available) 00868 // if (j == 0) { 00869 // sat_mode_msg = FALSE; 00870 // } else { 00871 // sat_mode_msg = TRUE; 00872 // } 00873 KMO_TRY_EXIT_IF_ERROR( 00874 kmo_reconstruct_sci(ifu_nr, 00875 bounds[2*(ifu_nr-1)], 00876 bounds[2*(ifu_nr-1)+1], 00877 rec_frame, 00878 input_frame_name, 00879 NULL, 00880 NULL, 00881 NULL, 00882 xcal_frame, 00883 ycal_frame, 00884 lcal_frame, 00885 NULL, 00886 NULL, 00887 &gd, 00888 &cube_data, 00889 &cube_noise, 00890 flux, 00891 background, 00892 xcal_interpolation)); 00893 00894 if (ref_spectrum_frame != NULL && cube_data != NULL) { 00895 KMO_TRY_EXIT_IF_NULL( 00896 lcorr_coeffs = kmo_lcorr_get(cube_data, 00897 actual_sub_header, 00898 ref_spectrum_frame, 00899 gd, 00900 my_filter_id, 00901 ifu_nr)); 00902 00903 cpl_imagelist_delete(cube_data); cube_data = NULL; 00904 if (cube_noise != NULL) { 00905 cpl_imagelist_delete(cube_noise); cube_noise = NULL; 00906 } 00907 KMO_TRY_EXIT_IF_ERROR( 00908 kmo_reconstruct_sci(ifu_nr, 00909 bounds[2*(ifu_nr-1)], 00910 bounds[2*(ifu_nr-1)+1], 00911 rec_frame, 00912 input_frame_name, 00913 NULL, 00914 NULL, 00915 NULL, 00916 xcal_frame, 00917 ycal_frame, 00918 lcal_frame, 00919 lcorr_coeffs, 00920 NULL, 00921 &gd, 00922 &cube_data, 00923 &cube_noise, 00924 flux, 00925 background, 00926 xcal_interpolation)); 00927 cpl_polynomial_delete(lcorr_coeffs); lcorr_coeffs = NULL; 00928 00929 } 00930 00931 // scale flux according to pixel_scale 00932 KMO_TRY_EXIT_IF_NULL( 00933 tmp_img = cpl_imagelist_get(cube_data, 0)); 00934 double scaling = (cpl_image_get_size_x(tmp_img)*cpl_image_get_size_y(tmp_img)) / 00935 (KMOS_SLITLET_X*KMOS_SLITLET_Y); 00936 KMO_TRY_EXIT_IF_ERROR( 00937 cpl_imagelist_divide_scalar(cube_data, scaling)); 00938 if (cube_noise != NULL) { 00939 KMO_TRY_EXIT_IF_ERROR( 00940 cpl_imagelist_divide_scalar(cube_noise, scaling)); 00941 } 00942 } else { 00943 // IFU is invalid 00944 actual_sub_header = sub_header_orig; 00945 cpl_error_reset(); 00946 } // if ((cpl_error_get_code() == CPL_ERROR_DATA_NOT_FOUND) .. 00947 00948 if (detectorimage) { 00949 if (cube_data != NULL) { 00950 for (l = 0; l < gd.l.dim; l++) { 00951 KMO_TRY_EXIT_IF_NULL( 00952 slice = cpl_image_get_data_float(cpl_imagelist_get(cube_data, l))); 00953 for (y = 0; y < gd.y.dim; y++) { 00954 for (x = 0; x < gd.x.dim; x++) { 00955 int ix = x + 00956 y * gd.x.dim + 00957 j * gd.x.dim*gd.y.dim + //IFU offset 00958 l * gd.x.dim*gd.y.dim*KMOS_IFUS_PER_DETECTOR; 00959 pdet_img_data[ix] = slice[x + y*gd.x.dim]; 00960 } 00961 } 00962 } 00963 } 00964 if (cube_noise != NULL) { 00965 if (detectorimage) { 00966 detImgCube = TRUE; 00967 } 00968 for (l = 0; l < gd.l.dim; l++) { 00969 KMO_TRY_EXIT_IF_NULL( 00970 slice = cpl_image_get_data_float(cpl_imagelist_get(cube_noise, l))); 00971 for (y = 0; y < gd.y.dim; y++) { 00972 for (x = 0; x < gd.x.dim; x++) { 00973 int ix = x + 00974 y * gd.x.dim + 00975 j * gd.x.dim*gd.y.dim + //IFU offset 00976 l * gd.x.dim*gd.y.dim*KMOS_IFUS_PER_DETECTOR; 00977 pdet_img_noise[ix] = slice[x + y*gd.x.dim]; 00978 } 00979 } 00980 } 00981 } 00982 } 00983 00984 // save output 00985 KMO_TRY_EXIT_IF_NULL( 00986 extname = kmo_extname_creator(ifu_frame, ifu_nr, 00987 EXT_DATA)); 00988 00989 KMO_TRY_EXIT_IF_ERROR( 00990 kmclipm_update_property_string(actual_sub_header, 00991 EXTNAME, 00992 extname, 00993 "FITS extension name")); 00994 00995 cpl_free(extname); extname = NULL; 00996 00997 KMO_TRY_EXIT_IF_ERROR( 00998 kmo_dfs_save_cube(cube_data, filename_cube, obs_suffix, 00999 actual_sub_header, 0./0.)); 01000 01001 if (cube_noise != NULL) { 01002 KMO_TRY_EXIT_IF_NULL( 01003 extname = kmo_extname_creator(ifu_frame, ifu_nr, 01004 EXT_NOISE)); 01005 01006 KMO_TRY_EXIT_IF_ERROR( 01007 kmclipm_update_property_string(actual_sub_header, 01008 EXTNAME, 01009 extname, 01010 "FITS extension name")); 01011 01012 cpl_free(extname); extname = NULL; 01013 01014 KMO_TRY_EXIT_IF_ERROR( 01015 kmo_dfs_save_cube(cube_noise, filename_cube, obs_suffix, 01016 actual_sub_header, 0./0.)); 01017 } 01018 01019 cpl_imagelist_delete(cube_data); cube_data = NULL; 01020 cpl_imagelist_delete(cube_noise); cube_noise = NULL; 01021 cpl_propertylist_delete(sub_header); sub_header = NULL; 01022 cpl_propertylist_delete(sub_header_orig); sub_header_orig = NULL; 01023 } // for j IFUs 01024 01025 if (detectorimage) { 01026 index = kmo_identify_index(cpl_frame_get_filename(rec_frame), 01027 i, FALSE); 01028 KMO_TRY_CHECK_ERROR_STATE(); 01029 01030 KMO_TRY_EXIT_IF_NULL( 01031 tmp_header = kmclipm_propertylist_load( 01032 cpl_frame_get_filename(rec_frame), index)); 01033 KMO_TRY_EXIT_IF_ERROR( 01034 kmo_save_det_img_ext(det_img_data[i-1], gd, i, filename_img, 01035 obs_suffix, tmp_header, FALSE, FALSE)); 01036 cpl_propertylist_delete(tmp_header); tmp_header = NULL; 01037 01038 if (detImgCube) { 01039 if (desc1.ex_noise) { 01040 index = kmo_identify_index(cpl_frame_get_filename(rec_frame), 01041 i, TRUE); 01042 KMO_TRY_CHECK_ERROR_STATE(); 01043 } else { 01044 // use same index as for data frame, since input frame 01045 // has just 3 extensions 01046 } 01047 KMO_TRY_EXIT_IF_NULL( 01048 tmp_header = kmclipm_propertylist_load( 01049 cpl_frame_get_filename(rec_frame), index)); 01050 KMO_TRY_EXIT_IF_ERROR( 01051 kmo_save_det_img_ext(det_img_noise[i-1], gd, i, filename_img, 01052 obs_suffix, tmp_header, 01053 FALSE, TRUE)); 01054 cpl_propertylist_delete(tmp_header); tmp_header = NULL; 01055 } 01056 } 01057 01058 // free memory 01059 cpl_imagelist_delete(cube_data); cube_data = NULL; 01060 cpl_imagelist_delete(cube_noise); cube_noise = NULL; 01061 cpl_propertylist_delete(sub_header); sub_header = NULL; 01062 cpl_propertylist_delete(sub_header_orig); sub_header_orig = NULL; 01063 } // for i devices 01064 } 01065 KMO_CATCH 01066 { 01067 KMO_CATCH_MSG(); 01068 ret_val = -1; 01069 } 01070 01071 kmo_free_fits_desc(&desc1); 01072 kmo_free_fits_desc(&desc2); 01073 for (i = 0; i < KMOS_NR_DETECTORS; i++) { 01074 cpl_image_delete(det_img_data[i]); det_img_data[i] = NULL; 01075 cpl_image_delete(det_img_noise[i]); det_img_noise[i] = NULL; 01076 } 01077 cpl_free(my_filter_id); my_filter_id = NULL; 01078 cpl_free(bounds); bounds = NULL; 01079 cpl_propertylist_delete(main_header); main_header = NULL; 01080 cpl_propertylist_delete(sub_header); sub_header = NULL; 01081 cpl_propertylist_delete(sub_header_orig); sub_header_orig = NULL; 01082 cpl_imagelist_delete(cube_data); cube_data = NULL; 01083 cpl_imagelist_delete(cube_noise); cube_noise = NULL; 01084 cpl_free(obs_suffix); obs_suffix = NULL; 01085 cpl_free(suffix); suffix = NULL; 01086 cpl_free(filename_img); filename_img = NULL; 01087 cpl_free(filename_cube); filename_cube = NULL; 01088 01089 return ret_val; 01090 } 01091