|
KMOS Pipeline Reference Manual
1.3.10
|
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 "kmclipm_constants.h" 00034 #include "kmclipm_functions.h" 00035 00036 #include "kmo_debug.h" 00037 #include "kmo_constants.h" 00038 #include "kmo_cpl_extensions.h" 00039 #include "kmo_priv_lcorr.h" 00040 #include "kmo_utils.h" 00041 #include "kmo_error.h" 00042 #include "kmo_dfs.h" 00043 #include "kmo_functions.h" 00044 #include "kmo_priv_make_image.h" 00045 00046 #include "kmo_priv_arithmetic.h" 00047 #include "kmo_priv_combine.h" 00048 #include "kmo_priv_functions.h" 00049 #include "kmo_priv_reconstruct.h" 00050 #include "kmos_priv_sky_tweak.h" 00051 00052 /*----------------------------------------------------------------------------- 00053 * Functions prototypes 00054 *----------------------------------------------------------------------------*/ 00055 00056 static int kmos_sci_red_clean_plist(cpl_propertylist *) ; 00057 static int kmos_sci_red_collapse_cubes(char *, cpl_frameset *, 00058 cpl_parameterlist *, double, const char *, const char *, double, 00059 double, int, int, int) ; 00060 static int kmos_sci_red_check_inputs(cpl_frameset *, int *); 00061 00062 static int kmos_sci_red_create(cpl_plugin *); 00063 static int kmos_sci_red_exec(cpl_plugin *); 00064 static int kmos_sci_red_destroy(cpl_plugin *); 00065 static int kmos_sci_red(cpl_parameterlist *, cpl_frameset *); 00066 00067 /*----------------------------------------------------------------------------- 00068 * Static variables 00069 *----------------------------------------------------------------------------*/ 00070 00071 static char kmos_sci_red_description[] = 00072 "Two data frames are expected in order to have a sky IFU for the IFU Objects.\n" 00073 "If an OH spectrum is given in the SOF file the lambda axis will be corrected\n" 00074 "using the OH lines as reference.\n" 00075 "Every IFU containing an object will be reconstructed and divided by telluric\n" 00076 "and illumination correction. By default these intermediate cubes are saved\n" 00077 "to disk. The reconstructed objects with the same object name are combined.\n" 00078 "In order to combine a specific object, the parameters --name or --ifus can\n" 00079 "be used.\n" 00080 "For exposures taken with the templates KMOS_spec_obs_mapping8 and\n" 00081 "KMOS_spec_obs_mapping24, all active IFUs are combined.\n" 00082 "\n" 00083 "--------------------------------------------------------------------------\n" 00084 " Input files:\n" 00085 "\n" 00086 " DO KMOS \n" 00087 " category Type Explanation Required #Frames\n" 00088 " -------- ----- ----------- -------- -------\n" 00089 " SCIENCE RAW The science frames Y >=1 \n" 00090 " XCAL F2D x calibration frame Y 1 \n" 00091 " YCAL F2D y calibration frame Y 1 \n" 00092 " LCAL F2D Wavelength calib. frame Y 1 \n" 00093 " WAVE_BAND F2L Table with start-/end-wavelengths Y 1 \n" 00094 " MASTER_FLAT F2D Master flat Y 0,1 \n" 00095 " ILLUM_CORR F2I Illumination correction N 0,1 \n" 00096 " TELLURIC F1I normalised telluric spectrum N 0,1 \n" 00097 " OH_SPEC F1S Vector holding OH lines N 0,1 \n" 00098 "\n" 00099 " Output files:\n" 00100 "\n" 00101 " DO KMOS\n" 00102 " category Type Explanation\n" 00103 " -------- ----- -----------\n" 00104 " SCI_COMBINED F3I Combined cubes with noise\n" 00105 " SCI_RECONSTRUCTED F3I Reconstructed cube with noise\n" 00106 " EXP_MASK F3I Exposure time mask (not for mapping-templates!)\n" 00107 " SCI_INTERIM_OBJECT F3I (optional) Intermediate reconstructed object \n" 00108 " cubes used for sky tweaking, no noise \n" 00109 " (set --sky_tweak and --save_interims)\n" 00110 " SCI_INTERIM_SKY F3I (optional) Intermediate reconstructed sky \n" 00111 " cubes used for sky tweaking, no noise\n" 00112 " (set --sky_tweak and --save_interims)\n" 00113 " SCI_COMBINED_COLL (optional) Collapsed combined cube\n" 00114 " (set --collapse_combined)\n" 00115 " SCI_RECONSTRUCTED_COLL (optional) Collapsed reconstructed cube\n" 00116 " (set --collapse_reconstructed)\n" 00117 "--------------------------------------------------------------------------\n" 00118 "\n"; 00119 00120 /*----------------------------------------------------------------------------- 00121 * Functions code 00122 *----------------------------------------------------------------------------*/ 00123 00124 /*----------------------------------------------------------------------------*/ 00129 /*----------------------------------------------------------------------------*/ 00130 00133 /*----------------------------------------------------------------------------*/ 00142 /*----------------------------------------------------------------------------*/ 00143 int cpl_plugin_get_info(cpl_pluginlist *list) 00144 { 00145 cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe); 00146 cpl_plugin *plugin = &recipe->interface; 00147 00148 cpl_plugin_init(plugin, 00149 CPL_PLUGIN_API, 00150 KMOS_BINARY_VERSION, 00151 CPL_PLUGIN_TYPE_RECIPE, 00152 "kmos_sci_red", 00153 "Reconstruct obj/sky-pairs individually and combine " 00154 "them afterwards", 00155 kmos_sci_red_description, 00156 "Alex Agudo Berbel, Yves Jung", 00157 "usd-help@eso.org", 00158 kmos_get_license(), 00159 kmos_sci_red_create, 00160 kmos_sci_red_exec, 00161 kmos_sci_red_destroy); 00162 00163 cpl_pluginlist_append(list, plugin); 00164 00165 return 0; 00166 } 00167 00168 /*----------------------------------------------------------------------------*/ 00176 /*----------------------------------------------------------------------------*/ 00177 static int kmos_sci_red_create(cpl_plugin *plugin) 00178 { 00179 cpl_recipe *recipe; 00180 cpl_parameter *p; 00181 00182 /* Check that the plugin is part of a valid recipe */ 00183 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00184 recipe = (cpl_recipe *)plugin; 00185 else 00186 return -1; 00187 00188 /* Create the parameters list in the cpl_recipe object */ 00189 recipe->parameters = cpl_parameterlist_new(); 00190 00191 /* --imethod (interpolation method) */ 00192 p = cpl_parameter_new_value("kmos.kmos_sci_red.imethod", CPL_TYPE_STRING, 00193 "Method to use for interpolation during reconstruction. " 00194 "[\"NN\" (nearest neighbour), " 00195 "\"lwNN\" (linear weighted nearest neighbor), " 00196 "\"swNN\" (square weighted nearest neighbor), " 00197 "\"MS\" (Modified Shepard's method)" 00198 "\"CS\" (Cubic spline)]", 00199 "kmos.kmos_sci_red", "CS"); 00200 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "imethod"); 00201 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00202 cpl_parameterlist_append(recipe->parameters, p); 00203 00204 /* --smethod (shift interpolation method) */ 00205 p = cpl_parameter_new_value("kmos.kmos_sci_red.smethod", CPL_TYPE_STRING, 00206 "Method to use for interpolation during shifting. " 00207 "[\"NN\" (nearest neighbour), " 00208 "\"CS\" (Cubic spline)]", 00209 "kmos.kmos_sci_red", "CS"); 00210 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "smethod"); 00211 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00212 cpl_parameterlist_append(recipe->parameters, p); 00213 00214 /* --method (shift method) */ 00215 p = cpl_parameter_new_value("kmos.kmos_sci_red.method", CPL_TYPE_STRING, 00216 "The shifting method: " 00217 "'none': no shifting, combined directly, " 00218 "'header': shift according to WCS (default), " 00219 "'center': centering algorithm, " 00220 "'user': read shifts from file", 00221 "kmos.kmos_sci_red", "header"); 00222 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "method"); 00223 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00224 cpl_parameterlist_append(recipe->parameters, p); 00225 00226 /* --fmethod */ 00227 p = cpl_parameter_new_value("kmos.kmos_sci_red.fmethod", CPL_TYPE_STRING, 00228 "The fitting method (applies only when method='center'): " 00229 "'gauss': fit a gauss function to collapsed image (default), " 00230 "'moffat': fit a moffat function to collapsed image", 00231 "kmos.kmos_sci_red", "gauss"); 00232 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "fmethod"); 00233 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00234 cpl_parameterlist_append(recipe->parameters, p); 00235 00236 /* --name */ 00237 p = cpl_parameter_new_value("kmos.kmos_sci_red.name", CPL_TYPE_STRING, 00238 "Name of the object to combine.", "kmos.kmos_sci_red", ""); 00239 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "name"); 00240 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00241 cpl_parameterlist_append(recipe->parameters, p); 00242 00243 /* --ifus */ 00244 p = cpl_parameter_new_value("kmos.kmos_sci_red.ifus", CPL_TYPE_STRING, 00245 "The indices of the IFUs to combine. \"ifu1;ifu2;...\"", 00246 "kmos.kmos_sci_red", ""); 00247 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "ifus"); 00248 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00249 cpl_parameterlist_append(recipe->parameters, p); 00250 00251 /* --pix_scale */ 00252 p = cpl_parameter_new_value("kmos.kmos_sci_red.pix_scale", CPL_TYPE_DOUBLE, 00253 "Change the pixel scale [arcsec]. " 00254 "Default of 0.2\" results into cubes of 14x14pix, " 00255 "a scale of 0.1\" results into cubes of 28x28pix, etc.", 00256 "kmos.kmos_sci_red", KMOS_PIX_RESOLUTION); 00257 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "pix_scale"); 00258 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00259 cpl_parameterlist_append(recipe->parameters, p); 00260 00261 /* --suppress_extension */ 00262 p = cpl_parameter_new_value("kmos.kmos_sci_red.suppress_extension", 00263 CPL_TYPE_BOOL, 00264 "Suppress arbitrary filename extension." 00265 "(TRUE (apply) or FALSE (don't apply)", 00266 "kmos.kmos_sci_red", FALSE); 00267 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "suppress_extension"); 00268 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00269 cpl_parameterlist_append(recipe->parameters, p); 00270 00271 /* --neighborhoodRange */ 00272 p = cpl_parameter_new_value("kmos.kmos_sci_red.neighborhoodRange", 00273 CPL_TYPE_DOUBLE, 00274 "Defines the range to search for neighbors in pixels", 00275 "kmos.kmos_sci_red", 1.001); 00276 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "neighborhoodRange"); 00277 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00278 cpl_parameterlist_append(recipe->parameters, p); 00279 00280 /* --filename */ 00281 p = cpl_parameter_new_value("kmos.kmos_sci_red.filename", CPL_TYPE_STRING, 00282 "The path to the file with the shift vectors." 00283 "(Applies only to method='user')", 00284 "kmos.kmos_sci_red", ""); 00285 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "filename"); 00286 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00287 cpl_parameterlist_append(recipe->parameters, p); 00288 00289 /* --flux */ 00290 p = cpl_parameter_new_value("kmos.kmos_sci_red.flux", CPL_TYPE_BOOL, 00291 "TRUE: Apply flux conservation. FALSE: otherwise", 00292 "kmos.kmos_sci_red", FALSE); 00293 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "flux"); 00294 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00295 cpl_parameterlist_append(recipe->parameters, p); 00296 00297 /* --background */ 00298 p = cpl_parameter_new_value("kmos.kmos_sci_red.background", CPL_TYPE_BOOL, 00299 "TRUE: Apply background removal. FALSE: otherwise", 00300 "kmos.kmos_sci_red", FALSE); 00301 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "background"); 00302 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00303 cpl_parameterlist_append(recipe->parameters, p); 00304 00305 /* --fast_mode */ 00306 p = cpl_parameter_new_value("kmos.kmos_sci_red.fast_mode", CPL_TYPE_BOOL, 00307 "FALSE: cubes are shifted and combined," 00308 "TRUE: cubes are collapsed and then shifted and combined", 00309 "kmos.kmos_sci_red", FALSE); 00310 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "fast_mode"); 00311 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00312 cpl_parameterlist_append(recipe->parameters, p); 00313 00314 /* --extrapolate */ 00315 p = cpl_parameter_new_value("kmos.kmos_sci_red.extrapolate", CPL_TYPE_BOOL, 00316 "Applies only to 'smethod=CS' when doing sub-pixel shifts: " 00317 "FALSE: shifted IFU will be filled with NaN's at the borders," 00318 "TRUE: shifted IFU will be extrapolated at the borders", 00319 "kmos.kmos_sci_red", FALSE); 00320 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "extrapolate"); 00321 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00322 cpl_parameterlist_append(recipe->parameters, p); 00323 00324 /* --xcal_interpolation */ 00325 p = cpl_parameter_new_value("kmos.kmos_sci_red.xcal_interpolation", 00326 CPL_TYPE_BOOL, 00327 "TRUE: Interpolate xcal between rotator angles. FALSE: otherwise", 00328 "kmos.kmos_sci_red", TRUE); 00329 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "xcal_interpolation"); 00330 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00331 cpl_parameterlist_append(recipe->parameters, p); 00332 00333 /* --edge_nan */ 00334 p = cpl_parameter_new_value("kmos.kmos_sci_red.edge_nan", CPL_TYPE_BOOL, 00335 "Set borders of cubes to NaN before combining them." 00336 "(TRUE (apply) or FALSE (don't apply)", 00337 "kmos.kmos_sci_red", FALSE); 00338 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "edge_nan"); 00339 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00340 cpl_parameterlist_append(recipe->parameters, p); 00341 00342 /* --no_combine */ 00343 p = cpl_parameter_new_value("kmos.kmos_sci_red.no_combine", CPL_TYPE_BOOL, 00344 "Don't combine cubes after reconstruction." 00345 "(TRUE (apply) or FALSE (don't apply)", 00346 "kmos.kmos_sci_red", FALSE); 00347 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "no_combine"); 00348 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00349 cpl_parameterlist_append(recipe->parameters, p); 00350 00351 /* --no_subtract */ 00352 p = cpl_parameter_new_value("kmos.kmos_sci_red.no_subtract", CPL_TYPE_BOOL, 00353 "Don't sky subtract object and references." 00354 "(TRUE (apply) or FALSE (don't apply)", 00355 "kmos.kmos_sci_red", FALSE); 00356 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "no_subtract"); 00357 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00358 cpl_parameterlist_append(recipe->parameters, p); 00359 00360 /* --sky_tweak */ 00361 p = cpl_parameter_new_value("kmos.kmos_sci_red.sky_tweak", CPL_TYPE_BOOL, 00362 "Use modified sky cube for sky subtraction." 00363 "(TRUE (apply) or FALSE (don't apply)", 00364 "kmos.kmos_sci_red", FALSE); 00365 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "sky_tweak"); 00366 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00367 cpl_parameterlist_append(recipe->parameters, p); 00368 00369 /* --tbsub */ 00370 p = cpl_parameter_new_value("kmos.kmos_sci_red.tbsub", CPL_TYPE_BOOL, 00371 "Subtract thermal background from input cube." 00372 "(TRUE (apply) or FALSE (don't apply)", 00373 "kmos.kmos_sci_red", TRUE); 00374 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "tbsub"); 00375 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00376 cpl_parameterlist_append(recipe->parameters, p); 00377 00378 // add parameters for band-definition 00379 kmos_band_pars_create(recipe->parameters, "kmos.kmos_sci_red"); 00380 00381 /* --obj_sky_table */ 00382 p = cpl_parameter_new_value("kmos.kmos_sci_red.obj_sky_table", 00383 CPL_TYPE_STRING, 00384 "The path to the file with the modified obj/sky associations.", 00385 "kmos.kmos_sci_red", ""); 00386 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "obj_sky_table"); 00387 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00388 cpl_parameterlist_append(recipe->parameters, p); 00389 00390 /* --velocity_offset */ 00391 p = cpl_parameter_new_value("kmos.kmos_sci_red.velocity_offset", 00392 CPL_TYPE_DOUBLE, 00393 "Specify velocity offset correction in km/s for lambda scale", 00394 "kmos.kmos_sci_red", 0.0); 00395 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "velocity_offset"); 00396 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00397 cpl_parameterlist_append(recipe->parameters, p); 00398 00399 /* --save_interims */ 00400 p=cpl_parameter_new_value("kmos.kmos_sci_red.save_interims", CPL_TYPE_BOOL, 00401 "Save interim object and sky cubes. " 00402 "Can only be used together with --sky_tweak", 00403 "kmos.kmos_sci_red", FALSE); 00404 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "save_interims"); 00405 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00406 cpl_parameterlist_append(recipe->parameters, p); 00407 00408 /* --collapse_reconstructed */ 00409 p = cpl_parameter_new_value("kmos.kmos_sci_red.collapse_reconstructed", 00410 CPL_TYPE_BOOL, "Flag to collapse the reconstructed images", 00411 "kmos.kmos_sci_red", FALSE); 00412 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,"collapse_reconstructed"); 00413 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00414 cpl_parameterlist_append(recipe->parameters, p); 00415 00416 /* --collapse_combined */ 00417 p = cpl_parameter_new_value("kmos.kmos_sci_red.collapse_combined", 00418 CPL_TYPE_BOOL, "Flag to collapse the combined images", 00419 "kmos.kmos_sci_red", FALSE); 00420 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "collapse_combined"); 00421 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00422 cpl_parameterlist_append(recipe->parameters, p); 00423 00424 return kmos_combine_pars_create(recipe->parameters, "kmos.kmos_sci_red", 00425 DEF_REJ_METHOD, FALSE); 00426 } 00427 00428 /*----------------------------------------------------------------------------*/ 00434 /*----------------------------------------------------------------------------*/ 00435 static int kmos_sci_red_exec(cpl_plugin *plugin) 00436 { 00437 cpl_recipe *recipe; 00438 00439 /* Get the recipe out of the plugin */ 00440 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00441 recipe = (cpl_recipe *)plugin; 00442 else return -1 ; 00443 00444 return kmos_sci_red(recipe->parameters, recipe->frames); 00445 } 00446 00447 /*----------------------------------------------------------------------------*/ 00453 /*----------------------------------------------------------------------------*/ 00454 static int kmos_sci_red_destroy(cpl_plugin *plugin) 00455 { 00456 cpl_recipe *recipe; 00457 00458 /* Get the recipe out of the plugin */ 00459 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00460 recipe = (cpl_recipe *)plugin; 00461 else return -1 ; 00462 00463 cpl_parameterlist_delete(recipe->parameters); 00464 return 0 ; 00465 } 00466 00467 /*----------------------------------------------------------------------------*/ 00480 /*----------------------------------------------------------------------------*/ 00481 static int kmos_sci_red(cpl_parameterlist * parlist, cpl_frameset * frameset) 00482 { 00483 const cpl_parameter * par ; 00484 /*********************/ 00485 /* Parsed Parameters */ 00486 int flux, background, extrapolate, fast_mode, edge_nan, no_combine, 00487 no_subtract, sky_tweak, tbsub, xcal_interpolation, suppress_extension, 00488 save_interims, citer, cmin, cmax, collapse_combined, 00489 collapse_reconstructed ; 00490 double neighborhoodRange, pix_scale, cpos_rej, cneg_rej, 00491 velo_offset, velo_corr ; 00492 double * velo_corr_ptr ; 00493 const char * imethod, * smethod, * cmethod, * comb_method, * fmethod, 00494 * filename, * ifus_txt, * name, * fn_obj_sky_table, * fn_reconstr ; 00495 /*********************/ 00496 00497 double scaling ; 00498 int print_once, cube_counter_data, cube_counter_noise, do_sky_subtraction, 00499 suppress_index, mapping_id, nb_science, nb_telluric, nb_illum_corr, 00500 telluric_ok, actual_msg_level, nr_data ; 00501 int i, j, jj, sf, ifu_nr, sky_ifu_nr, det_nr ; 00502 char * suffix ; 00503 char * mapping_mode ; 00504 char * extname ; 00505 char * keyword ; 00506 char ** split ; 00507 char * fn_suffix ; 00508 const char * tmp_str ; 00509 const char * fn_obj ; 00510 const char * filter_id ; 00511 const char * fn_out ; 00512 00513 /*****************************/ 00514 /* TO BE CHECKED AND REMOVED */ 00515 enum kmo_frame_type ft ; 00516 char content[256]; 00517 main_fits_desc desc_telluric, desc1 ; 00518 int tmp_int, idx ; 00519 /*****************************/ 00520 00521 enum extrapolationType extrapol_enum ; 00522 cpl_propertylist * header_tmp ; 00523 cpl_propertylist * main_header ; 00524 int * bounds ; 00525 gridDefinition gd ; 00526 armNameStruct * arm_name_struct ; 00527 00528 cpl_polynomial * oh_lcorr_coeffs ; 00529 cpl_vector * ifus ; 00530 cpl_array ** unused_ifus_before ; 00531 cpl_array ** unused_ifus_after ; 00532 cpl_frame * sky_frame ; 00533 cpl_frame * sky_as_object_frame ; 00534 cpl_frame * ref_spectrum_frame ; 00535 cpl_frame * xcal_frame ; 00536 cpl_frame * ycal_frame ; 00537 cpl_frame * lcal_frame ; 00538 cpl_frame * flat_frame ; 00539 cpl_frame * telluric_frame ; 00540 cpl_frame * tmp_frame ; 00541 00542 cpl_table * band_table ; 00543 00544 cpl_imagelist * combined_data ; 00545 cpl_imagelist * combined_noise ; 00546 cpl_imagelist * tmp_cube1 ; 00547 cpl_imagelist * tmp_cube2 ; 00548 00549 cpl_image * tmpImg ; 00550 cpl_image * exp_mask ; 00551 cpl_image * illum_data ; 00552 cpl_image * illum_noise ; 00553 00554 cpl_imagelist ** cube_data ; 00555 cpl_imagelist ** cube_noise ; 00556 cpl_imagelist ** cube_interim_object ; 00557 cpl_imagelist ** cube_interim_sky ; 00558 00559 cpl_propertylist ** header_data ; 00560 cpl_propertylist ** header_noise ; 00561 cpl_propertylist ** header_sky ; 00562 00563 kmclipm_vector * telluric_data ; 00564 kmclipm_vector * telluric_noise ; 00565 00566 /* Initialise */ 00567 print_once = FALSE ; 00568 cube_counter_data = cube_counter_noise = 0 ; 00569 do_sky_subtraction = FALSE ; 00570 suppress_index = 0 ; 00571 mapping_id = -1 ; 00572 combined_data = combined_noise = NULL ; 00573 00574 /* Check entries */ 00575 if (parlist == NULL || frameset == NULL) { 00576 cpl_msg_error(__func__, "Null Inputs") ; 00577 cpl_error_set(__func__, CPL_ERROR_NULL_INPUT) ; 00578 return -1 ; 00579 } 00580 00581 /* Get parameters */ 00582 par = cpl_parameterlist_find_const(parlist, "kmos.kmos_sci_red.flux"); 00583 flux = cpl_parameter_get_bool(par); 00584 par = cpl_parameterlist_find_const(parlist, "kmos.kmos_sci_red.background"); 00585 background = cpl_parameter_get_bool(par); 00586 par = cpl_parameterlist_find_const(parlist, "kmos.kmos_sci_red.imethod"); 00587 imethod = cpl_parameter_get_string(par) ; 00588 par = cpl_parameterlist_find_const(parlist, "kmos.kmos_sci_red.smethod"); 00589 smethod = cpl_parameter_get_string(par) ; 00590 par = cpl_parameterlist_find_const(parlist, 00591 "kmos.kmos_sci_red.neighborhoodRange"); 00592 neighborhoodRange = cpl_parameter_get_double(par) ; 00593 par = cpl_parameterlist_find_const(parlist, "kmos.kmos_sci_red.method"); 00594 comb_method = cpl_parameter_get_string(par) ; 00595 par = cpl_parameterlist_find_const(parlist, "kmos.kmos_sci_red.fmethod"); 00596 fmethod = cpl_parameter_get_string(par) ; 00597 par = cpl_parameterlist_find_const(parlist, "kmos.kmos_sci_red.filename"); 00598 filename = cpl_parameter_get_string(par) ; 00599 par = cpl_parameterlist_find_const(parlist, "kmos.kmos_sci_red.ifus"); 00600 ifus_txt = cpl_parameter_get_string(par) ; 00601 par = cpl_parameterlist_find_const(parlist, "kmos.kmos_sci_red.name"); 00602 name = cpl_parameter_get_string(par) ; 00603 kmos_band_pars_load(parlist, "kmos.kmos_sci_red"); 00604 par = cpl_parameterlist_find_const(parlist,"kmos.kmos_sci_red.extrapolate"); 00605 extrapolate = cpl_parameter_get_bool(par); 00606 par = cpl_parameterlist_find_const(parlist,"kmos.kmos_sci_red.fast_mode"); 00607 fast_mode = cpl_parameter_get_bool(par); 00608 par = cpl_parameterlist_find_const(parlist,"kmos.kmos_sci_red.edge_nan"); 00609 edge_nan = cpl_parameter_get_bool(par); 00610 par = cpl_parameterlist_find_const(parlist,"kmos.kmos_sci_red.no_combine"); 00611 no_combine = cpl_parameter_get_bool(par); 00612 par = cpl_parameterlist_find_const(parlist,"kmos.kmos_sci_red.no_subtract"); 00613 no_subtract = cpl_parameter_get_bool(par); 00614 par = cpl_parameterlist_find_const(parlist,"kmos.kmos_sci_red.sky_tweak"); 00615 sky_tweak = cpl_parameter_get_bool(par); 00616 par = cpl_parameterlist_find_const(parlist,"kmos.kmos_sci_red.tbsub"); 00617 tbsub = cpl_parameter_get_bool(par); 00618 par = cpl_parameterlist_find_const(parlist, "kmos.kmos_sci_red.pix_scale"); 00619 pix_scale = cpl_parameter_get_double(par) ; 00620 par = cpl_parameterlist_find_const(parlist, 00621 "kmos.kmos_sci_red.xcal_interpolation"); 00622 xcal_interpolation = cpl_parameter_get_bool(par); 00623 par = cpl_parameterlist_find_const(parlist, 00624 "kmos.kmos_sci_red.suppress_extension"); 00625 suppress_extension = cpl_parameter_get_bool(par); 00626 par = cpl_parameterlist_find_const(parlist, 00627 "kmos.kmos_sci_red.obj_sky_table"); 00628 fn_obj_sky_table = cpl_parameter_get_string(par) ; 00629 kmos_combine_pars_load(parlist, "kmos.kmos_sci_red", &cmethod, &cpos_rej, 00630 &cneg_rej, &citer, &cmin, &cmax, FALSE); 00631 par = cpl_parameterlist_find_const(parlist, 00632 "kmos.kmos_sci_red.velocity_offset"); 00633 velo_offset = cpl_parameter_get_double(par) ; 00634 velo_corr = 1. + velo_offset * 1000. / CPL_PHYS_C; 00635 velo_corr_ptr = &velo_corr; 00636 par = cpl_parameterlist_find_const(parlist, 00637 "kmos.kmos_sci_red.save_interims"); 00638 save_interims = cpl_parameter_get_bool(par); 00639 par = cpl_parameterlist_find_const(parlist, 00640 "kmos.kmos_sci_red.collapse_combined"); 00641 collapse_combined = cpl_parameter_get_bool(par); 00642 par = cpl_parameterlist_find_const(parlist, 00643 "kmos.kmos_sci_red.collapse_reconstructed"); 00644 collapse_reconstructed = cpl_parameter_get_bool(par); 00645 00646 /* Check Parameters */ 00647 if (strcmp(imethod, "NN") && strcmp(imethod, "lwNN") && 00648 strcmp(imethod, "swNN") && strcmp(imethod, "MS") && 00649 strcmp(imethod, "CS")) { 00650 cpl_msg_error(__func__, 00651 "imethod must be 'NN','lwNN','swNN','MS' or 'CS'") ; 00652 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00653 return -1 ; 00654 } 00655 if (strcmp(smethod, "NN") && strcmp(smethod, "CS")) { 00656 cpl_msg_error(__func__, 00657 "smethod must be 'NN' or 'CS'") ; 00658 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00659 return -1 ; 00660 } 00661 if (neighborhoodRange <= 0.0) { 00662 cpl_msg_error(__func__, 00663 "neighborhoodRange must be greater than 0.0") ; 00664 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00665 return -1 ; 00666 } 00667 if (strcmp(comb_method, "none") && strcmp(comb_method, "header") && 00668 strcmp(comb_method, "center") && strcmp(comb_method, "user")) { 00669 cpl_msg_error(__func__, 00670 "shift methods must be 'none', 'header', 'center' or 'user'") ; 00671 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00672 return -1 ; 00673 } 00674 if (strcmp(ifus_txt, "") && strcmp(name, "")) { 00675 cpl_msg_error(__func__, 00676 "name and IFU indices cannot be both provided") ; 00677 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00678 return -1 ; 00679 } 00680 if (strcmp(smethod, "NN") && strcmp(smethod, "CS")) { 00681 cpl_msg_error(__func__, "smethod must be 'NN' or 'CS'") ; 00682 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00683 return -1 ; 00684 } 00685 if (!strcmp(smethod, "NN") && extrapolate == TRUE) { 00686 cpl_msg_error(__func__, 00687 "extrapolation in not compatible with smethod 'NN'"); 00688 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00689 return -1 ; 00690 } 00691 if (!strcmp(smethod, "CS")) smethod = "BCS"; 00692 if (!strcmp(smethod, "BCS") && extrapolate == TRUE) 00693 extrapol_enum = BCS_NATURAL; 00694 else 00695 extrapol_enum = NONE_NANS; 00696 00697 if (no_subtract && sky_tweak) { 00698 cpl_msg_error(__func__,"no_subtract and sky_tweak cannot be both TRUE"); 00699 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00700 return -1 ; 00701 } 00702 if (pix_scale < 0.01 || pix_scale > 0.4) { 00703 cpl_msg_error(__func__, "pix_scale must be between 0.01 and 0.4"); 00704 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00705 return -1 ; 00706 } 00707 00708 if (cpl_frameset_count_tags(frameset, SCIENCE) == 1 || no_subtract) { 00709 no_combine = TRUE; 00710 cpl_msg_info(__func__, 00711 "--no_combine set to TRUE (1 SCIENCE frame or --no_subtract"); 00712 } 00713 00714 00715 /* Identify the RAW and CALIB frames in the input frameset */ 00716 if (kmo_dfs_set_groups(frameset, "kmos_sci_red") != 1) { 00717 cpl_msg_error(__func__, "Cannot identify RAW and CALIB frames") ; 00718 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00719 return -1 ; 00720 } 00721 00722 /* Check the inputs consistency */ 00723 if (kmos_sci_red_check_inputs(frameset, &mapping_id) != 1) { 00724 cpl_msg_error(__func__, "Input frameset is not consistent") ; 00725 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00726 return -1 ; 00727 } 00728 if (mapping_id == 0) mapping_mode = NULL ; 00729 if (mapping_id == 1) mapping_mode = "mapping8" ; 00730 if (mapping_id == 2) mapping_mode = "mapping24" ; 00731 00732 /* Instrument setup */ 00733 suffix = kmo_dfs_get_suffix(kmo_dfs_get_frame(frameset,SCIENCE),TRUE,FALSE); 00734 cpl_msg_info(__func__, "Detected instrument setup: %s", suffix+1); 00735 cpl_free(suffix); 00736 00737 /* Load IFUS if specified */ 00738 if (strcmp(ifus_txt, "")) { 00739 nb_science = cpl_frameset_count_tags(frameset, SCIENCE); 00740 ifus = kmo_identify_values(ifus_txt); 00741 if (ifus == NULL || cpl_vector_get_size(ifus) != nb_science) { 00742 if (ifus != NULL) cpl_vector_delete(ifus); 00743 cpl_msg_error(__func__, "ifus size must match the science frames") ; 00744 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00745 return -1 ; 00746 } 00747 } else { 00748 ifus = NULL ; 00749 } 00750 00751 /* Mapping mode */ 00752 if (mapping_id > 0) { 00753 if ((ifus != NULL) || (strcmp(name, ""))) { 00754 cpl_msg_warning(__func__,"Mapping Mode ٍ+ Specific IFUs requested") ; 00755 } else { 00756 if (!strcmp(smethod, "BCS")) { 00757 extrapol_enum = BCS_NATURAL; 00758 cpl_msg_info(__func__, "Mapping Mode : extrapolation set") ; 00759 } 00760 } 00761 } 00762 00763 /* Check which IFUs are active for all frames */ 00764 unused_ifus_before = kmo_get_unused_ifus(frameset, 1, 1); 00765 unused_ifus_after = kmo_duplicate_unused_ifus(unused_ifus_before); 00766 kmo_print_unused_ifus(unused_ifus_before, FALSE); 00767 kmo_free_unused_ifus(unused_ifus_before); 00768 00769 /* Setup grid definition, wavelength start and end are set later */ 00770 kmclipm_setup_grid(&gd, imethod, neighborhoodRange, pix_scale, 0.); 00771 00772 /* Get frames */ 00773 xcal_frame = kmo_dfs_get_frame(frameset, XCAL) ; 00774 ycal_frame = kmo_dfs_get_frame(frameset, YCAL) ; 00775 lcal_frame = kmo_dfs_get_frame(frameset, LCAL) ; 00776 flat_frame = kmo_dfs_get_frame(frameset, MASTER_FLAT) ; 00777 ref_spectrum_frame = kmo_dfs_get_frame(frameset, OH_SPEC) ; 00778 00779 /* Get left and right bounds of IFUs from XCAL */ 00780 header_tmp = kmo_dfs_load_primary_header(frameset, XCAL); 00781 bounds = kmclipm_extract_bounds(header_tmp); 00782 cpl_propertylist_delete(header_tmp); 00783 if (bounds == NULL) { 00784 if (ifus != NULL) cpl_vector_delete(ifus); 00785 kmo_free_unused_ifus(unused_ifus_after); 00786 cpl_msg_error(__func__, "Cannot compute bounds") ; 00787 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00788 return -1 ; 00789 } 00790 00791 /* armNameStruct: objects that need to be reconstructed and their 00792 associated sky. Valid STD frames with objects and associated sky. 00793 Get valid object names, either one object name in several frames, 00794 or all object names */ 00795 if (!strcmp(fn_obj_sky_table, "")) { 00796 arm_name_struct = kmo_create_armNameStruct(frameset, SCIENCE, ifus, 00797 name, unused_ifus_after, bounds, mapping_mode, no_subtract); 00798 /* TODO : need to save ?? */ 00799 kmo_save_objSkyStruct(arm_name_struct->obj_sky_struct); 00800 } else { 00801 // read in obj/sky-table 00802 objSkyStruct *obj_sky_struct = NULL; 00803 obj_sky_struct = kmo_read_objSkyStruct(fn_obj_sky_table, frameset, 00804 SCIENCE); 00805 00806 /* Check if any sky-IFUs have been specified not beeing the */ 00807 /* same IFU# for objects. */ 00808 // In this case sky_tweak must be activated 00809 for (i = 0; i < obj_sky_struct->size; i++) { 00810 if (obj_sky_struct->table[i].objFrame != NULL) { 00811 for (j = 0; j < KMOS_NR_IFUS; j++) { 00812 if ((obj_sky_struct->table[i].skyIfus[j] > 0) && 00813 (sky_tweak == FALSE)) { 00814 kmo_print_objSkyStruct(obj_sky_struct); 00815 kmo_delete_objSkyStruct(obj_sky_struct); 00816 cpl_msg_error(__func__, 00817 "--sky_tweak needs to be set when sky are used from other IFUs"); 00818 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00819 return -1 ; 00820 } 00821 } 00822 } 00823 } 00824 arm_name_struct = kmo_create_armNameStruct2(obj_sky_struct, frameset, 00825 SCIENCE, ifus, name, unused_ifus_after, bounds, mapping_mode, 00826 no_subtract); 00827 } 00828 if (ifus != NULL) cpl_vector_delete(ifus); 00829 if (arm_name_struct == NULL) { 00830 kmo_free_unused_ifus(unused_ifus_after); 00831 cpl_free(bounds); 00832 cpl_msg_error(__func__, "Cannot compute ARM/name structure") ; 00833 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00834 return -1 ; 00835 } 00836 kmo_print_armNameStruct(frameset, arm_name_struct); 00837 00838 /* Check Telluric availability for each Object */ 00839 /* in mapping-mode check if for all IFUs there is either no */ 00840 /* telluric at all or the same number of tellurics than object names */ 00841 nb_telluric = cpl_frameset_count_tags(frameset, TELLURIC); 00842 if (nb_telluric > 0 && mapping_id > 0) { 00843 for (i = 0; i < arm_name_struct->nrNames; i++) { 00844 if (arm_name_struct->telluricCnt[i] =! arm_name_struct->namesCnt[i] 00845 && (arm_name_struct->telluricCnt[i] =! 0)) { 00846 cpl_msg_error(__func__, "Mosaics need a TELLURIC per detector"); 00847 cpl_error_set(__func__, CPL_ERROR_UNSUPPORTED_MODE) ; 00848 return -1 ; 00849 } 00850 } 00851 } 00852 00853 /* Allocate data */ 00854 cube_data=(cpl_imagelist**)cpl_calloc(KMOS_NR_IFUS, sizeof(cpl_imagelist*)); 00855 cube_noise=(cpl_imagelist**)cpl_calloc(KMOS_NR_IFUS,sizeof(cpl_imagelist*)); 00856 header_data = (cpl_propertylist**)cpl_calloc(KMOS_NR_IFUS, 00857 sizeof(cpl_propertylist*)); 00858 header_noise = (cpl_propertylist**)cpl_calloc(KMOS_NR_IFUS, 00859 sizeof(cpl_propertylist*)); 00860 if (save_interims) { 00861 cube_interim_object=(cpl_imagelist**)cpl_calloc(KMOS_NR_IFUS, 00862 sizeof(cpl_imagelist*)); 00863 cube_interim_sky =(cpl_imagelist**)cpl_calloc(KMOS_NR_IFUS, 00864 sizeof(cpl_imagelist*)); 00865 header_sky = (cpl_propertylist**)cpl_calloc(KMOS_NR_IFUS, 00866 sizeof(cpl_propertylist*)); 00867 } 00868 00869 /* Loop all science frames containing at least one object */ 00870 cpl_msg_info(__func__, "Reconstructing & saving cubes with objects"); 00871 for (sf = 0; sf < arm_name_struct->size; sf++) { 00872 fn_obj = cpl_frame_get_filename( 00873 arm_name_struct->obj_sky_struct->table[sf].objFrame); 00874 if ((main_header = kmclipm_propertylist_load(fn_obj, 0)) == NULL) { 00875 kmo_free_unused_ifus(unused_ifus_after); 00876 cpl_free(bounds); 00877 kmo_delete_armNameStruct(arm_name_struct); 00878 cpl_free(cube_data) ; 00879 cpl_free(cube_noise) ; 00880 cpl_free(header_data) ; 00881 cpl_free(header_noise) ; 00882 if (save_interims) { 00883 cpl_free(cube_interim_object) ; 00884 cpl_free(cube_interim_sky) ; 00885 cpl_free(header_sky) ; 00886 } 00887 cpl_msg_error(__func__, "Cannot Load main header"); 00888 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00889 return -1 ; 00890 } 00891 actual_msg_level = cpl_msg_get_level(); 00892 00893 /* Reconstruct science frame */ 00894 cpl_msg_info(__func__, " > processing frame: %s", fn_obj); 00895 for (ifu_nr = 1; ifu_nr <= KMOS_NR_IFUS; ifu_nr++) { 00896 00897 /* Initialise */ 00898 cube_data[ifu_nr-1] = cube_noise[ifu_nr-1] = NULL ; 00899 00900 sky_ifu_nr = ifu_nr; 00901 det_nr = (ifu_nr - 1)/KMOS_IFUS_PER_DETECTOR + 1; 00902 00903 /* Get subheader data */ 00904 header_data[ifu_nr-1] = kmclipm_propertylist_load(fn_obj, det_nr); 00905 extname = kmo_extname_creator(ifu_frame, ifu_nr, EXT_DATA); 00906 kmclipm_update_property_string(header_data[ifu_nr-1], 00907 EXTNAME, extname, "FITS extension name"); 00908 cpl_free(extname); 00909 00910 if (arm_name_struct->name_ids[ifu_nr-1+sf*KMOS_NR_IFUS] >= 1) { 00911 // IFU is valid 00912 00913 /* Fill sky_as_object_frame, do_sky_subtraction and sky_frame */ 00914 sky_as_object_frame = NULL ; 00915 if ((arm_name_struct->obj_sky_struct->table[sf].skyFrames[ifu_nr-1] != NO_CORRESPONDING_SKYFRAME) && !no_subtract) { 00916 do_sky_subtraction = TRUE; 00917 if (no_subtract) sky_frame = NULL; 00918 else sky_frame = 00919 arm_name_struct->obj_sky_struct->table[sf].skyFrames[ifu_nr-1]; 00920 00921 if (sky_tweak){ 00922 sky_as_object_frame = sky_frame; 00923 sky_frame = NULL; 00924 sky_ifu_nr = arm_name_struct->obj_sky_struct->table[sf].skyIfus[ifu_nr-1]; 00925 } 00926 } else { 00927 do_sky_subtraction = FALSE; 00928 sky_frame = NULL; 00929 } 00930 00931 /* Get filter and setup grid definition using WAVE_BAND */ 00932 keyword = cpl_sprintf("%s%d%s", IFU_FILTID_PREFIX, det_nr, 00933 IFU_FILTID_POSTFIX); 00934 filter_id = cpl_propertylist_get_string(main_header, keyword); 00935 cpl_free(keyword); 00936 00937 if (print_once) cpl_msg_set_level(CPL_MSG_WARNING); 00938 print_once = TRUE; 00939 00940 band_table = kmo_dfs_load_table(frameset, WAVE_BAND, 1, 0); 00941 kmclipm_setup_grid_band_lcal(&gd, filter_id, band_table); 00942 cpl_table_delete(band_table); 00943 00944 cpl_msg_set_level(actual_msg_level); 00945 00946 /* calc WCS & update subheader */ 00947 kmo_calc_wcs_gd(main_header, header_data[ifu_nr-1], ifu_nr, gd); 00948 00949 /* Update some keywords */ 00950 kmclipm_update_property_int(header_data[ifu_nr-1], NAXIS, 3, 00951 "number of data axes"); 00952 kmclipm_update_property_int(header_data[ifu_nr-1], NAXIS1, 00953 gd.x.dim, "length of data axis 1"); 00954 kmclipm_update_property_int(header_data[ifu_nr-1], NAXIS2, 00955 gd.y.dim, "length of data axis 2"); 00956 kmclipm_update_property_int(header_data[ifu_nr-1], NAXIS3, 00957 gd.l.dim, "length of data axis 3"); 00958 00959 /* Option save_interim only applies if sky_tweak is used */ 00960 if (save_interims && sky_as_object_frame != NULL) { 00961 header_tmp = kmclipm_propertylist_load( 00962 cpl_frame_get_filename(sky_as_object_frame), 0); 00963 00964 header_sky[ifu_nr-1]=kmclipm_propertylist_load( 00965 cpl_frame_get_filename(sky_as_object_frame),det_nr); 00966 extname = kmo_extname_creator(ifu_frame, ifu_nr, EXT_DATA); 00967 kmclipm_update_property_string(header_sky[ifu_nr-1], 00968 EXTNAME, extname, "FITS extension name"); 00969 cpl_free(extname); 00970 00971 kmo_calc_wcs_gd(header_tmp, header_sky[ifu_nr-1], 00972 ifu_nr, gd); 00973 kmclipm_update_property_int(header_sky[ifu_nr-1], NAXIS, 3, 00974 "number of data axes"); 00975 kmclipm_update_property_int(header_sky[ifu_nr-1], NAXIS1, 00976 gd.x.dim, "length of data axis 1"); 00977 kmclipm_update_property_int(header_sky[ifu_nr-1], NAXIS2, 00978 gd.y.dim, "length of data axis 2"); 00979 kmclipm_update_property_int(header_sky[ifu_nr-1], NAXIS3, 00980 gd.l.dim, "length of data axis 3"); 00981 cpl_propertylist_delete(header_tmp); 00982 } 00983 00984 00985 /* OH lines based lambda correction */ 00986 oh_lcorr_coeffs = NULL ; 00987 if (ref_spectrum_frame != NULL) { 00988 if (kmo_reconstruct_sci(ifu_nr, bounds[2*(ifu_nr-1)], 00989 bounds[2*(ifu_nr-1)+1], 00990 arm_name_struct->obj_sky_struct->table[sf].objFrame, 00991 SCIENCE, NULL, NULL, flat_frame, xcal_frame, 00992 ycal_frame, lcal_frame, NULL, NULL, &gd, &tmp_cube1, 00993 &tmp_cube2, FALSE, FALSE, 00994 xcal_interpolation) == CPL_ERROR_NONE) { 00995 oh_lcorr_coeffs = kmo_lcorr_get(tmp_cube1, 00996 header_data[ifu_nr-1], ref_spectrum_frame, gd, 00997 filter_id, ifu_nr); 00998 cpl_imagelist_delete(tmp_cube1); 00999 cpl_imagelist_delete(tmp_cube2); 01000 } 01001 } 01002 01003 /* Reconstruct object */ 01004 kmo_reconstruct_sci(ifu_nr, bounds[2*(ifu_nr-1)], 01005 bounds[2*(ifu_nr-1)+1], 01006 arm_name_struct->obj_sky_struct->table[sf].objFrame, 01007 SCIENCE, sky_frame, SCIENCE, flat_frame, xcal_frame, 01008 ycal_frame, lcal_frame, oh_lcorr_coeffs, velo_corr_ptr, 01009 &gd, &cube_data[ifu_nr-1], &cube_noise[ifu_nr-1], flux, 01010 background, xcal_interpolation); 01011 01012 if (oh_lcorr_coeffs != NULL) 01013 cpl_polynomial_delete(oh_lcorr_coeffs); 01014 01015 if (cpl_error_get_code() != CPL_ERROR_NONE) { 01016 kmo_free_unused_ifus(unused_ifus_after); 01017 cpl_free(bounds); 01018 kmo_delete_armNameStruct(arm_name_struct); 01019 for (j=0 ; j<ifu_nr-1 ; j++) { 01020 if (cube_data[j] != NULL) 01021 cpl_imagelist_delete(cube_data[j]); 01022 if (cube_noise[j] != NULL) 01023 cpl_imagelist_delete(cube_noise[j]); 01024 cpl_propertylist_delete(header_data[j]); 01025 cpl_propertylist_delete(header_noise[j]); 01026 if (save_interims) { 01027 cpl_imagelist_delete(cube_interim_object[j]); 01028 cpl_imagelist_delete(cube_interim_sky[j]); 01029 cpl_propertylist_delete(header_sky[j]); 01030 } 01031 } 01032 cpl_propertylist_delete(header_data[ifu_nr-1]); 01033 cpl_free(cube_data) ; 01034 cpl_free(cube_noise) ; 01035 cpl_free(header_data) ; 01036 cpl_free(header_noise) ; 01037 if (save_interims) { 01038 cpl_free(cube_interim_object) ; 01039 cpl_free(cube_interim_sky) ; 01040 cpl_free(header_sky) ; 01041 } 01042 cpl_msg_error(__func__, "Cannot reconstruct"); 01043 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 01044 return -1 ; 01045 } 01046 01047 /* If sky_tweak is set, reconstruct sky frame as object */ 01048 /* use kmos_priv_sky_tweak to subtract a modified sky cube */ 01049 if (do_sky_subtraction && sky_tweak) { 01050 01051 /* OH lines based lambda correction */ 01052 oh_lcorr_coeffs = NULL ; 01053 if (ref_spectrum_frame != NULL) { 01054 if (kmo_reconstruct_sci(sky_ifu_nr, 01055 bounds[2*(sky_ifu_nr-1)], 01056 bounds[2*(sky_ifu_nr-1)+1], 01057 sky_as_object_frame, SCIENCE, NULL, NULL, 01058 flat_frame, xcal_frame, ycal_frame, 01059 lcal_frame, NULL, NULL, &gd, &tmp_cube1, 01060 &tmp_cube2, FALSE, FALSE, 01061 xcal_interpolation) == CPL_ERROR_NONE) { 01062 oh_lcorr_coeffs = kmo_lcorr_get(tmp_cube1, 01063 header_data[ifu_nr-1], ref_spectrum_frame, 01064 gd, filter_id, ifu_nr); 01065 cpl_imagelist_delete(tmp_cube1); 01066 cpl_imagelist_delete(tmp_cube2); 01067 } 01068 } 01069 01070 /* Reconstruct object */ 01071 kmo_reconstruct_sci(sky_ifu_nr, 01072 bounds[2*(sky_ifu_nr-1)], 01073 bounds[2*(sky_ifu_nr-1)+1], sky_as_object_frame, 01074 SCIENCE, sky_frame, SCIENCE, flat_frame, 01075 xcal_frame, ycal_frame, lcal_frame, oh_lcorr_coeffs, 01076 velo_corr_ptr, &gd, &tmp_cube1, &tmp_cube2, 01077 flux, background, xcal_interpolation); 01078 01079 cpl_imagelist_delete(tmp_cube2); 01080 if (oh_lcorr_coeffs != NULL) 01081 cpl_polynomial_delete(oh_lcorr_coeffs); 01082 01083 if (save_interims && (sky_as_object_frame != NULL)) { 01084 cube_interim_object[ifu_nr-1]= 01085 cpl_imagelist_duplicate(cube_data[ifu_nr-1]); 01086 cube_interim_sky[ifu_nr-1]= 01087 cpl_imagelist_duplicate(tmp_cube1); 01088 } 01089 01090 /* Apply the SKY tweaking */ 01091 tmp_cube2 = kmos_priv_sky_tweak(cube_data[ifu_nr-1], 01092 tmp_cube1,header_data[ifu_nr-1], .3, tbsub, ifu_nr); 01093 cpl_imagelist_delete(cube_data[ifu_nr-1]); 01094 cpl_imagelist_delete(tmp_cube1); 01095 cube_data[ifu_nr-1] = tmp_cube2 ; 01096 } 01097 01098 /* Maintain flux constant in case the pixscale is diff */ 01099 /* For example, pixscale=0.1 => images 28x28 => scaling=4 */ 01100 tmpImg = cpl_imagelist_get(cube_data[ifu_nr-1], 0); 01101 scaling = (cpl_image_get_size_x(tmpImg) * 01102 cpl_image_get_size_y(tmpImg)) / 01103 (KMOS_SLITLET_X*KMOS_SLITLET_Y); 01104 cpl_imagelist_divide_scalar(cube_data[ifu_nr-1], scaling); 01105 if (cube_noise[ifu_nr-1] != NULL) { 01106 cpl_imagelist_divide_scalar(cube_noise[ifu_nr-1], scaling); 01107 } 01108 01109 /* Divide cube by telluric correction */ 01110 if (nb_telluric > 0) { 01111 /* Create the mapping string */ 01112 if (mapping_id == 0) { 01113 /* Get object name */ 01114 keyword = cpl_sprintf("%s%d%s", IFU_NAME_PREFIX, 01115 ifu_nr, IFU_NAME_POSTFIX); 01116 tmp_str = cpl_propertylist_get_string( 01117 header_data[ifu_nr-1], keyword); 01118 cpl_free(keyword); 01119 } else if (mapping_id == 1) { 01120 tmp_str = "mapping8"; 01121 } else if (mapping_id == 2) { 01122 tmp_str = "mapping24"; 01123 } 01124 01125 /* Check if the nb of occurences of the object name */ 01126 /* is the same as the number of found tellurics for */ 01127 /* this object (which can be on different arms) */ 01128 telluric_ok = FALSE; 01129 for (jj = 0; jj < arm_name_struct->nrNames; jj++) { 01130 if ((!strcmp(arm_name_struct->names[jj], tmp_str) || 01131 !strcmp(arm_name_struct->names[jj], IFUS_USER_DEFINED)) && 01132 arm_name_struct->telluricCnt[jj] == arm_name_struct->namesCnt[jj]) { 01133 telluric_ok = TRUE; 01134 break; 01135 } 01136 } 01137 01138 if (telluric_ok) { 01139 telluric_data = kmo_tweak_load_telluric(frameset, 01140 ifu_nr, FALSE, no_subtract); 01141 if (telluric_data != NULL) { 01142 telluric_frame=kmo_dfs_get_frame(frameset,TELLURIC); 01143 kmo_init_fits_desc(&desc_telluric); 01144 desc_telluric=kmo_identify_fits_header( 01145 cpl_frame_get_filename(telluric_frame)); 01146 01147 /* Get the index of the telluric noise */ 01148 idx = kmo_identify_index_desc(desc_telluric, 01149 ifu_nr, TRUE); 01150 if (desc_telluric.sub_desc[idx-1].valid_data) { 01151 /* Load noise if present */ 01152 telluric_noise = kmo_tweak_load_telluric( 01153 frameset,ifu_nr, TRUE, no_subtract); 01154 } else { 01155 telluric_noise = NULL ; 01156 } 01157 kmo_free_fits_desc(&desc_telluric); 01158 01159 kmo_arithmetic_3D_1D(cube_data[ifu_nr-1], 01160 telluric_data, cube_noise[ifu_nr-1], 01161 telluric_noise, "/"); 01162 if (telluric_noise != NULL) 01163 kmclipm_vector_delete(telluric_noise); 01164 kmclipm_vector_delete(telluric_data); 01165 } 01166 } 01167 } 01168 01169 /* Divide cube by illumination correction */ 01170 nb_illum_corr = cpl_frameset_count_tags(frameset, ILLUM_CORR); 01171 if (nb_illum_corr > 0) { 01172 illum_data = kmo_dfs_load_image(frameset, ILLUM_CORR, 01173 ifu_nr, FALSE, FALSE, NULL); 01174 illum_noise = kmo_dfs_load_image(frameset, ILLUM_CORR, 01175 ifu_nr, TRUE, FALSE, NULL); 01176 if (cpl_error_get_code() != CPL_ERROR_NONE) { 01177 cpl_msg_warning(__func__, 01178 "No illumination correction for IFU %d available! " 01179 "Proceeding anyway.", ifu_nr); 01180 if (illum_data != NULL) cpl_image_delete(illum_data); 01181 if (illum_noise != NULL) cpl_image_delete(illum_noise); 01182 cpl_error_reset(); 01183 } else { 01184 kmo_arithmetic_3D_2D(cube_data[ifu_nr-1], illum_data, 01185 cube_noise[ifu_nr-1], illum_noise, "/"); 01186 cpl_image_delete(illum_data); 01187 cpl_image_delete(illum_noise); 01188 } 01189 } 01190 } 01191 01192 /* Duplicate subheader data */ 01193 header_noise[ifu_nr-1] = cpl_propertylist_duplicate( 01194 header_data[ifu_nr-1]); 01195 extname = kmo_extname_creator(ifu_frame, ifu_nr, EXT_NOISE); 01196 kmclipm_update_property_string(header_noise[ifu_nr-1], EXTNAME, 01197 extname, "FITS extension name"); 01198 cpl_free(extname); 01199 } 01200 cpl_propertylist_delete(main_header) ; 01201 01202 /* Count number of reconstructed data- and noise-cubes */ 01203 for (ifu_nr = 1; ifu_nr <= KMOS_NR_IFUS; ifu_nr++) { 01204 if (cube_data[ifu_nr-1] != NULL) cube_counter_data++; 01205 if (cube_noise[ifu_nr-1] != NULL) cube_counter_noise++; 01206 } 01207 01208 /* Save reconstructed cubes of science frame */ 01209 if (cube_counter_data > 0) { 01210 cpl_msg_info(__func__, " > saving..."); 01211 01212 if (!suppress_extension) { 01213 fn_out = fn_obj; 01214 01215 int nr_found = 0; 01216 // remove any path-elements from filename and use it as suffix 01217 split = kmo_strsplit(fn_out, "/", &nr_found); 01218 fn_suffix = cpl_sprintf("_%s", split[nr_found-1]); 01219 kmo_strfreev(split); 01220 01221 // remove '.fits' at the end if there is any 01222 char *fff = fn_suffix; 01223 fff += strlen(fn_suffix)-5; 01224 if (strcmp(fff, ".fits") == 0) { 01225 fn_suffix[strlen(fn_suffix)-5] = '\0'; 01226 } 01227 } else { 01228 fn_suffix = cpl_sprintf("_%d", suppress_index++); 01229 } 01230 01231 fn_out = RECONSTRUCTED_CUBE; 01232 01233 /* Create Primary Header */ 01234 kmo_dfs_save_main_header(frameset, fn_out, fn_suffix, 01235 arm_name_struct->obj_sky_struct->table[sf].objFrame, NULL, 01236 parlist, cpl_func); 01237 /* save intermediate products (only in sky tweak case) */ 01238 if (save_interims && (sky_as_object_frame != NULL)) { 01239 kmo_dfs_save_main_header(frameset, INTERIM_OBJECT_CUBE, 01240 fn_suffix, 01241 arm_name_struct->obj_sky_struct->table[sf].objFrame, 01242 NULL, parlist, cpl_func); 01243 kmo_dfs_save_main_header(frameset, INTERIM_OBJECT_SKY, 01244 fn_suffix, 01245 arm_name_struct->obj_sky_struct->table[sf].objFrame, 01246 NULL, parlist, cpl_func); 01247 } 01248 01249 /* Loop on IFUs */ 01250 for (ifu_nr = 1; ifu_nr <= KMOS_NR_IFUS; ifu_nr++) { 01251 /* Save data Extension */ 01252 kmo_dfs_save_cube(cube_data[ifu_nr-1], fn_out, fn_suffix, 01253 header_data[ifu_nr-1], 0./0.); 01254 cpl_imagelist_delete(cube_data[ifu_nr-1]); 01255 01256 /* Save noise Extension */ 01257 if (cube_counter_noise > 0) { 01258 kmo_dfs_save_cube(cube_noise[ifu_nr-1], fn_out, fn_suffix, 01259 header_noise[ifu_nr-1], 0./0.); 01260 } 01261 cpl_propertylist_delete(header_noise[ifu_nr-1]); 01262 cpl_imagelist_delete(cube_noise[ifu_nr-1]); 01263 01264 /* save intermediate products (only in sky tweak case */ 01265 if (save_interims && (sky_as_object_frame != NULL)) { 01266 kmo_dfs_save_cube(cube_interim_object[ifu_nr-1], 01267 INTERIM_OBJECT_CUBE, fn_suffix, 01268 header_data[ifu_nr-1], 0./0.); 01269 kmo_dfs_save_cube(cube_interim_sky[ifu_nr-1], 01270 INTERIM_OBJECT_SKY, fn_suffix, header_sky[ifu_nr-1], 01271 0./0.); 01272 } 01273 cpl_propertylist_delete(header_data[ifu_nr-1]); 01274 if (save_interims) { 01275 cpl_imagelist_delete(cube_interim_object[ifu_nr-1]); 01276 cpl_imagelist_delete(cube_interim_sky[ifu_nr-1]); 01277 cpl_propertylist_delete(header_sky[ifu_nr-1]); 01278 } 01279 } 01280 cpl_free(fn_suffix); 01281 } else { 01282 cpl_msg_info(__func__, " > all IFUs invalid, don't save"); 01283 for (ifu_nr = 1; ifu_nr <= KMOS_NR_IFUS; ifu_nr++) { 01284 cpl_propertylist_delete(header_data[ifu_nr-1]); 01285 cpl_propertylist_delete(header_noise[ifu_nr-1]); 01286 } 01287 } 01288 } 01289 cpl_free(bounds) ; 01290 cpl_free(cube_data); 01291 cpl_free(cube_noise); 01292 cpl_free(header_data); 01293 cpl_free(header_noise); 01294 if (save_interims) { 01295 cpl_free(cube_interim_object); 01296 cpl_free(cube_interim_sky); 01297 cpl_free(header_sky); 01298 } 01299 01300 kmo_print_unused_ifus(unused_ifus_after, TRUE); 01301 kmo_free_unused_ifus(unused_ifus_after); 01302 01303 /* Combine */ 01304 suppress_index = 0; 01305 if (!no_combine) { 01306 cpl_msg_info(__func__, "Combining reconstructed objects"); 01307 if (mapping_id==0 || (mapping_id>0 && (strcmp(ifus_txt, "") || 01308 strcmp(name,"")))){ 01309 /* Loop all available objects */ 01310 for (i = 0; i < arm_name_struct->nrNames; i++) { 01311 cpl_msg_info(__func__, 01312 " > object: %s", arm_name_struct->names[i]); 01313 nr_data = arm_name_struct->namesCnt[i]; 01314 cube_data=(cpl_imagelist**)cpl_calloc(nr_data, 01315 sizeof(cpl_imagelist*)); 01316 cube_noise=(cpl_imagelist**)cpl_calloc(nr_data, 01317 sizeof(cpl_imagelist*)); 01318 header_data=(cpl_propertylist**)cpl_calloc(nr_data, 01319 sizeof(cpl_propertylist*)); 01320 header_noise=(cpl_propertylist**)cpl_calloc(nr_data, 01321 sizeof(cpl_propertylist*)); 01322 01323 /* Initialise */ 01324 for (jj = 0; jj < nr_data; jj++) { 01325 cube_data[jj] = NULL ; 01326 cube_noise[jj] = NULL ; 01327 header_data[jj] = NULL ; 01328 header_noise[jj] = NULL ; 01329 } 01330 01331 // setup cube-list and header-list for kmo_priv_combine() 01332 cube_counter_data = 0; 01333 cube_counter_noise = 0; 01334 tmp_frame = kmo_dfs_get_frame(frameset, RECONSTRUCTED_CUBE); 01335 while (tmp_frame != NULL ) { 01336 fn_reconstr = cpl_frame_get_filename(tmp_frame); 01337 main_header = kmclipm_propertylist_load(fn_reconstr, 0); 01338 01339 kmo_init_fits_desc(&desc1); 01340 desc1 = kmo_identify_fits_header(fn_reconstr); 01341 01342 for (ifu_nr = 1; ifu_nr <= KMOS_NR_IFUS; ifu_nr++) { 01343 // check if object-name equals the one in our list 01344 keyword = cpl_sprintf("%s%d%s", IFU_NAME_PREFIX, ifu_nr, 01345 IFU_NAME_POSTFIX); 01346 tmp_str=cpl_propertylist_get_string(main_header, 01347 keyword); 01348 cpl_free(keyword); 01349 01350 if (!strcmp(arm_name_struct->names[i],tmp_str) || 01351 !strcmp(arm_name_struct->names[i], IFUS_USER_DEFINED)) { 01352 /* Found object-IFU with matching name */ 01353 /* Load data & subheader */ 01354 idx=kmo_identify_index(fn_reconstr,ifu_nr,FALSE); 01355 01356 if (desc1.sub_desc[idx-1].valid_data) { 01357 cube_data[cube_counter_data] = 01358 kmclipm_imagelist_load(fn_reconstr, 01359 CPL_TYPE_FLOAT, idx); 01360 /* Set cubes borders (1 pixel) to Nan to avoid jumps in combined cube */ 01361 if (edge_nan) { 01362 kmo_edge_nan(cube_data[cube_counter_data], 01363 ifu_nr); 01364 } 01365 01366 header_data[cube_counter_data] = 01367 kmclipm_propertylist_load(fn_reconstr, 01368 idx); 01369 cpl_propertylist_update_string( 01370 header_data[cube_counter_data], 01371 "ESO PRO FRNAME", fn_reconstr); 01372 cpl_propertylist_update_int( 01373 header_data[cube_counter_data], 01374 "ESO PRO IFUNR", ifu_nr); 01375 cube_counter_data++; 01376 } 01377 01378 /* Load noise & subheader (if existing) */ 01379 if (desc1.ex_noise) { 01380 idx = kmo_identify_index(fn_reconstr, ifu_nr, 01381 TRUE); 01382 if (desc1.sub_desc[idx-1].valid_data) { 01383 cube_noise[cube_counter_noise] = 01384 kmclipm_imagelist_load(fn_reconstr, 01385 CPL_TYPE_FLOAT, idx); 01386 if (edge_nan) { 01387 kmo_edge_nan( 01388 cube_noise[cube_counter_noise], 01389 ifu_nr); 01390 } 01391 header_noise[cube_counter_noise] = 01392 kmclipm_propertylist_load(fn_reconstr, 01393 idx); 01394 cube_counter_noise++; 01395 } 01396 } 01397 cpl_error_reset(); 01398 } 01399 } 01400 kmo_free_fits_desc(&desc1); 01401 cpl_propertylist_delete(main_header); 01402 tmp_frame = kmo_dfs_get_frame(frameset, NULL); 01403 } 01404 01405 if (cube_counter_noise == 0) { 01406 cpl_free(cube_noise); 01407 cube_noise = NULL ; 01408 } 01409 01410 if (cube_counter_data > 1) { 01411 if (cube_counter_data == cube_counter_noise || 01412 cube_counter_noise == 0) { 01413 kmo_priv_combine(cube_data, cube_noise, header_data, 01414 header_noise, cube_counter_data, 01415 cube_counter_noise, arm_name_struct->names[i], 01416 "", comb_method, smethod, fmethod, filename, 01417 cmethod, cpos_rej, cneg_rej, citer, cmin, cmax, 01418 extrapol_enum, flux, &combined_data, 01419 &combined_noise, &exp_mask); 01420 } else { 01421 cpl_msg_error(__func__, "Data/Noise cubes nb mismatch"); 01422 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 01423 return -1 ; 01424 } 01425 } else if (cube_counter_data == 1) { 01426 cpl_msg_warning(__func__, 01427 "Only one reconstructed cube with this object"); 01428 combined_data = cpl_imagelist_duplicate(cube_data[0]); 01429 tmpImg = cpl_imagelist_get(combined_data, 0); 01430 exp_mask = cpl_image_new(cpl_image_get_size_x(tmpImg), 01431 cpl_image_get_size_y(tmpImg), CPL_TYPE_FLOAT); 01432 kmo_image_fill(exp_mask, 1.); 01433 01434 combined_noise = NULL ; 01435 if (cube_counter_noise > 0 && cube_noise[0] != NULL) { 01436 combined_noise = cpl_imagelist_duplicate(cube_noise[0]); 01437 } 01438 } else { 01439 cpl_msg_error(__func__, "No cube found with this obj name"); 01440 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 01441 return -1 ; 01442 } 01443 for (jj = 0; jj < nr_data; jj++) { 01444 cpl_imagelist_delete(cube_data[jj]); 01445 if (cube_counter_noise > 0) 01446 cpl_imagelist_delete(cube_noise[jj]); 01447 } 01448 cpl_free(cube_data); 01449 cpl_free(cube_noise); 01450 01451 fn_out = COMBINED_CUBE; 01452 if (!suppress_extension) { 01453 char tmp_suffix[1024]; 01454 tmp_suffix[0] = '\0'; 01455 01456 if (arm_name_struct->telluricCnt[i] == 01457 arm_name_struct->namesCnt[i]) { 01458 strcat(tmp_suffix, "_telluric"); 01459 } 01460 if (nb_illum_corr > 0) strcat(tmp_suffix, "_illum"); 01461 if (sky_tweak) strcat(tmp_suffix, "_skytweak"); 01462 01463 if (strlen(tmp_suffix) > 0) { 01464 fn_suffix = cpl_sprintf("_%s_%s", 01465 arm_name_struct->names[i], tmp_suffix); 01466 } else { 01467 fn_suffix = cpl_sprintf("_%s", 01468 arm_name_struct->names[i]); 01469 } 01470 } else { 01471 fn_suffix = cpl_sprintf("_%d", suppress_index++); 01472 } 01473 01474 // save combined cube 01475 tmp_frame = kmo_dfs_get_frame(frameset, RECONSTRUCTED_CUBE); 01476 kmo_dfs_save_main_header(frameset, fn_out, fn_suffix, 01477 tmp_frame, NULL, parlist, cpl_func); 01478 kmo_dfs_save_main_header(frameset, EXP_MASK, fn_suffix, 01479 tmp_frame, NULL, parlist, cpl_func); 01480 kmo_dfs_save_cube(combined_data, fn_out, fn_suffix, 01481 header_data[0], 0./0.); 01482 kmo_dfs_save_image(exp_mask, EXP_MASK, fn_suffix, 01483 header_data[0], 0./0.); 01484 cpl_image_delete(exp_mask); 01485 01486 if (header_noise[0] == NULL) { 01487 header_noise[0]=cpl_propertylist_duplicate(header_data[0]); 01488 tmp_str=cpl_propertylist_get_string(header_data[0],EXTNAME); 01489 kmo_extname_extractor(tmp_str, &ft, &tmp_int, content); 01490 extname = kmo_extname_creator(ifu_frame, tmp_int,EXT_NOISE); 01491 kmclipm_update_property_string(header_noise[0], EXTNAME, 01492 extname, "FITS extension name"); 01493 cpl_free(extname); 01494 } 01495 kmo_dfs_save_cube(combined_noise, fn_out, fn_suffix, 01496 header_noise[0], 0./0.); 01497 01498 cpl_free(fn_suffix); 01499 for (jj = 0; jj < nr_data; jj++) { 01500 cpl_propertylist_delete(header_data[jj]); 01501 cpl_propertylist_delete(header_noise[jj]); 01502 } 01503 cpl_free(header_data); 01504 cpl_free(header_noise); 01505 cpl_imagelist_delete(combined_data); 01506 if (combined_noise != NULL) 01507 cpl_imagelist_delete(combined_noise); 01508 } 01509 } else { 01510 /* Mapping_mode */ 01511 nr_data = KMOS_NR_IFUS * 01512 cpl_frameset_count_tags(frameset,RECONSTRUCTED_CUBE); 01513 cube_data = (cpl_imagelist**)cpl_calloc(nr_data, 01514 sizeof(cpl_imagelist*)); 01515 cube_noise = (cpl_imagelist**)cpl_calloc(nr_data, 01516 sizeof(cpl_imagelist*)); 01517 header_data=(cpl_propertylist**)cpl_calloc(nr_data, 01518 sizeof(cpl_propertylist*)); 01519 header_noise=(cpl_propertylist**)cpl_calloc(nr_data, 01520 sizeof(cpl_propertylist*)); 01521 01522 /* Initialise */ 01523 for (jj = 0; jj < nr_data; jj++) { 01524 cube_data[jj] = NULL ; 01525 cube_noise[jj] = NULL ; 01526 header_data[jj] = NULL ; 01527 header_noise[jj] = NULL ; 01528 } 01529 01530 cube_counter_data = 0; 01531 cube_counter_noise = 0; 01532 tmp_frame = kmo_dfs_get_frame(frameset, RECONSTRUCTED_CUBE); 01533 while (tmp_frame != NULL ) { 01534 fn_reconstr = cpl_frame_get_filename(tmp_frame); 01535 01536 kmo_init_fits_desc(&desc1); 01537 desc1 = kmo_identify_fits_header(fn_reconstr); 01538 for (ifu_nr = 1; ifu_nr <= KMOS_NR_IFUS; ifu_nr++) { 01539 idx = kmo_identify_index(fn_reconstr, ifu_nr, FALSE); 01540 01541 if (desc1.sub_desc[idx-1].valid_data) { 01542 cpl_msg_debug(__func__, 01543 "Load in cube_data - Frame: %s IFU: %d", 01544 fn_reconstr, ifu_nr) ; 01545 cube_data[cube_counter_data] = kmclipm_imagelist_load( 01546 fn_reconstr, CPL_TYPE_FLOAT, idx); 01547 if (edge_nan) 01548 kmo_edge_nan(cube_data[cube_counter_data], ifu_nr); 01549 01550 if (fast_mode) { 01551 tmpImg = cpl_imagelist_collapse_median_create( 01552 cube_data[cube_counter_data]); 01553 tmp_cube1 = cpl_imagelist_new(); 01554 cpl_imagelist_set(tmp_cube1, tmpImg, 0); 01555 cpl_imagelist_delete(cube_data[cube_counter_data]); 01556 cube_data[cube_counter_data] = tmp_cube1; 01557 } 01558 01559 cpl_msg_debug(__func__, 01560 "Load in header_data - Frame: %s IFU: %d", 01561 fn_reconstr, ifu_nr) ; 01562 header_data[cube_counter_data] = 01563 kmclipm_propertylist_load(fn_reconstr, idx); 01564 cpl_propertylist_update_string( 01565 header_data[cube_counter_data], 01566 "ESO PRO FRNAME", fn_reconstr); 01567 cpl_propertylist_update_int( 01568 header_data[cube_counter_data], 01569 "ESO PRO IFUNR", ifu_nr); 01570 cube_counter_data++; 01571 cpl_msg_debug(__func__, "cube_counter_data: %d\n", 01572 cube_counter_data) ; 01573 } 01574 01575 /* Load noise & subheader (if existing) */ 01576 if (desc1.ex_noise) { 01577 idx = kmo_identify_index(fn_reconstr,ifu_nr,TRUE); 01578 if (desc1.sub_desc[idx-1].valid_data) { 01579 cpl_msg_debug(__func__, 01580 "Load in cube_noise - Frame: %s IFU: %d", 01581 fn_reconstr, ifu_nr) ; 01582 cube_noise[cube_counter_noise] = 01583 kmclipm_imagelist_load(fn_reconstr, 01584 CPL_TYPE_FLOAT, idx); 01585 01586 if (edge_nan) 01587 kmo_edge_nan(cube_noise[cube_counter_noise], 01588 ifu_nr); 01589 if (fast_mode) { 01590 tmpImg=cpl_imagelist_collapse_median_create( 01591 cube_noise[cube_counter_noise]); 01592 tmp_cube1 = cpl_imagelist_new(); 01593 cpl_imagelist_set(tmp_cube1, tmpImg, 0); 01594 cpl_imagelist_delete( 01595 cube_noise[cube_counter_noise]); 01596 cube_noise[cube_counter_noise] = tmp_cube1; 01597 } 01598 cpl_msg_debug(__func__, 01599 "Load in header_noise - Frame: %s IFU: %d", 01600 fn_reconstr, ifu_nr) ; 01601 header_noise[cube_counter_noise] = 01602 kmclipm_propertylist_load(fn_reconstr, idx); 01603 cube_counter_noise++; 01604 cpl_msg_debug(__func__, "cube_counter_noise: %d\n", 01605 cube_counter_noise) ; 01606 } 01607 } 01608 cpl_error_reset(); 01609 } 01610 kmo_free_fits_desc(&desc1); 01611 tmp_frame = kmo_dfs_get_frame(frameset, NULL); 01612 } 01613 01614 if (cube_counter_noise == 0) { 01615 cpl_free(cube_noise); 01616 cube_noise = NULL ; 01617 } 01618 01619 if (cube_counter_data > 1) { 01620 if (cube_counter_data == cube_counter_noise || 01621 cube_counter_noise == 0) { 01622 kmo_priv_combine(cube_data, cube_noise, header_data, 01623 header_noise, cube_counter_data, cube_counter_noise, 01624 mapping_mode, "", comb_method, smethod, fmethod, 01625 filename, cmethod, cpos_rej, cneg_rej, citer, cmin, 01626 cmax, extrapol_enum, flux, &combined_data, 01627 &combined_noise, NULL); 01628 } else { 01629 cpl_msg_error(__func__, "Data/Noise cubes nb mismatch"); 01630 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 01631 return -1 ; 01632 } 01633 } else { 01634 cpl_msg_warning(__func__, 01635 "There is only one reconstructed cube - Save it"); 01636 combined_data = cpl_imagelist_duplicate(cube_data[0]); 01637 01638 if (cube_noise[0] != NULL) { 01639 combined_noise = cpl_imagelist_duplicate(cube_noise[0]); 01640 } 01641 } 01642 fn_out = COMBINED_CUBE; 01643 fn_suffix = cpl_sprintf("_%s", mapping_mode); 01644 01645 // save combined cube 01646 tmp_frame = kmo_dfs_get_frame(frameset, RECONSTRUCTED_CUBE); 01647 kmo_dfs_save_main_header(frameset, fn_out, fn_suffix, tmp_frame, 01648 NULL, parlist, cpl_func); 01649 kmo_dfs_save_cube(combined_data, fn_out, fn_suffix, header_data[0], 01650 0./0.); 01651 01652 if (cube_counter_noise == 0) { 01653 header_noise[0] = cpl_propertylist_duplicate(header_data[0]); 01654 tmp_str = cpl_propertylist_get_string(header_data[0], EXTNAME); 01655 kmo_extname_extractor(tmp_str, &ft, &tmp_int, content); 01656 extname = kmo_extname_creator(ifu_frame, tmp_int, EXT_NOISE); 01657 kmclipm_update_property_string(header_noise[0], EXTNAME, 01658 extname, "FITS extension name"); 01659 cpl_free(extname); 01660 } 01661 kmo_dfs_save_cube(combined_noise, fn_out, fn_suffix, 01662 header_noise[0], 0./0.); 01663 01664 if (cube_counter_noise == 0) 01665 cpl_propertylist_delete(header_noise[0]); 01666 cpl_free(fn_suffix); 01667 for (i = 0; i < cube_counter_data ; i++) { 01668 cpl_propertylist_delete(header_data[i]); 01669 cpl_imagelist_delete(cube_data[i]); 01670 } 01671 for (i = 0; i < cube_counter_noise ; i++) { 01672 cpl_propertylist_delete(header_noise[i]); 01673 cpl_imagelist_delete(cube_noise[i]); 01674 } 01675 cpl_free(cube_data); 01676 cpl_free(cube_noise); 01677 cpl_free(header_data); 01678 cpl_free(header_noise); 01679 cpl_imagelist_delete(combined_data); 01680 cpl_imagelist_delete(combined_noise); 01681 } 01682 } 01683 kmo_delete_armNameStruct(arm_name_struct); 01684 01685 /* Collapse the reconstructed cubes if requested */ 01686 if (collapse_reconstructed) { 01687 kmos_sci_red_collapse_cubes(RECONSTRUCTED_CUBE, frameset, parlist, 0.1, 01688 "", DEF_REJ_METHOD, DEF_POS_REJ_THRES, DEF_NEG_REJ_THRES, 01689 DEF_ITERATIONS, DEF_NR_MIN_REJ, DEF_NR_MAX_REJ) ; 01690 } 01691 01692 /* Collapse the combined cubes if requested */ 01693 if (collapse_combined) { 01694 kmos_sci_red_collapse_cubes(COMBINED_CUBE, frameset, parlist, 0.1, "", 01695 DEF_REJ_METHOD, DEF_POS_REJ_THRES, DEF_NEG_REJ_THRES, 01696 DEF_ITERATIONS, DEF_NR_MIN_REJ, DEF_NR_MAX_REJ) ; 01697 } 01698 return 0; 01699 } 01700 01703 /*----------------------------------------------------------------------------*/ 01709 /*----------------------------------------------------------------------------*/ 01710 static int kmos_sci_red_collapse_cubes( 01711 char * pro_catg, 01712 cpl_frameset * frameset, 01713 cpl_parameterlist * parlist, 01714 double threshold, 01715 const char * range, 01716 const char * cmethod, 01717 double cpos_rej, 01718 double cneg_rej, 01719 int citer, 01720 int cmin, 01721 int cmax) 01722 { 01723 cpl_frame * in_cube_frame ; 01724 cpl_frame * ref_spectrum_frame ; 01725 const char * fn_cube ; 01726 const char * pro_catg_out ; 01727 cpl_vector * ranges ; 01728 cpl_vector * spec_data_in ; 01729 cpl_vector * spec_lambda_in ; 01730 cpl_vector * identified_slices ; 01731 cpl_propertylist * sub_header_data ; 01732 cpl_propertylist * sub_header_noise ; 01733 cpl_propertylist * plist ; 01734 cpl_propertylist * pro_plist ; 01735 cpl_imagelist * data_in ; 01736 cpl_imagelist * noise_in ; 01737 cpl_image * data_out ; 01738 cpl_image * noise_out ; 01739 kmclipm_vector * kmclipm_tmp_vec ; 01740 double spec_crpix, spec_crval, spec_cdelt, 01741 ifu_crpix, ifu_crval, ifu_cdelt ; 01742 char * filename ; 01743 int nr_devices, devnr, index_data, index_noise ; 01744 main_fits_desc desc1 ; 01745 int i; 01746 01747 /* Check Inputs */ 01748 if (frameset == NULL || parlist == NULL || pro_catg == NULL) return -1 ; 01749 01750 if (!strcmp(pro_catg, COMBINED_CUBE)) { 01751 pro_catg_out = COMBINED_COLLAPSED ; 01752 } else if (!strcmp(pro_catg, RECONSTRUCTED_CUBE)) { 01753 pro_catg_out = RECONSTRUCTED_COLLAPSED ; 01754 } else { 01755 return -1 ; 01756 } 01757 01758 /* Get ranges */ 01759 ranges = kmo_identify_ranges(range); 01760 01761 /* Get OH_SPEC */ 01762 if (ref_spectrum_frame = kmo_dfs_get_frame(frameset, OH_SPEC)) { 01763 plist = kmos_dfs_load_sub_header(ref_spectrum_frame, 1, FALSE); 01764 spec_crpix = cpl_propertylist_get_double(plist, CRPIX1); 01765 spec_crval = cpl_propertylist_get_double(plist, CRVAL1); 01766 spec_cdelt = cpl_propertylist_get_double(plist, CDELT1); 01767 cpl_propertylist_delete(plist) ; 01768 01769 /* Load OH lines data */ 01770 kmclipm_tmp_vec = kmos_dfs_load_vector(ref_spectrum_frame, 1, FALSE) ; 01771 spec_data_in = kmclipm_vector_create_non_rejected(kmclipm_tmp_vec); 01772 kmclipm_vector_delete(kmclipm_tmp_vec); 01773 01774 /* Convert threshold from percentage to absolute value */ 01775 threshold = threshold * cpl_vector_get_max(spec_data_in); 01776 01777 /* Create lambda-vector for OH-lines */ 01778 spec_lambda_in = kmo_create_lambda_vec( 01779 cpl_vector_get_size(spec_data_in), (int)spec_crpix, spec_crval, 01780 spec_cdelt) ; 01781 } else { 01782 spec_data_in = NULL ; 01783 spec_lambda_in = NULL ; 01784 } 01785 01786 /* Loop on the cubes with the requested PRO.CATG */ 01787 in_cube_frame = kmo_dfs_get_frame(frameset, pro_catg); 01788 while (in_cube_frame != NULL ) { 01789 fn_cube = cpl_frame_get_filename(in_cube_frame); 01790 kmo_init_fits_desc(&desc1); 01791 desc1 = kmo_identify_fits_header(fn_cube); 01792 01793 /* Create the Header and save the initial file */ 01794 pro_plist = cpl_propertylist_new() ; 01795 cpl_propertylist_update_string(pro_plist,CPL_DFS_PRO_CATG,pro_catg_out); 01796 filename = cpl_sprintf("make_image_%s", fn_cube) ; 01797 cpl_dfs_save_propertylist(frameset, NULL, parlist, frameset, 01798 in_cube_frame, "kmos_sci_red", pro_plist, NULL, VERSION, 01799 filename) ; 01800 cpl_propertylist_delete(pro_plist) ; 01801 01802 if (desc1.ex_noise == TRUE) nr_devices = desc1.nr_ext / 2; 01803 else nr_devices = desc1.nr_ext; 01804 for (i = 1; i <= nr_devices; i++) { 01805 if (desc1.ex_noise == FALSE) devnr=desc1.sub_desc[i-1].device_nr; 01806 else devnr=desc1.sub_desc[2*i-1].device_nr; 01807 if (desc1.ex_badpix == FALSE) 01808 index_data = kmo_identify_index_desc(desc1, devnr, FALSE); 01809 else 01810 index_data = kmo_identify_index_desc(desc1, devnr, 2); 01811 index_noise = 0 ; 01812 if (desc1.ex_noise) 01813 index_noise = kmo_identify_index_desc(desc1, devnr, TRUE); 01814 01815 /* Load the Extension Header */ 01816 sub_header_data = kmos_dfs_load_sub_header(in_cube_frame, devnr, 01817 FALSE); 01818 01819 /* Load noise */ 01820 sub_header_noise = NULL ; 01821 if (desc1.ex_noise) 01822 sub_header_noise=kmos_dfs_load_sub_header(in_cube_frame, devnr, 01823 TRUE); 01824 01825 /* If Data Valid */ 01826 if (desc1.sub_desc[index_data-1].valid_data == TRUE) { 01827 /* Interpolate oh-lines to fit input data */ 01828 ifu_crpix = cpl_propertylist_get_double(sub_header_data,CRPIX3); 01829 ifu_crval = cpl_propertylist_get_double(sub_header_data,CRVAL3); 01830 ifu_cdelt = cpl_propertylist_get_double(sub_header_data,CDELT3); 01831 01832 if (spec_data_in == NULL) { 01833 identified_slices = kmo_identify_slices(ranges, ifu_crpix, 01834 ifu_crval, ifu_cdelt, desc1.naxis3); 01835 } else { 01836 identified_slices = kmo_identify_slices_with_oh( 01837 spec_data_in, spec_lambda_in, ranges, threshold, 01838 ifu_crpix, ifu_crval, ifu_cdelt, desc1.naxis3); 01839 } 01840 kmos_sci_red_clean_plist(sub_header_data) ; 01841 01842 /* Load data */ 01843 data_in = kmos_dfs_load_cube(in_cube_frame, devnr, FALSE) ; 01844 01845 /* Load noise, if existing */ 01846 noise_in = NULL ; 01847 if (desc1.ex_noise && desc1.sub_desc[index_noise-1].valid_data) 01848 noise_in = kmos_dfs_load_cube(in_cube_frame, devnr, TRUE) ; 01849 01850 /* Process */ 01851 noise_out = NULL ; 01852 kmclipm_make_image(data_in, noise_in, &data_out, &noise_out, 01853 identified_slices, cmethod, cpos_rej, cneg_rej, citer, 01854 cmax, cmin); 01855 cpl_imagelist_delete(data_in); 01856 if (noise_in != NULL) 01857 cpl_imagelist_delete(noise_in); 01858 cpl_vector_delete(identified_slices); 01859 01860 /* Save Data */ 01861 kmclipm_image_save(data_out, filename, CPL_BPP_IEEE_FLOAT, 01862 sub_header_data, CPL_IO_EXTEND, 0./0.) ; 01863 01864 /* Process & save noise, if existing */ 01865 if (desc1.ex_noise) { 01866 kmclipm_image_save(noise_out, filename, CPL_BPP_IEEE_FLOAT, 01867 sub_header_noise, CPL_IO_EXTEND, 0./0.); 01868 } 01869 01870 /* Free memory */ 01871 cpl_image_delete(data_out); 01872 if (noise_out != NULL) cpl_image_delete(noise_out); 01873 } else { 01874 kmos_sci_red_clean_plist(sub_header_data) ; 01875 01876 /* invalid IFU, just save sub_headers */ 01877 cpl_propertylist_save(sub_header_data, filename, CPL_IO_EXTEND); 01878 01879 if (desc1.ex_noise) 01880 cpl_propertylist_save(sub_header_noise, filename, 01881 CPL_IO_EXTEND); 01882 } 01883 cpl_propertylist_delete(sub_header_data); 01884 if (sub_header_noise != NULL) 01885 cpl_propertylist_delete(sub_header_noise); 01886 } 01887 cpl_free(filename) ; 01888 kmo_free_fits_desc(&desc1); 01889 01890 /* Next candidate */ 01891 in_cube_frame = kmo_dfs_get_frame(frameset, NULL); 01892 } 01893 01894 if (spec_data_in != NULL) cpl_vector_delete(spec_data_in); 01895 if (spec_lambda_in != NULL) cpl_vector_delete(spec_lambda_in); 01896 return 0 ; 01897 01898 } 01899 01900 /*----------------------------------------------------------------------------*/ 01906 /*----------------------------------------------------------------------------*/ 01907 static int kmos_sci_red_clean_plist(cpl_propertylist * plist) 01908 { 01909 if (cpl_propertylist_has(plist, CRPIX3)) 01910 cpl_propertylist_erase(plist, CRPIX3); 01911 if (cpl_propertylist_has(plist, CRVAL3)) 01912 cpl_propertylist_erase(plist, CRVAL3); 01913 if (cpl_propertylist_has(plist, CDELT3)) 01914 cpl_propertylist_erase(plist, CDELT3); 01915 if (cpl_propertylist_has(plist, CTYPE3)) 01916 cpl_propertylist_erase(plist, CTYPE3); 01917 if (cpl_propertylist_has(plist, CUNIT3)) 01918 cpl_propertylist_erase(plist, CUNIT3); 01919 if (cpl_propertylist_has(plist, CD1_3)) 01920 cpl_propertylist_erase(plist, CD1_3); 01921 if (cpl_propertylist_has(plist, CD2_3)) 01922 cpl_propertylist_erase(plist, CD2_3); 01923 if (cpl_propertylist_has(plist, CD3_3)) 01924 cpl_propertylist_erase(plist, CD3_3); 01925 if (cpl_propertylist_has(plist, CD3_2)) 01926 cpl_propertylist_erase(plist, CD3_2); 01927 if (cpl_propertylist_has(plist, CD3_1)) 01928 cpl_propertylist_erase(plist, CD3_1); 01929 01930 return 0 ; 01931 } 01932 01933 /*----------------------------------------------------------------------------*/ 01940 /*----------------------------------------------------------------------------*/ 01941 static int kmos_sci_red_check_inputs( 01942 cpl_frameset * frameset, 01943 int * mapping_id) 01944 { 01945 int nb_science, nb_xcal, nb_ycal, nb_lcal, nb_wave_band, 01946 nb_master_flat, nb_illum_corr, nb_telluric, nb_oh_spec ; 01947 cpl_error_code err ; 01948 const cpl_frame * frame1 ; 01949 const cpl_frame * frame2 ; 01950 int next1, next2, mapping_id_loc, mapping_id_curr ; 01951 cpl_propertylist * mh ; 01952 const char * tmp_str ; 01953 01954 /* Check Entries */ 01955 if (frameset == NULL || mapping_id == NULL) return -1; 01956 01957 /* Count frames */ 01958 nb_science = cpl_frameset_count_tags(frameset, SCIENCE) ; 01959 nb_xcal = cpl_frameset_count_tags(frameset, XCAL) ; 01960 nb_ycal = cpl_frameset_count_tags(frameset, YCAL) ; 01961 nb_lcal = cpl_frameset_count_tags(frameset, LCAL) ; 01962 nb_wave_band = cpl_frameset_count_tags(frameset, WAVE_BAND) ; 01963 nb_master_flat = cpl_frameset_count_tags(frameset, MASTER_FLAT); 01964 nb_illum_corr = cpl_frameset_count_tags(frameset, ILLUM_CORR); 01965 nb_telluric = cpl_frameset_count_tags(frameset, TELLURIC); 01966 nb_oh_spec = cpl_frameset_count_tags(frameset, OH_SPEC) ; 01967 01968 /* Checks */ 01969 if (nb_science < 1) { 01970 cpl_msg_error(__func__, "At least one SCIENCE frame is required") ; 01971 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 01972 return 0 ; 01973 } 01974 if (nb_science == 1) { 01975 cpl_msg_warning(__func__, 01976 "Only 1 SCIENCE: no sky subtraction - reconstruct all IFUs"); 01977 } 01978 if (nb_xcal != 1 || nb_ycal != 1 || nb_lcal != 1) { 01979 cpl_msg_error(__func__, "Exactly 1 XCAL/YCAL/LCAL expected") ; 01980 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 01981 return 0 ; 01982 } 01983 if (nb_wave_band != 1) { 01984 cpl_msg_error(__func__, "At most one WAVE_BAND frame expected") ; 01985 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 01986 return 0 ; 01987 } 01988 01989 if (nb_master_flat > 1 || nb_illum_corr > 1 || nb_telluric > 1 || 01990 nb_oh_spec > 1) { 01991 cpl_msg_error(__func__, 01992 "MASTER_FLAT/ILLUM_CORR/OH_SPEC/TELLURIC: 0 or 1 frame expected") ; 01993 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 01994 return 0 ; 01995 } 01996 01997 /* filter_id, grating_id and rotator offset match all detectors */ 01998 err = CPL_ERROR_NONE ; 01999 err += kmo_check_frameset_setup(frameset, SCIENCE, TRUE, FALSE, TRUE); 02000 err += kmo_check_frame_setup(frameset, SCIENCE, YCAL, TRUE, FALSE, TRUE); 02001 err += kmo_check_frame_setup(frameset, XCAL, YCAL, TRUE, FALSE, TRUE); 02002 err += kmo_check_frame_setup(frameset, XCAL, LCAL, TRUE, FALSE, TRUE); 02003 if (nb_master_flat > 0) err += kmo_check_frame_setup(frameset, XCAL, 02004 MASTER_FLAT, TRUE, FALSE, TRUE); 02005 if (nb_telluric > 0) err += kmo_check_frame_setup(frameset, XCAL, 02006 TELLURIC, TRUE, FALSE, TRUE); 02007 if (nb_oh_spec > 0) err += kmo_check_oh_spec_setup(frameset, XCAL); 02008 02009 /* Check XCAL */ 02010 frame1 = kmo_dfs_get_frame(frameset, XCAL); 02011 next1 = cpl_frame_get_nextensions(frame1); 02012 if (next1 % KMOS_NR_DETECTORS) { 02013 cpl_msg_error(__func__, "XCAL wrong format") ; 02014 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 02015 return 0 ; 02016 } 02017 /* Check YCAL */ 02018 frame2 = kmo_dfs_get_frame(frameset, YCAL); 02019 next2 = cpl_frame_get_nextensions(frame2); 02020 if (next1 != next2) { 02021 cpl_msg_error(__func__, "YCAL wrong format") ; 02022 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 02023 return 0 ; 02024 } 02025 /* Check LCAL */ 02026 frame2 = kmo_dfs_get_frame(frameset, LCAL); 02027 next2 = cpl_frame_get_nextensions(frame2); 02028 if (next1 != next2) { 02029 cpl_msg_error(__func__, "LCAL wrong format") ; 02030 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 02031 return 0 ; 02032 } 02033 /* Check MASTER_FLAT */ 02034 if (nb_master_flat > 1) { 02035 frame2 = kmo_dfs_get_frame(frameset, MASTER_FLAT); 02036 next2 = cpl_frame_get_nextensions(frame2); 02037 if (next2 % (2*KMOS_NR_DETECTORS)) { 02038 cpl_msg_error(__func__, "MASTER_FLAT wrong format") ; 02039 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 02040 return 0 ; 02041 } 02042 } 02043 /* Check ILLUM_CORR */ 02044 if (nb_illum_corr > 1) { 02045 frame2 = kmo_dfs_get_frame(frameset, ILLUM_CORR); 02046 next2 = cpl_frame_get_nextensions(frame2); 02047 if (next2 != 24 && next2 != 48) { 02048 cpl_msg_error(__func__, "MASTER_FLAT wrong format") ; 02049 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 02050 return 0 ; 02051 } 02052 } 02053 /* Check TELLURIC */ 02054 if (nb_illum_corr > 1) { 02055 frame2 = kmo_dfs_get_frame(frameset, TELLURIC); 02056 next2 = cpl_frame_get_nextensions(frame2); 02057 if (next2 != 24 && next2 != 48) { 02058 cpl_msg_error(__func__, "TELLURIC wrong format") ; 02059 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 02060 return 0 ; 02061 } 02062 } 02063 02064 /* Loop on the SCIENCE frames */ 02065 frame2 = kmo_dfs_get_frame(frameset, SCIENCE); 02066 mapping_id_loc = -1 ; 02067 while (frame2 != NULL ) { 02068 next2 = cpl_frame_get_nextensions(frame2); 02069 if (next2 != 3) { 02070 cpl_msg_error(__func__, "SCIENCE wrong format") ; 02071 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 02072 return 0 ; 02073 } 02074 02075 mh = cpl_propertylist_load(cpl_frame_get_filename(frame2), 0); 02076 tmp_str = cpl_propertylist_get_string(mh, TPL_ID); 02077 if (!strcmp(tmp_str, MAPPING8)) mapping_id_curr = 1 ; 02078 else if (strcmp(tmp_str, MAPPING24) == 0) mapping_id_curr = 2 ; 02079 else mapping_id_curr = 0 ; 02080 cpl_propertylist_delete(mh); 02081 02082 if (mapping_id_loc < 0) mapping_id_loc = mapping_id_curr ; 02083 if (mapping_id_curr != mapping_id_loc) { 02084 cpl_msg_error(__func__, "Inconsistent MAPPING information") ; 02085 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 02086 return 0 ; 02087 } 02088 frame2 = kmo_dfs_get_frame(frameset, NULL); 02089 } 02090 02091 /* Verify that XCAL / YCAL were generated together */ 02092 err += kmo_check_frame_setup_md5_xycal(frameset); 02093 /* Verify that XCAL and YCAL / LCAL were generated together */ 02094 err += kmo_check_frame_setup_md5(frameset); 02095 /* b_start/b_end/b_samples used for LCAL and TELLURIC were the same */ 02096 err += kmo_check_frame_setup_sampling(frameset); 02097 02098 if (err != CPL_ERROR_NONE) { 02099 cpl_msg_warning(__func__, "Frames are inconsistent") ; 02100 return 0 ; 02101 } 02102 02103 /* Return */ 02104 *mapping_id = mapping_id_loc ; 02105 return 1 ; 02106 } 02107 02108
1.7.6.1