KMOS Pipeline Reference Manual
1.3.0
|
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 #include <string.h> 00028 #include <math.h> 00029 00030 #include <cpl.h> 00031 00032 #include "kmclipm_constants.h" 00033 #include "kmclipm_functions.h" 00034 00035 #include "kmo_debug.h" 00036 #include "kmo_constants.h" 00037 #include "kmo_cpl_extensions.h" 00038 #include "kmo_priv_lcorr.h" 00039 #include "kmo_utils.h" 00040 #include "kmo_error.h" 00041 #include "kmo_dfs.h" 00042 #include "kmo_functions.h" 00043 #include "kmo_priv_arithmetic.h" 00044 #include "kmo_priv_combine.h" 00045 #include "kmo_priv_functions.h" 00046 #include "kmo_priv_reconstruct.h" 00047 #include "kmo_priv_multi_reconstruct.h" 00048 00049 /*----------------------------------------------------------------------------- 00050 * Types 00051 *-----------------------------------------------------------------------------*/ 00052 00053 /*----------------------------------------------------------------------------- 00054 * Functions prototypes 00055 *----------------------------------------------------------------------------*/ 00056 00057 static int kmo_multi_reconstruct_create(cpl_plugin *); 00058 static int kmo_multi_reconstruct_exec(cpl_plugin *); 00059 static int kmo_multi_reconstruct_destroy(cpl_plugin *); 00060 static int kmo_multi_reconstruct(cpl_parameterlist *, cpl_frameset *); 00061 00062 /*----------------------------------------------------------------------------- 00063 * Static variables 00064 *----------------------------------------------------------------------------*/ 00065 00066 static char kmo_multi_reconstruct_description[] = 00067 "Ideally at least two data frames have to be provided since we need for each IFU\n" 00068 "pointing to an object as well a sky frame for the same IFU.\n" 00069 "If an OH spectrum is given in the SOF file the lambda axis will be corrected\n" 00070 "using the OH lines as reference.\n" 00071 "All IFUs with the same object name will be reconstructed and combined in one step\n" 00072 "Telluric correction is only supported if the objects have been observed with\n" 00073 "the same IFU on all exposures (dithering).\n" 00074 "The number of created files depends on the number of objects of different name.\n" 00075 "If the user just wants to combine a certain object, the parameters --name or\n" 00076 "--ifus can be used.\n" 00077 "\n" 00078 "Exposures taken with the templates KMOS_spec_obs_mapping8 and\n" 00079 "KMOS_spec_obs_mapping24 can't be processed with this recipe! Use kmo_sci_red\n" 00080 "instead.\n" 00081 "\n" 00082 "BASIC PARAMETERS:\n" 00083 "-----------------\n" 00084 "--imethod\n" 00085 "The interpolation method used for reconstruction.\n" 00086 "\n" 00087 "--name\n" 00088 "--ifus\n" 00089 "Since an object can be present only once per exposure and since it can be\n" 00090 "located in different IFUs for the existing exposures, there are two modes to\n" 00091 "identify the objects:\n" 00092 " * Combine by object names (default)\n" 00093 " In this case the object name must be provided via the --name parameter. The\n" 00094 " object name will be searched for in all primary headers of all provided\n" 00095 " frames in the keyword ESO OCS ARMx NAME.\n" 00096 "\n" 00097 " * Combine by index (advanced)\n" 00098 " In this case the --ifus parameter must be provided. The parameter must have\n" 00099 " the same number of entries as frames are provided, e.g. \"3;1;24\" for 3\n" 00100 " exposures. The index doesn't reference the extension in the frame but the\n" 00101 " real index of the IFU as defined in the EXTNAME keyword.\n" 00102 " (e.g. 'IFU.3.DATA')\n" 00103 "\n" 00104 "ADVANCED PARAMETERS\n" 00105 "-------------------\n" 00106 "--flux\n" 00107 "Specify if flux conservation should be applied.\n" 00108 "\n" 00109 "--background\n" 00110 "Specify if background removal should be applied.\n" 00111 "\n" 00112 "--suppress_extension\n" 00113 "If set to TRUE, the arbitrary filename extensions are supressed. If multiple\n" 00114 "products with the same category are produced, they will be numered consecutively\n" 00115 "starting from 0.\n" 00116 "\n" 00117 "--obj_sky_table\n" 00118 "The automatic obj-sky-associations can be modified by indicating a file with\n" 00119 "the desired associations. Therefore the file written to disk by default\n" 00120 "(without setting this option) can be edited manually. The formatting must\n" 00121 "absolutely be retained, just the type codes ('O' and'S') and the associated\n" 00122 "frame indices should be altered\n" 00123 "\n" 00124 " Advanced reconstruction parameters\n" 00125 " ----------------------------------\n" 00126 "--neighborhoodRange\n" 00127 "Defines the range to search for neighbors during reconstruction\n" 00128 "\n" 00129 "--b_samples\n" 00130 "The number of samples in spectral direction for the reconstructed cube.\n" 00131 "Ideally this number should be greater than 2048, the detector size.\n" 00132 "\n" 00133 "--b_start\n" 00134 "--b_end\n" 00135 "Used to define manually the start and end wavelength for the reconstructed\n" 00136 "cube. By default the internally defined values are used.\n" 00137 "\n" 00138 "--pix_scale\n" 00139 "Change the pixel scale [arcsec]. Default of 0.2\" results into cubes of\n" 00140 "14x14pix, a scale of 0.1\" results into cubes of 28x28pix, etc.\n" 00141 "\n" 00142 "--no_subtract\n" 00143 "If set to TRUE, the found objects and references won't be sky subtracted. \n" 00144 "Additionally all IFUs will be reconstructed, even the ones containing skies. \n" 00145 "\n" 00146 "--xcal_interpolation\n" 00147 "If true interpolate the pixel position in the slitlet (xcal) using the two\n" 00148 "closest rotator angles in the calibration file. Otherwise take the values\n" 00149 "of the closest rotator angle\n" 00150 "\n" 00151 " Advanced combining parameters\n" 00152 " ----------------------------------\n" 00153 "--method\n" 00154 "There are following sources to get the shift parameters from:\n" 00155 " * 'header' (default)\n" 00156 " The shifts are calculated according to the WCS information stored in the\n" 00157 " header of every IFU. The output frame will get larger, except the object is\n" 00158 " at the exact same position for all exposures. The size of the exposures can\n" 00159 " differ, but the orientation must be the same for all exposures.\n" 00160 "\n" 00161 " * 'none'\n" 00162 " The cubes are directly recombined, not shifting at all. The ouput frame\n" 00163 " will have the same dimensions as the input cubes.\n" 00164 " If the size differs a warning will be emitted and the cubes will be aligned\n" 00165 " to the lower left corner. If the orientation differs a warning will be\n" 00166 " emitted, but the cubes are combined anyway.\n" 00167 "\n" 00168 " * 'center'\n" 00169 " The shifts are calculated using a centering algorithm. The cube will be\n" 00170 " collapsed and a 2D profile will be fitted to it to identify the centre.\n" 00171 " With the parameter --fmethod the function to fit can be provided. The size\n" 00172 " of the exposures can differ, but the orientation must be the same for all\n" 00173 " exposures.\n" 00174 "\n" 00175 " * 'user'\n" 00176 " Read the shifts from a user specified file. The path of the file must be\n" 00177 " provided using the --filename parameter. For every exposure (except the\n" 00178 " first one) two shift values are expected per line, they have to be separa-\n" 00179 " ted with simple spaces. The values indicate pixel shifts and are referenced\n" 00180 " to the first frame. The 1st value is the shift in x-direction to the left,\n" 00181 " the 2nd the shift in y-direction upwards. The size of the exposures can\n" 00182 " differ, but the orientation must be the same for all exposures.\n" 00183 "\n" 00184 "--fmethod\n" 00185 "see --method='center'\n" 00186 "The type of function that should be fitted spatially to the collapsed image.\n" 00187 "This fit is used to create a mask to extract the spectrum of the object. Valid\n" 00188 "values are 'gauss' and 'moffat'.\n" 00189 "\n" 00190 "--filename\n" 00191 "see --method='user'\n" 00192 "\n" 00193 "--cmethod\n" 00194 "Following methods of frame combination are available:\n" 00195 " * 'ksigma' (Default)\n" 00196 " An iterative sigma clipping. For each position all pixels in the spectrum\n" 00197 " are examined. If they deviate significantly, they will be rejected according\n" 00198 " to the conditions:\n" 00199 " val > mean + stdev * cpos_rej\n" 00200 " and\n" 00201 " val < mean - stdev * cneg_rej\n" 00202 " where --cpos_rej, --cneg_rej and --citer are the corresponding configuration\n" 00203 " parameters. In the first iteration median and percentile level are used.\n" 00204 "\n" 00205 " * 'median'\n" 00206 " At each pixel position the median is calculated.\n" 00207 "\n" 00208 " * 'average'\n" 00209 " At each pixel position the average is calculated.\n" 00210 "\n" 00211 " * 'sum'\n" 00212 " At each pixel position the sum is calculated.\n" 00213 "\n" 00214 " * 'min_max'\n" 00215 " The specified number of minimum and maximum pixel values will be rejected.\n" 00216 " --cmax and --cmin apply to this method.\n" 00217 "\n" 00218 "--cpos_rej\n" 00219 "--cneg_rej\n" 00220 "--citer\n" 00221 "see --cmethod='ksigma'\n" 00222 "\n" 00223 "--cmax\n" 00224 "--cmin\n" 00225 "see --cmethod='min_max'\n" 00226 "\n" 00227 "------------------------------------------------------------------------------\n" 00228 " Input files:\n" 00229 "\n" 00230 " DO KMOS \n" 00231 " category Type Explanation Required #Frames\n" 00232 " -------- ----- ----------- -------- -------\n" 00233 " SCIENCE RAW The science frames Y >=1 \n" 00234 " XCAL F2D x calibration frame Y 1 \n" 00235 " YCAL F2D y calibration frame Y 1 \n" 00236 " LCAL F2D Wavelength calib. frame Y 1 \n" 00237 " MASTER_FLAT F2D Master flat Y 0,1 \n" 00238 " WAVE_BAND F2L Table with start-/end-wavelengths Y 1 \n" 00239 " TELLURIC F1I normalised telluric spectrum N 0,1 \n" 00240 " OH_SPEC F1S Vector holding OH lines N 0,1 \n" 00241 "\n" 00242 " Output files:\n" 00243 "\n" 00244 " DO KMOS\n" 00245 " category Type Explanation\n" 00246 " -------- ----- -----------\n" 00247 " CUBE_MULTI F3I Combined cubes with noise\n" 00248 "------------------------------------------------------------------------------\n" 00249 "\n"; 00250 00251 /*----------------------------------------------------------------------------- 00252 * Functions code 00253 *----------------------------------------------------------------------------*/ 00254 00272 int cpl_plugin_get_info(cpl_pluginlist *list) 00273 { 00274 cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe); 00275 cpl_plugin *plugin = &recipe->interface; 00276 00277 cpl_plugin_init(plugin, 00278 CPL_PLUGIN_API, 00279 KMOS_BINARY_VERSION, 00280 CPL_PLUGIN_TYPE_RECIPE, 00281 "kmo_multi_reconstruct", 00282 "Reconstruct and combine obj/sky-pairs in one step.", 00283 kmo_multi_reconstruct_description, 00284 "Alex Agudo Berbel", 00285 "usd-help@eso.org", 00286 kmos_get_license(), 00287 kmo_multi_reconstruct_create, 00288 kmo_multi_reconstruct_exec, 00289 kmo_multi_reconstruct_destroy); 00290 00291 cpl_pluginlist_append(list, plugin); 00292 00293 return 0; 00294 } 00295 00303 static int kmo_multi_reconstruct_create(cpl_plugin *plugin) 00304 { 00305 cpl_recipe *recipe; 00306 cpl_parameter *p; 00307 00308 /* Check that the plugin is part of a valid recipe */ 00309 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00310 recipe = (cpl_recipe *)plugin; 00311 else 00312 return -1; 00313 00314 /* Create the parameters list in the cpl_recipe object */ 00315 recipe->parameters = cpl_parameterlist_new(); 00316 00317 /* --imethod (interpolation method) */ 00318 p = cpl_parameter_new_value("kmos.kmo_multi_reconstruct.imethod", 00319 CPL_TYPE_STRING, 00320 "Method to use for interpolation during reconstruction. " 00321 "[\"NN\" (nearest neighbour), " 00322 "\"lwNN\" (linear weighted nearest neighbor), " 00323 "\"swNN\" (square weighted nearest neighbor), " 00324 "\"MS\" (Modified Shepard's method)", 00325 "kmos.kmo_multi_reconstruct", 00326 "MS"); 00327 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "imethod"); 00328 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00329 cpl_parameterlist_append(recipe->parameters, p); 00330 00331 /* --method (shift method) */ 00332 p = cpl_parameter_new_value("kmos.kmo_multi_reconstruct.method", 00333 CPL_TYPE_STRING, 00334 "The shifting method: " 00335 "'none': no shifting, combined directly, " 00336 "'header': shift according to WCS (default), " 00337 "'center': centering algorithm, " 00338 "'user': read shifts from file", 00339 "kmos.kmo_multi_reconstruct", 00340 "header"); 00341 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "method"); 00342 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00343 cpl_parameterlist_append(recipe->parameters, p); 00344 00345 /* --fmethod */ 00346 p = cpl_parameter_new_value("kmos.kmo_multi_reconstruct.fmethod", 00347 CPL_TYPE_STRING, 00348 "The fitting method (applies only when " 00349 "method='center'): " 00350 "'gauss': fit a gauss function to collapsed " 00351 "image (default), " 00352 "'moffat': fit a moffat function to collapsed" 00353 " image", 00354 "kmos.kmo_multi_reconstruct", 00355 "gauss"); 00356 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "fmethod"); 00357 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00358 cpl_parameterlist_append(recipe->parameters, p); 00359 00360 /* --name */ 00361 p = cpl_parameter_new_value("kmos.kmo_multi_reconstruct.name", 00362 CPL_TYPE_STRING, 00363 "Name of the object to combine.", 00364 "kmos.kmo_multi_reconstruct", 00365 ""); 00366 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "name"); 00367 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00368 cpl_parameterlist_append(recipe->parameters, p); 00369 00370 /* --ifus */ 00371 p = cpl_parameter_new_value("kmos.kmo_multi_reconstruct.ifus", 00372 CPL_TYPE_STRING, 00373 "The indices of the IFUs to combine. " 00374 "\"ifu1;ifu2;...\"", 00375 "kmos.kmo_multi_reconstruct", 00376 ""); 00377 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "ifus"); 00378 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00379 cpl_parameterlist_append(recipe->parameters, p); 00380 00381 /* --pix_scale */ 00382 p = cpl_parameter_new_value("kmos.kmo_multi_reconstruct.pix_scale", 00383 CPL_TYPE_DOUBLE, 00384 "Change the pixel scale [arcsec]. " 00385 "Default of 0.2\" results into cubes of 14x14pix, " 00386 "a scale of 0.1\" results into cubes of 28x28pix, " 00387 "etc.", 00388 "kmos.kmo_multi_reconstruct", 00389 KMOS_PIX_RESOLUTION); 00390 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "pix_scale"); 00391 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00392 cpl_parameterlist_append(recipe->parameters, p); 00393 00394 /* --suppress_extension */ 00395 p = cpl_parameter_new_value("kmos.kmo_multi_reconstruct.suppress_extension", 00396 CPL_TYPE_BOOL, 00397 "Suppress arbitrary filename extension." 00398 "(TRUE (apply) or FALSE (don't apply)", 00399 "kmos.kmo_multi_reconstruct", 00400 FALSE); 00401 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "suppress_extension"); 00402 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00403 cpl_parameterlist_append(recipe->parameters, p); 00404 00405 /* --neighborhoodRange */ 00406 p = cpl_parameter_new_value("kmos.kmo_multi_reconstruct.neighborhoodRange", 00407 CPL_TYPE_DOUBLE, 00408 "Defines the range to search for neighbors " 00409 "in pixels", 00410 "kmos.kmo_multi_reconstruct", 00411 1.001); 00412 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "neighborhoodRange"); 00413 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00414 cpl_parameterlist_append(recipe->parameters, p); 00415 00416 /* --filename */ 00417 p = cpl_parameter_new_value("kmos.kmo_multi_reconstruct.filename", 00418 CPL_TYPE_STRING, 00419 "The path to the file with the shift vectors." 00420 "(Applies only to method='user')", 00421 "kmos.kmo_multi_reconstruct", 00422 ""); 00423 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "filename"); 00424 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00425 cpl_parameterlist_append(recipe->parameters, p); 00426 00427 /* --flux */ 00428 p = cpl_parameter_new_value("kmos.kmo_multi_reconstruct.flux", 00429 CPL_TYPE_BOOL, 00430 "TRUE: Apply flux conservation. FALSE: otherwise", 00431 "kmos.kmo_multi_reconstruct", 00432 FALSE); 00433 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "flux"); 00434 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00435 cpl_parameterlist_append(recipe->parameters, p); 00436 00437 /* --background */ 00438 p = cpl_parameter_new_value("kmos.kmo_multi_reconstruct.background", 00439 CPL_TYPE_BOOL, 00440 "TRUE: Apply background removal. FALSE: otherwise", 00441 "kmos.kmo_multi_reconstruct", 00442 FALSE); 00443 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "background"); 00444 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00445 cpl_parameterlist_append(recipe->parameters, p); 00446 00447 /* --xcal_interpolation */ 00448 p = cpl_parameter_new_value("kmos.kmo_multi_reconstruct.xcal_interpolation", 00449 CPL_TYPE_BOOL, 00450 "TRUE: Interpolate xcal between rotator angles. FALSE: otherwise", 00451 "kmos.kmo_multi_reconstruct", 00452 TRUE); 00453 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "xcal_interpolation"); 00454 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00455 cpl_parameterlist_append(recipe->parameters, p); 00456 00457 /* --no_subtract */ 00458 p = cpl_parameter_new_value("kmos.kmo_multi_reconstruct.no_subtract", 00459 CPL_TYPE_BOOL, 00460 "Don't sky subtract object and references." 00461 "(TRUE (apply) or " 00462 "FALSE (don't apply)", 00463 "kmos.kmo_multi_reconstruct", 00464 FALSE); 00465 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "no_subtract"); 00466 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00467 cpl_parameterlist_append(recipe->parameters, p); 00468 00469 /* --dev_cal */ 00470 p = cpl_parameter_new_value("kmos.kmo_multi_reconstruct.dev_cal", 00471 CPL_TYPE_BOOL, 00472 "Development only: If calibration data is to be " 00473 "reconstructed the ALPHA/DELTA keywords are " 00474 "missing. Setting this parameter to TRUE prevents " 00475 "according data check", 00476 "kmos.kmo_multi_reconstruct", 00477 FALSE); 00478 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "dev_cal"); 00479 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00480 cpl_parameterlist_append(recipe->parameters, p); 00481 00482 /* --obj_sky_table */ 00483 p = cpl_parameter_new_value("kmos.kmo_multi_reconstruct.obj_sky_table", 00484 CPL_TYPE_STRING, 00485 "The path to the file with the modified obj/sky associations.", 00486 "kmos.kmo_multi_reconstruct", 00487 ""); 00488 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "obj_sky_table"); 00489 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00490 cpl_parameterlist_append(recipe->parameters, p); 00491 00492 00493 // add parameters for band-definition 00494 kmo_band_pars_create(recipe->parameters, 00495 "kmos.kmo_multi_reconstruct"); 00496 00497 return kmo_combine_pars_create(recipe->parameters, 00498 "kmos.kmo_multi_reconstruct", 00499 DEF_REJ_METHOD, 00500 FALSE); 00501 } 00502 00508 static int kmo_multi_reconstruct_exec(cpl_plugin *plugin) 00509 { 00510 cpl_recipe *recipe; 00511 00512 /* Get the recipe out of the plugin */ 00513 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00514 recipe = (cpl_recipe *)plugin; 00515 else return -1 ; 00516 00517 return kmo_multi_reconstruct(recipe->parameters, recipe->frames); 00518 } 00519 00525 static int kmo_multi_reconstruct_destroy(cpl_plugin *plugin) 00526 { 00527 cpl_recipe *recipe; 00528 00529 /* Get the recipe out of the plugin */ 00530 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00531 recipe = (cpl_recipe *)plugin; 00532 else return -1 ; 00533 00534 cpl_parameterlist_delete(recipe->parameters); 00535 return 0 ; 00536 } 00537 00552 static int kmo_multi_reconstruct(cpl_parameterlist *parlist, cpl_frameset *frameset) 00553 { 00554 int ret_val = 0, 00555 nr_science_frames = 0, 00556 has_illum_corr = 0, 00557 has_master_flat = 0, 00558 has_telluric = 0, 00559 *bounds = NULL, 00560 citer = 0, 00561 cmin = 0, 00562 cmax = 0, 00563 flux = FALSE, 00564 background = FALSE, 00565 no_subtract = FALSE, 00566 xcal_interpolation = FALSE, 00567 suppress_extension = FALSE, 00568 dev_cal = 0, 00569 cnt = 0, 00570 arm_index = 0, 00571 suppress_index = 0, 00572 xdim = 0, 00573 ydim = 0, 00574 iy = 0, 00575 ix = 0, 00576 ifu_nr = 0, 00577 nr_frames = 0; 00578 double xmin = DBL_MAX, 00579 xmax = -DBL_MAX, 00580 ymin = DBL_MAX, 00581 ymax = -DBL_MAX, 00582 gxshift = 0., 00583 gyshift = 0., 00584 gxdim = 0., 00585 gydim = 0., 00586 neighborhoodRange = 1.001, 00587 cpos_rej = 0.0, 00588 cneg_rej = 0.0, 00589 pix_scale = 0.0, 00590 *xshifts = NULL, 00591 *yshifts = NULL; 00592 char *suffix = NULL, 00593 *mapping_mode = NULL, 00594 *fn_cube = NULL, 00595 *fn_suffix = NULL, 00596 *filter_id = NULL, 00597 *extname = NULL; 00598 const char *imethod = NULL, 00599 *ifus_txt = NULL, 00600 *name = NULL, 00601 *tmp_str = NULL, 00602 *filename = NULL, 00603 *fn_obj_sky_table = NULL, 00604 *comb_method = NULL, 00605 *cmethod = NULL, 00606 *fmethod = NULL, 00607 *filter_keyword = "ESO INS FILT1 ID"; 00608 cpl_array **unused_ifus_before = NULL, 00609 **unused_ifus_after = NULL; 00610 cpl_frame *xcal_frame = NULL, 00611 *ycal_frame = NULL, 00612 *lcal_frame = NULL, 00613 *flat_frame = NULL, 00614 *illum_frame = NULL, 00615 *telluric_frame = NULL, 00616 *science_frame = NULL, 00617 *ref_spectrum_frame = NULL; 00618 cpl_propertylist *tmp_header = NULL, 00619 *ref_sub_header = NULL, 00620 *science_frame_header = NULL, 00621 **sub_headers = NULL; 00622 cpl_vector *ifus = NULL; 00623 cpl_table *band_table = NULL; 00624 00625 cpl_polynomial **lcorr_coeffs = NULL; 00626 cpl_imagelist *cube_combined_data = NULL, 00627 *cube_combined_noise = NULL, 00628 **pre_data_cube_list = NULL; 00629 kmclipm_vector *telluric_data = NULL, 00630 *telluric_noise = NULL; 00631 main_fits_desc desc1, 00632 desc2, 00633 desc_telluric; 00634 gridDefinition gd, 00635 gd_14x14; 00636 armNameStruct *arm_name_struct = NULL; 00637 00638 KMO_TRY 00639 { 00640 00641 kmo_init_fits_desc(&desc1); 00642 kmo_init_fits_desc(&desc2); 00643 kmo_init_fits_desc(&desc_telluric); 00644 00645 // 00646 // check frameset 00647 // 00648 KMO_TRY_ASSURE((parlist != NULL) && 00649 (frameset != NULL), 00650 CPL_ERROR_NULL_INPUT, 00651 "Not all input data is provided!"); 00652 00653 nr_science_frames = cpl_frameset_count_tags(frameset, SCIENCE); 00654 KMO_TRY_ASSURE(nr_science_frames >= 1, 00655 CPL_ERROR_ILLEGAL_INPUT, 00656 "At least one SCIENCE frame is required!"); 00657 if (nr_science_frames == 1) { 00658 cpl_msg_warning("", "At least two SCIENCE frames should be provided " 00659 "in order to apply sky subtraction!"); 00660 cpl_msg_warning("", "All IFUs will be reconstructed regardless if " 00661 "they contain object, reference or sky!"); 00662 } 00663 00664 KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, XCAL) == 1, 00665 CPL_ERROR_FILE_NOT_FOUND, 00666 "Exactly one XCAL frame is required!"); 00667 00668 KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, YCAL) == 1, 00669 CPL_ERROR_FILE_NOT_FOUND, 00670 "Exactly one YCAL frame is required!"); 00671 00672 KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, LCAL) == 1, 00673 CPL_ERROR_FILE_NOT_FOUND, 00674 "Exactly one LCAL frame is required!"); 00675 00676 has_master_flat = cpl_frameset_count_tags(frameset, MASTER_FLAT); 00677 KMO_TRY_ASSURE((has_master_flat == 0) || (has_master_flat == 1), 00678 CPL_ERROR_FILE_NOT_FOUND, 00679 "At most one MASTER_FLAT frame can be provided!"); 00680 00681 KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, WAVE_BAND) == 1, 00682 CPL_ERROR_FILE_NOT_FOUND, 00683 "Exactly one WAVE_BAND frame is required!"); 00684 00685 has_illum_corr = cpl_frameset_count_tags(frameset, ILLUM_CORR); 00686 KMO_TRY_ASSURE((has_illum_corr == 0) || (has_illum_corr == 1), 00687 CPL_ERROR_FILE_NOT_FOUND, 00688 "At most one ILLUM_CORR frame can be provided!"); 00689 00690 has_telluric = cpl_frameset_count_tags(frameset, TELLURIC); 00691 KMO_TRY_ASSURE((has_telluric == 0) || (has_telluric == 1), 00692 CPL_ERROR_FILE_NOT_FOUND, 00693 "At most one TELLURIC frame can be provided!"); 00694 00695 KMO_TRY_ASSURE(kmo_dfs_set_groups(frameset, "kmo_multi_reconstruct") == 1, 00696 CPL_ERROR_ILLEGAL_INPUT, 00697 "Cannot identify RAW and CALIB frames!"); 00698 00699 KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, OH_SPEC) == 0 || 00700 cpl_frameset_count_tags(frameset, OH_SPEC) == 1, 00701 CPL_ERROR_ILLEGAL_INPUT, 00702 "Only a single reference spectrum can be provided!"); 00703 // 00704 // get parameters 00705 // 00706 cpl_msg_info("", "--- Parameter setup for kmo_multi_reconstruct ------"); 00707 00708 flux = kmo_dfs_get_parameter_bool(parlist, "kmos.kmo_multi_reconstruct.flux"); 00709 KMO_TRY_ASSURE((flux == 0) || 00710 (flux == 1), 00711 CPL_ERROR_ILLEGAL_INPUT, 00712 "flux must be either FALSE or TRUE! %d", flux); 00713 KMO_TRY_EXIT_IF_ERROR( 00714 kmo_dfs_print_parameter_help(parlist, "kmos.kmo_multi_reconstruct.flux")); 00715 00716 background = kmo_dfs_get_parameter_bool(parlist, "kmos.kmo_multi_reconstruct.background"); 00717 KMO_TRY_ASSURE((background == 0) || 00718 (background == 1), 00719 CPL_ERROR_ILLEGAL_INPUT, 00720 "background must be either FALSE or TRUE! %d", background); 00721 KMO_TRY_EXIT_IF_ERROR( 00722 kmo_dfs_print_parameter_help(parlist, "kmos.kmo_multi_reconstruct.background")); 00723 00724 KMO_TRY_EXIT_IF_NULL( 00725 imethod = kmo_dfs_get_parameter_string(parlist, "kmos.kmo_multi_reconstruct.imethod")); 00726 KMO_TRY_ASSURE((strcmp(imethod, "NN") == 0) || 00727 (strcmp(imethod, "lwNN") == 0) || 00728 (strcmp(imethod, "swNN") == 0) || 00729 (strcmp(imethod, "MS") == 0), 00730 CPL_ERROR_ILLEGAL_INPUT, 00731 "imethod must be either \"NN\", \"lwNN\", " 00732 "\"swNN\" or \"MS\"!"); 00733 KMO_TRY_EXIT_IF_ERROR( 00734 kmo_dfs_print_parameter_help(parlist, "kmos.kmo_multi_reconstruct.imethod")); 00735 00736 neighborhoodRange = kmo_dfs_get_parameter_double(parlist, "kmos.kmo_multi_reconstruct.neighborhoodRange"); 00737 KMO_TRY_CHECK_ERROR_STATE(); 00738 KMO_TRY_ASSURE(neighborhoodRange > 0.0, 00739 CPL_ERROR_ILLEGAL_INPUT, 00740 "neighborhoodRange must be greater than 0.0"); 00741 KMO_TRY_EXIT_IF_ERROR( 00742 kmo_dfs_print_parameter_help(parlist, "kmos.kmo_multi_reconstruct.neighborhoodRange")); 00743 00744 KMO_TRY_EXIT_IF_NULL( 00745 comb_method = kmo_dfs_get_parameter_string(parlist, "kmos.kmo_multi_reconstruct.method")); 00746 KMO_TRY_EXIT_IF_NULL( 00747 fmethod = kmo_dfs_get_parameter_string(parlist, "kmos.kmo_multi_reconstruct.fmethod")); 00748 KMO_TRY_ASSURE((strcmp(comb_method, "none") == 0) || 00749 (strcmp(comb_method, "header") == 0) || 00750 (strcmp(comb_method, "center") == 0) || 00751 (strcmp(comb_method, "user") == 0), 00752 CPL_ERROR_ILLEGAL_INPUT, 00753 "Following shift methods are available : 'none', " 00754 "'header', 'center' or 'user'"); 00755 00756 if (strcmp(comb_method, "user") == 0) { 00757 filename = kmo_dfs_get_parameter_string(parlist, "kmos.kmo_multi_reconstruct.filename"); 00758 KMO_TRY_CHECK_ERROR_STATE(); 00759 KMO_TRY_ASSURE(strcmp(filename, "") != 0, 00760 CPL_ERROR_ILLEGAL_INPUT, 00761 "path of file with shift information must be " 00762 "provided!"); 00763 KMO_TRY_EXIT_IF_ERROR( 00764 kmo_dfs_print_parameter_help(parlist, "kmos.kmo_multi_reconstruct.filename")); 00765 } 00766 00767 KMO_TRY_EXIT_IF_ERROR( 00768 kmo_dfs_print_parameter_help(parlist, "kmos.kmo_multi_reconstruct.method")); 00769 ifus_txt = kmo_dfs_get_parameter_string(parlist, 00770 "kmos.kmo_multi_reconstruct.ifus"); 00771 KMO_TRY_CHECK_ERROR_STATE(); 00772 name = kmo_dfs_get_parameter_string(parlist, "kmos.kmo_multi_reconstruct.name"); 00773 KMO_TRY_CHECK_ERROR_STATE(); 00774 00775 if (strcmp(ifus_txt, "") != 0) { 00776 KMO_TRY_ASSURE(strcmp(name, "") == 0, 00777 CPL_ERROR_ILLEGAL_INPUT, 00778 "name parameter must be NULL if IFU indices are " 00779 "provided!"); 00780 00781 KMO_TRY_EXIT_IF_NULL( 00782 ifus = kmo_identify_values(ifus_txt)); 00783 00784 KMO_TRY_ASSURE(cpl_vector_get_size(ifus) == nr_science_frames, 00785 CPL_ERROR_ILLEGAL_INPUT, 00786 "ifus parameter must have the same number of values " 00787 "than frames provided (for frames just containing " 00788 "skies insert 0)) (%lld=%d)", 00789 cpl_vector_get_size(ifus), nr_science_frames); 00790 } 00791 00792 if (strcmp(name, "") != 0) { 00793 KMO_TRY_ASSURE(strcmp(ifus_txt, "") == 0, 00794 CPL_ERROR_ILLEGAL_INPUT, 00795 "ifus parameter must be NULL if name is provided!"); 00796 } 00797 00798 KMO_TRY_EXIT_IF_ERROR( 00799 kmo_dfs_print_parameter_help(parlist, "kmos.kmo_multi_reconstruct.ifus")); 00800 KMO_TRY_EXIT_IF_ERROR( 00801 kmo_dfs_print_parameter_help(parlist, "kmos.kmo_multi_reconstruct.name")); 00802 00803 kmo_band_pars_load(parlist, "kmos.kmo_multi_reconstruct"); 00804 00805 no_subtract = kmo_dfs_get_parameter_bool(parlist, "kmos.kmo_multi_reconstruct.no_subtract"); 00806 KMO_TRY_CHECK_ERROR_STATE(); 00807 KMO_TRY_ASSURE((no_subtract == TRUE) || (no_subtract == FALSE), 00808 CPL_ERROR_ILLEGAL_INPUT, 00809 "no_subtract must be TRUE or FALSE!"); 00810 KMO_TRY_EXIT_IF_ERROR( 00811 kmo_dfs_print_parameter_help(parlist, "kmos.kmo_multi_reconstruct.no_subtract")); 00812 00813 pix_scale = kmo_dfs_get_parameter_double(parlist, "kmos.kmo_multi_reconstruct.pix_scale"); 00814 KMO_TRY_CHECK_ERROR_STATE(); 00815 KMO_TRY_ASSURE((pix_scale >= 0.01) && 00816 (pix_scale <= 0.4), 00817 CPL_ERROR_ILLEGAL_INPUT, 00818 "pix_scale must be between 0.01 and 0.4 (results in cubes " 00819 "with 7x7 to 280x280 pixels)!"); 00820 KMO_TRY_EXIT_IF_ERROR( 00821 kmo_dfs_print_parameter_help(parlist, "kmos.kmo_multi_reconstruct.pix_scale")); 00822 00823 xcal_interpolation = kmo_dfs_get_parameter_bool(parlist, "kmos.kmo_multi_reconstruct.xcal_interpolation"); 00824 KMO_TRY_CHECK_ERROR_STATE(); 00825 KMO_TRY_ASSURE((xcal_interpolation == TRUE) || 00826 (xcal_interpolation == FALSE), 00827 CPL_ERROR_ILLEGAL_INPUT, 00828 "xcal_interpolation must be TRUE or FALSE!"); 00829 KMO_TRY_EXIT_IF_ERROR( 00830 kmo_dfs_print_parameter_help(parlist, "kmos.kmo_multi_reconstruct.xcal_interpolation")); 00831 00832 suppress_extension = kmo_dfs_get_parameter_bool(parlist, "kmos.kmo_multi_reconstruct.suppress_extension"); 00833 KMO_TRY_CHECK_ERROR_STATE(); 00834 KMO_TRY_ASSURE((suppress_extension == TRUE) || (suppress_extension == FALSE), 00835 CPL_ERROR_ILLEGAL_INPUT, 00836 "suppress_extension must be TRUE or FALSE!"); 00837 KMO_TRY_EXIT_IF_ERROR( 00838 kmo_dfs_print_parameter_help(parlist, "kmos.kmo_multi_reconstruct.suppress_extension")); 00839 00840 dev_cal = kmo_dfs_get_parameter_bool(parlist, "kmos.kmo_multi_reconstruct.dev_cal"); 00841 KMO_TRY_CHECK_ERROR_STATE(); 00842 KMO_TRY_ASSURE((dev_cal == TRUE) || (dev_cal == FALSE), 00843 CPL_ERROR_ILLEGAL_INPUT, 00844 "dev_cal must be TRUE or FALSE!"); 00845 KMO_TRY_EXIT_IF_ERROR( 00846 kmo_dfs_print_parameter_help(parlist, "kmos.kmo_multi_reconstruct.dev_cal")); 00847 00848 fn_obj_sky_table = kmo_dfs_get_parameter_string(parlist, 00849 "kmos.kmo_multi_reconstruct.obj_sky_table"); 00850 KMO_TRY_CHECK_ERROR_STATE(); 00851 00852 KMO_TRY_EXIT_IF_ERROR( 00853 kmo_dfs_print_parameter_help(parlist, 00854 "kmos.kmo_multi_reconstruct.obj_sky_table")); 00855 00856 00857 KMO_TRY_EXIT_IF_ERROR( 00858 kmo_combine_pars_load(parlist, 00859 "kmos.kmo_multi_reconstruct", 00860 &cmethod, 00861 &cpos_rej, 00862 &cneg_rej, 00863 &citer, 00864 &cmin, 00865 &cmax, 00866 FALSE)); 00867 00868 cpl_msg_info("", "-------------------------------------------"); 00869 00870 // 00871 // assure that filters, grating and rotation offsets match for 00872 // XCAL, YCAL, LCAL and for data frame to reconstruct (except DARK 00873 // frames) 00874 // 00875 00876 // check if filter_id and grating_id match for all detectors 00877 KMO_TRY_EXIT_IF_ERROR( 00878 kmo_check_frameset_setup(frameset, SCIENCE, TRUE, FALSE, TRUE)); 00879 KMO_TRY_EXIT_IF_ERROR( 00880 kmo_check_frame_setup(frameset, SCIENCE, YCAL, TRUE, FALSE, TRUE)); 00881 KMO_TRY_EXIT_IF_ERROR( 00882 kmo_check_frame_setup(frameset, XCAL, YCAL, TRUE, FALSE, TRUE)); 00883 KMO_TRY_EXIT_IF_ERROR( 00884 kmo_check_frame_setup(frameset, XCAL, LCAL, TRUE, FALSE, TRUE)); 00885 if (has_master_flat) { 00886 KMO_TRY_EXIT_IF_ERROR( 00887 kmo_check_frame_setup(frameset, XCAL, MASTER_FLAT, TRUE, FALSE, TRUE)); 00888 } 00889 if (has_telluric) { 00890 KMO_TRY_EXIT_IF_ERROR( 00891 kmo_check_frame_setup(frameset, XCAL, TELLURIC, 00892 TRUE, FALSE, TRUE)); 00893 } 00894 00895 if (cpl_frameset_count_tags(frameset, OH_SPEC) > 0) { 00896 KMO_TRY_EXIT_IF_ERROR(kmo_check_oh_spec_setup(frameset, XCAL)); 00897 } 00898 00899 // check descriptors of all frames 00900 KMO_TRY_EXIT_IF_NULL( 00901 xcal_frame = kmo_dfs_get_frame(frameset, XCAL)); 00902 00903 desc1 = kmo_identify_fits_header(cpl_frame_get_filename(xcal_frame)); 00904 KMO_TRY_CHECK_ERROR_STATE(); 00905 00906 KMO_TRY_ASSURE((desc1.nr_ext % KMOS_NR_DETECTORS == 0) && 00907 (desc1.ex_badpix == FALSE) && 00908 (desc1.fits_type == f2d_fits) && 00909 (desc1.frame_type == detector_frame), 00910 CPL_ERROR_ILLEGAL_INPUT, 00911 "XCAL isn't in the correct format!!!"); 00912 00913 KMO_TRY_EXIT_IF_NULL( 00914 ycal_frame = kmo_dfs_get_frame(frameset, YCAL)); 00915 desc2 = kmo_identify_fits_header(cpl_frame_get_filename(ycal_frame)); 00916 KMO_TRY_CHECK_ERROR_STATE(); 00917 00918 KMO_TRY_ASSURE((desc1.nr_ext == desc2.nr_ext) && 00919 (desc1.ex_badpix == desc2.ex_badpix) && 00920 (desc1.fits_type == desc2.fits_type) && 00921 (desc1.frame_type == desc2.frame_type), 00922 CPL_ERROR_ILLEGAL_INPUT, 00923 "YCAL isn't in the correct format!!!"); 00924 kmo_free_fits_desc(&desc2); 00925 kmo_init_fits_desc(&desc2); 00926 00927 KMO_TRY_EXIT_IF_NULL( 00928 lcal_frame = kmo_dfs_get_frame(frameset, LCAL)); 00929 desc2 = kmo_identify_fits_header(cpl_frame_get_filename(lcal_frame)); 00930 KMO_TRY_CHECK_ERROR_STATE(); 00931 00932 KMO_TRY_ASSURE((desc2.nr_ext % KMOS_NR_DETECTORS == 0) && 00933 (desc1.ex_badpix == desc2.ex_badpix) && 00934 (desc1.fits_type == desc2.fits_type) && 00935 (desc1.frame_type == desc2.frame_type), 00936 CPL_ERROR_ILLEGAL_INPUT, 00937 "LCAL isn't in the correct format!!!"); 00938 kmo_free_fits_desc(&desc2); 00939 kmo_init_fits_desc(&desc2); 00940 00941 if (has_master_flat) { 00942 KMO_TRY_EXIT_IF_NULL( 00943 flat_frame = kmo_dfs_get_frame(frameset, MASTER_FLAT)); 00944 desc2 = kmo_identify_fits_header(cpl_frame_get_filename(flat_frame)); 00945 KMO_TRY_CHECK_ERROR_STATE(); 00946 00947 KMO_TRY_ASSURE((desc2.nr_ext % (2*KMOS_NR_DETECTORS) == 0) && 00948 (desc1.ex_badpix == desc2.ex_badpix) && 00949 (desc1.fits_type == desc2.fits_type) && 00950 (desc1.frame_type == desc2.frame_type), 00951 CPL_ERROR_ILLEGAL_INPUT, 00952 "MASTER_FLAT isn't in the correct format!!!"); 00953 kmo_free_fits_desc(&desc2); 00954 kmo_init_fits_desc(&desc2); 00955 } 00956 00957 if (has_illum_corr) { 00958 KMO_TRY_EXIT_IF_NULL( 00959 illum_frame = kmo_dfs_get_frame(frameset, ILLUM_CORR)); 00960 desc2 = kmo_identify_fits_header( 00961 cpl_frame_get_filename(illum_frame)); 00962 KMO_TRY_CHECK_ERROR_STATE(); 00963 KMO_TRY_ASSURE(((desc2.nr_ext == 24) || (desc2.nr_ext == 48)) && 00964 (desc2.ex_badpix == FALSE) && 00965 (desc2.fits_type == f2i_fits) && 00966 (desc2.frame_type == ifu_frame), 00967 CPL_ERROR_ILLEGAL_INPUT, 00968 "ILLUM_CORR isn't in the correct format!!!"); 00969 kmo_free_fits_desc(&desc2); 00970 kmo_init_fits_desc(&desc2); 00971 } 00972 00973 if (has_telluric) { 00974 KMO_TRY_EXIT_IF_NULL( 00975 telluric_frame = kmo_dfs_get_frame(frameset, TELLURIC)); 00976 desc_telluric = kmo_identify_fits_header( 00977 cpl_frame_get_filename(telluric_frame)); 00978 KMO_TRY_CHECK_ERROR_STATE(); 00979 KMO_TRY_ASSURE(((desc_telluric.nr_ext == 24) || (desc_telluric.nr_ext == 48)) && 00980 (desc_telluric.ex_badpix == FALSE) && 00981 (desc_telluric.fits_type == f1i_fits) && 00982 (desc_telluric.frame_type == ifu_frame), 00983 CPL_ERROR_ILLEGAL_INPUT, 00984 "TELLURIC isn't in the correct format!!!"); 00985 } 00986 00987 KMO_TRY_EXIT_IF_NULL( 00988 science_frame = kmo_dfs_get_frame(frameset, SCIENCE)); 00989 while (science_frame != NULL ) { 00990 desc2 = kmo_identify_fits_header(cpl_frame_get_filename(science_frame)); 00991 KMO_TRY_CHECK_ERROR_STATE(); 00992 KMO_TRY_ASSURE((desc2.nr_ext == 3) && 00993 (desc2.ex_badpix == FALSE) && 00994 (desc2.fits_type == raw_fits) && 00995 (desc2.frame_type == detector_frame), 00996 CPL_ERROR_ILLEGAL_INPUT, 00997 "SCIENCE isn't in the correct format!!!"); 00998 kmo_free_fits_desc(&desc2); 00999 kmo_init_fits_desc(&desc2); 01000 01001 if (mapping_mode == NULL) { 01002 KMO_TRY_EXIT_IF_NULL( 01003 tmp_header = 01004 kmclipm_propertylist_load( 01005 cpl_frame_get_filename(science_frame), 0)); 01006 if (cpl_propertylist_has(tmp_header, TPL_ID)) { 01007 KMO_TRY_EXIT_IF_NULL( 01008 tmp_str = cpl_propertylist_get_string(tmp_header, 01009 TPL_ID)); 01010 if (strcmp(tmp_str, MAPPING8) == 0) 01011 { 01012 mapping_mode = cpl_sprintf("%s", "mapping8"); 01013 } 01014 if (strcmp(tmp_str, MAPPING24) == 0) 01015 { 01016 mapping_mode = cpl_sprintf("%s", "mapping24"); 01017 } 01018 } 01019 01020 // when mapping-mode should be supported, remove this if-statement... 01021 if (mapping_mode != NULL) { 01022 cpl_msg_error("", "*******************************************************"); 01023 cpl_msg_error("", "*******************************************************"); 01024 cpl_msg_error("", "*** ***"); 01025 cpl_msg_error("", "*** The provided SCIENCE frames have been produced ***"); 01026 cpl_msg_error("", "*** with template %s ***", tmp_str); 01027 cpl_msg_error("", "*** ***"); 01028 cpl_msg_error("", "*** kmo_multi_reconstruct doesn't support yet this ***"); 01029 cpl_msg_error("", "*** observation mode. Please use recipe kmo_sci_red ***"); 01030 cpl_msg_error("", "*** instead! ***"); 01031 cpl_msg_error("", "*** ***"); 01032 cpl_msg_error("", "*******************************************************"); 01033 cpl_msg_error("", "*******************************************************"); 01034 KMO_TRY_ASSURE(1==0, 01035 CPL_ERROR_ILLEGAL_INPUT, 01036 " "); 01037 } 01038 01039 cpl_propertylist_delete(tmp_header); tmp_header = NULL; 01040 } 01041 01042 science_frame = kmo_dfs_get_frame(frameset, NULL); 01043 KMO_TRY_CHECK_ERROR_STATE(); 01044 } 01045 01046 if ((mapping_mode != NULL) && ((ifus != NULL) || (strcmp(name, "") != 0))) { 01047 cpl_msg_warning("","The SCIENCE frames have been taken in one of the " 01048 "mapping modes AND specific IFUs have been " 01049 "specified! --> Only processing these!"); 01050 } 01051 01052 KMO_TRY_EXIT_IF_NULL( 01053 suffix = kmo_dfs_get_suffix(xcal_frame, TRUE, FALSE)); 01054 01055 KMO_TRY_EXIT_IF_ERROR( 01056 kmo_check_frame_setup_md5_xycal(frameset)); 01057 KMO_TRY_EXIT_IF_ERROR( 01058 kmo_check_frame_setup_md5(frameset)); 01059 KMO_TRY_EXIT_IF_ERROR( 01060 kmo_check_frame_setup_sampling(frameset)); 01061 01062 cpl_msg_info("", "Detected instrument setup: %s", suffix+1); 01063 cpl_msg_info("", "(grating 1, 2 & 3)"); 01064 cpl_msg_info("", "-------------------------------------------"); 01065 cpl_free(suffix); suffix = NULL; 01066 01067 if (cpl_frameset_count_tags(frameset, OH_SPEC) != 0) { 01068 int is_all_obs = TRUE, 01069 has_all_origfile = TRUE; 01070 cpl_frame *tmp_frame = NULL; 01071 01072 KMO_TRY_EXIT_IF_NULL( 01073 tmp_frame = kmo_dfs_get_frame(frameset, SCIENCE)); 01074 while (tmp_frame != NULL ) { 01075 KMO_TRY_EXIT_IF_NULL( 01076 tmp_header = kmclipm_propertylist_load(cpl_frame_get_filename(tmp_frame), 0)); 01077 01078 if (cpl_propertylist_has(tmp_header, ORIGFILE)) { 01079 KMO_TRY_EXIT_IF_NULL( 01080 tmp_str = cpl_propertylist_get_string(tmp_header, ORIGFILE)); 01081 if (strstr(tmp_str, "OBS") == NULL) { 01082 is_all_obs = FALSE; 01083 } 01084 } else { 01085 has_all_origfile = FALSE; 01086 } 01087 cpl_propertylist_delete(tmp_header); tmp_header = NULL; 01088 tmp_frame = kmo_dfs_get_frame(frameset, NULL); 01089 KMO_TRY_CHECK_ERROR_STATE(); 01090 } 01091 01092 if (has_all_origfile) { 01093 if (is_all_obs) { 01094 // we are reconstructing an OBS-frame, allow OH_SPEC correction 01095 KMO_TRY_EXIT_IF_NULL( 01096 ref_spectrum_frame = kmo_dfs_get_frame(frameset, OH_SPEC)); 01097 } else { 01098 cpl_msg_warning("", "Supplied OH_SPEC is ignored since a calibration " 01099 "frame is being used as SCIENCE frame."); 01100 } 01101 } else { 01102 cpl_msg_warning("", "The supplied SCIENCE frames are all assumed to be " 01103 "science frames. If any of them is a calibration frame, " 01104 "omit OH_SPEC from sof-file"); 01105 KMO_TRY_EXIT_IF_NULL( 01106 ref_spectrum_frame = kmo_dfs_get_frame(frameset, OH_SPEC)); 01107 } 01108 } 01109 01110 // 01111 // check which IFUs are active for all frames 01112 // 01113 KMO_TRY_EXIT_IF_NULL( 01114 unused_ifus_before = kmo_get_unused_ifus(frameset, 1, 1)); 01115 01116 KMO_TRY_EXIT_IF_NULL( 01117 unused_ifus_after = kmo_duplicate_unused_ifus(unused_ifus_before)); 01118 01119 kmo_print_unused_ifus(unused_ifus_before, FALSE); 01120 01121 // 01122 // get bounds, setup grid, setup arm_name-struct 01123 // 01124 01125 // get left and right bounds of IFUs 01126 KMO_TRY_EXIT_IF_NULL( 01127 tmp_header = kmo_dfs_load_primary_header(frameset, XCAL)); 01128 KMO_TRY_EXIT_IF_NULL( 01129 bounds = kmclipm_extract_bounds(tmp_header)); 01130 cpl_propertylist_delete(tmp_header); tmp_header = NULL; 01131 01132 // setup grid definition, wavelength start and end points will be set 01133 // in the detector loop 01134 KMO_TRY_EXIT_IF_ERROR( 01135 kmclipm_setup_grid(&gd, imethod, neighborhoodRange, pix_scale, 0.)); 01136 KMO_TRY_EXIT_IF_ERROR( 01137 kmclipm_setup_grid(&gd_14x14, imethod, neighborhoodRange, pix_scale, 0.)); 01138 01139 KMO_TRY_EXIT_IF_NULL( 01140 band_table = kmo_dfs_load_table(frameset, WAVE_BAND, 1, 0)); 01141 KMO_TRY_EXIT_IF_NULL( 01142 tmp_header = kmo_dfs_load_primary_header(frameset, LCAL)); 01143 KMO_TRY_EXIT_IF_NULL( 01144 filter_id = cpl_sprintf("%s", cpl_propertylist_get_string(tmp_header, filter_keyword))); 01145 KMO_TRY_EXIT_IF_ERROR( 01146 kmclipm_setup_grid_band_lcal(&gd, filter_id, band_table)); 01147 KMO_TRY_EXIT_IF_ERROR( 01148 kmclipm_setup_grid_band_lcal(&gd_14x14, filter_id, band_table)); 01149 cpl_propertylist_delete(tmp_header); tmp_header = NULL; 01150 cpl_table_delete(band_table); band_table = NULL; 01151 01152 // 01153 // get valid object names to process, either one object name across 01154 // several SCIENCE frames, or all object names 01155 // 01156 if (strcmp(fn_obj_sky_table, "") == 0) { 01157 KMO_TRY_EXIT_IF_NULL( 01158 arm_name_struct = kmo_create_armNameStruct(frameset, 01159 SCIENCE, 01160 ifus, 01161 name, 01162 unused_ifus_after, 01163 bounds, 01164 mapping_mode, 01165 no_subtract)); 01166 KMO_TRY_EXIT_IF_ERROR( 01167 kmo_save_objSkyStruct(arm_name_struct->obj_sky_struct)); 01168 } else { 01169 // read in obj/sky-table 01170 objSkyStruct *obj_sky_struct = NULL; 01171 01172 KMO_TRY_EXIT_IF_NULL( 01173 obj_sky_struct = kmo_read_objSkyStruct(fn_obj_sky_table, 01174 frameset, 01175 SCIENCE)); 01176 01177 KMO_TRY_EXIT_IF_NULL( 01178 arm_name_struct = kmo_create_armNameStruct2(obj_sky_struct, 01179 frameset, 01180 SCIENCE, 01181 ifus, 01182 name, 01183 unused_ifus_after, 01184 bounds, 01185 mapping_mode, 01186 no_subtract)); 01187 01188 } 01189 kmo_print_armNameStruct(frameset, arm_name_struct); 01190 cpl_free(bounds); bounds = NULL; 01191 01192 // 01193 // check availability of tellurics for the different IFUs used 01194 // 01195 if (has_telluric && (mapping_mode != NULL)) { 01196 // in mapping-mode check if for all IFUs there is either no telluric at all 01197 // or the same number of tellurics than object names 01198 int telluric_ok = TRUE; 01199 for (cnt = 0; cnt < arm_name_struct->nrNames; cnt++) { 01200 if (!((arm_name_struct->telluricCnt[cnt] == arm_name_struct->namesCnt[cnt]) || 01201 (arm_name_struct->telluricCnt[cnt] == 0))) 01202 { 01203 telluric_ok = FALSE; 01204 break; 01205 } 01206 } 01207 if (!telluric_ok) { 01208 KMO_TRY_ASSURE(1==0, 01209 CPL_ERROR_UNSUPPORTED_MODE, 01210 "Mosaics need a TELLURIC frame with at least a telluric correction per detector available! " 01211 "Omit the TELLURIC from your sof-file or choose another TELLURIC!"); 01212 } 01213 } 01214 01215 // 01216 // loop over all object names 01217 // (for mapping template only once,) 01218 // (when ifus or name is set as well only once) 01219 // 01220 for (arm_index = 0; arm_index < arm_name_struct->nrNames; arm_index++) { 01221 01222 nr_frames = arm_name_struct->namesCnt[arm_index]; 01223 01224 KMO_TRY_EXIT_IF_NULL( 01225 sub_headers = kmo_mr_get_headers(arm_name_struct, 01226 arm_index+1, 01227 frameset, 01228 gd_14x14)); 01229 01230 if ((strcmp(comb_method, "center") == 0) || 01231 (ref_spectrum_frame != NULL)) 01232 { 01233 // 01234 // reconstruct preliminary cubes 01235 // 01236 KMO_TRY_EXIT_IF_NULL( 01237 pre_data_cube_list = kmo_mr_create_datacubes(arm_name_struct, 01238 arm_index+1, 01239 frameset, 01240 gd_14x14, 01241 xcal_interpolation)); 01242 // 01243 // calculate lambda-correction coefficients 01244 // 01245 if (ref_spectrum_frame != NULL) { 01246 KMO_TRY_EXIT_IF_NULL( 01247 lcorr_coeffs = cpl_calloc(nr_frames, sizeof(cpl_polynomial*))); 01248 01249 cnt = 0; 01250 for (iy = 0; iy < arm_name_struct->size; iy++) { 01251 for (ix = 0; ix < KMOS_NR_IFUS; ix++) { 01252 ifu_nr = ix + 1; 01253 if (arm_name_struct->name_ids[ix+iy*KMOS_NR_IFUS] == arm_index+1) { 01254 KMO_TRY_EXIT_IF_NULL( 01255 lcorr_coeffs[cnt] = kmo_lcorr_get(pre_data_cube_list[cnt], 01256 sub_headers[cnt], 01257 ref_spectrum_frame, 01258 gd_14x14, 01259 filter_id, 01260 ifu_nr)); 01261 cnt++; 01262 } 01263 } 01264 } 01265 } // end if (lcorr) 01266 } // end if (center, lcorr) 01267 01268 // 01269 // calculate offsets 01270 // 01271 KMO_TRY_EXIT_IF_ERROR( 01272 kmo_mr_get_offsets(arm_name_struct, 01273 arm_index+1, 01274 comb_method, 01275 imethod, 01276 filename, 01277 frameset, 01278 pre_data_cube_list, 01279 sub_headers, 01280 fmethod, 01281 cmethod, 01282 cpos_rej, 01283 cneg_rej, 01284 citer, 01285 cmin, 01286 cmax, 01287 dev_cal, 01288 mapping_mode, 01289 &xshifts, 01290 &yshifts)); 01291 01292 KMO_TRY_EXIT_IF_NULL( 01293 ref_sub_header = cpl_propertylist_duplicate(sub_headers[0])); 01294 01295 for (cnt = 0; cnt < nr_frames; cnt++) { 01296 cpl_propertylist_delete(sub_headers[cnt]); sub_headers[cnt] = NULL; 01297 } 01298 cpl_free(sub_headers); sub_headers = NULL; 01299 01300 if (pre_data_cube_list != NULL) { 01301 for (cnt = 0; cnt < nr_frames; cnt++) { 01302 cpl_imagelist_delete(pre_data_cube_list[cnt]); 01303 } 01304 cpl_free(pre_data_cube_list); pre_data_cube_list = NULL; 01305 } 01306 01307 // 01308 // set spatial part of the grid 01309 // 01310 for (cnt = 0; cnt < nr_frames; cnt++) { 01311 if (xmin > xshifts[cnt]) { 01312 xmin = xshifts[cnt]; 01313 } 01314 if (xmax < xshifts[cnt]) { 01315 xmax = xshifts[cnt]; 01316 } 01317 if (ymin > yshifts[cnt]) { 01318 ymin = yshifts[cnt]; 01319 } 01320 if (ymax < yshifts[cnt]) { 01321 ymax = yshifts[cnt]; 01322 } 01323 } 01324 01325 if (xmax > 0.0001) { 01326 gxshift = -rint(xmax); //(int)xmax; // gxshift = - ceil(xmax); 01327 } else { 01328 gxshift = 0.; 01329 } 01330 if (ymin < -0.0001) { 01331 gyshift = rint(ymin); //(int)ymin; // gyshift = floor(ymin); 01332 } else { 01333 gyshift = 0.; 01334 } 01335 if (xmin < -0.0001) { 01336 gxdim = - floor(xmin); 01337 } else { 01338 gxdim = 0.; 01339 } 01340 if (ymax > 0.0001) { 01341 gydim = ceil(ymax); 01342 } else { 01343 gydim = 0.; 01344 } 01345 01346 xdim = (int)(gxdim - gxshift + .5); 01347 ydim = (int)(gydim - gyshift + .5); 01348 gd.x.start += gxshift * pix_scale*1000; 01349 gd.y.start += gyshift * pix_scale*1000; 01350 gd.x.dim += xdim; 01351 gd.y.dim += ydim; 01352 01353 // cpl_msg_set_level(CPL_MSG_DEBUG); 01354 // cpl_msg_debug(cpl_func,"x: %f < %f, y: %f < %f", 01355 // xmin,xmax,ymin,ymax); 01356 // cpl_msg_debug(cpl_func,"gxshift: %f gxdim: %f xdim: %d, gyshift: %f gydim: %f ydim: %d", 01357 // gxshift, gxdim, xdim, gyshift, gydim, ydim); 01358 // cpl_msg_debug(cpl_func,"gd: start delta dim"); 01359 // cpl_msg_debug(cpl_func," x: %f %f %d", gd.x.start, gd.x.delta, gd.x.dim); 01360 // cpl_msg_debug(cpl_func," y: %f %f %d", gd.y.start, gd.y.delta, gd.y.dim); 01361 // cpl_msg_debug(cpl_func," l: %f %f %d", gd.l.start, gd.l.delta, gd.l.dim); 01362 // cpl_msg_set_level(CPL_MSG_INFO); 01363 01364 // 01365 // reconstruct multiple detector images 01366 // 01367 KMO_TRY_EXIT_IF_ERROR( 01368 kmo_mr_reconstruct(frameset, 01369 arm_name_struct, 01370 arm_index+1, 01371 xshifts, 01372 yshifts, 01373 gd, 01374 gd_14x14, 01375 pix_scale, 01376 xcal_interpolation, 01377 lcorr_coeffs, 01378 &cube_combined_data, 01379 &cube_combined_noise, 01380 no_subtract, 01381 flux, 01382 background)); 01383 01384 if (lcorr_coeffs != NULL) { 01385 for (cnt = 0; cnt < nr_frames; cnt++) { 01386 cpl_polynomial_delete(lcorr_coeffs[cnt]); lcorr_coeffs[cnt] = NULL; 01387 } 01388 cpl_free(lcorr_coeffs); lcorr_coeffs = NULL; 01389 } 01390 01391 // 01392 // identify ifu_nr of current object name in first SCIENCE frame 01393 // containing this object name (e.g. first frame could contain skies only) 01394 // 01395 ifu_nr = -1; 01396 science_frame = NULL; 01397 for (iy = 0; iy < arm_name_struct->size; iy++) { 01398 for (ix = 0; ix < KMOS_NR_IFUS; ix++) { 01399 if (arm_name_struct->name_ids[ix+iy*KMOS_NR_IFUS] == arm_index+1) { 01400 if (ifu_nr == -1) { 01401 KMO_TRY_EXIT_IF_NULL( 01402 science_frame = arm_name_struct->obj_sky_struct->table[iy].objFrame); 01403 01404 ifu_nr = ix + 1; 01405 break; 01406 } 01407 } 01408 } 01409 if (ifu_nr != -1) { break; } 01410 } 01411 01412 // 01413 // divide cube by telluric correction 01414 // 01415 if (has_telluric && 01416 (arm_name_struct->sameTelluric[arm_index] > 0)) 01417 { 01418 telluric_data = kmo_tweak_load_telluric(frameset, ifu_nr, FALSE, no_subtract); 01419 KMO_TRY_CHECK_ERROR_STATE(); 01420 if (telluric_data != NULL) { 01421 int index = kmo_identify_index_desc(desc_telluric, ifu_nr, TRUE); 01422 KMO_TRY_CHECK_ERROR_STATE(); 01423 if (desc_telluric.sub_desc[index-1].valid_data == TRUE) { 01424 // load noise if present 01425 telluric_noise = kmo_tweak_load_telluric(frameset, ifu_nr, TRUE, no_subtract); 01426 KMO_TRY_CHECK_ERROR_STATE(); 01427 } else { 01428 if (print_warning_once_tweak_std_noise && (cube_combined_noise != NULL)) { 01429 cpl_msg_warning("","************************************************************"); 01430 cpl_msg_warning("","* Noise cubes were calculated, but won't be divided by *"); 01431 cpl_msg_warning("","* telluric error since it is missing. *"); 01432 cpl_msg_warning("","* In order to get a telluric with errors, execute *"); 01433 cpl_msg_warning("","* kmo_std_star with one of the nearest neighbour methods *"); 01434 cpl_msg_warning("","* (set --imethod to NN, lwNN or swNN) *"); 01435 cpl_msg_warning("","************************************************************"); 01436 print_warning_once_tweak_std_noise = FALSE; 01437 } 01438 } 01439 01440 KMO_TRY_EXIT_IF_ERROR( 01441 kmo_arithmetic_3D_1D( 01442 cube_combined_data, telluric_data, 01443 cube_combined_noise, telluric_noise, "/")); 01444 } 01445 kmclipm_vector_delete(telluric_data); telluric_data = NULL; 01446 kmclipm_vector_delete(telluric_noise); telluric_noise = NULL; 01447 } 01448 01449 // 01450 // saving 01451 // 01452 fn_cube = CUBE_MULTI; 01453 if (!suppress_extension) { 01454 char tmp_suffix[1024]; 01455 tmp_suffix[0] = '\0'; 01456 01457 if (arm_name_struct->telluricCnt[arm_index] == nr_frames) { 01458 strcat(tmp_suffix, "_telluric"); 01459 } 01460 if (has_illum_corr) { 01461 strcat(tmp_suffix, "_illum"); 01462 } 01463 // if (sky_tweak) { 01464 // strcat(tmp_suffix, "_skytweak"); 01465 // } 01466 01467 if (strlen(tmp_suffix) > 0) { 01468 KMO_TRY_EXIT_IF_NULL( 01469 fn_suffix = cpl_sprintf("_%s_%s", arm_name_struct->names[arm_index], tmp_suffix)); 01470 } else { 01471 KMO_TRY_EXIT_IF_NULL( 01472 fn_suffix = cpl_sprintf("_%s", arm_name_struct->names[arm_index])); 01473 } 01474 } else { 01475 KMO_TRY_EXIT_IF_NULL( 01476 fn_suffix = cpl_sprintf("_%d", suppress_index++)); 01477 } 01478 01479 // 01480 // calculate WCS 01481 // 01482 KMO_TRY_EXIT_IF_NULL( 01483 science_frame_header = kmclipm_propertylist_load(cpl_frame_get_filename(science_frame), 0)); 01484 01485 KMO_TRY_EXIT_IF_ERROR( 01486 kmo_calc_wcs_gd(science_frame_header, ref_sub_header, ifu_nr, gd)); 01487 01488 cpl_propertylist_delete(science_frame_header); science_frame_header = NULL; 01489 01490 // 01491 // save product 01492 // 01493 KMO_TRY_EXIT_IF_ERROR( 01494 kmo_dfs_save_main_header(frameset, fn_cube, fn_suffix, 01495 science_frame, NULL, parlist, cpl_func)); 01496 01497 KMO_TRY_EXIT_IF_NULL( 01498 extname = cpl_sprintf("%s.DATA", arm_name_struct->names[arm_index])); 01499 KMO_TRY_EXIT_IF_ERROR( 01500 kmclipm_update_property_string(ref_sub_header, 01501 EXTNAME, 01502 extname, 01503 "FITS extension name")); 01504 cpl_free(extname); extname = NULL; 01505 01506 KMO_TRY_EXIT_IF_ERROR( 01507 kmo_dfs_save_cube(cube_combined_data, fn_cube, fn_suffix, 01508 ref_sub_header, 0./0.)); 01509 01510 if (cube_combined_noise != NULL) { 01511 KMO_TRY_EXIT_IF_NULL( 01512 extname = cpl_sprintf("%s.NOISE", arm_name_struct->names[arm_index])); 01513 KMO_TRY_EXIT_IF_ERROR( 01514 kmclipm_update_property_string(ref_sub_header, 01515 EXTNAME, 01516 extname, 01517 "FITS extension name")); 01518 cpl_free(extname); extname = NULL; 01519 01520 KMO_TRY_EXIT_IF_ERROR( 01521 kmo_dfs_save_cube(cube_combined_noise, fn_cube, fn_suffix, 01522 ref_sub_header, 0./0.)); 01523 } 01524 01525 cpl_imagelist_delete(cube_combined_data); cube_combined_data = NULL; 01526 cpl_imagelist_delete(cube_combined_noise); cube_combined_noise = NULL; 01527 cpl_propertylist_delete(ref_sub_header); ref_sub_header = NULL; 01528 cpl_free(fn_suffix); fn_suffix = NULL; 01529 cpl_free(xshifts); xshifts = NULL; 01530 cpl_free(yshifts); yshifts = NULL; 01531 } // for (arm_index = nrNames) 01532 01533 kmo_print_unused_ifus(unused_ifus_after, TRUE); 01534 } 01535 KMO_CATCH 01536 { 01537 KMO_CATCH_MSG(); 01538 ret_val = -1; 01539 } 01540 01541 kmo_free_fits_desc(&desc1); 01542 kmo_free_fits_desc(&desc2); 01543 kmo_free_fits_desc(&desc_telluric); 01544 cpl_vector_delete(ifus); ifus = NULL; 01545 cpl_free(mapping_mode); mapping_mode = NULL; 01546 if (unused_ifus_before != NULL) { 01547 kmo_free_unused_ifus(unused_ifus_before); unused_ifus_before = NULL; 01548 } 01549 if (unused_ifus_after != NULL) { 01550 kmo_free_unused_ifus(unused_ifus_after); unused_ifus_after = NULL; 01551 } 01552 if (bounds != NULL) { 01553 cpl_free(bounds); bounds = NULL; 01554 } 01555 01556 kmo_delete_armNameStruct(arm_name_struct); 01557 01558 // frees for the case of errors 01559 kmclipm_vector_delete(telluric_data); telluric_data = NULL; 01560 kmclipm_vector_delete(telluric_noise); telluric_noise = NULL; 01561 cpl_propertylist_delete(tmp_header); tmp_header = NULL; 01562 cpl_table_delete(band_table); band_table = NULL; 01563 cpl_free(suffix); suffix = NULL; 01564 cpl_free(fn_suffix); fn_suffix = NULL; 01565 cpl_free(filter_id); filter_id = NULL; 01566 01567 return ret_val; 01568 } 01569