|
KMOS Pipeline Reference Manual
1.3.16
|
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 int * qc_output_unit ; 00547 int * bounds ; 00548 gridDefinition gd ; 00549 armNameStruct * arm_name_struct ; 00550 00551 cpl_propertylist * plist ; 00552 cpl_polynomial * oh_lcorr_coeffs ; 00553 cpl_vector * ifus ; 00554 cpl_array ** unused_ifus_before ; 00555 cpl_array ** unused_ifus_after ; 00556 cpl_frame * sky_frame ; 00557 cpl_frame * sky_as_object_frame ; 00558 cpl_frame * ref_spectrum_frame ; 00559 cpl_frame * xcal_frame ; 00560 cpl_frame * ycal_frame ; 00561 cpl_frame * lcal_frame ; 00562 cpl_frame * flat_frame ; 00563 cpl_frame * telluric_frame ; 00564 cpl_frame * tmp_frame ; 00565 00566 cpl_table * band_table ; 00567 00568 cpl_imagelist * combined_data ; 00569 cpl_imagelist * combined_noise ; 00570 cpl_imagelist * tmp_cube1 ; 00571 cpl_imagelist * tmp_cube2 ; 00572 00573 cpl_image * tmpImg ; 00574 cpl_image * exp_mask ; 00575 cpl_image * illum_data ; 00576 cpl_image * illum_noise ; 00577 00578 cpl_imagelist ** cube_data ; 00579 cpl_imagelist ** cube_noise ; 00580 cpl_imagelist ** cube_interim_object ; 00581 cpl_imagelist ** cube_interim_sky ; 00582 00583 cpl_propertylist ** header_data ; 00584 cpl_propertylist ** header_noise ; 00585 cpl_propertylist ** header_sky ; 00586 00587 kmclipm_vector * telluric_data ; 00588 kmclipm_vector * telluric_noise ; 00589 00590 /* Initialise */ 00591 print_once = FALSE ; 00592 cube_counter_data = cube_counter_noise = 0 ; 00593 do_sky_subtraction = FALSE ; 00594 suppress_index = 0 ; 00595 mapping_id = -1 ; 00596 combined_data = combined_noise = NULL ; 00597 sky_as_object_frame = NULL ; 00598 00599 /* Check entries */ 00600 if (parlist == NULL || frameset == NULL) { 00601 cpl_msg_error(__func__, "Null Inputs") ; 00602 cpl_error_set(__func__, CPL_ERROR_NULL_INPUT) ; 00603 return -1 ; 00604 } 00605 00606 /* Get parameters */ 00607 par = cpl_parameterlist_find_const(parlist, "kmos.kmos_sci_red.flux"); 00608 flux = cpl_parameter_get_bool(par); 00609 par = cpl_parameterlist_find_const(parlist, "kmos.kmos_sci_red.background"); 00610 background = cpl_parameter_get_bool(par); 00611 par = cpl_parameterlist_find_const(parlist, "kmos.kmos_sci_red.imethod"); 00612 imethod = cpl_parameter_get_string(par) ; 00613 par = cpl_parameterlist_find_const(parlist, "kmos.kmos_sci_red.smethod"); 00614 smethod = cpl_parameter_get_string(par) ; 00615 par = cpl_parameterlist_find_const(parlist, 00616 "kmos.kmos_sci_red.neighborhoodRange"); 00617 neighborhoodRange = cpl_parameter_get_double(par) ; 00618 par = cpl_parameterlist_find_const(parlist, "kmos.kmos_sci_red.method"); 00619 comb_method = cpl_parameter_get_string(par) ; 00620 par = cpl_parameterlist_find_const(parlist, "kmos.kmos_sci_red.fmethod"); 00621 fmethod = cpl_parameter_get_string(par) ; 00622 par = cpl_parameterlist_find_const(parlist, "kmos.kmos_sci_red.filename"); 00623 filename = cpl_parameter_get_string(par) ; 00624 par = cpl_parameterlist_find_const(parlist, "kmos.kmos_sci_red.ifus"); 00625 ifus_txt = cpl_parameter_get_string(par) ; 00626 par = cpl_parameterlist_find_const(parlist, "kmos.kmos_sci_red.name"); 00627 name = cpl_parameter_get_string(par) ; 00628 kmos_band_pars_load(parlist, "kmos.kmos_sci_red"); 00629 par = cpl_parameterlist_find_const(parlist,"kmos.kmos_sci_red.extrapolate"); 00630 extrapolate = cpl_parameter_get_bool(par); 00631 par = cpl_parameterlist_find_const(parlist,"kmos.kmos_sci_red.fast_mode"); 00632 fast_mode = cpl_parameter_get_bool(par); 00633 par = cpl_parameterlist_find_const(parlist,"kmos.kmos_sci_red.edge_nan"); 00634 edge_nan = cpl_parameter_get_bool(par); 00635 par = cpl_parameterlist_find_const(parlist,"kmos.kmos_sci_red.no_combine"); 00636 no_combine = cpl_parameter_get_bool(par); 00637 par = cpl_parameterlist_find_const(parlist,"kmos.kmos_sci_red.no_subtract"); 00638 no_subtract = cpl_parameter_get_bool(par); 00639 par = cpl_parameterlist_find_const(parlist,"kmos.kmos_sci_red.sky_tweak"); 00640 sky_tweak = cpl_parameter_get_bool(par); 00641 par = cpl_parameterlist_find_const(parlist, 00642 "kmos.kmos_sci_red.discard_subband"); 00643 discard_subband = cpl_parameter_get_bool(par); 00644 par = cpl_parameterlist_find_const(parlist,"kmos.kmos_sci_red.tbsub"); 00645 tbsub = cpl_parameter_get_bool(par); 00646 par = cpl_parameterlist_find_const(parlist, "kmos.kmos_sci_red.oscan"); 00647 oscan = cpl_parameter_get_bool(par); 00648 par = cpl_parameterlist_find_const(parlist, "kmos.kmos_sci_red.pix_scale"); 00649 pix_scale = cpl_parameter_get_double(par) ; 00650 par = cpl_parameterlist_find_const(parlist, 00651 "kmos.kmos_sci_red.xcal_interpolation"); 00652 xcal_interpolation = cpl_parameter_get_bool(par); 00653 par = cpl_parameterlist_find_const(parlist, 00654 "kmos.kmos_sci_red.suppress_extension"); 00655 suppress_extension = cpl_parameter_get_bool(par); 00656 par = cpl_parameterlist_find_const(parlist, 00657 "kmos.kmos_sci_red.obj_sky_table"); 00658 fn_obj_sky_table = cpl_parameter_get_string(par) ; 00659 kmos_combine_pars_load(parlist, "kmos.kmos_sci_red", &cmethod, &cpos_rej, 00660 &cneg_rej, &citer, &cmin, &cmax, FALSE); 00661 par = cpl_parameterlist_find_const(parlist, 00662 "kmos.kmos_sci_red.velocity_offset"); 00663 velo_offset = cpl_parameter_get_double(par) ; 00664 velo_corr = 1. + velo_offset * 1000. / CPL_PHYS_C; 00665 velo_corr_ptr = &velo_corr; 00666 par = cpl_parameterlist_find_const(parlist, 00667 "kmos.kmos_sci_red.save_interims"); 00668 save_interims = cpl_parameter_get_bool(par); 00669 par = cpl_parameterlist_find_const(parlist, 00670 "kmos.kmos_sci_red.collapse_combined"); 00671 collapse_combined = cpl_parameter_get_bool(par); 00672 par = cpl_parameterlist_find_const(parlist, 00673 "kmos.kmos_sci_red.collapse_reconstructed"); 00674 collapse_reconstructed = cpl_parameter_get_bool(par); 00675 00676 /* Check Parameters */ 00677 if (strcmp(imethod, "NN") && strcmp(imethod, "lwNN") && 00678 strcmp(imethod, "swNN") && strcmp(imethod, "MS") && 00679 strcmp(imethod, "CS")) { 00680 cpl_msg_error(__func__, 00681 "imethod must be 'NN','lwNN','swNN','MS' or 'CS'") ; 00682 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00683 return -1 ; 00684 } 00685 if (strcmp(smethod, "NN") && strcmp(smethod, "CS")) { 00686 cpl_msg_error(__func__, 00687 "smethod must be 'NN' or 'CS'") ; 00688 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00689 return -1 ; 00690 } 00691 if (neighborhoodRange <= 0.0) { 00692 cpl_msg_error(__func__, 00693 "neighborhoodRange must be greater than 0.0") ; 00694 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00695 return -1 ; 00696 } 00697 if (strcmp(comb_method, "none") && strcmp(comb_method, "header") && 00698 strcmp(comb_method, "center") && strcmp(comb_method, "user")) { 00699 cpl_msg_error(__func__, 00700 "shift methods must be 'none', 'header', 'center' or 'user'") ; 00701 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00702 return -1 ; 00703 } 00704 if (strcmp(ifus_txt, "") && strcmp(name, "")) { 00705 cpl_msg_error(__func__, 00706 "name and IFU indices cannot be both provided") ; 00707 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00708 return -1 ; 00709 } 00710 if (strcmp(smethod, "NN") && strcmp(smethod, "CS")) { 00711 cpl_msg_error(__func__, "smethod must be 'NN' or 'CS'") ; 00712 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00713 return -1 ; 00714 } 00715 if (!strcmp(smethod, "NN") && extrapolate == TRUE) { 00716 cpl_msg_error(__func__, 00717 "extrapolation in not compatible with smethod 'NN'"); 00718 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00719 return -1 ; 00720 } 00721 if (!strcmp(smethod, "CS")) smethod = "BCS"; 00722 if (!strcmp(smethod, "BCS") && extrapolate == TRUE) 00723 extrapol_enum = BCS_NATURAL; 00724 else 00725 extrapol_enum = NONE_NANS; 00726 00727 if (no_subtract && sky_tweak) { 00728 cpl_msg_error(__func__,"no_subtract and sky_tweak cannot be both TRUE"); 00729 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00730 return -1 ; 00731 } 00732 if (pix_scale < 0.01 || pix_scale > 0.4) { 00733 cpl_msg_error(__func__, "pix_scale must be between 0.01 and 0.4"); 00734 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00735 return -1 ; 00736 } 00737 00738 if (cpl_frameset_count_tags(frameset, SCIENCE) == 1 || no_subtract) { 00739 no_combine = TRUE; 00740 cpl_msg_info(__func__, 00741 "--no_combine set to TRUE (1 SCIENCE frame or --no_subtract"); 00742 } 00743 00744 /* Identify the RAW and CALIB frames in the input frameset */ 00745 if (kmo_dfs_set_groups(frameset, "kmos_sci_red") != 1) { 00746 cpl_msg_error(__func__, "Cannot identify RAW and CALIB frames") ; 00747 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00748 return -1 ; 00749 } 00750 00751 /* Check the inputs consistency */ 00752 if (kmos_sci_red_check_inputs(frameset, pix_scale, &mapping_id) != 1) { 00753 cpl_msg_error(__func__, "Input frameset is not consistent") ; 00754 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00755 return -1 ; 00756 } 00757 if (mapping_id == 0) mapping_mode = NULL ; 00758 if (mapping_id == 1) mapping_mode = "mapping8" ; 00759 if (mapping_id == 2) mapping_mode = "mapping24" ; 00760 00761 /* Instrument setup */ 00762 suffix = kmo_dfs_get_suffix(kmo_dfs_get_frame(frameset,SCIENCE),TRUE,FALSE); 00763 cpl_msg_info(__func__, "Detected instrument setup: %s", suffix+1); 00764 cpl_free(suffix); 00765 00766 /* Load IFUS if specified */ 00767 if (strcmp(ifus_txt, "")) { 00768 nb_science = cpl_frameset_count_tags(frameset, SCIENCE); 00769 ifus = kmo_identify_values(ifus_txt); 00770 if (ifus == NULL || cpl_vector_get_size(ifus) != nb_science) { 00771 if (ifus != NULL) cpl_vector_delete(ifus); 00772 cpl_msg_error(__func__, "ifus size must match the science frames") ; 00773 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00774 return -1 ; 00775 } 00776 } else { 00777 ifus = NULL ; 00778 } 00779 00780 /* Mapping mode */ 00781 if (mapping_id > 0) { 00782 if ((ifus != NULL) || (strcmp(name, ""))) { 00783 cpl_msg_warning(__func__,"Mapping Mode ٍ+ Specific IFUs requested") ; 00784 } else { 00785 if (!strcmp(smethod, "BCS")) { 00786 extrapol_enum = BCS_NATURAL; 00787 cpl_msg_info(__func__, "Mapping Mode : extrapolation set") ; 00788 } 00789 } 00790 } 00791 00792 /* Check which IFUs are active for all frames */ 00793 unused_ifus_before = kmo_get_unused_ifus(frameset, 1, 1); 00794 unused_ifus_after = kmo_duplicate_unused_ifus(unused_ifus_before); 00795 kmo_print_unused_ifus(unused_ifus_before, FALSE); 00796 kmo_free_unused_ifus(unused_ifus_before); 00797 00798 /* Setup grid definition, wavelength start and end are set later */ 00799 kmclipm_setup_grid(&gd, imethod, neighborhoodRange, pix_scale, 0.); 00800 00801 /* Get frames */ 00802 xcal_frame = kmo_dfs_get_frame(frameset, XCAL) ; 00803 ycal_frame = kmo_dfs_get_frame(frameset, YCAL) ; 00804 lcal_frame = kmo_dfs_get_frame(frameset, LCAL) ; 00805 flat_frame = kmo_dfs_get_frame(frameset, MASTER_FLAT) ; 00806 ref_spectrum_frame = kmo_dfs_get_frame(frameset, OH_SPEC) ; 00807 nb_illum_corr = cpl_frameset_count_tags(frameset, ILLUM_CORR); 00808 00809 /* Get left and right bounds of IFUs from XCAL */ 00810 header_tmp = kmo_dfs_load_primary_header(frameset, XCAL); 00811 bounds = kmclipm_extract_bounds(header_tmp); 00812 cpl_propertylist_delete(header_tmp); 00813 if (bounds == NULL) { 00814 if (ifus != NULL) cpl_vector_delete(ifus); 00815 kmo_free_unused_ifus(unused_ifus_after); 00816 cpl_msg_error(__func__, "Cannot compute bounds") ; 00817 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00818 return -1 ; 00819 } 00820 00821 /* armNameStruct: objects that need to be reconstructed and their 00822 associated sky. Valid STD frames with objects and associated sky. 00823 Get valid object names, either one object name in several frames, 00824 or all object names */ 00825 if (!strcmp(fn_obj_sky_table, "")) { 00826 arm_name_struct = kmo_create_armNameStruct(frameset, SCIENCE, ifus, 00827 name, unused_ifus_after, bounds, mapping_mode, no_subtract); 00828 /* TODO : need to save ?? */ 00829 kmo_save_objSkyStruct(arm_name_struct->obj_sky_struct); 00830 } else { 00831 // read in obj/sky-table 00832 objSkyStruct *obj_sky_struct = NULL; 00833 obj_sky_struct = kmo_read_objSkyStruct(fn_obj_sky_table, frameset, 00834 SCIENCE); 00835 00836 /* Check if any sky-IFUs have been specified not beeing the */ 00837 /* same IFU# for objects. */ 00838 // In this case sky_tweak must be activated 00839 for (i = 0; i < obj_sky_struct->size; i++) { 00840 if (obj_sky_struct->table[i].objFrame != NULL) { 00841 for (j = 0; j < KMOS_NR_IFUS; j++) { 00842 if ((obj_sky_struct->table[i].skyIfus[j] > 0) && 00843 (sky_tweak == FALSE)) { 00844 kmo_print_objSkyStruct(obj_sky_struct); 00845 kmo_delete_objSkyStruct(obj_sky_struct); 00846 cpl_msg_error(__func__, 00847 "--sky_tweak needs to be set when sky are used from other IFUs"); 00848 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00849 return -1 ; 00850 } 00851 } 00852 } 00853 } 00854 arm_name_struct = kmo_create_armNameStruct2(obj_sky_struct, frameset, 00855 SCIENCE, ifus, name, unused_ifus_after, bounds, mapping_mode, 00856 no_subtract); 00857 } 00858 if (ifus != NULL) cpl_vector_delete(ifus); 00859 if (arm_name_struct == NULL) { 00860 kmo_free_unused_ifus(unused_ifus_after); 00861 cpl_free(bounds); 00862 cpl_msg_error(__func__, "Cannot compute ARM/name structure") ; 00863 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00864 return -1 ; 00865 } 00866 kmo_print_armNameStruct(frameset, arm_name_struct); 00867 00868 /* Check Telluric availability for each Object */ 00869 /* in mapping-mode check if for all IFUs there is either no */ 00870 /* telluric at all or the same number of tellurics than object names */ 00871 nb_telluric = cpl_frameset_count_tags(frameset, TELLURIC); 00872 if (nb_telluric > 0 && mapping_id > 0) { 00873 for (i = 0; i < arm_name_struct->nrNames; i++) { 00874 if (arm_name_struct->telluricCnt[i] != arm_name_struct->namesCnt[i] 00875 && (arm_name_struct->telluricCnt[i] != 0)) { 00876 cpl_msg_error(__func__, "Mosaics need a TELLURIC per detector"); 00877 cpl_error_set(__func__, CPL_ERROR_UNSUPPORTED_MODE) ; 00878 return -1 ; 00879 } 00880 } 00881 } 00882 00883 /* Allocate data */ 00884 cube_data=(cpl_imagelist**)cpl_calloc(KMOS_NR_IFUS, sizeof(cpl_imagelist*)); 00885 cube_noise=(cpl_imagelist**)cpl_calloc(KMOS_NR_IFUS,sizeof(cpl_imagelist*)); 00886 header_data = (cpl_propertylist**)cpl_calloc(KMOS_NR_IFUS, 00887 sizeof(cpl_propertylist*)); 00888 header_noise = (cpl_propertylist**)cpl_calloc(KMOS_NR_IFUS, 00889 sizeof(cpl_propertylist*)); 00890 if (save_interims) { 00891 cube_interim_object=(cpl_imagelist**)cpl_calloc(KMOS_NR_IFUS, 00892 sizeof(cpl_imagelist*)); 00893 cube_interim_sky =(cpl_imagelist**)cpl_calloc(KMOS_NR_IFUS, 00894 sizeof(cpl_imagelist*)); 00895 header_sky = (cpl_propertylist**)cpl_calloc(KMOS_NR_IFUS, 00896 sizeof(cpl_propertylist*)); 00897 } 00898 00899 /* Loop all science frames containing at least one object */ 00900 cpl_msg_info(__func__, "Reconstructing & saving cubes with objects"); 00901 for (sf = 0; sf < arm_name_struct->size; sf++) { 00902 fn_obj = cpl_frame_get_filename( 00903 arm_name_struct->obj_sky_struct->table[sf].objFrame); 00904 if ((main_header = kmclipm_propertylist_load(fn_obj, 0)) == NULL) { 00905 kmo_free_unused_ifus(unused_ifus_after); 00906 cpl_free(bounds); 00907 kmo_delete_armNameStruct(arm_name_struct); 00908 cpl_free(qc_output_unit) ; 00909 cpl_free(cube_data) ; 00910 cpl_free(cube_noise) ; 00911 cpl_free(header_data) ; 00912 cpl_free(header_noise) ; 00913 if (save_interims) { 00914 cpl_free(cube_interim_object) ; 00915 cpl_free(cube_interim_sky) ; 00916 cpl_free(header_sky) ; 00917 } 00918 cpl_msg_error(__func__, "Cannot Load main header"); 00919 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00920 return -1 ; 00921 } 00922 actual_msg_level = cpl_msg_get_level(); 00923 00924 /* Hold the QC parameter */ 00925 qc_output_unit = cpl_calloc(KMOS_NR_IFUS, sizeof(int)) ; 00926 00927 /* Reconstruct science frame */ 00928 cpl_msg_info(__func__, " > processing frame: %s", fn_obj); 00929 for (ifu_nr = 1; ifu_nr <= KMOS_NR_IFUS; ifu_nr++) { 00930 00931 /* Initialise */ 00932 cube_data[ifu_nr-1] = cube_noise[ifu_nr-1] = NULL ; 00933 00934 sky_ifu_nr = ifu_nr; 00935 det_nr = (ifu_nr - 1)/KMOS_IFUS_PER_DETECTOR + 1; 00936 00937 /* Get subheader data */ 00938 header_data[ifu_nr-1] = kmclipm_propertylist_load(fn_obj, det_nr); 00939 extname = kmo_extname_creator(ifu_frame, ifu_nr, EXT_DATA); 00940 kmclipm_update_property_string(header_data[ifu_nr-1], 00941 EXTNAME, extname, "FITS extension name"); 00942 cpl_free(extname); 00943 00944 if (arm_name_struct->name_ids[ifu_nr-1+sf*KMOS_NR_IFUS] >= 1) { 00945 // IFU is valid 00946 00947 /* Fill sky_as_object_frame, do_sky_subtraction and sky_frame */ 00948 sky_as_object_frame = NULL ; 00949 if ((arm_name_struct->obj_sky_struct->table[sf].skyFrames[ifu_nr-1] != NO_CORRESPONDING_SKYFRAME) && !no_subtract) { 00950 do_sky_subtraction = TRUE; 00951 if (no_subtract) sky_frame = NULL; 00952 else sky_frame = 00953 arm_name_struct->obj_sky_struct->table[sf].skyFrames[ifu_nr-1]; 00954 00955 if (sky_tweak){ 00956 sky_as_object_frame = sky_frame; 00957 sky_frame = NULL; 00958 sky_ifu_nr = arm_name_struct->obj_sky_struct->table[sf].skyIfus[ifu_nr-1]; 00959 } 00960 } else { 00961 do_sky_subtraction = FALSE; 00962 sky_frame = NULL; 00963 } 00964 00965 /* Get filter and setup grid definition using WAVE_BAND */ 00966 keyword = cpl_sprintf("%s%d%s", IFU_FILTID_PREFIX, det_nr, 00967 IFU_FILTID_POSTFIX); 00968 filter_id = cpl_propertylist_get_string(main_header, keyword); 00969 cpl_free(keyword); 00970 00971 if (print_once) cpl_msg_set_level(CPL_MSG_WARNING); 00972 print_once = TRUE; 00973 00974 band_table = kmo_dfs_load_table(frameset, WAVE_BAND, 1, 0); 00975 kmclipm_setup_grid_band_lcal(&gd, filter_id, band_table); 00976 cpl_table_delete(band_table); 00977 00978 cpl_msg_set_level(actual_msg_level); 00979 00980 /* calc WCS & update subheader */ 00981 kmo_calc_wcs_gd(main_header, header_data[ifu_nr-1], ifu_nr, gd); 00982 00983 /* Update some keywords */ 00984 kmclipm_update_property_int(header_data[ifu_nr-1], NAXIS, 3, 00985 "number of data axes"); 00986 kmclipm_update_property_int(header_data[ifu_nr-1], NAXIS1, 00987 gd.x.dim, "length of data axis 1"); 00988 kmclipm_update_property_int(header_data[ifu_nr-1], NAXIS2, 00989 gd.y.dim, "length of data axis 2"); 00990 kmclipm_update_property_int(header_data[ifu_nr-1], NAXIS3, 00991 gd.l.dim, "length of data axis 3"); 00992 00993 /* Option save_interim only applies if sky_tweak is used */ 00994 if (save_interims && sky_as_object_frame != NULL) { 00995 header_tmp = kmclipm_propertylist_load( 00996 cpl_frame_get_filename(sky_as_object_frame), 0); 00997 00998 header_sky[ifu_nr-1]=kmclipm_propertylist_load( 00999 cpl_frame_get_filename(sky_as_object_frame),det_nr); 01000 extname = kmo_extname_creator(ifu_frame, ifu_nr, EXT_DATA); 01001 kmclipm_update_property_string(header_sky[ifu_nr-1], 01002 EXTNAME, extname, "FITS extension name"); 01003 cpl_free(extname); 01004 01005 kmo_calc_wcs_gd(header_tmp, header_sky[ifu_nr-1], 01006 ifu_nr, gd); 01007 kmclipm_update_property_int(header_sky[ifu_nr-1], NAXIS, 3, 01008 "number of data axes"); 01009 kmclipm_update_property_int(header_sky[ifu_nr-1], NAXIS1, 01010 gd.x.dim, "length of data axis 1"); 01011 kmclipm_update_property_int(header_sky[ifu_nr-1], NAXIS2, 01012 gd.y.dim, "length of data axis 2"); 01013 kmclipm_update_property_int(header_sky[ifu_nr-1], NAXIS3, 01014 gd.l.dim, "length of data axis 3"); 01015 cpl_propertylist_delete(header_tmp); 01016 } 01017 01018 /* OH lines based lambda correction */ 01019 oh_lcorr_coeffs = NULL ; 01020 if (ref_spectrum_frame != NULL) { 01021 if (kmo_reconstruct_sci(ifu_nr, bounds[2*(ifu_nr-1)], 01022 bounds[2*(ifu_nr-1)+1], 01023 arm_name_struct->obj_sky_struct->table[sf].objFrame, 01024 SCIENCE, NULL, NULL, flat_frame, xcal_frame, 01025 ycal_frame, lcal_frame, NULL, NULL, &gd, &tmp_cube1, 01026 &tmp_cube2, FALSE, FALSE, xcal_interpolation, 01027 oscan) == CPL_ERROR_NONE) { 01028 oh_lcorr_coeffs = kmo_lcorr_get(tmp_cube1, 01029 header_data[ifu_nr-1], ref_spectrum_frame, gd, 01030 filter_id, ifu_nr); 01031 cpl_imagelist_delete(tmp_cube1); 01032 cpl_imagelist_delete(tmp_cube2); 01033 } 01034 } 01035 01036 /* Reconstruct object */ 01037 kmo_reconstruct_sci(ifu_nr, bounds[2*(ifu_nr-1)], 01038 bounds[2*(ifu_nr-1)+1], 01039 arm_name_struct->obj_sky_struct->table[sf].objFrame, 01040 SCIENCE, sky_frame, SCIENCE, flat_frame, xcal_frame, 01041 ycal_frame, lcal_frame, oh_lcorr_coeffs, velo_corr_ptr, 01042 &gd, &cube_data[ifu_nr-1], &cube_noise[ifu_nr-1], flux, 01043 background, xcal_interpolation, oscan); 01044 01045 if (oh_lcorr_coeffs != NULL) 01046 cpl_polynomial_delete(oh_lcorr_coeffs); 01047 01048 if (cpl_error_get_code() != CPL_ERROR_NONE) { 01049 kmo_free_unused_ifus(unused_ifus_after); 01050 cpl_free(bounds); 01051 kmo_delete_armNameStruct(arm_name_struct); 01052 for (j=0 ; j<ifu_nr-1 ; j++) { 01053 if (cube_data[j] != NULL) 01054 cpl_imagelist_delete(cube_data[j]); 01055 if (cube_noise[j] != NULL) 01056 cpl_imagelist_delete(cube_noise[j]); 01057 cpl_propertylist_delete(header_data[j]); 01058 cpl_propertylist_delete(header_noise[j]); 01059 if (save_interims) { 01060 cpl_imagelist_delete(cube_interim_object[j]); 01061 cpl_imagelist_delete(cube_interim_sky[j]); 01062 cpl_propertylist_delete(header_sky[j]); 01063 } 01064 } 01065 cpl_propertylist_delete(header_data[ifu_nr-1]); 01066 cpl_free(cube_data) ; 01067 cpl_free(cube_noise) ; 01068 cpl_free(header_data) ; 01069 cpl_free(header_noise) ; 01070 if (save_interims) { 01071 cpl_free(cube_interim_object) ; 01072 cpl_free(cube_interim_sky) ; 01073 cpl_free(header_sky) ; 01074 } 01075 cpl_msg_error(__func__, "Cannot reconstruct"); 01076 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 01077 return -1 ; 01078 } 01079 01080 /* If sky_tweak is set, reconstruct sky frame as object */ 01081 /* use kmos_priv_sky_tweak to subtract a modified sky cube */ 01082 if (do_sky_subtraction && sky_tweak) { 01083 01084 /* OH lines based lambda correction */ 01085 oh_lcorr_coeffs = NULL ; 01086 if (ref_spectrum_frame != NULL) { 01087 if (kmo_reconstruct_sci(sky_ifu_nr, 01088 bounds[2*(sky_ifu_nr-1)], 01089 bounds[2*(sky_ifu_nr-1)+1], 01090 sky_as_object_frame, SCIENCE, NULL, NULL, 01091 flat_frame, xcal_frame, ycal_frame, 01092 lcal_frame, NULL, NULL, &gd, &tmp_cube1, 01093 &tmp_cube2, FALSE, FALSE, 01094 xcal_interpolation, 01095 oscan) == CPL_ERROR_NONE) { 01096 oh_lcorr_coeffs = kmo_lcorr_get(tmp_cube1, 01097 header_data[ifu_nr-1], ref_spectrum_frame, 01098 gd, filter_id, ifu_nr); 01099 cpl_imagelist_delete(tmp_cube1); 01100 cpl_imagelist_delete(tmp_cube2); 01101 } 01102 } 01103 01104 /* Reconstruct object */ 01105 kmo_reconstruct_sci(sky_ifu_nr, 01106 bounds[2*(sky_ifu_nr-1)], 01107 bounds[2*(sky_ifu_nr-1)+1], sky_as_object_frame, 01108 SCIENCE, sky_frame, SCIENCE, flat_frame, 01109 xcal_frame, ycal_frame, lcal_frame, oh_lcorr_coeffs, 01110 velo_corr_ptr, &gd, &tmp_cube1, &tmp_cube2, 01111 flux, background, xcal_interpolation, oscan); 01112 01113 cpl_imagelist_delete(tmp_cube2); 01114 if (oh_lcorr_coeffs != NULL) 01115 cpl_polynomial_delete(oh_lcorr_coeffs); 01116 01117 if (save_interims && (sky_as_object_frame != NULL)) { 01118 cube_interim_object[ifu_nr-1]= 01119 cpl_imagelist_duplicate(cube_data[ifu_nr-1]); 01120 cube_interim_sky[ifu_nr-1]= 01121 cpl_imagelist_duplicate(tmp_cube1); 01122 } 01123 01124 /* Apply the SKY tweaking */ 01125 tmp_cube2 = kmos_priv_sky_tweak(cube_data[ifu_nr-1], 01126 tmp_cube1,header_data[ifu_nr-1], .3, tbsub, 01127 ifu_nr, discard_subband); 01128 cpl_imagelist_delete(cube_data[ifu_nr-1]); 01129 cpl_imagelist_delete(tmp_cube1); 01130 cube_data[ifu_nr-1] = tmp_cube2 ; 01131 } 01132 01133 /* Maintain flux constant in case the pixscale is diff */ 01134 /* For example, pixscale=0.1 => images 28x28 => scaling=4 */ 01135 tmpImg = cpl_imagelist_get(cube_data[ifu_nr-1], 0); 01136 scaling = (cpl_image_get_size_x(tmpImg) * 01137 cpl_image_get_size_y(tmpImg)) / 01138 (KMOS_SLITLET_X*KMOS_SLITLET_Y); 01139 cpl_imagelist_divide_scalar(cube_data[ifu_nr-1], scaling); 01140 if (cube_noise[ifu_nr-1] != NULL) { 01141 cpl_imagelist_divide_scalar(cube_noise[ifu_nr-1], scaling); 01142 } 01143 01144 /* Divide cube by telluric correction */ 01145 qc_output_unit[ifu_nr-1] = 0 ; 01146 if (nb_telluric > 0) { 01147 /* Create the mapping string */ 01148 if (mapping_id == 0) { 01149 /* Get object name */ 01150 keyword = cpl_sprintf("%s%d%s", IFU_NAME_PREFIX, 01151 ifu_nr, IFU_NAME_POSTFIX); 01152 tmp_str = cpl_propertylist_get_string( 01153 header_data[ifu_nr-1], keyword); 01154 cpl_free(keyword); 01155 } else if (mapping_id == 1) { 01156 tmp_str = "mapping8"; 01157 } else if (mapping_id == 2) { 01158 tmp_str = "mapping24"; 01159 } 01160 01161 /* Check if the nb of occurences of the object name */ 01162 /* is the same as the number of found tellurics for */ 01163 /* this object (which can be on different arms) */ 01164 telluric_ok = FALSE; 01165 for (jj = 0; jj < arm_name_struct->nrNames; jj++) { 01166 if ((!strcmp(arm_name_struct->names[jj], tmp_str) || 01167 !strcmp(arm_name_struct->names[jj], IFUS_USER_DEFINED)) && 01168 arm_name_struct->telluricCnt[jj] == arm_name_struct->namesCnt[jj]) { 01169 telluric_ok = TRUE; 01170 break; 01171 } 01172 } 01173 01174 if (telluric_ok) { 01175 telluric_data = kmo_tweak_load_telluric(frameset, 01176 ifu_nr, FALSE, no_subtract, &ifu_nr_telluric); 01177 if (telluric_data != NULL) { 01178 telluric_frame=kmo_dfs_get_frame(frameset,TELLURIC); 01179 kmo_init_fits_desc(&desc_telluric); 01180 desc_telluric=kmo_identify_fits_header( 01181 cpl_frame_get_filename(telluric_frame)); 01182 01183 /* Get the index of the telluric noise */ 01184 idx = kmo_identify_index_desc(desc_telluric, 01185 ifu_nr, TRUE); 01186 if (desc_telluric.sub_desc[idx-1].valid_data) { 01187 /* Load noise if present */ 01188 telluric_noise = kmo_tweak_load_telluric( 01189 frameset,ifu_nr, TRUE, no_subtract, 01190 &ifu_nr_telluric); 01191 } else { 01192 telluric_noise = NULL ; 01193 } 01194 kmo_free_fits_desc(&desc_telluric); 01195 01196 kmo_arithmetic_3D_1D(cube_data[ifu_nr-1], 01197 telluric_data, cube_noise[ifu_nr-1], 01198 telluric_noise, "/"); 01199 if (telluric_noise != NULL) 01200 kmclipm_vector_delete(telluric_noise); 01201 kmclipm_vector_delete(telluric_data); 01202 01203 /* Convert to ERG if zpoint available */ 01204 zpoint = kmos_sci_red_get_zpoint(telluric_frame, 01205 ifu_nr_telluric) ; 01206 if (zpoint > 0.0) { 01207 f_0 = kmos_sci_red_get_f0(filter_id, gd.l.dim, 01208 gd.l.start, gd.l.delta) ; 01209 if (f_0 > 0.0) { 01210 conversion = f_0*pow(10,-0.4*zpoint)/10.0 ; 01211 cpl_msg_info(__func__, 01212 "Apply Unit conversion factor %g for IFU nb %d", 01213 conversion, ifu_nr) ; 01214 kmo_arithmetic_3D_scalar( 01215 cube_data[ifu_nr-1], conversion, 01216 cube_noise[ifu_nr-1], "*") ; 01217 qc_output_unit[ifu_nr-1] = 1 ; 01218 } 01219 } 01220 } 01221 } 01222 } 01223 01224 /* Divide cube by illumination correction */ 01225 if (nb_illum_corr > 0) { 01226 illum_data = kmo_dfs_load_image(frameset, ILLUM_CORR, 01227 ifu_nr, FALSE, FALSE, NULL); 01228 illum_noise = kmo_dfs_load_image(frameset, ILLUM_CORR, 01229 ifu_nr, TRUE, FALSE, NULL); 01230 if (cpl_error_get_code() != CPL_ERROR_NONE) { 01231 cpl_msg_warning(__func__, 01232 "No illumination correction for IFU %d available! " 01233 "Proceeding anyway.", ifu_nr); 01234 if (illum_data != NULL) cpl_image_delete(illum_data); 01235 if (illum_noise != NULL) cpl_image_delete(illum_noise); 01236 cpl_error_reset(); 01237 } else { 01238 kmo_arithmetic_3D_2D(cube_data[ifu_nr-1], illum_data, 01239 cube_noise[ifu_nr-1], illum_noise, "/"); 01240 cpl_image_delete(illum_data); 01241 cpl_image_delete(illum_noise); 01242 } 01243 } 01244 } 01245 01246 /* Duplicate subheader data */ 01247 header_noise[ifu_nr-1] = cpl_propertylist_duplicate( 01248 header_data[ifu_nr-1]); 01249 extname = kmo_extname_creator(ifu_frame, ifu_nr, EXT_NOISE); 01250 kmclipm_update_property_string(header_noise[ifu_nr-1], EXTNAME, 01251 extname, "FITS extension name"); 01252 cpl_free(extname); 01253 } 01254 cpl_propertylist_delete(main_header) ; 01255 01256 /* Convert from ADU->ADU/sec by dividing by DIT */ 01257 plist = cpl_propertylist_load(cpl_frame_get_filename( 01258 arm_name_struct->obj_sky_struct->table[sf].objFrame), 0); 01259 dit = kmos_pfits_get_dit(plist) ; 01260 cpl_propertylist_delete(plist) ; 01261 for (ifu_nr = 1; ifu_nr <= KMOS_NR_IFUS; ifu_nr++) { 01262 /* Data / DIT */ 01263 if (cube_data[ifu_nr-1] != NULL) { 01264 kmo_arithmetic_3D_scalar(cube_data[ifu_nr-1], dit, 01265 cube_noise[ifu_nr-1], "/") ; 01266 } 01267 } 01268 01269 /* Count number of reconstructed data- and noise-cubes */ 01270 for (ifu_nr = 1; ifu_nr <= KMOS_NR_IFUS; ifu_nr++) { 01271 if (cube_data[ifu_nr-1] != NULL) cube_counter_data++; 01272 if (cube_noise[ifu_nr-1] != NULL) cube_counter_noise++; 01273 } 01274 01275 /* Save reconstructed cubes of science frame */ 01276 if (cube_counter_data > 0) { 01277 cpl_msg_info(__func__, " > saving..."); 01278 01279 if (!suppress_extension) { 01280 fn_out = fn_obj; 01281 01282 int nr_found = 0; 01283 // remove any path-elements from filename and use it as suffix 01284 split = kmo_strsplit(fn_out, "/", &nr_found); 01285 fn_suffix = cpl_sprintf("_%s", split[nr_found-1]); 01286 kmo_strfreev(split); 01287 01288 // remove '.fits' at the end if there is any 01289 char *fff = fn_suffix; 01290 fff += strlen(fn_suffix)-5; 01291 if (strcmp(fff, ".fits") == 0) { 01292 fn_suffix[strlen(fn_suffix)-5] = '\0'; 01293 } 01294 } else { 01295 fn_suffix = cpl_sprintf("_%d", suppress_index++); 01296 } 01297 01298 fn_out = RECONSTRUCTED_CUBE; 01299 01300 /* Create Primary Header */ 01301 kmo_dfs_save_main_header(frameset, fn_out, fn_suffix, 01302 arm_name_struct->obj_sky_struct->table[sf].objFrame, NULL, 01303 parlist, cpl_func); 01304 /* save intermediate products (only in sky tweak case) */ 01305 if (save_interims && (sky_as_object_frame != NULL)) { 01306 kmo_dfs_save_main_header(frameset, INTERIM_OBJECT_CUBE, 01307 fn_suffix, 01308 arm_name_struct->obj_sky_struct->table[sf].objFrame, 01309 NULL, parlist, cpl_func); 01310 kmo_dfs_save_main_header(frameset, INTERIM_OBJECT_SKY, 01311 fn_suffix, 01312 arm_name_struct->obj_sky_struct->table[sf].objFrame, 01313 NULL, parlist, cpl_func); 01314 } 01315 01316 /* Loop on IFUs */ 01317 for (ifu_nr = 1; ifu_nr <= KMOS_NR_IFUS; ifu_nr++) { 01318 01319 /* Hold the QC */ 01320 if (qc_output_unit[ifu_nr-1] == 0) 01321 kmclipm_update_property_string(header_data[ifu_nr-1], 01322 "ESO QC CUBE_UNIT", "ADU/sec", "Cube Unit"); 01323 else 01324 kmclipm_update_property_string(header_data[ifu_nr-1], 01325 "ESO QC CUBE_UNIT", "ERG/sec/cm2/A", "Cube Unit"); 01326 01327 /* Save data Extension */ 01328 kmo_dfs_save_cube(cube_data[ifu_nr-1], fn_out, fn_suffix, 01329 header_data[ifu_nr-1], 0./0.); 01330 cpl_imagelist_delete(cube_data[ifu_nr-1]); 01331 01332 /* Save noise Extension */ 01333 if (cube_counter_noise > 0) { 01334 kmo_dfs_save_cube(cube_noise[ifu_nr-1], fn_out, fn_suffix, 01335 header_noise[ifu_nr-1], 0./0.); 01336 } 01337 cpl_propertylist_delete(header_noise[ifu_nr-1]); 01338 cpl_imagelist_delete(cube_noise[ifu_nr-1]); 01339 01340 /* save intermediate products (only in sky tweak case */ 01341 if (save_interims && (sky_as_object_frame != NULL)) { 01342 kmo_dfs_save_cube(cube_interim_object[ifu_nr-1], 01343 INTERIM_OBJECT_CUBE, fn_suffix, 01344 header_data[ifu_nr-1], 0./0.); 01345 kmo_dfs_save_cube(cube_interim_sky[ifu_nr-1], 01346 INTERIM_OBJECT_SKY, fn_suffix, header_sky[ifu_nr-1], 01347 0./0.); 01348 } 01349 cpl_propertylist_delete(header_data[ifu_nr-1]); 01350 if (save_interims) { 01351 cpl_imagelist_delete(cube_interim_object[ifu_nr-1]); 01352 cpl_imagelist_delete(cube_interim_sky[ifu_nr-1]); 01353 cpl_propertylist_delete(header_sky[ifu_nr-1]); 01354 } 01355 } 01356 cpl_free(fn_suffix); 01357 } else { 01358 cpl_msg_info(__func__, " > all IFUs invalid, don't save"); 01359 for (ifu_nr = 1; ifu_nr <= KMOS_NR_IFUS; ifu_nr++) { 01360 cpl_propertylist_delete(header_data[ifu_nr-1]); 01361 cpl_propertylist_delete(header_noise[ifu_nr-1]); 01362 } 01363 } 01364 cpl_free(qc_output_unit) ; 01365 } 01366 cpl_free(bounds) ; 01367 cpl_free(cube_data); 01368 cpl_free(cube_noise); 01369 cpl_free(header_data); 01370 cpl_free(header_noise); 01371 if (save_interims) { 01372 cpl_free(cube_interim_object); 01373 cpl_free(cube_interim_sky); 01374 cpl_free(header_sky); 01375 } 01376 01377 kmo_print_unused_ifus(unused_ifus_after, TRUE); 01378 kmo_free_unused_ifus(unused_ifus_after); 01379 01380 /* Combine */ 01381 suppress_index = 0; 01382 if (!no_combine) { 01383 cpl_msg_info(__func__, "Combining reconstructed objects"); 01384 if (mapping_id==0 || (mapping_id>0 && (strcmp(ifus_txt, "") || 01385 strcmp(name,"")))){ 01386 /* Loop all available objects */ 01387 for (i = 0; i < arm_name_struct->nrNames; i++) { 01388 cpl_msg_info(__func__, 01389 " > object: %s", arm_name_struct->names[i]); 01390 nr_data = arm_name_struct->namesCnt[i]; 01391 cube_data=(cpl_imagelist**)cpl_calloc(nr_data, 01392 sizeof(cpl_imagelist*)); 01393 cube_noise=(cpl_imagelist**)cpl_calloc(nr_data, 01394 sizeof(cpl_imagelist*)); 01395 header_data=(cpl_propertylist**)cpl_calloc(nr_data, 01396 sizeof(cpl_propertylist*)); 01397 header_noise=(cpl_propertylist**)cpl_calloc(nr_data, 01398 sizeof(cpl_propertylist*)); 01399 01400 /* Initialise */ 01401 for (jj = 0; jj < nr_data; jj++) { 01402 cube_data[jj] = NULL ; 01403 cube_noise[jj] = NULL ; 01404 header_data[jj] = NULL ; 01405 header_noise[jj] = NULL ; 01406 } 01407 01408 // setup cube-list and header-list for kmo_priv_combine() 01409 cube_counter_data = 0; 01410 cube_counter_noise = 0; 01411 tmp_frame = kmo_dfs_get_frame(frameset, RECONSTRUCTED_CUBE); 01412 while (tmp_frame != NULL ) { 01413 fn_reconstr = cpl_frame_get_filename(tmp_frame); 01414 main_header = kmclipm_propertylist_load(fn_reconstr, 0); 01415 01416 kmo_init_fits_desc(&desc1); 01417 desc1 = kmo_identify_fits_header(fn_reconstr); 01418 01419 for (ifu_nr = 1; ifu_nr <= KMOS_NR_IFUS; ifu_nr++) { 01420 // check if object-name equals the one in our list 01421 keyword = cpl_sprintf("%s%d%s", IFU_NAME_PREFIX, ifu_nr, 01422 IFU_NAME_POSTFIX); 01423 tmp_str=cpl_propertylist_get_string(main_header, 01424 keyword); 01425 cpl_free(keyword); 01426 01427 if (!strcmp(arm_name_struct->names[i],tmp_str) || 01428 !strcmp(arm_name_struct->names[i], IFUS_USER_DEFINED)) { 01429 /* Found object-IFU with matching name */ 01430 /* Load data & subheader */ 01431 idx=kmo_identify_index(fn_reconstr,ifu_nr,FALSE); 01432 01433 if (desc1.sub_desc[idx-1].valid_data) { 01434 cube_data[cube_counter_data] = 01435 kmclipm_imagelist_load(fn_reconstr, 01436 CPL_TYPE_FLOAT, idx); 01437 /* Set cubes borders (1 pixel) to Nan to avoid jumps in combined cube */ 01438 if (edge_nan) { 01439 kmo_edge_nan(cube_data[cube_counter_data], 01440 ifu_nr); 01441 } 01442 01443 header_data[cube_counter_data] = 01444 kmclipm_propertylist_load(fn_reconstr, 01445 idx); 01446 cpl_propertylist_update_string( 01447 header_data[cube_counter_data], 01448 "ESO PRO FRNAME", fn_reconstr); 01449 cpl_propertylist_update_int( 01450 header_data[cube_counter_data], 01451 "ESO PRO IFUNR", ifu_nr); 01452 cube_counter_data++; 01453 } 01454 01455 /* Load noise & subheader (if existing) */ 01456 if (desc1.ex_noise) { 01457 idx = kmo_identify_index(fn_reconstr, ifu_nr, 01458 TRUE); 01459 if (desc1.sub_desc[idx-1].valid_data) { 01460 cube_noise[cube_counter_noise] = 01461 kmclipm_imagelist_load(fn_reconstr, 01462 CPL_TYPE_FLOAT, idx); 01463 if (edge_nan) { 01464 kmo_edge_nan( 01465 cube_noise[cube_counter_noise], 01466 ifu_nr); 01467 } 01468 header_noise[cube_counter_noise] = 01469 kmclipm_propertylist_load(fn_reconstr, 01470 idx); 01471 cube_counter_noise++; 01472 } 01473 } 01474 cpl_error_reset(); 01475 } 01476 } 01477 kmo_free_fits_desc(&desc1); 01478 cpl_propertylist_delete(main_header); 01479 tmp_frame = kmo_dfs_get_frame(frameset, NULL); 01480 } 01481 01482 if (cube_counter_noise == 0) { 01483 cpl_free(cube_noise); 01484 cube_noise = NULL ; 01485 } 01486 01487 if (cube_counter_data > 1) { 01488 if (cube_counter_data == cube_counter_noise || 01489 cube_counter_noise == 0) { 01490 kmo_priv_combine(cube_data, cube_noise, header_data, 01491 header_noise, cube_counter_data, 01492 cube_counter_noise, arm_name_struct->names[i], 01493 "", comb_method, smethod, fmethod, filename, 01494 cmethod, cpos_rej, cneg_rej, citer, cmin, cmax, 01495 extrapol_enum, flux, &combined_data, 01496 &combined_noise, &exp_mask); 01497 } else { 01498 cpl_msg_error(__func__, "Data/Noise cubes nb mismatch"); 01499 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 01500 return -1 ; 01501 } 01502 } else if (cube_counter_data == 1) { 01503 cpl_msg_warning(__func__, 01504 "Only one reconstructed cube with this object"); 01505 combined_data = cpl_imagelist_duplicate(cube_data[0]); 01506 tmpImg = cpl_imagelist_get(combined_data, 0); 01507 exp_mask = cpl_image_new(cpl_image_get_size_x(tmpImg), 01508 cpl_image_get_size_y(tmpImg), CPL_TYPE_FLOAT); 01509 kmo_image_fill(exp_mask, 1.); 01510 01511 combined_noise = NULL ; 01512 if (cube_counter_noise > 0 && cube_noise[0] != NULL) { 01513 combined_noise = cpl_imagelist_duplicate(cube_noise[0]); 01514 } 01515 } else { 01516 cpl_msg_error(__func__, "No cube found with this obj name"); 01517 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 01518 return -1 ; 01519 } 01520 for (jj = 0; jj < nr_data; jj++) { 01521 cpl_imagelist_delete(cube_data[jj]); 01522 if (cube_counter_noise > 0) 01523 cpl_imagelist_delete(cube_noise[jj]); 01524 } 01525 cpl_free(cube_data); 01526 cpl_free(cube_noise); 01527 01528 fn_out = COMBINED_CUBE; 01529 if (!suppress_extension) { 01530 char tmp_suffix[1024]; 01531 tmp_suffix[0] = '\0'; 01532 01533 if (arm_name_struct->telluricCnt[i] == 01534 arm_name_struct->namesCnt[i]) { 01535 strcat(tmp_suffix, "_telluric"); 01536 } 01537 if (nb_illum_corr > 0) strcat(tmp_suffix, "_illum"); 01538 if (sky_tweak) strcat(tmp_suffix, "_skytweak"); 01539 01540 if (strlen(tmp_suffix) > 0) { 01541 fn_suffix = cpl_sprintf("_%s_%s", 01542 arm_name_struct->names[i], tmp_suffix); 01543 } else { 01544 fn_suffix = cpl_sprintf("_%s", 01545 arm_name_struct->names[i]); 01546 } 01547 } else { 01548 fn_suffix = cpl_sprintf("_%d", suppress_index++); 01549 } 01550 01551 // save combined cube 01552 tmp_frame = kmo_dfs_get_frame(frameset, RECONSTRUCTED_CUBE); 01553 kmo_dfs_save_main_header(frameset, fn_out, fn_suffix, 01554 tmp_frame, NULL, parlist, cpl_func); 01555 kmo_dfs_save_main_header(frameset, EXP_MASK, fn_suffix, 01556 tmp_frame, NULL, parlist, cpl_func); 01557 kmo_dfs_save_cube(combined_data, fn_out, fn_suffix, 01558 header_data[0], 0./0.); 01559 kmo_dfs_save_image(exp_mask, EXP_MASK, fn_suffix, 01560 header_data[0], 0./0.); 01561 cpl_image_delete(exp_mask); 01562 01563 if (header_noise[0] == NULL) { 01564 header_noise[0]=cpl_propertylist_duplicate(header_data[0]); 01565 tmp_str=cpl_propertylist_get_string(header_data[0],EXTNAME); 01566 kmo_extname_extractor(tmp_str, &ft, &tmp_int, content); 01567 extname = kmo_extname_creator(ifu_frame, tmp_int,EXT_NOISE); 01568 kmclipm_update_property_string(header_noise[0], EXTNAME, 01569 extname, "FITS extension name"); 01570 cpl_free(extname); 01571 } 01572 kmo_dfs_save_cube(combined_noise, fn_out, fn_suffix, 01573 header_noise[0], 0./0.); 01574 01575 cpl_free(fn_suffix); 01576 for (jj = 0; jj < nr_data; jj++) { 01577 cpl_propertylist_delete(header_data[jj]); 01578 cpl_propertylist_delete(header_noise[jj]); 01579 } 01580 cpl_free(header_data); 01581 cpl_free(header_noise); 01582 cpl_imagelist_delete(combined_data); 01583 if (combined_noise != NULL) 01584 cpl_imagelist_delete(combined_noise); 01585 } 01586 } else { 01587 /* Mapping_mode */ 01588 nr_data = KMOS_NR_IFUS * 01589 cpl_frameset_count_tags(frameset,RECONSTRUCTED_CUBE); 01590 cube_data = (cpl_imagelist**)cpl_calloc(nr_data, 01591 sizeof(cpl_imagelist*)); 01592 cube_noise = (cpl_imagelist**)cpl_calloc(nr_data, 01593 sizeof(cpl_imagelist*)); 01594 header_data=(cpl_propertylist**)cpl_calloc(nr_data, 01595 sizeof(cpl_propertylist*)); 01596 header_noise=(cpl_propertylist**)cpl_calloc(nr_data, 01597 sizeof(cpl_propertylist*)); 01598 01599 /* Initialise */ 01600 for (jj = 0; jj < nr_data; jj++) { 01601 cube_data[jj] = NULL ; 01602 cube_noise[jj] = NULL ; 01603 header_data[jj] = NULL ; 01604 header_noise[jj] = NULL ; 01605 } 01606 01607 cube_counter_data = 0; 01608 cube_counter_noise = 0; 01609 tmp_frame = kmo_dfs_get_frame(frameset, RECONSTRUCTED_CUBE); 01610 while (tmp_frame != NULL ) { 01611 fn_reconstr = cpl_frame_get_filename(tmp_frame); 01612 01613 kmo_init_fits_desc(&desc1); 01614 desc1 = kmo_identify_fits_header(fn_reconstr); 01615 for (ifu_nr = 1; ifu_nr <= KMOS_NR_IFUS; ifu_nr++) { 01616 idx = kmo_identify_index(fn_reconstr, ifu_nr, FALSE); 01617 01618 if (desc1.sub_desc[idx-1].valid_data) { 01619 cpl_msg_debug(__func__, 01620 "Load in cube_data - Frame: %s IFU: %d", 01621 fn_reconstr, ifu_nr) ; 01622 cube_data[cube_counter_data] = kmclipm_imagelist_load( 01623 fn_reconstr, CPL_TYPE_FLOAT, idx); 01624 if (edge_nan) 01625 kmo_edge_nan(cube_data[cube_counter_data], ifu_nr); 01626 01627 if (fast_mode) { 01628 tmpImg = cpl_imagelist_collapse_median_create( 01629 cube_data[cube_counter_data]); 01630 tmp_cube1 = cpl_imagelist_new(); 01631 cpl_imagelist_set(tmp_cube1, tmpImg, 0); 01632 cpl_imagelist_delete(cube_data[cube_counter_data]); 01633 cube_data[cube_counter_data] = tmp_cube1; 01634 } 01635 01636 cpl_msg_debug(__func__, 01637 "Load in header_data - Frame: %s IFU: %d", 01638 fn_reconstr, ifu_nr) ; 01639 header_data[cube_counter_data] = 01640 kmclipm_propertylist_load(fn_reconstr, idx); 01641 cpl_propertylist_update_string( 01642 header_data[cube_counter_data], 01643 "ESO PRO FRNAME", fn_reconstr); 01644 cpl_propertylist_update_int( 01645 header_data[cube_counter_data], 01646 "ESO PRO IFUNR", ifu_nr); 01647 cube_counter_data++; 01648 cpl_msg_debug(__func__, "cube_counter_data: %d\n", 01649 cube_counter_data) ; 01650 } 01651 01652 /* Load noise & subheader (if existing) */ 01653 if (desc1.ex_noise) { 01654 idx = kmo_identify_index(fn_reconstr,ifu_nr,TRUE); 01655 if (desc1.sub_desc[idx-1].valid_data) { 01656 cpl_msg_debug(__func__, 01657 "Load in cube_noise - Frame: %s IFU: %d", 01658 fn_reconstr, ifu_nr) ; 01659 cube_noise[cube_counter_noise] = 01660 kmclipm_imagelist_load(fn_reconstr, 01661 CPL_TYPE_FLOAT, idx); 01662 01663 if (edge_nan) 01664 kmo_edge_nan(cube_noise[cube_counter_noise], 01665 ifu_nr); 01666 if (fast_mode) { 01667 tmpImg=cpl_imagelist_collapse_median_create( 01668 cube_noise[cube_counter_noise]); 01669 tmp_cube1 = cpl_imagelist_new(); 01670 cpl_imagelist_set(tmp_cube1, tmpImg, 0); 01671 cpl_imagelist_delete( 01672 cube_noise[cube_counter_noise]); 01673 cube_noise[cube_counter_noise] = tmp_cube1; 01674 } 01675 cpl_msg_debug(__func__, 01676 "Load in header_noise - Frame: %s IFU: %d", 01677 fn_reconstr, ifu_nr) ; 01678 header_noise[cube_counter_noise] = 01679 kmclipm_propertylist_load(fn_reconstr, idx); 01680 cube_counter_noise++; 01681 cpl_msg_debug(__func__, "cube_counter_noise: %d\n", 01682 cube_counter_noise) ; 01683 } 01684 } 01685 cpl_error_reset(); 01686 } 01687 kmo_free_fits_desc(&desc1); 01688 tmp_frame = kmo_dfs_get_frame(frameset, NULL); 01689 } 01690 01691 if (cube_counter_noise == 0) { 01692 cpl_free(cube_noise); 01693 cube_noise = NULL ; 01694 } 01695 01696 if (cube_counter_data > 1) { 01697 if (cube_counter_data == cube_counter_noise || 01698 cube_counter_noise == 0) { 01699 kmo_priv_combine(cube_data, cube_noise, header_data, 01700 header_noise, cube_counter_data, cube_counter_noise, 01701 mapping_mode, "", comb_method, smethod, fmethod, 01702 filename, cmethod, cpos_rej, cneg_rej, citer, cmin, 01703 cmax, extrapol_enum, flux, &combined_data, 01704 &combined_noise, NULL); 01705 } else { 01706 cpl_msg_error(__func__, "Data/Noise cubes nb mismatch"); 01707 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 01708 return -1 ; 01709 } 01710 } else { 01711 cpl_msg_warning(__func__, 01712 "There is only one reconstructed cube - Save it"); 01713 combined_data = cpl_imagelist_duplicate(cube_data[0]); 01714 01715 if (cube_noise[0] != NULL) { 01716 combined_noise = cpl_imagelist_duplicate(cube_noise[0]); 01717 } 01718 } 01719 fn_out = COMBINED_CUBE; 01720 fn_suffix = cpl_sprintf("_%s", mapping_mode); 01721 01722 // save combined cube 01723 tmp_frame = kmo_dfs_get_frame(frameset, RECONSTRUCTED_CUBE); 01724 kmo_dfs_save_main_header(frameset, fn_out, fn_suffix, tmp_frame, 01725 NULL, parlist, cpl_func); 01726 kmo_dfs_save_cube(combined_data, fn_out, fn_suffix, header_data[0], 01727 0./0.); 01728 01729 if (cube_counter_noise == 0) { 01730 header_noise[0] = cpl_propertylist_duplicate(header_data[0]); 01731 tmp_str = cpl_propertylist_get_string(header_data[0], EXTNAME); 01732 kmo_extname_extractor(tmp_str, &ft, &tmp_int, content); 01733 extname = kmo_extname_creator(ifu_frame, tmp_int, EXT_NOISE); 01734 kmclipm_update_property_string(header_noise[0], EXTNAME, 01735 extname, "FITS extension name"); 01736 cpl_free(extname); 01737 } 01738 kmo_dfs_save_cube(combined_noise, fn_out, fn_suffix, 01739 header_noise[0], 0./0.); 01740 01741 if (cube_counter_noise == 0) 01742 cpl_propertylist_delete(header_noise[0]); 01743 cpl_free(fn_suffix); 01744 for (i = 0; i < cube_counter_data ; i++) { 01745 cpl_propertylist_delete(header_data[i]); 01746 cpl_imagelist_delete(cube_data[i]); 01747 } 01748 for (i = 0; i < cube_counter_noise ; i++) { 01749 cpl_propertylist_delete(header_noise[i]); 01750 cpl_imagelist_delete(cube_noise[i]); 01751 } 01752 cpl_free(cube_data); 01753 cpl_free(cube_noise); 01754 cpl_free(header_data); 01755 cpl_free(header_noise); 01756 cpl_imagelist_delete(combined_data); 01757 cpl_imagelist_delete(combined_noise); 01758 } 01759 } 01760 kmo_delete_armNameStruct(arm_name_struct); 01761 01762 /* Collapse the reconstructed cubes if requested */ 01763 if (collapse_reconstructed) { 01764 kmos_collapse_cubes(RECONSTRUCTED_CUBE, frameset, parlist, 0.1, 01765 "", DEF_REJ_METHOD, DEF_POS_REJ_THRES, DEF_NEG_REJ_THRES, 01766 DEF_ITERATIONS, DEF_NR_MIN_REJ, DEF_NR_MAX_REJ) ; 01767 } 01768 01769 /* Collapse the combined cubes if requested */ 01770 if (collapse_combined) { 01771 kmos_collapse_cubes(COMBINED_CUBE, frameset, parlist, 0.1, "", 01772 DEF_REJ_METHOD, DEF_POS_REJ_THRES, DEF_NEG_REJ_THRES, 01773 DEF_ITERATIONS, DEF_NR_MIN_REJ, DEF_NR_MAX_REJ) ; 01774 } 01775 return 0; 01776 } 01777 01780 /*----------------------------------------------------------------------------*/ 01788 /*----------------------------------------------------------------------------*/ 01789 static int kmos_sci_red_check_inputs( 01790 cpl_frameset * frameset, 01791 double pix_scale, 01792 int * mapping_id) 01793 { 01794 int nb_science, nb_xcal, nb_ycal, nb_lcal, nb_wave_band, 01795 nb_master_flat, nb_illum_corr, nb_telluric, nb_oh_spec ; 01796 cpl_error_code err ; 01797 const cpl_frame * frame1 ; 01798 const cpl_frame * frame2 ; 01799 int next1, next2, mapping_id_loc, 01800 mapping_id_curr, nx, ny ; 01801 cpl_propertylist * mh ; 01802 cpl_propertylist * eh ; 01803 const char * tmp_str ; 01804 01805 /* Check Entries */ 01806 if (frameset == NULL || mapping_id == NULL) return -1; 01807 01808 /* Count frames */ 01809 nb_science = cpl_frameset_count_tags(frameset, SCIENCE) ; 01810 nb_xcal = cpl_frameset_count_tags(frameset, XCAL) ; 01811 nb_ycal = cpl_frameset_count_tags(frameset, YCAL) ; 01812 nb_lcal = cpl_frameset_count_tags(frameset, LCAL) ; 01813 nb_wave_band = cpl_frameset_count_tags(frameset, WAVE_BAND) ; 01814 nb_master_flat = cpl_frameset_count_tags(frameset, MASTER_FLAT); 01815 nb_illum_corr = cpl_frameset_count_tags(frameset, ILLUM_CORR); 01816 nb_telluric = cpl_frameset_count_tags(frameset, TELLURIC); 01817 nb_oh_spec = cpl_frameset_count_tags(frameset, OH_SPEC) ; 01818 01819 /* Checks */ 01820 if (nb_science < 1) { 01821 cpl_msg_error(__func__, "At least one SCIENCE frame is required") ; 01822 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 01823 return 0 ; 01824 } 01825 if (nb_science == 1) { 01826 cpl_msg_warning(__func__, 01827 "Only 1 SCIENCE: no sky subtraction - reconstruct all IFUs"); 01828 } 01829 if (nb_xcal != 1 || nb_ycal != 1 || nb_lcal != 1) { 01830 cpl_msg_error(__func__, "Exactly 1 XCAL/YCAL/LCAL expected") ; 01831 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 01832 return 0 ; 01833 } 01834 if (nb_wave_band != 1) { 01835 cpl_msg_error(__func__, "At most one WAVE_BAND frame expected") ; 01836 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 01837 return 0 ; 01838 } 01839 01840 if (nb_master_flat > 1 || nb_illum_corr > 1 || nb_telluric > 1 || 01841 nb_oh_spec > 1) { 01842 cpl_msg_error(__func__, 01843 "MASTER_FLAT/ILLUM_CORR/OH_SPEC/TELLURIC: 0 or 1 frame expected") ; 01844 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 01845 return 0 ; 01846 } 01847 01848 /* filter_id, grating_id and rotator offset match all detectors */ 01849 err = CPL_ERROR_NONE ; 01850 err += kmo_check_frameset_setup(frameset, SCIENCE, TRUE, FALSE, TRUE); 01851 err += kmo_check_frame_setup(frameset, SCIENCE, YCAL, TRUE, FALSE, TRUE); 01852 err += kmo_check_frame_setup(frameset, XCAL, YCAL, TRUE, FALSE, TRUE); 01853 err += kmo_check_frame_setup(frameset, XCAL, LCAL, TRUE, FALSE, TRUE); 01854 if (nb_master_flat > 0) err += kmo_check_frame_setup(frameset, XCAL, 01855 MASTER_FLAT, TRUE, FALSE, TRUE); 01856 if (nb_telluric > 0) err += kmo_check_frame_setup(frameset, XCAL, 01857 TELLURIC, TRUE, FALSE, TRUE); 01858 if (nb_oh_spec > 0) err += kmo_check_oh_spec_setup(frameset, XCAL); 01859 01860 /* Check XCAL */ 01861 frame1 = kmo_dfs_get_frame(frameset, XCAL); 01862 next1 = cpl_frame_get_nextensions(frame1); 01863 if (next1 % KMOS_NR_DETECTORS) { 01864 cpl_msg_error(__func__, "XCAL wrong format") ; 01865 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 01866 return 0 ; 01867 } 01868 /* Check YCAL */ 01869 frame2 = kmo_dfs_get_frame(frameset, YCAL); 01870 next2 = cpl_frame_get_nextensions(frame2); 01871 if (next1 != next2) { 01872 cpl_msg_error(__func__, "YCAL wrong format") ; 01873 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 01874 return 0 ; 01875 } 01876 /* Check LCAL */ 01877 frame2 = kmo_dfs_get_frame(frameset, LCAL); 01878 next2 = cpl_frame_get_nextensions(frame2); 01879 if (next1 != next2) { 01880 cpl_msg_error(__func__, "LCAL wrong format") ; 01881 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 01882 return 0 ; 01883 } 01884 /* Check MASTER_FLAT */ 01885 if (nb_master_flat >= 1) { 01886 frame2 = kmo_dfs_get_frame(frameset, MASTER_FLAT); 01887 next2 = cpl_frame_get_nextensions(frame2); 01888 if (next2 % (2*KMOS_NR_DETECTORS)) { 01889 cpl_msg_error(__func__, "MASTER_FLAT wrong format") ; 01890 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 01891 return 0 ; 01892 } 01893 } 01894 /* Check ILLUM_CORR */ 01895 if (nb_illum_corr >= 1) { 01896 frame2 = kmo_dfs_get_frame(frameset, ILLUM_CORR); 01897 /* Check number of extensions */ 01898 next2 = cpl_frame_get_nextensions(frame2); 01899 if (next2 != 24 && next2 != 48) { 01900 cpl_msg_error(__func__, "ILLUM wrong format") ; 01901 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 01902 return 0 ; 01903 } 01904 /* Check Size regarding the pixscale */ 01905 eh = cpl_propertylist_load(cpl_frame_get_filename(frame2), 1); 01906 nx = kmos_pfits_get_naxis1(eh) ; 01907 ny = kmos_pfits_get_naxis2(eh) ; 01908 cpl_propertylist_delete(eh) ; 01909 if (fabs(nx*pix_scale-2.8) > 1e-3 || fabs(ny*pix_scale-2.8) > 1e-3) { 01910 cpl_msg_error(__func__, 01911 "ILLUM wrong Size (nx/y*pix_scale= %g/%g <> 2.8)", 01912 nx*pix_scale, ny*pix_scale) ; 01913 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 01914 return 0 ; 01915 } 01916 } 01917 /* Check TELLURIC */ 01918 if (nb_telluric >= 1) { 01919 frame2 = kmo_dfs_get_frame(frameset, TELLURIC); 01920 next2 = cpl_frame_get_nextensions(frame2); 01921 if (next2 != 24 && next2 != 48) { 01922 cpl_msg_error(__func__, "TELLURIC wrong format") ; 01923 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 01924 return 0 ; 01925 } 01926 } 01927 01928 /* Loop on the SCIENCE frames */ 01929 frame2 = kmo_dfs_get_frame(frameset, SCIENCE); 01930 mapping_id_loc = -1 ; 01931 while (frame2 != NULL ) { 01932 next2 = cpl_frame_get_nextensions(frame2); 01933 if (next2 != 3) { 01934 cpl_msg_error(__func__, "SCIENCE wrong format") ; 01935 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 01936 return 0 ; 01937 } 01938 01939 mh = cpl_propertylist_load(cpl_frame_get_filename(frame2), 0); 01940 tmp_str = cpl_propertylist_get_string(mh, TPL_ID); 01941 if (!strcmp(tmp_str, MAPPING8)) mapping_id_curr = 1 ; 01942 else if (strcmp(tmp_str, MAPPING24) == 0) mapping_id_curr = 2 ; 01943 else mapping_id_curr = 0 ; 01944 cpl_propertylist_delete(mh); 01945 01946 if (mapping_id_loc < 0) mapping_id_loc = mapping_id_curr ; 01947 if (mapping_id_curr != mapping_id_loc) { 01948 cpl_msg_error(__func__, "Inconsistent MAPPING information") ; 01949 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 01950 return 0 ; 01951 } 01952 frame2 = kmo_dfs_get_frame(frameset, NULL); 01953 } 01954 01955 /* Verify that XCAL / YCAL were generated together */ 01956 err += kmo_check_frame_setup_md5_xycal(frameset); 01957 /* Verify that XCAL and YCAL / LCAL were generated together */ 01958 err += kmo_check_frame_setup_md5(frameset); 01959 /* b_start/b_end/b_samples used for LCAL and TELLURIC were the same */ 01960 err += kmo_check_frame_setup_sampling(frameset); 01961 01962 if (err != CPL_ERROR_NONE) { 01963 cpl_msg_warning(__func__, "Frames are inconsistent") ; 01964 return 0 ; 01965 } 01966 01967 /* Return */ 01968 *mapping_id = mapping_id_loc ; 01969 return 1 ; 01970 } 01971 01972 /*----------------------------------------------------------------------------*/ 01979 /*----------------------------------------------------------------------------*/ 01980 static double kmos_sci_red_get_zpoint( 01981 cpl_frame * frame, 01982 int ifu_nr) 01983 { 01984 cpl_propertylist * plist ; 01985 double zpoint ; 01986 int nb_ext, ext_nb ; 01987 01988 /* Check entries */ 01989 if (frame == NULL) return -1.0 ; 01990 if (cpl_error_get_code() != CPL_ERROR_NONE) return -1.0 ; 01991 01992 /* Get the number of extentions */ 01993 nb_ext = cpl_frame_get_nextensions(frame); 01994 01995 /* Compute ext_nb */ 01996 if (nb_ext == KMOS_NR_IFUS) ext_nb = ifu_nr ; 01997 else if (nb_ext == 2 * KMOS_NR_IFUS) ext_nb = 2 * ifu_nr - 1 ; 01998 else return -1.0 ; 01999 02000 /* Get QC ZPOINT */ 02001 plist = cpl_propertylist_load(cpl_frame_get_filename(frame), ext_nb); 02002 zpoint = cpl_propertylist_get_double(plist, "ESO QC ZPOINT") ; 02003 cpl_propertylist_delete(plist) ; 02004 02005 if (cpl_error_get_code() != CPL_ERROR_NONE) { 02006 cpl_error_reset() ; 02007 zpoint = -1.0 ; 02008 } 02009 02010 return zpoint ; 02011 } 02012 02013 /*----------------------------------------------------------------------------*/ 02019 /*----------------------------------------------------------------------------*/ 02020 static double kmos_sci_red_get_f0( 02021 const char * filter_id, 02022 int lam_dim, 02023 double lam_start, 02024 double lam_delta) 02025 { 02026 double f_0 = -1.0 ; 02027 double cent_wl = lam_start + (lam_delta * (lam_dim/2.0)) ; 02028 if (!strcmp(filter_id, "H")) f_0 = 1.133e-9 ; 02029 if (!strcmp(filter_id, "HK") && cent_wl < 1.9) f_0 = 1.133e-9 ; 02030 if (!strcmp(filter_id, "HK") && cent_wl >= 1.9) f_0 = 4.283e-10 ; 02031 if (!strcmp(filter_id, "K")) f_0 = 4.283e-10 ; 02032 if (!strcmp(filter_id, "YJ")) f_0 = 3.129e-9 ; 02033 if (!strcmp(filter_id, "IZ")) f_0 = 7.63e-9 ; 02034 return f_0 ; 02035 } 02036 02037 02038 02039 int print_warning_once_tweak_std = TRUE; 02040 /*----------------------------------------------------------------------------*/ 02065 /*----------------------------------------------------------------------------*/ 02066 static kmclipm_vector * kmo_tweak_load_telluric( 02067 cpl_frameset * frameset, 02068 int ifu_nr, 02069 int is_noise, 02070 int no_subtract, 02071 int * ifu_nr_telluric) 02072 { 02073 kmclipm_vector *vec = NULL; 02074 cpl_propertylist *header = NULL; 02075 const char *tplid = NULL; 02076 int actual_msg_level = 0 ; 02077 02078 02079 /* Check entries */ 02080 if (frameset == NULL || ifu_nr_telluric == NULL) return NULL ; 02081 if (ifu_nr < 1 || ifu_nr > KMOS_NR_IFUS) return NULL ; 02082 02083 header = kmo_dfs_load_primary_header(frameset, TELLURIC); 02084 tplid = cpl_propertylist_get_string(header, TPL_ID); 02085 if (!strcmp(tplid, "KMOS_spec_cal_stdstar")) { 02086 if (print_warning_once_tweak_std) { 02087 cpl_msg_warning(__func__, 02088 "KMOS_spec_cal_stdstar template used => 1 telluric/detector"); 02089 print_warning_once_tweak_std = FALSE; 02090 } 02091 } 02092 02093 *ifu_nr_telluric = kmo_tweak_find_ifu(frameset, ifu_nr); 02094 if (ifu_nr!=*ifu_nr_telluric && *ifu_nr_telluric!=-1 && no_subtract!=-1) { 02095 if (!no_subtract) { 02096 cpl_msg_info(__func__, "Telluric IFU %d selected", 02097 *ifu_nr_telluric); 02098 } else { 02099 cpl_msg_info(__func__, "For IFU %d, telluric in IFU %d selected", 02100 ifu_nr, *ifu_nr_telluric); 02101 } 02102 } 02103 02104 actual_msg_level = cpl_msg_get_level(); 02105 cpl_msg_set_level(CPL_MSG_OFF); 02106 vec = kmo_dfs_load_vector(frameset, TELLURIC, *ifu_nr_telluric,is_noise); 02107 cpl_msg_set_level(actual_msg_level); 02108 02109 if (cpl_error_get_code() != CPL_ERROR_NONE) cpl_error_reset(); 02110 02111 cpl_propertylist_delete(header); 02112 if ((vec == NULL) && !is_noise && (no_subtract != -1)) { 02113 if (!no_subtract) { 02114 cpl_msg_warning(__func__, "No telluric on this detector"); 02115 } else { 02116 cpl_msg_warning(__func__, "No telluric on this detector for IFU %d", 02117 ifu_nr); 02118 } 02119 } 02120 02121 return vec; 02122 } 02123
1.7.6.1