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