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