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