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