|
KMOS Pipeline Reference Manual
1.3.17
|
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 #include "kmos_oscan.h" 00045 00046 /*----------------------------------------------------------------------------- 00047 * Functions prototypes 00048 *----------------------------------------------------------------------------*/ 00049 00050 static int kmos_reconstruct_check_inputs(cpl_frameset *, const char *); 00051 00052 static int kmos_reconstruct_create(cpl_plugin *); 00053 static int kmos_reconstruct_exec(cpl_plugin *); 00054 static int kmos_reconstruct_destroy(cpl_plugin *); 00055 static int kmos_reconstruct(cpl_parameterlist *, cpl_frameset *); 00056 00057 /*----------------------------------------------------------------------------- 00058 * Static variables 00059 *----------------------------------------------------------------------------*/ 00060 00061 static char kmos_reconstruct_description[] = 00062 "Data with or without noise is reconstructed into a cube using X/Y/LCAL, YCAL\n" 00063 "The input data can contain noise extensions and will be reconstructed into\n" 00064 "additional extensions.\n" 00065 "If an OH spectrum is given in the SOF file the lambda axis will be corrected\n" 00066 "using the OH lines as reference.\n" 00067 "\n" 00068 "---------------------------------------------------------------------------\n" 00069 " Input files:\n" 00070 "\n" 00071 " DO KMOS \n" 00072 " category Type Explanation Required #Frames\n" 00073 " -------- ----- ----------- -------- -------\n" 00074 " DARK or RAW/F2D data with Y 1 \n" 00075 " FLAT_ON or RAW/F2D or without noise \n" 00076 " ARC_ON or RAW/F2D \n" 00077 " OBJECT or RAW \n" 00078 " STD or RAW \n" 00079 " SCIENCE RAW \n" 00080 " XCAL F2D x-direction calib. frame Y 1 \n" 00081 " YCAL F2D y-direction calib. frame Y 1 \n" 00082 " LCAL F2D Wavelength calib. frame Y 1 \n" 00083 " WAVE_BAND F2L Table with start-/end-wavelengths Y 1 \n" 00084 " OH_SPEC F1S Vector holding OH lines N 1 \n" 00085 "\n" 00086 " Output files:\n" 00087 "\n" 00088 " DO KMOS\n" 00089 " category Type Explanation\n" 00090 " -------- ----- -----------\n" 00091 " CUBE_DARK or F3I Reconstructed cube \n" 00092 " CUBE_FLAT or RAW/F2D with or without noise\n" 00093 " CUBE_ARC or \n" 00094 " CUBE_OBJECT or \n" 00095 " CUBE_STD or \n" 00096 " CUBE_SCIENCE \n" 00097 "---------------------------------------------------------------------------\n" 00098 "\n"; 00099 00100 /*----------------------------------------------------------------------------- 00101 * Functions code 00102 *----------------------------------------------------------------------------*/ 00103 00104 /*----------------------------------------------------------------------------*/ 00108 /*----------------------------------------------------------------------------*/ 00109 00112 /*----------------------------------------------------------------------------*/ 00121 /*----------------------------------------------------------------------------*/ 00122 int cpl_plugin_get_info(cpl_pluginlist *list) 00123 { 00124 cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe); 00125 cpl_plugin *plugin = &recipe->interface; 00126 00127 cpl_plugin_init(plugin, 00128 CPL_PLUGIN_API, 00129 KMOS_BINARY_VERSION, 00130 CPL_PLUGIN_TYPE_RECIPE, 00131 "kmos_reconstruct", 00132 "Performs the cube reconstruction", 00133 kmos_reconstruct_description, 00134 "Alex Agudo Berbel, Y. Jung", 00135 "usd-help@eso.org", 00136 kmos_get_license(), 00137 kmos_reconstruct_create, 00138 kmos_reconstruct_exec, 00139 kmos_reconstruct_destroy); 00140 00141 cpl_pluginlist_append(list, plugin); 00142 00143 return 0; 00144 } 00145 00146 /*----------------------------------------------------------------------------*/ 00154 /*----------------------------------------------------------------------------*/ 00155 static int kmos_reconstruct_create(cpl_plugin *plugin) 00156 { 00157 cpl_recipe *recipe; 00158 cpl_parameter *p; 00159 00160 /* Check that the plugin is part of a valid recipe */ 00161 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00162 recipe = (cpl_recipe *)plugin; 00163 else 00164 return -1; 00165 00166 /* Create the parameters list in the cpl_recipe object */ 00167 recipe->parameters = cpl_parameterlist_new(); 00168 00169 /* Fill the parameters list */ 00170 /* --imethod */ 00171 p = cpl_parameter_new_value("kmos.kmos_reconstruct.imethod", 00172 CPL_TYPE_STRING, 00173 "Method to use for interpolation. [\"NN\" (nearest neighbour), " 00174 "\"lwNN\" (linear weighted nearest neighbor), " 00175 "\"swNN\" (square weighted nearest neighbor), " 00176 "\"MS\" (Modified Shepard's method)" 00177 "\"CS\" (Cubic spline)]", 00178 "kmos.kmos_reconstruct", "CS"); 00179 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "imethod"); 00180 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00181 cpl_parameterlist_append(recipe->parameters, p); 00182 00183 /* --neighborhoodRange */ 00184 p = cpl_parameter_new_value("kmos.kmos_reconstruct.neighborhoodRange", 00185 CPL_TYPE_DOUBLE, 00186 "Defines the range to search for neighbors. in pixels", 00187 "kmos.kmos_reconstruct", 1.001); 00188 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "neighborhoodRange"); 00189 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00190 cpl_parameterlist_append(recipe->parameters, p); 00191 00192 /* --flux */ 00193 p = cpl_parameter_new_value("kmos.kmos_reconstruct.flux", CPL_TYPE_BOOL, 00194 "TRUE: Apply flux conservation. FALSE: otherwise", 00195 "kmos.kmos_reconstruct", FALSE); 00196 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "flux"); 00197 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00198 cpl_parameterlist_append(recipe->parameters, p); 00199 00200 /* --detectorimage */ 00201 p = cpl_parameter_new_value("kmos.kmos_reconstruct.detectorimage", 00202 CPL_TYPE_BOOL, 00203 "TRUE: if resampled detector frame should be " 00204 "created, FALSE: otherwise", 00205 "kmos.kmos_reconstruct", FALSE); 00206 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "detimg"); 00207 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00208 cpl_parameterlist_append(recipe->parameters, p); 00209 00210 /* --file_extension */ 00211 p = cpl_parameter_new_value("kmos.kmos_reconstruct.file_extension", 00212 CPL_TYPE_BOOL, 00213 "TRUE: if OBS_ID keyword should be appended to " 00214 "output frames, FALSE: otherwise", 00215 "kmos.kmos_reconstruct", FALSE); 00216 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "file_extension"); 00217 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00218 cpl_parameterlist_append(recipe->parameters, p); 00219 00220 /* --pix_scale */ 00221 p = cpl_parameter_new_value("kmos.kmos_reconstruct.pix_scale", 00222 CPL_TYPE_DOUBLE, 00223 "Change the pixel scale [arcsec]. " 00224 "Default of 0.2\" results into cubes of 14x14pix, " 00225 "a scale of 0.1\" results into cubes of 28x28pix, etc.", 00226 "kmos.kmos_reconstruct", KMOS_PIX_RESOLUTION); 00227 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "pix_scale"); 00228 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00229 cpl_parameterlist_append(recipe->parameters, p); 00230 00231 /* --xcal_interpolation */ 00232 p = cpl_parameter_new_value("kmos.kmos_reconstruct.xcal_interpolation", 00233 CPL_TYPE_BOOL, 00234 "TRUE: Interpolate xcal between rotator angles. FALSE: otherwise", 00235 "kmos.kmos_reconstruct", TRUE); 00236 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "xcal_interpolation"); 00237 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00238 cpl_parameterlist_append(recipe->parameters, p); 00239 00240 /* --oscan */ 00241 p = cpl_parameter_new_value("kmos.kmos_reconstruct.oscan", 00242 CPL_TYPE_BOOL, "Apply Overscan Correction", 00243 "kmos.kmos_reconstruct", TRUE); 00244 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "oscan"); 00245 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00246 cpl_parameterlist_append(recipe->parameters, p); 00247 00248 /* Add parameters for band-definition */ 00249 kmos_band_pars_create(recipe->parameters, "kmos.kmos_reconstruct"); 00250 return 0; 00251 } 00252 00253 /*----------------------------------------------------------------------------*/ 00259 /*----------------------------------------------------------------------------*/ 00260 static int kmos_reconstruct_exec(cpl_plugin *plugin) 00261 { 00262 cpl_recipe *recipe; 00263 00264 /* Get the recipe out of the plugin */ 00265 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00266 recipe = (cpl_recipe *)plugin; 00267 else return -1; 00268 00269 return kmos_reconstruct(recipe->parameters, recipe->frames); 00270 } 00271 00272 /*----------------------------------------------------------------------------*/ 00278 /*----------------------------------------------------------------------------*/ 00279 static int kmos_reconstruct_destroy(cpl_plugin *plugin) 00280 { 00281 cpl_recipe *recipe; 00282 00283 /* Get the recipe out of the plugin */ 00284 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00285 recipe = (cpl_recipe *)plugin; 00286 else return -1 ; 00287 00288 cpl_parameterlist_delete(recipe->parameters); 00289 return 0 ; 00290 } 00291 00292 /*----------------------------------------------------------------------------*/ 00305 /*----------------------------------------------------------------------------*/ 00306 static int kmos_reconstruct(cpl_parameterlist *parlist, cpl_frameset *frameset) 00307 { 00308 const cpl_parameter * par ; 00309 const char * imethod ; 00310 int flux, detectorimage, xcal_interpolation, 00311 file_extension, oscan ; 00312 double neighborhoodRange, pix_scale, scaling ; 00313 cpl_frame * input_frame ; 00314 cpl_frame * xcal_frame ; 00315 cpl_frame * ycal_frame ; 00316 cpl_frame * lcal_frame ; 00317 cpl_frame * ref_spectrum_frame ; 00318 float * pdet_img_data ; 00319 float * pdet_img_noise ; 00320 float * slice ; 00321 const char * input_frame_name ; 00322 const char * output_frame_name ; 00323 const char * filter_id ; 00324 char * keyword ; 00325 char * suffix ; 00326 char * obs_suffix ; 00327 char * extname ; 00328 int * bounds ; 00329 cpl_image * det_img_data ; 00330 cpl_image * det_img_noise; 00331 cpl_image * tmp_img ; 00332 cpl_imagelist * cube_data ; 00333 cpl_imagelist * cube_noise ; 00334 cpl_propertylist * main_header ; 00335 cpl_propertylist * sub_header ; 00336 cpl_propertylist * tmp_header ; 00337 cpl_table * band_table ; 00338 gridDefinition gd ; 00339 cpl_polynomial * lcorr_coeffs ; 00340 main_fits_desc desc1 ; 00341 int i, j, index, ifu_nr, detImgCube, l, x, y ; 00342 00343 /* Initialise */ 00344 detImgCube = FALSE ; 00345 00346 /* Check Entries */ 00347 if (parlist == NULL || frameset == NULL) { 00348 cpl_msg_error(__func__, "Null Inputs") ; 00349 cpl_error_set(__func__, CPL_ERROR_NULL_INPUT) ; 00350 return -1 ; 00351 } 00352 00353 /* Get parameters */ 00354 par = cpl_parameterlist_find_const(parlist,"kmos.kmos_reconstruct.imethod"); 00355 imethod = cpl_parameter_get_string(par) ; 00356 par = cpl_parameterlist_find_const(parlist, "kmos.kmos_reconstruct.flux"); 00357 flux = cpl_parameter_get_bool(par); 00358 par = cpl_parameterlist_find_const(parlist, 00359 "kmos.kmos_reconstruct.detectorimage"); 00360 detectorimage = cpl_parameter_get_bool(par); 00361 par = cpl_parameterlist_find_const(parlist, 00362 "kmos.kmos_reconstruct.neighborhoodRange"); 00363 neighborhoodRange = cpl_parameter_get_double(par) ; 00364 kmos_band_pars_load(parlist, "kmos.kmos_reconstruct"); 00365 par = cpl_parameterlist_find_const(parlist, 00366 "kmos.kmos_reconstruct.file_extension"); 00367 file_extension = cpl_parameter_get_bool(par); 00368 par = cpl_parameterlist_find_const(parlist, 00369 "kmos.kmos_reconstruct.pix_scale"); 00370 pix_scale = cpl_parameter_get_double(par) ; 00371 par = cpl_parameterlist_find_const(parlist, 00372 "kmos.kmos_reconstruct.xcal_interpolation"); 00373 xcal_interpolation = cpl_parameter_get_bool(par); 00374 par = cpl_parameterlist_find_const(parlist, "kmos.kmos_reconstruct.oscan"); 00375 oscan = cpl_parameter_get_bool(par); 00376 00377 /* Check Parameters */ 00378 if (strcmp(imethod, "NN") && strcmp(imethod, "lwNN") && 00379 strcmp(imethod, "swNN") && strcmp(imethod, "MS") && 00380 strcmp(imethod, "CS")) { 00381 cpl_msg_error(__func__, 00382 "imethod must be 'NN','lwNN','swNN','MS' or 'CS'") ; 00383 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00384 return -1 ; 00385 } 00386 if (neighborhoodRange <= 0.0) { 00387 cpl_msg_error(__func__, 00388 "neighborhoodRange must be greater than 0.0") ; 00389 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00390 return -1 ; 00391 } 00392 if (pix_scale < 0.01 || pix_scale > 0.4) { 00393 cpl_msg_error(__func__, "pix_scale must be between 0.01 and 0.4"); 00394 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00395 return -1 ; 00396 } 00397 00398 /* Identify the RAW and CALIB frames in the input frameset */ 00399 if (kmo_dfs_set_groups(frameset, "kmos_reconstruct") != 1) { 00400 cpl_msg_error(__func__, "Cannot identify RAW and CALIB frames") ; 00401 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00402 return -1 ; 00403 } 00404 00405 /* IO File names */ 00406 if (cpl_frameset_count_tags(frameset, DARK) == 1) { 00407 input_frame_name = DARK; 00408 output_frame_name = CUBE_DARK; 00409 } else if (cpl_frameset_count_tags(frameset, FLAT_ON) == 1) { 00410 input_frame_name = FLAT_ON; 00411 output_frame_name = CUBE_FLAT; 00412 } else if (cpl_frameset_count_tags(frameset, ARC_ON) == 1) { 00413 input_frame_name = ARC_ON; 00414 output_frame_name = CUBE_ARC; 00415 } else if (cpl_frameset_count_tags(frameset, OBJECT) == 1) { 00416 input_frame_name = OBJECT; 00417 output_frame_name = CUBE_OBJECT; 00418 } else if (cpl_frameset_count_tags(frameset, STD) == 1) { 00419 input_frame_name = STD; 00420 output_frame_name = CUBE_STD; 00421 } else if (cpl_frameset_count_tags(frameset, SCIENCE) == 1) { 00422 input_frame_name = SCIENCE; 00423 output_frame_name = CUBE_SCIENCE; 00424 } else { 00425 cpl_msg_error(__func__, "Missing Inputs") ; 00426 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00427 return -1 ; 00428 } 00429 00430 /* Check the inputs consistency */ 00431 if (kmos_reconstruct_check_inputs(frameset, input_frame_name) != 1) { 00432 cpl_msg_error(__func__, "Input frameset is not consistent") ; 00433 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00434 return -1 ; 00435 } 00436 00437 /* Instrument setup */ 00438 input_frame = kmo_dfs_get_frame(frameset, input_frame_name); 00439 suffix = kmo_dfs_get_suffix(input_frame, TRUE, TRUE); 00440 cpl_msg_info(__func__, "Detected instrument setup: %s", suffix+1); 00441 cpl_free(suffix); 00442 00443 /* Get frames */ 00444 xcal_frame = kmo_dfs_get_frame(frameset, XCAL); 00445 ycal_frame = kmo_dfs_get_frame(frameset, YCAL) ; 00446 lcal_frame = kmo_dfs_get_frame(frameset, LCAL) ; 00447 ref_spectrum_frame = kmo_dfs_get_frame(frameset, OH_SPEC) ; 00448 00449 /* Get input frame primary header */ 00450 main_header = kmo_dfs_load_primary_header(frameset, input_frame_name); 00451 00452 /* Use the OBS ID in the file name */ 00453 if (file_extension) { 00454 obs_suffix = cpl_sprintf("_%d", 00455 cpl_propertylist_get_int(main_header, OBS_ID)); 00456 } else { 00457 obs_suffix = cpl_sprintf("%s", ""); 00458 } 00459 00460 /* Save Product (reconstructed) Main Header */ 00461 kmo_dfs_save_main_header(frameset, output_frame_name, obs_suffix, 00462 input_frame, NULL, parlist, cpl_func); 00463 00464 /* Save Product (detector image) Main Header */ 00465 if (detectorimage == TRUE) 00466 kmo_dfs_save_main_header(frameset, DET_IMG_REC, obs_suffix, 00467 input_frame, NULL, parlist, cpl_func); 00468 00469 /* Grid definition, wavelength start and end are set later */ 00470 kmclipm_setup_grid(&gd, imethod, neighborhoodRange, pix_scale, 0.); 00471 00472 /* READ Wavelength bounds */ 00473 tmp_header = kmo_dfs_load_primary_header(frameset, XCAL); 00474 bounds = kmclipm_extract_bounds(tmp_header); 00475 cpl_propertylist_delete(tmp_header); 00476 00477 kmo_init_fits_desc(&desc1); 00478 desc1 = kmo_identify_fits_header(cpl_frame_get_filename(input_frame)); 00479 00480 /* Loop through detectors */ 00481 for (i = 1; i <= KMOS_NR_DETECTORS; i++) { 00482 cpl_msg_info("","Processing detector No. %d", i); 00483 00484 /* Load LCAL image close to ROTANGLE 0. assuming that the */ 00485 /* wavelength range doesn't differ with different ROTANGLEs. */ 00486 print_cal_angle_msg_once = FALSE; 00487 print_xcal_angle_msg_once = FALSE; 00488 if (i==1) { 00489 print_cal_angle_msg_once = TRUE; 00490 print_xcal_angle_msg_once = TRUE; 00491 } 00492 00493 /* Read Filter ID */ 00494 keyword = cpl_sprintf("%s%d%s", IFU_FILTID_PREFIX,i,IFU_FILTID_POSTFIX); 00495 filter_id = cpl_propertylist_get_string(main_header, keyword); 00496 cpl_free(keyword); 00497 00498 /* Load Band Info */ 00499 band_table = kmo_dfs_load_table(frameset, WAVE_BAND, 1, FALSE); 00500 kmclipm_setup_grid_band_lcal(&gd, filter_id, band_table); 00501 cpl_table_delete(band_table); 00502 00503 /* Create empty detector images */ 00504 if (detectorimage == TRUE) { 00505 det_img_data = cpl_image_new( 00506 gd.x.dim*gd.y.dim*KMOS_IFUS_PER_DETECTOR, gd.l.dim, 00507 CPL_TYPE_FLOAT); 00508 pdet_img_data = cpl_image_get_data_float(det_img_data); 00509 00510 det_img_noise = cpl_image_new( 00511 gd.x.dim*gd.y.dim*KMOS_IFUS_PER_DETECTOR, gd.l.dim, 00512 CPL_TYPE_FLOAT); 00513 pdet_img_noise = cpl_image_get_data_float(det_img_noise); 00514 } 00515 00516 /* Loop on IFUs */ 00517 for (j = 0; j < KMOS_IFUS_PER_DETECTOR; j++) { 00518 ifu_nr = (i-1)*KMOS_IFUS_PER_DETECTOR + j + 1; 00519 00520 /* Load sub-header*/ 00521 sub_header = kmo_dfs_load_sub_header(frameset, input_frame_name, 00522 i, FALSE); 00523 00524 /* Check if IFU is valid according to main header keywords */ 00525 if (bounds[2*(ifu_nr-1)] != -1 && bounds[2*(ifu_nr-1)+1] != -1) { 00526 /* IFU valid */ 00527 00528 /* calc WCS & update subheader */ 00529 kmo_calc_wcs_gd(main_header, sub_header, ifu_nr, gd); 00530 kmclipm_update_property_int(sub_header, NAXIS, 3, 00531 "number of data axes"); 00532 kmclipm_update_property_int(sub_header, NAXIS1, 00533 gd.x.dim, "length of data axis 1"); 00534 kmclipm_update_property_int(sub_header, NAXIS2, 00535 gd.y.dim, "length of data axis 2"); 00536 kmclipm_update_property_int(sub_header, NAXIS3, 00537 gd.l.dim, "length of data axis 3"); 00538 00539 /* Reconstruct data and noise (if available) */ 00540 kmo_reconstruct_sci(ifu_nr, bounds[2*(ifu_nr-1)], 00541 bounds[2*(ifu_nr-1)+1], input_frame, input_frame_name, 00542 NULL, NULL, NULL, xcal_frame, ycal_frame, lcal_frame, 00543 NULL, NULL, &gd, &cube_data, &cube_noise, flux, 00544 0, xcal_interpolation, oscan); 00545 00546 /* Reconstruct again using OH_SPEC */ 00547 if (ref_spectrum_frame != NULL && cube_data != NULL) { 00548 lcorr_coeffs = kmo_lcorr_get(cube_data, sub_header, 00549 ref_spectrum_frame, gd, filter_id, ifu_nr); 00550 cpl_imagelist_delete(cube_data); 00551 if (cube_noise != NULL) cpl_imagelist_delete(cube_noise); 00552 kmo_reconstruct_sci(ifu_nr, bounds[2*(ifu_nr-1)], 00553 bounds[2*(ifu_nr-1)+1], input_frame, 00554 input_frame_name, NULL, NULL, NULL, xcal_frame, 00555 ycal_frame, lcal_frame, lcorr_coeffs, NULL, &gd, 00556 &cube_data, &cube_noise, flux, 0, 00557 xcal_interpolation, oscan); 00558 cpl_polynomial_delete(lcorr_coeffs); 00559 } 00560 00561 /* Scale flux according to pixel_scale */ 00562 tmp_img = cpl_imagelist_get(cube_data, 0); 00563 scaling = (cpl_image_get_size_x(tmp_img)* 00564 cpl_image_get_size_y(tmp_img)) / 00565 (KMOS_SLITLET_X*KMOS_SLITLET_Y); 00566 cpl_imagelist_divide_scalar(cube_data, scaling); 00567 if (cube_noise != NULL) 00568 cpl_imagelist_divide_scalar(cube_noise, scaling); 00569 } else { 00570 /* IFU invalid */ 00571 cube_data = cube_noise = NULL ; 00572 } 00573 00574 /* Fill detector images */ 00575 if (detectorimage) { 00576 if (cube_data != NULL) { 00577 for (l = 0; l < gd.l.dim; l++) { 00578 slice = cpl_image_get_data_float( 00579 cpl_imagelist_get(cube_data, l)); 00580 for (y = 0; y < gd.y.dim; y++) { 00581 for (x = 0; x < gd.x.dim; x++) { 00582 int ix = x + 00583 y* gd.x.dim + 00584 j* gd.x.dim*gd.y.dim + //IFU offset 00585 l* gd.x.dim*gd.y.dim*KMOS_IFUS_PER_DETECTOR; 00586 pdet_img_data[ix] = slice[x + y*gd.x.dim]; 00587 } 00588 } 00589 } 00590 } 00591 if (cube_noise != NULL) { 00592 detImgCube = TRUE; 00593 for (l = 0; l < gd.l.dim; l++) { 00594 slice = cpl_image_get_data_float( 00595 cpl_imagelist_get(cube_noise, l)); 00596 for (y = 0; y < gd.y.dim; y++) { 00597 for (x = 0; x < gd.x.dim; x++) { 00598 int ix = x + 00599 y* gd.x.dim + 00600 j* gd.x.dim*gd.y.dim + //IFU offset 00601 l* gd.x.dim*gd.y.dim*KMOS_IFUS_PER_DETECTOR; 00602 pdet_img_noise[ix] = slice[x + y*gd.x.dim]; 00603 } 00604 } 00605 } 00606 } 00607 } 00608 00609 /* Save Product (reconstructed) Data Cube */ 00610 extname = kmo_extname_creator(ifu_frame, ifu_nr, EXT_DATA); 00611 kmclipm_update_property_string(sub_header, EXTNAME, extname, 00612 "FITS extension name"); 00613 cpl_free(extname); 00614 kmo_dfs_save_cube(cube_data, output_frame_name, obs_suffix, 00615 sub_header, 0./0.); 00616 00617 /* Save Product (reconstructed) Noise Cube */ 00618 if (cube_noise != NULL) { 00619 extname = kmo_extname_creator(ifu_frame, ifu_nr, EXT_NOISE); 00620 kmclipm_update_property_string(sub_header, EXTNAME, 00621 extname, "FITS extension name"); 00622 cpl_free(extname); 00623 kmo_dfs_save_cube(cube_noise, output_frame_name, obs_suffix, 00624 sub_header, 0./0.); 00625 } 00626 00627 cpl_imagelist_delete(cube_data); 00628 if (cube_noise != NULL) cpl_imagelist_delete(cube_noise); 00629 cpl_propertylist_delete(sub_header); 00630 } // IFUs loop 00631 00632 if (detectorimage) { 00633 /* Save Product (detector image) Data Cube */ 00634 index = kmo_identify_index(cpl_frame_get_filename(input_frame), i, 00635 FALSE); 00636 tmp_header = kmclipm_propertylist_load( 00637 cpl_frame_get_filename(input_frame), index); 00638 kmo_save_det_img_ext(det_img_data, gd, i, DET_IMG_REC, 00639 obs_suffix, tmp_header, FALSE, FALSE); 00640 cpl_propertylist_delete(tmp_header); 00641 cpl_image_delete(det_img_data); 00642 00643 if (detImgCube) { 00644 /* Save Product (detector image) Noise Cube */ 00645 /* Index changes (*2) if Noise extensions are there */ 00646 if (desc1.ex_noise) { 00647 index = kmo_identify_index( 00648 cpl_frame_get_filename(input_frame), i, TRUE); 00649 } 00650 tmp_header = kmclipm_propertylist_load( 00651 cpl_frame_get_filename(input_frame), index); 00652 kmo_save_det_img_ext(det_img_noise, gd, i, DET_IMG_REC, 00653 obs_suffix, tmp_header, FALSE, TRUE); 00654 cpl_propertylist_delete(tmp_header); 00655 } 00656 cpl_image_delete(det_img_noise); 00657 } 00658 } // Detectors loop 00659 cpl_propertylist_delete(main_header); 00660 cpl_free(obs_suffix); 00661 kmo_free_fits_desc(&desc1); 00662 cpl_free(bounds); 00663 00664 return 0; 00665 } 00666 00669 /*----------------------------------------------------------------------------*/ 00676 /*----------------------------------------------------------------------------*/ 00677 static int kmos_reconstruct_check_inputs( 00678 cpl_frameset * frameset, 00679 const char * input_frame_name) 00680 { 00681 cpl_propertylist * lcal_header ; 00682 cpl_propertylist * input_header ; 00683 int nb_xcal, nb_ycal, nb_lcal, nb_oh_spec ; 00684 char * keyword ; 00685 const char * filter_id ; 00686 const char * filter_id_tmp ; 00687 int i ; 00688 00689 /* Check entries */ 00690 if (frameset == NULL || input_frame_name == NULL) return -1; 00691 00692 /* Count frames */ 00693 if (cpl_frameset_count_tags(frameset, DARK) != 1 && 00694 cpl_frameset_count_tags(frameset, FLAT_ON) != 1 && 00695 cpl_frameset_count_tags(frameset, ARC_ON) != 1 && 00696 cpl_frameset_count_tags(frameset, OBJECT) != 1 && 00697 cpl_frameset_count_tags(frameset, STD) != 1 && 00698 cpl_frameset_count_tags(frameset, SCIENCE) != 1) { 00699 cpl_msg_error(__func__, "1 data frame must be provided") ; 00700 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00701 return 0 ; 00702 } 00703 nb_xcal = cpl_frameset_count_tags(frameset, XCAL) ; 00704 nb_ycal = cpl_frameset_count_tags(frameset, YCAL) ; 00705 nb_lcal = cpl_frameset_count_tags(frameset, LCAL) ; 00706 if (nb_xcal != 1 || nb_ycal != 1 || nb_lcal != 1) { 00707 cpl_msg_error(__func__, "Exactly 1 XCAL/YCAL/LCAL expected") ; 00708 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00709 return 0 ; 00710 } 00711 if (cpl_frameset_count_tags(frameset, WAVE_BAND) != 1) { 00712 cpl_msg_error(__func__, "Missing WAVE_BAND") ; 00713 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00714 return 0 ; 00715 } 00716 nb_oh_spec = cpl_frameset_count_tags(frameset, OH_SPEC) ; 00717 if (nb_oh_spec != 0 && nb_oh_spec != 1) { 00718 cpl_msg_error(__func__, "Only 1 reference spectrum can be provided") ; 00719 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00720 return 0 ; 00721 } 00722 00723 /* Check filters, rotation consistencies */ 00724 kmo_check_frame_setup(frameset, XCAL, YCAL, TRUE, FALSE, TRUE); 00725 kmo_check_frame_setup(frameset, XCAL, LCAL, TRUE, FALSE, TRUE); 00726 if (nb_oh_spec == 1) kmo_check_oh_spec_setup(frameset, XCAL); 00727 00728 if (cpl_frameset_count_tags(frameset, DARK) != 1) { 00729 kmo_check_frame_setup(frameset, XCAL, input_frame_name, TRUE, FALSE, 00730 FALSE); 00731 } 00732 kmo_check_frame_setup_md5_xycal(frameset); 00733 kmo_check_frame_setup_md5(frameset); 00734 00735 /* Check filters */ 00736 input_header = kmo_dfs_load_primary_header(frameset, input_frame_name); 00737 lcal_header = kmo_dfs_load_primary_header(frameset, LCAL); 00738 for (i = 1; i <= KMOS_NR_DETECTORS; i++) { 00739 // ESO INS FILTi ID 00740 keyword = cpl_sprintf("%s%d%s", IFU_FILTID_PREFIX,i,IFU_FILTID_POSTFIX); 00741 filter_id = cpl_propertylist_get_string(lcal_header, keyword); 00742 if (strcmp(filter_id, "IZ") && strcmp(filter_id, "YJ") && 00743 strcmp(filter_id, "H") && strcmp(filter_id, "K") && 00744 strcmp(filter_id, "HK")) { 00745 cpl_free(keyword) ; 00746 cpl_propertylist_delete(input_header) ; 00747 cpl_propertylist_delete(lcal_header) ; 00748 cpl_msg_error(__func__,"LCAL Filter ID must be IZ, YJ, H, HK or K"); 00749 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00750 return 0 ; 00751 } 00752 00753 /* Dark not taken with filter */ 00754 if (!strcmp(input_frame_name, DARK)) { 00755 filter_id_tmp = cpl_propertylist_get_string(input_header, keyword); 00756 if (strcmp(filter_id, filter_id_tmp)) { 00757 cpl_free(keyword) ; 00758 cpl_propertylist_delete(input_header) ; 00759 cpl_propertylist_delete(lcal_header) ; 00760 cpl_msg_error(__func__,"Filter mismatch"); 00761 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00762 return 0 ; 00763 } 00764 } 00765 cpl_free(keyword); 00766 } 00767 cpl_propertylist_delete(input_header) ; 00768 cpl_propertylist_delete(lcal_header) ; 00769 00770 return 1 ; 00771 } 00772
1.7.6.1