KMOS Pipeline Reference Manual
1.3.0
|
00001 /* 00002 * This file is part of the KMOS Pipeline 00003 * Copyright (C) 2002,2003 European Southern Observatory 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License as published by 00007 * the Free Software Foundation; either version 2 of the License, or 00008 * (at your option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 * GNU General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU General Public License 00016 * along with this program; if not, write to the Free Software 00017 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00018 */ 00019 00020 #ifdef HAVE_CONFIG_H 00021 #include <config.h> 00022 #endif 00023 00024 /*----------------------------------------------------------------------------- 00025 * Includes 00026 *----------------------------------------------------------------------------*/ 00027 00028 #include <string.h> 00029 #include <math.h> 00030 00031 #include <cpl.h> 00032 00033 #include "kmclipm_constants.h" 00034 #include "kmclipm_functions.h" 00035 00036 #include "kmo_debug.h" 00037 #include "kmo_constants.h" 00038 #include "kmo_cpl_extensions.h" 00039 #include "kmo_priv_lcorr.h" 00040 #include "kmo_utils.h" 00041 #include "kmo_error.h" 00042 #include "kmo_dfs.h" 00043 #include "kmo_functions.h" 00044 #include "kmo_priv_arithmetic.h" 00045 #include "kmo_priv_combine.h" 00046 #include "kmo_priv_functions.h" 00047 #include "kmo_priv_reconstruct.h" 00048 #include "kmo_priv_sky_tweak.h" 00049 00050 /*----------------------------------------------------------------------------- 00051 * Functions prototypes 00052 *----------------------------------------------------------------------------*/ 00053 00054 static int kmo_sci_red_create(cpl_plugin *); 00055 static int kmo_sci_red_exec(cpl_plugin *); 00056 static int kmo_sci_red_destroy(cpl_plugin *); 00057 static int kmo_sci_red(cpl_parameterlist *, cpl_frameset *); 00058 00059 /*----------------------------------------------------------------------------- 00060 * Static variables 00061 *----------------------------------------------------------------------------*/ 00062 00063 static char kmo_sci_red_description[] = 00064 "Ideally at least two data frames have to be provided since we need for each\n" 00065 "IFU pointing to an object as well a sky frame for the same IFU.\n" 00066 "If an OH spectrum is given in the SOF file the lambda axis will be corrected\n" 00067 "using the OH lines as reference.\n" 00068 "Every IFU containing an object will be reconstructed and divided by telluric\n" 00069 "and illumination correction. By default these intermediate cubes are saved\n" 00070 "to disk. Frames just containing skies won’t produce an output here, so the\n" 00071 "number of output frames can be smaller than the number of input frames.\n" 00072 "Then the reconstructed objects with the same object name are combined. These\n" 00073 "outputs are also saved to disk, the number of created files depends on the\n" 00074 "number of reconstructed objects of different name. If the user just wants to\n" 00075 "combine a certain object, the parameters --name or --ifus can be used.\n" 00076 "For exposures taken with the templates KMOS_spec_obs_mapping8 and\n" 00077 "KMOS_spec_obs_mapping24 the recipe behaves a bit different: All active IFUs\n" 00078 "will be combined, regardless of the object names.\n" 00079 "\n" 00080 "BASIC PARAMETERS:\n" 00081 "-----------------\n" 00082 "--imethod\n" 00083 "The interpolation method used for reconstruction.\n" 00084 "\n" 00085 "--smethod\n" 00086 "The interpolation method used for shifting.\n" 00087 "\n" 00088 "--name\n" 00089 "--ifus\n" 00090 "Since an object can be present only once per exposure and since it can be\n" 00091 "located in different IFUs for the existing exposures, there are two modes\n" 00092 "to identify the objects:\n" 00093 " * Combine by object names (default)\n" 00094 " In this case the object name must be provided via the --name parameter.\n" 00095 " The object name will be searched for in all primary headers of all\n" 00096 " provided frames in the keyword ESO OCS ARMx NAME.\n" 00097 "\n" 00098 " * Combine by index (advanced)\n" 00099 " In this case the --ifus parameter must be provided. The parameter must\n" 00100 " have the same number of entries as frames are provided, e.g. \"3;1;24\"\n" 00101 " for 3 exposures. The index doesn't reference the extension in the frame\n" 00102 " but the real index of the IFU as defined in the EXTNAME keyword.\n" 00103 " (e.g. 'IFU.3.DATA')\n" 00104 "\n" 00105 "ADVANCED PARAMETERS\n" 00106 "-------------------\n" 00107 "--flux\n" 00108 "Specify if flux conservation should be applied.\n" 00109 "\n" 00110 "--background\n" 00111 "Specify if background removal should be applied.\n" 00112 "\n" 00113 "--suppress_extension\n" 00114 "If set to TRUE, the arbitrary filename extensions are supressed. If multiple\n" 00115 "products with the same category are produced, they will be numered\n" 00116 "consecutively starting from 0.\n" 00117 "\n" 00118 "--sky_tweak\n" 00119 "If set to TRUE sky substraction is not done by subtracting the corresponding\n" 00120 "detector images but subtracting a modified sky cube from the object cube.\n" 00121 "It is not allowed that \"--sky_tweak\" and \"--no_subtract\" both are TRUE.\n" 00122 "\n" 00123 "--tbsub\n" 00124 "If set to TRUE subtract the thermal background from the cube resulting from\n" 00125 "sky tweaking.\n" 00126 "Default value is TRUE.\n" 00127 "\n" 00128 "--obj_sky_table\n" 00129 "The automatic obj-sky-associations can be modified by indicating a file with\n" 00130 "the desired associations. Therefore the file written to disk by default\n" 00131 "(without setting this option) can be edited manually. The formatting must\n" 00132 "absolutely be retained, just the type codes ('O' and'S') and the associated\n" 00133 "frame indices should be altered\n" 00134 "\n" 00135 " Advanced reconstruction parameters\n" 00136 " ----------------------------------\n" 00137 "--neighborhoodRange\n" 00138 "Defines the range to search for neighbors during reconstruction\n" 00139 "\n" 00140 "--b_samples\n" 00141 "The number of samples in spectral direction for the reconstructed cube.\n" 00142 "Ideally this number should be greater than 2048, the detector size.\n" 00143 "\n" 00144 "--b_start\n" 00145 "--b_end\n" 00146 "Used to define manually the start and end wavelength for the reconstructed\n" 00147 "cube. By default the internally defined values are used.\n" 00148 "\n" 00149 "--fast_mode\n" 00150 "If set to TRUE, the reconstructed cubes will be collapsed (using median) and\n" 00151 "only then be shifted and combined.\n" 00152 "\n" 00153 "--pix_scale\n" 00154 "Change the pixel scale [arcsec]. Default of 0.2\" results into cubes of\n" 00155 "14x14pix, a scale of 0.1\" results into cubes of 28x28pix, etc.\n" 00156 "\n" 00157 "--no_subtract\n" 00158 "If set to TRUE, the found objects and references won't be sky subtracted. \n" 00159 "Additionally all IFUs will be reconstructed, even the ones containing skies.\n" 00160 "This option sets the parameter no_combine to TRUE automatically.\n" 00161 "\n" 00162 "--xcal_interpolation\n" 00163 "If true interpolate the pixel position in the slitlet (xcal) using the two\n" 00164 "closest rotator angles in the calibration file. Otherwise take the values\n" 00165 "of the closest rotator angle\n" 00166 "\n" 00167 "--extrapolate\n" 00168 "By default no extrapolation is applied. This means that the intermediate\n" 00169 "reconstructed cubes will shrink at most one pixel, which is ok for templates\n" 00170 "like KMOS_spec_obs_nodtosky or KMOS_spec_obs_freedither. When the cubes will\n" 00171 "be arranged as a map, a grid is likely to occur between the IFUs. Therefore\n" 00172 "extrapolation during the shifting process can be switched on in order to get\n" 00173 "IFUs of original size. For frames taken with mapping templates,\n" 00174 "extrapolation is switched on automatically.\n" 00175 "\n" 00176 "--velocity_offset\n" 00177 "Specifies the velocity offset correction in km/s for lambda scale.\n" 00178 "Default is 0.0 km/s, i.e. no velocity correction.\n" 00179 "\n" 00180 "--save_interims\n" 00181 "If set to TRUE the interim object and sky cubes used for sky tweaking are\n" 00182 "saved to FITS file in the same format as SCI_RECONSTRUCTED\n" 00183 "Default is FALSE.\n" 00184 "\n" 00185 " Advanced combining parameters\n" 00186 " ----------------------------------\n" 00187 "--edge_nan\n" 00188 "Set borders of two sides of the cubes to NaN before combining them. This\n" 00189 "minimises unwanted border effects when dithering.\n" 00190 "\n" 00191 "--no_combine\n" 00192 "If set to TRUE, the reconstructed cubes will not be combined.\n" 00193 "\n" 00194 "--method\n" 00195 "There are following sources to get the shift parameters from:\n" 00196 " * 'header' (default)\n" 00197 " The shifts are calculated according to the WCS information stored in the\n" 00198 " header of every IFU. The output frame will get larger, except the object\n" 00199 " is at the exact same position for all exposures. The size of the\n" 00200 " exposures can differ, but the orientation must be the same for all\n" 00201 " exposures.\n" 00202 "\n" 00203 " * 'none'\n" 00204 " The cubes are directly recombined, not shifting at all. The ouput frame\n" 00205 " will have the same dimensions as the input cubes.\n" 00206 " If the size differs a warning will be emitted and the cubes will be\n" 00207 " aligned to the lower left corner. If the orientation differs a warning\n" 00208 " will be emitted, but the cubes are combined anyway.\n" 00209 "\n" 00210 " * 'center'\n" 00211 " The shifts are calculated using a centering algorithm. The cube will be\n" 00212 " collapsed and a 2D profile will be fitted to it to identify the centre.\n" 00213 " With the parameter --fmethod the function to fit can be provided. The\n" 00214 " size of the exposures can differ, but the orientation must be the same\n" 00215 " for all exposures.\n" 00216 "\n" 00217 " * 'user'\n" 00218 " Read the shifts from a user specified file. The path of the file must be\n" 00219 " provided using the --filename parameter. For every exposure (except the\n" 00220 " first one) two shift values are expected per line, they have to be\n" 00221 " separated with simple spaces. The values indicate pixel shifts and are\n" 00222 " referenced to the first frame. The 1st value is the shift in x-direction\n" 00223 " to the left, the 2nd the shift in y-direction upwards. The size of the\n" 00224 " exposures can differ, but the orientation must be the same for all\n" 00225 " exposures.\n" 00226 "\n" 00227 "--fmethod\n" 00228 "see --method='center'\n" 00229 "The type of function that should be fitted spatially to the collapsed image.\n" 00230 "This fit is used to create a mask to extract the spectrum of the object.\n" 00231 "Valid values are 'gauss' and 'moffat'.\n" 00232 "\n" 00233 "--filename\n" 00234 "see --method='user'\n" 00235 "\n" 00236 "--cmethod\n" 00237 "Following methods of frame combination are available:\n" 00238 " * 'ksigma' (Default)\n" 00239 " An iterative sigma clipping. For each position all pixels in the spectrum\n" 00240 " are examined. If they deviate significantly, they will be rejected\n" 00241 " according to the conditions:\n" 00242 " val > mean + stdev * cpos_rej\n" 00243 " and\n" 00244 " val < mean - stdev * cneg_rej\n" 00245 " where --cpos_rej, --cneg_rej and --citer are the corresponding\n" 00246 " configuration parameters. In the first iteration median and percentile\n" 00247 " level are used.\n" 00248 "\n" 00249 " * 'median'\n" 00250 " At each pixel position the median is calculated.\n" 00251 "\n" 00252 " * 'average'\n" 00253 " At each pixel position the average is calculated.\n" 00254 "\n" 00255 " * 'sum'\n" 00256 " At each pixel position the sum is calculated.\n" 00257 "\n" 00258 " * 'min_max'\n" 00259 " The specified number of minimum and maximum pixel values will be\n" 00260 " rejected.\n" 00261 " --cmax and --cmin apply to this method.\n" 00262 "\n" 00263 "--cpos_rej\n" 00264 "--cneg_rej\n" 00265 "--citer\n" 00266 "see --cmethod='ksigma'\n" 00267 "\n" 00268 "--cmax\n" 00269 "--cmin\n" 00270 "see --cmethod='min_max'\n" 00271 "\n" 00272 "--------------------------------------------------------------------------\n" 00273 " Input files:\n" 00274 "\n" 00275 " DO KMOS \n" 00276 " category Type Explanation Required #Frames\n" 00277 " -------- ----- ----------- -------- -------\n" 00278 " SCIENCE RAW The science frames Y >=1 \n" 00279 " XCAL F2D x calibration frame Y 1 \n" 00280 " YCAL F2D y calibration frame Y 1 \n" 00281 " LCAL F2D Wavelength calib. frame Y 1 \n" 00282 " WAVE_BAND F2L Table with start-/end-wavelengths Y 1 \n" 00283 " MASTER_FLAT F2D Master flat Y 0,1 \n" 00284 " ILLUM_CORR F2I Illumination correction N 0,1 \n" 00285 " TELLURIC F1I normalised telluric spectrum N 0,1 \n" 00286 " OH_SPEC F1S Vector holding OH lines N 0,1 \n" 00287 "\n" 00288 " Output files:\n" 00289 "\n" 00290 " DO KMOS\n" 00291 " category Type Explanation\n" 00292 " -------- ----- -----------\n" 00293 " SCI_COMBINED F3I Combined cubes with noise\n" 00294 " SCI_RECONSTRUCTED F3I Reconstructed cube with noise\n" 00295 " EXP_MASK F3I Exposure time mask (not for mapping-templates!)\n" 00296 " SCI_INTERIM_OBJECT F3I (optional) Intermediate reconstructed object \n" 00297 " cubes used for sky tweaking, no noise \n" 00298 " (set --sky_tweak and --save_interims)\n" 00299 " SCI_INTERIM_SKY F3I (optional) Intermediate reconstructed sky \n" 00300 " cubes used for sky tweaking, no noise\n" 00301 " (set --sky_tweak and --save_interims)\n" 00302 "--------------------------------------------------------------------------\n" 00303 "\n"; 00304 00305 /*----------------------------------------------------------------------------- 00306 * Functions code 00307 *----------------------------------------------------------------------------*/ 00308 00309 /*----------------------------------------------------------------------------*/ 00314 /*----------------------------------------------------------------------------*/ 00315 00318 /*----------------------------------------------------------------------------*/ 00327 /*----------------------------------------------------------------------------*/ 00328 int cpl_plugin_get_info(cpl_pluginlist *list) 00329 { 00330 cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe); 00331 cpl_plugin *plugin = &recipe->interface; 00332 00333 cpl_plugin_init(plugin, 00334 CPL_PLUGIN_API, 00335 KMOS_BINARY_VERSION, 00336 CPL_PLUGIN_TYPE_RECIPE, 00337 "kmo_sci_red", 00338 "Reconstruct obj/sky-pairs individually and combine " 00339 "them afterwards", 00340 kmo_sci_red_description, 00341 "Alex Agudo Berbel", 00342 "usd-help@eso.org", 00343 kmos_get_license(), 00344 kmo_sci_red_create, 00345 kmo_sci_red_exec, 00346 kmo_sci_red_destroy); 00347 00348 cpl_pluginlist_append(list, plugin); 00349 00350 return 0; 00351 } 00352 00353 /*----------------------------------------------------------------------------*/ 00361 /*----------------------------------------------------------------------------*/ 00362 static int kmo_sci_red_create(cpl_plugin *plugin) 00363 { 00364 cpl_recipe *recipe; 00365 cpl_parameter *p; 00366 00367 /* Check that the plugin is part of a valid recipe */ 00368 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00369 recipe = (cpl_recipe *)plugin; 00370 else 00371 return -1; 00372 00373 /* Create the parameters list in the cpl_recipe object */ 00374 recipe->parameters = cpl_parameterlist_new(); 00375 00376 /* --imethod (interpolation method) */ 00377 p = cpl_parameter_new_value("kmos.kmo_sci_red.imethod", CPL_TYPE_STRING, 00378 "Method to use for interpolation during reconstruction. " 00379 "[\"NN\" (nearest neighbour), " 00380 "\"lwNN\" (linear weighted nearest neighbor), " 00381 "\"swNN\" (square weighted nearest neighbor), " 00382 "\"MS\" (Modified Shepard's method)" 00383 "\"CS\" (Cubic spline)]", 00384 "kmos.kmo_sci_red", "CS"); 00385 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "imethod"); 00386 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00387 cpl_parameterlist_append(recipe->parameters, p); 00388 00389 /* --smethod (shift interpolation method) */ 00390 p = cpl_parameter_new_value("kmos.kmo_sci_red.smethod", CPL_TYPE_STRING, 00391 "Method to use for interpolation during shifting. " 00392 "[\"NN\" (nearest neighbour), " 00393 "\"CS\" (Cubic spline)]", 00394 "kmos.kmo_sci_red", "CS"); 00395 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "smethod"); 00396 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00397 cpl_parameterlist_append(recipe->parameters, p); 00398 00399 /* --method (shift method) */ 00400 p = cpl_parameter_new_value("kmos.kmo_sci_red.method", CPL_TYPE_STRING, 00401 "The shifting method: " 00402 "'none': no shifting, combined directly, " 00403 "'header': shift according to WCS (default), " 00404 "'center': centering algorithm, " 00405 "'user': read shifts from file", 00406 "kmos.kmo_sci_red", "header"); 00407 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "method"); 00408 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00409 cpl_parameterlist_append(recipe->parameters, p); 00410 00411 /* --fmethod */ 00412 p = cpl_parameter_new_value("kmos.kmo_sci_red.fmethod", CPL_TYPE_STRING, 00413 "The fitting method (applies only when method='center'): " 00414 "'gauss': fit a gauss function to collapsed image (default), " 00415 "'moffat': fit a moffat function to collapsed image", 00416 "kmos.kmo_sci_red", "gauss"); 00417 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "fmethod"); 00418 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00419 cpl_parameterlist_append(recipe->parameters, p); 00420 00421 /* --name */ 00422 p = cpl_parameter_new_value("kmos.kmo_sci_red.name", CPL_TYPE_STRING, 00423 "Name of the object to combine.", "kmos.kmo_sci_red", ""); 00424 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "name"); 00425 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00426 cpl_parameterlist_append(recipe->parameters, p); 00427 00428 /* --ifus */ 00429 p = cpl_parameter_new_value("kmos.kmo_sci_red.ifus", CPL_TYPE_STRING, 00430 "The indices of the IFUs to combine. \"ifu1;ifu2;...\"", 00431 "kmos.kmo_sci_red", ""); 00432 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "ifus"); 00433 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00434 cpl_parameterlist_append(recipe->parameters, p); 00435 00436 /* --pix_scale */ 00437 p = cpl_parameter_new_value("kmos.kmo_sci_red.pix_scale", CPL_TYPE_DOUBLE, 00438 "Change the pixel scale [arcsec]. " 00439 "Default of 0.2\" results into cubes of 14x14pix, " 00440 "a scale of 0.1\" results into cubes of 28x28pix, etc.", 00441 "kmos.kmo_sci_red", KMOS_PIX_RESOLUTION); 00442 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "pix_scale"); 00443 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00444 cpl_parameterlist_append(recipe->parameters, p); 00445 00446 /* --suppress_extension */ 00447 p = cpl_parameter_new_value("kmos.kmo_sci_red.suppress_extension", 00448 CPL_TYPE_BOOL, 00449 "Suppress arbitrary filename extension." 00450 "(TRUE (apply) or FALSE (don't apply)", 00451 "kmos.kmo_sci_red", FALSE); 00452 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "suppress_extension"); 00453 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00454 cpl_parameterlist_append(recipe->parameters, p); 00455 00456 /* --neighborhoodRange */ 00457 p = cpl_parameter_new_value("kmos.kmo_sci_red.neighborhoodRange", 00458 CPL_TYPE_DOUBLE, 00459 "Defines the range to search for neighbors in pixels", 00460 "kmos.kmo_sci_red", 1.001); 00461 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "neighborhoodRange"); 00462 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00463 cpl_parameterlist_append(recipe->parameters, p); 00464 00465 /* --filename */ 00466 p = cpl_parameter_new_value("kmos.kmo_sci_red.filename", CPL_TYPE_STRING, 00467 "The path to the file with the shift vectors." 00468 "(Applies only to method='user')", 00469 "kmos.kmo_sci_red", ""); 00470 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "filename"); 00471 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00472 cpl_parameterlist_append(recipe->parameters, p); 00473 00474 /* --flux */ 00475 p = cpl_parameter_new_value("kmos.kmo_sci_red.flux", CPL_TYPE_BOOL, 00476 "TRUE: Apply flux conservation. FALSE: otherwise", 00477 "kmos.kmo_sci_red", FALSE); 00478 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "flux"); 00479 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00480 cpl_parameterlist_append(recipe->parameters, p); 00481 00482 /* --background */ 00483 p = cpl_parameter_new_value("kmos.kmo_sci_red.background", CPL_TYPE_BOOL, 00484 "TRUE: Apply background removal. FALSE: otherwise", 00485 "kmos.kmo_sci_red", FALSE); 00486 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "background"); 00487 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00488 cpl_parameterlist_append(recipe->parameters, p); 00489 00490 /* --fast_mode */ 00491 p = cpl_parameter_new_value("kmos.kmo_sci_red.fast_mode", CPL_TYPE_BOOL, 00492 "FALSE: cubes are shifted and combined," 00493 "TRUE: cubes are collapsed and then shifted and combined", 00494 "kmos.kmo_sci_red", FALSE); 00495 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "fast_mode"); 00496 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00497 cpl_parameterlist_append(recipe->parameters, p); 00498 00499 /* --extrapolate */ 00500 p = cpl_parameter_new_value("kmos.kmo_sci_red.extrapolate", CPL_TYPE_BOOL, 00501 "Applies only to 'smethod=CS' when doing sub-pixel shifts: " 00502 "FALSE: shifted IFU will be filled with NaN's at the borders," 00503 "TRUE: shifted IFU will be extrapolated at the borders", 00504 "kmos.kmo_sci_red", FALSE); 00505 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "extrapolate"); 00506 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00507 cpl_parameterlist_append(recipe->parameters, p); 00508 00509 /* --xcal_interpolation */ 00510 p = cpl_parameter_new_value("kmos.kmo_sci_red.xcal_interpolation", 00511 CPL_TYPE_BOOL, 00512 "TRUE: Interpolate xcal between rotator angles. FALSE: otherwise", 00513 "kmos.kmo_sci_red", TRUE); 00514 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "xcal_interpolation"); 00515 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00516 cpl_parameterlist_append(recipe->parameters, p); 00517 00518 /* --edge_nan */ 00519 p = cpl_parameter_new_value("kmos.kmo_sci_red.edge_nan", CPL_TYPE_BOOL, 00520 "Set borders of cubes to NaN before combining them." 00521 "(TRUE (apply) or FALSE (don't apply)", 00522 "kmos.kmo_sci_red", FALSE); 00523 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "edge_nan"); 00524 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00525 cpl_parameterlist_append(recipe->parameters, p); 00526 00527 /* --no_combine */ 00528 p = cpl_parameter_new_value("kmos.kmo_sci_red.no_combine", CPL_TYPE_BOOL, 00529 "Don't combine cubes after reconstruction." 00530 "(TRUE (apply) or FALSE (don't apply)", 00531 "kmos.kmo_sci_red", FALSE); 00532 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "no_combine"); 00533 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00534 cpl_parameterlist_append(recipe->parameters, p); 00535 00536 /* --no_subtract */ 00537 p = cpl_parameter_new_value("kmos.kmo_sci_red.no_subtract", CPL_TYPE_BOOL, 00538 "Don't sky subtract object and references." 00539 "(TRUE (apply) or FALSE (don't apply)", 00540 "kmos.kmo_sci_red", FALSE); 00541 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "no_subtract"); 00542 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00543 cpl_parameterlist_append(recipe->parameters, p); 00544 00545 /* --sky_tweak */ 00546 p = cpl_parameter_new_value("kmos.kmo_sci_red.sky_tweak", CPL_TYPE_BOOL, 00547 "Use modified sky cube for sky subtraction." 00548 "(TRUE (apply) or FALSE (don't apply)", 00549 "kmos.kmo_sci_red", FALSE); 00550 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "sky_tweak"); 00551 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00552 cpl_parameterlist_append(recipe->parameters, p); 00553 00554 /* --tbsub */ 00555 p = cpl_parameter_new_value("kmos.kmo_sci_red.tbsub", CPL_TYPE_BOOL, 00556 "Subtract thermal background from input cube." 00557 "(TRUE (apply) or FALSE (don't apply)", 00558 "kmos.kmo_sci_red", TRUE); 00559 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "tbsub"); 00560 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00561 cpl_parameterlist_append(recipe->parameters, p); 00562 00563 // add parameters for band-definition 00564 kmo_band_pars_create(recipe->parameters, "kmos.kmo_sci_red"); 00565 00566 /* --obj_sky_table */ 00567 p = cpl_parameter_new_value("kmos.kmo_sci_red.obj_sky_table", 00568 CPL_TYPE_STRING, 00569 "The path to the file with the modified obj/sky associations.", 00570 "kmos.kmo_sci_red", ""); 00571 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "obj_sky_table"); 00572 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00573 cpl_parameterlist_append(recipe->parameters, p); 00574 00575 /* --velocity_offset */ 00576 p = cpl_parameter_new_value("kmos.kmo_sci_red.velocity_offset", 00577 CPL_TYPE_DOUBLE, 00578 "Specify velocity offset correction in km/s for lambda scale", 00579 "kmos.kmo_sci_red", 0.0); 00580 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "velocity_offset"); 00581 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00582 cpl_parameterlist_append(recipe->parameters, p); 00583 00584 /* --save_interims */ 00585 p = cpl_parameter_new_value("kmos.kmo_sci_red.save_interims", CPL_TYPE_BOOL, 00586 "Save interim object and sky cubes. " 00587 "Can only be used together with --sky_tweak", 00588 "kmos.kmo_sci_red", FALSE); 00589 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "save_interims"); 00590 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00591 cpl_parameterlist_append(recipe->parameters, p); 00592 00593 return kmo_combine_pars_create(recipe->parameters, "kmos.kmo_sci_red", 00594 DEF_REJ_METHOD, FALSE); 00595 } 00596 00597 /*----------------------------------------------------------------------------*/ 00603 /*----------------------------------------------------------------------------*/ 00604 static int kmo_sci_red_exec(cpl_plugin *plugin) 00605 { 00606 cpl_recipe *recipe; 00607 00608 /* Get the recipe out of the plugin */ 00609 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00610 recipe = (cpl_recipe *)plugin; 00611 else return -1 ; 00612 00613 return kmo_sci_red(recipe->parameters, recipe->frames); 00614 } 00615 00616 /*----------------------------------------------------------------------------*/ 00622 /*----------------------------------------------------------------------------*/ 00623 static int kmo_sci_red_destroy(cpl_plugin *plugin) 00624 { 00625 cpl_recipe *recipe; 00626 00627 /* Get the recipe out of the plugin */ 00628 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00629 recipe = (cpl_recipe *)plugin; 00630 else return -1 ; 00631 00632 cpl_parameterlist_delete(recipe->parameters); 00633 return 0 ; 00634 } 00635 00636 /*----------------------------------------------------------------------------*/ 00649 /*----------------------------------------------------------------------------*/ 00650 static int kmo_sci_red(cpl_parameterlist *parlist, cpl_frameset *frameset) 00651 { 00652 int ret_val = 0, 00653 nr_science_frames = 0, 00654 nr_reconstructed_frames = 0, 00655 has_illum_corr = 0, 00656 has_master_flat = 0, 00657 has_telluric = 0, 00658 has_oh_spec = 0, 00659 telluric_ok = 0, 00660 *bounds = NULL, 00661 det_nr = 0, 00662 actual_msg_level = 0, 00663 print_once = FALSE, 00664 cube_counter_data = 0, 00665 cube_counter_noise = 0, 00666 citer = 0, 00667 cmin = 0, 00668 cmax = 0, 00669 extrapolate = 0, 00670 flux = FALSE, 00671 background = FALSE, 00672 index = 0, 00673 nr_data_alloc = 0, 00674 tmp_int = 0, 00675 fast_mode = FALSE, 00676 edge_nan = FALSE, 00677 no_combine = FALSE, 00678 no_subtract = FALSE, 00679 do_sky_subtraction = FALSE, 00680 sky_tweak = FALSE, 00681 tbsub = TRUE, 00682 save_interims = FALSE, 00683 xcal_interpolation = FALSE, 00684 suppress_extension = FALSE, 00685 suppress_index = 0, 00686 i = 0, 00687 sf = 0, 00688 jj = 0, 00689 ifu_nr = 0, 00690 sky_ifu_nr = 0; 00691 double neighborhoodRange = 1.001, 00692 cpos_rej = 0.0, 00693 cneg_rej = 0.0, 00694 pix_scale = 0.0, 00695 velo_offset = 0.0, 00696 velo_corr = 0.0; 00697 double *velo_corr_ptr = NULL; 00698 char *suffix = NULL, 00699 *keyword = NULL, 00700 *extname = NULL, 00701 *fn_suffix = NULL, 00702 *mapping_mode = NULL, 00703 **split = NULL, 00704 content[256]; 00705 const char *imethod = NULL, 00706 *smethod = NULL, 00707 *ifus_txt = NULL, 00708 *name = NULL, 00709 *filter_id = NULL, 00710 *tmp_str = NULL, 00711 *filename = NULL, 00712 *fn_obj_sky_table = NULL, 00713 *fn_out = NULL, 00714 *fn_out_mask = NULL, 00715 *fn_obj = NULL, 00716 *fn_sky = NULL, 00717 *fn_reconstr = NULL, 00718 *fn_interim_object = NULL, 00719 *fn_interim_sky = NULL, 00720 *comb_method = NULL, 00721 *cmethod = NULL, 00722 *fmethod = NULL; 00723 cpl_array **unused_ifus_before = NULL, 00724 **unused_ifus_after = NULL; 00725 cpl_frame *xcal_frame = NULL, 00726 *ycal_frame = NULL, 00727 *lcal_frame = NULL, 00728 *flat_frame = NULL, 00729 *illum_frame = NULL, 00730 *telluric_frame = NULL, 00731 *tmp_frame = NULL; 00732 cpl_propertylist *tmp_header = NULL, 00733 *main_header = NULL, 00734 *main_sky_header = NULL, 00735 **header_data = NULL, 00736 **header_noise = NULL, 00737 **header_sky = NULL; 00738 cpl_vector *ifus = NULL; 00739 kmclipm_vector *telluric_data = NULL, 00740 *telluric_noise = NULL; 00741 cpl_image **lcal = NULL, 00742 *illum_data = NULL, 00743 *illum_noise = NULL, 00744 *tmpImg = NULL, 00745 *exp_mask = NULL; 00746 cpl_imagelist **cube_data = NULL, 00747 **cube_noise = NULL, 00748 **cube_interim_object = NULL, 00749 **cube_interim_sky = NULL, 00750 *sky_data = NULL, 00751 *sky_noise = NULL, 00752 *combined_data = NULL, 00753 *combined_noise = NULL, 00754 *tmpCube = NULL; 00755 cpl_table *band_table = NULL; 00756 cpl_frame *sky_frame = NULL, 00757 *sky_as_object_frame = NULL, 00758 *ref_spectrum_frame = NULL; 00759 cpl_polynomial *oh_lcorr_coeffs = NULL; 00760 main_fits_desc desc1, 00761 desc2, 00762 desc_telluric; 00763 gridDefinition gd; 00764 armNameStruct *arm_name_struct = NULL; 00765 enum extrapolationType extrapol_enum = 0; 00766 enum kmo_frame_type ft = 0; 00767 00768 KMO_TRY 00769 { 00770 kmo_init_fits_desc(&desc1); 00771 kmo_init_fits_desc(&desc2); 00772 kmo_init_fits_desc(&desc_telluric); 00773 00774 /* Check frameset */ 00775 KMO_TRY_ASSURE((parlist != NULL) && (frameset != NULL), 00776 CPL_ERROR_NULL_INPUT, "Not all input data is provided!"); 00777 00778 nr_science_frames = cpl_frameset_count_tags(frameset, SCIENCE); 00779 KMO_TRY_ASSURE(nr_science_frames >= 1, CPL_ERROR_ILLEGAL_INPUT, 00780 "At least one SCIENCE frame is required!"); 00781 if (nr_science_frames == 1) { 00782 cpl_msg_warning(__func__, 00783 "2 SCIENCE frames are needed for sky subtraction"); 00784 cpl_msg_warning(__func__, 00785 "All IFUs are reconstructed (object, reference and sky"); 00786 } 00787 00788 KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, XCAL) == 1, 00789 CPL_ERROR_FILE_NOT_FOUND, 00790 "Exactly one XCAL frame is required"); 00791 00792 KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, YCAL) == 1, 00793 CPL_ERROR_FILE_NOT_FOUND, 00794 "Exactly one YCAL frame is required"); 00795 00796 KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, LCAL) == 1, 00797 CPL_ERROR_FILE_NOT_FOUND, 00798 "Exactly one LCAL frame is required"); 00799 00800 has_master_flat = cpl_frameset_count_tags(frameset, MASTER_FLAT); 00801 KMO_TRY_ASSURE((has_master_flat == 0) || (has_master_flat == 1), 00802 CPL_ERROR_FILE_NOT_FOUND, 00803 "At most one MASTER_FLAT frame can be provided"); 00804 00805 KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, WAVE_BAND) == 1, 00806 CPL_ERROR_FILE_NOT_FOUND, 00807 "Exactly one WAVE_BAND frame is required"); 00808 00809 has_illum_corr = cpl_frameset_count_tags(frameset, ILLUM_CORR); 00810 KMO_TRY_ASSURE((has_illum_corr == 0) || (has_illum_corr == 1), 00811 CPL_ERROR_FILE_NOT_FOUND, 00812 "At most one ILLUM_CORR frame can be provided"); 00813 00814 has_telluric = cpl_frameset_count_tags(frameset, TELLURIC); 00815 KMO_TRY_ASSURE((has_telluric == 0) || (has_telluric == 1), 00816 CPL_ERROR_FILE_NOT_FOUND, 00817 "At most one TELLURIC frame can be provided"); 00818 00819 has_oh_spec = cpl_frameset_count_tags(frameset, OH_SPEC) ; 00820 KMO_TRY_ASSURE(has_oh_spec == 0 || has_oh_spec == 1, 00821 CPL_ERROR_ILLEGAL_INPUT, 00822 "Only a single reference spectrum can be provided!"); 00823 00824 KMO_TRY_ASSURE(kmo_dfs_set_groups(frameset, "kmo_sci_red") == 1, 00825 CPL_ERROR_ILLEGAL_INPUT, 00826 "Cannot identify RAW and CALIB frames!"); 00827 00828 /* Get parameters */ 00829 cpl_msg_info("", "--- Parameter setup for kmo_sci_red ------"); 00830 flux = kmo_dfs_get_parameter_bool(parlist, "kmos.kmo_sci_red.flux"); 00831 KMO_TRY_ASSURE((flux == 0) || (flux == 1), CPL_ERROR_ILLEGAL_INPUT, 00832 "flux must be either FALSE or TRUE! %d", flux); 00833 KMO_TRY_EXIT_IF_ERROR( 00834 kmo_dfs_print_parameter_help(parlist, "kmos.kmo_sci_red.flux")); 00835 background = kmo_dfs_get_parameter_bool(parlist, 00836 "kmos.kmo_sci_red.background"); 00837 KMO_TRY_ASSURE((background == 0) || (background == 1), 00838 CPL_ERROR_ILLEGAL_INPUT, 00839 "background must be either FALSE or TRUE! %d", background); 00840 KMO_TRY_EXIT_IF_ERROR( 00841 kmo_dfs_print_parameter_help(parlist, 00842 "kmos.kmo_sci_red.background")); 00843 KMO_TRY_EXIT_IF_NULL( 00844 imethod = kmo_dfs_get_parameter_string(parlist, 00845 "kmos.kmo_sci_red.imethod")); 00846 KMO_TRY_ASSURE((strcmp(imethod, "NN") == 0) || 00847 (strcmp(imethod, "lwNN") == 0) || 00848 (strcmp(imethod, "swNN") == 0) || 00849 (strcmp(imethod, "MS") == 0) || 00850 (strcmp(imethod, "CS") == 0), 00851 CPL_ERROR_ILLEGAL_INPUT, 00852 "imethod must be either \"NN\", \"lwNN\", \"swNN\", \"MS\" or \"CS\"!"); 00853 KMO_TRY_EXIT_IF_ERROR( 00854 kmo_dfs_print_parameter_help(parlist, "kmos.kmo_sci_red.imethod")); 00855 KMO_TRY_EXIT_IF_NULL( 00856 smethod = kmo_dfs_get_parameter_string(parlist, 00857 "kmos.kmo_sci_red.smethod")); 00858 KMO_TRY_ASSURE((strcmp(smethod, "NN") == 0) || 00859 (strcmp(smethod, "CS") == 0), CPL_ERROR_ILLEGAL_INPUT, 00860 "smethod must be either \"NN\" or \"CS\"!"); 00861 KMO_TRY_EXIT_IF_ERROR( 00862 kmo_dfs_print_parameter_help(parlist, "kmos.kmo_sci_red.smethod")); 00863 neighborhoodRange = kmo_dfs_get_parameter_double(parlist, 00864 "kmos.kmo_sci_red.neighborhoodRange"); 00865 KMO_TRY_CHECK_ERROR_STATE(); 00866 KMO_TRY_ASSURE(neighborhoodRange > 0.0, CPL_ERROR_ILLEGAL_INPUT, 00867 "neighborhoodRange must be greater than 0.0"); 00868 KMO_TRY_EXIT_IF_ERROR( 00869 kmo_dfs_print_parameter_help(parlist, 00870 "kmos.kmo_sci_red.neighborhoodRange")); 00871 KMO_TRY_EXIT_IF_NULL( 00872 comb_method = kmo_dfs_get_parameter_string(parlist, 00873 "kmos.kmo_sci_red.method")); 00874 KMO_TRY_EXIT_IF_NULL( 00875 fmethod = kmo_dfs_get_parameter_string(parlist, 00876 "kmos.kmo_sci_red.fmethod")); 00877 KMO_TRY_ASSURE((strcmp(comb_method, "none") == 0) || 00878 (strcmp(comb_method, "header") == 0) || 00879 (strcmp(comb_method, "center") == 0) || 00880 (strcmp(comb_method, "user") == 0), CPL_ERROR_ILLEGAL_INPUT, 00881 "Following shift methods are available : 'none', 'header', 'center' or 'user'"); 00882 if (strcmp(comb_method, "user") == 0) { 00883 filename = kmo_dfs_get_parameter_string(parlist, 00884 "kmos.kmo_sci_red.filename"); 00885 KMO_TRY_CHECK_ERROR_STATE(); 00886 KMO_TRY_ASSURE(strcmp(filename, "") != 0, CPL_ERROR_ILLEGAL_INPUT, 00887 "path of file with shift information must be provided!"); 00888 KMO_TRY_EXIT_IF_ERROR( 00889 kmo_dfs_print_parameter_help(parlist, 00890 "kmos.kmo_sci_red.filename")); 00891 } 00892 KMO_TRY_EXIT_IF_ERROR( 00893 kmo_dfs_print_parameter_help(parlist, "kmos.kmo_sci_red.method")); 00894 00895 ifus_txt=kmo_dfs_get_parameter_string(parlist, "kmos.kmo_sci_red.ifus"); 00896 KMO_TRY_CHECK_ERROR_STATE(); 00897 name = kmo_dfs_get_parameter_string(parlist, "kmos.kmo_sci_red.name"); 00898 KMO_TRY_CHECK_ERROR_STATE(); 00899 if (strcmp(ifus_txt, "") != 0) { 00900 KMO_TRY_ASSURE(strcmp(name, "") == 0, CPL_ERROR_ILLEGAL_INPUT, 00901 "name parameter must be NULL if IFU indices are provided!"); 00902 KMO_TRY_EXIT_IF_NULL(ifus = kmo_identify_values(ifus_txt)); 00903 KMO_TRY_ASSURE(cpl_vector_get_size(ifus) == nr_science_frames, 00904 CPL_ERROR_ILLEGAL_INPUT, 00905 "ifus parameter must have the same number of values than" 00906 "frames provided (for frames just containing " 00907 "skies insert 0)) (%lld!=%d)", 00908 cpl_vector_get_size(ifus), nr_science_frames); 00909 } 00910 00911 if (strcmp(name, "") != 0) { 00912 KMO_TRY_ASSURE(strcmp(ifus_txt, "") == 0, CPL_ERROR_ILLEGAL_INPUT, 00913 "ifus parameter must be NULL if name is provided!"); 00914 } 00915 00916 KMO_TRY_EXIT_IF_ERROR( 00917 kmo_dfs_print_parameter_help(parlist, "kmos.kmo_sci_red.ifus")); 00918 00919 KMO_TRY_EXIT_IF_ERROR( 00920 kmo_dfs_print_parameter_help(parlist, "kmos.kmo_sci_red.name")); 00921 00922 kmo_band_pars_load(parlist, "kmos.kmo_sci_red"); 00923 00924 extrapolate = kmo_dfs_get_parameter_bool(parlist, 00925 "kmos.kmo_sci_red.extrapolate"); 00926 KMO_TRY_CHECK_ERROR_STATE(); 00927 00928 if (strcmp(smethod, "NN") == 0) { 00929 if (extrapolate == TRUE) { 00930 cpl_msg_warning(__func__, 00931 "extrapolation for smethod='NN' not available!"); 00932 } 00933 extrapol_enum = NONE_NANS; 00934 } else if (strcmp(smethod, "CS") == 0) { 00935 if (extrapolate == FALSE) { 00936 extrapol_enum = NONE_NANS; 00937 } else if (extrapolate == TRUE) { 00938 extrapol_enum = BCS_NATURAL; 00939 } else { 00940 KMO_TRY_ASSURE(1 == 0, CPL_ERROR_ILLEGAL_INPUT, 00941 "extrapolate must be either FALSE or TRUE"); 00942 } 00943 smethod = "BCS"; 00944 } else { 00945 KMO_TRY_ASSURE(1 == 0, CPL_ERROR_ILLEGAL_INPUT, 00946 "smethod must be either \"CS\" or \"NN\""); 00947 } 00948 KMO_TRY_CHECK_ERROR_STATE(); 00949 00950 KMO_TRY_EXIT_IF_ERROR( 00951 kmo_dfs_print_parameter_help(parlist, 00952 "kmos.kmo_sci_red.extrapolate")); 00953 00954 fast_mode = kmo_dfs_get_parameter_bool(parlist, 00955 "kmos.kmo_sci_red.fast_mode"); 00956 KMO_TRY_CHECK_ERROR_STATE(); 00957 KMO_TRY_ASSURE((fast_mode == TRUE) || (fast_mode == FALSE), 00958 CPL_ERROR_ILLEGAL_INPUT, "fast_mode is either FALSE or TRUE"); 00959 KMO_TRY_EXIT_IF_ERROR( 00960 kmo_dfs_print_parameter_help(parlist,"kmos.kmo_sci_red.fast_mode")); 00961 edge_nan = kmo_dfs_get_parameter_bool(parlist, 00962 "kmos.kmo_sci_red.edge_nan"); 00963 KMO_TRY_CHECK_ERROR_STATE(); 00964 KMO_TRY_EXIT_IF_ERROR( 00965 kmo_dfs_print_parameter_help(parlist, "kmos.kmo_sci_red.edge_nan")); 00966 KMO_TRY_ASSURE((edge_nan == TRUE) || (edge_nan == FALSE), 00967 CPL_ERROR_ILLEGAL_INPUT, "edge_nan must be TRUE or FALSE"); 00968 no_combine = kmo_dfs_get_parameter_bool(parlist, 00969 "kmos.kmo_sci_red.no_combine"); 00970 KMO_TRY_CHECK_ERROR_STATE(); 00971 KMO_TRY_EXIT_IF_ERROR( 00972 kmo_dfs_print_parameter_help(parlist, 00973 "kmos.kmo_sci_red.no_combine")); 00974 KMO_TRY_ASSURE((no_combine == TRUE) || (no_combine == FALSE), 00975 CPL_ERROR_ILLEGAL_INPUT, "no_combine must be TRUE or FALSE!"); 00976 no_subtract = kmo_dfs_get_parameter_bool(parlist, 00977 "kmos.kmo_sci_red.no_subtract"); 00978 KMO_TRY_CHECK_ERROR_STATE(); 00979 KMO_TRY_EXIT_IF_ERROR( 00980 kmo_dfs_print_parameter_help(parlist, 00981 "kmos.kmo_sci_red.no_subtract")); 00982 KMO_TRY_ASSURE((no_subtract == TRUE) || (no_subtract == FALSE), 00983 CPL_ERROR_ILLEGAL_INPUT, "no_subtract must be TRUE or FALSE"); 00984 sky_tweak = kmo_dfs_get_parameter_bool(parlist, 00985 "kmos.kmo_sci_red.sky_tweak"); 00986 KMO_TRY_CHECK_ERROR_STATE(); 00987 KMO_TRY_EXIT_IF_ERROR( 00988 kmo_dfs_print_parameter_help(parlist,"kmos.kmo_sci_red.sky_tweak")); 00989 KMO_TRY_ASSURE((sky_tweak == TRUE) || (sky_tweak == FALSE), 00990 CPL_ERROR_ILLEGAL_INPUT, "sky_tweak must be TRUE or FALSE"); 00991 KMO_TRY_ASSURE(!((no_subtract == TRUE) && (sky_tweak == TRUE)), 00992 CPL_ERROR_ILLEGAL_INPUT, 00993 "Either no_subtract or sky_tweak or both must be FALSE (try instead sky_tweak and save_interims)!"); 00994 tbsub = kmo_dfs_get_parameter_bool(parlist, "kmos.kmo_sci_red.tbsub"); 00995 KMO_TRY_CHECK_ERROR_STATE(); 00996 00997 pix_scale = kmo_dfs_get_parameter_double(parlist, 00998 "kmos.kmo_sci_red.pix_scale"); 00999 KMO_TRY_CHECK_ERROR_STATE(); 01000 KMO_TRY_EXIT_IF_ERROR( 01001 kmo_dfs_print_parameter_help(parlist, "kmos.kmo_sci_red.pix_scale")); 01002 KMO_TRY_ASSURE((pix_scale >= 0.01) && (pix_scale <= 0.4), 01003 CPL_ERROR_ILLEGAL_INPUT, 01004 "pix_scale must be between 0.01 and 0.4 (results in cubes " 01005 "with 7x7 to 280x280 pixels)!"); 01006 xcal_interpolation = kmo_dfs_get_parameter_bool(parlist, 01007 "kmos.kmo_sci_red.xcal_interpolation"); 01008 KMO_TRY_CHECK_ERROR_STATE(); 01009 KMO_TRY_EXIT_IF_ERROR( 01010 kmo_dfs_print_parameter_help(parlist, 01011 "kmos.kmo_sci_red.xcal_interpolation")); 01012 KMO_TRY_ASSURE((xcal_interpolation == TRUE) || 01013 (xcal_interpolation == FALSE), 01014 CPL_ERROR_ILLEGAL_INPUT, 01015 "xcal_interpolation must be TRUE or FALSE!"); 01016 suppress_extension = kmo_dfs_get_parameter_bool(parlist, 01017 "kmos.kmo_sci_red.suppress_extension"); 01018 KMO_TRY_CHECK_ERROR_STATE(); 01019 KMO_TRY_EXIT_IF_ERROR( 01020 kmo_dfs_print_parameter_help(parlist, 01021 "kmos.kmo_sci_red.suppress_extension")); 01022 KMO_TRY_ASSURE((suppress_extension == TRUE) || 01023 (suppress_extension == FALSE), 01024 CPL_ERROR_ILLEGAL_INPUT, 01025 "suppress_extension must be TRUE or FALSE!"); 01026 fn_obj_sky_table = kmo_dfs_get_parameter_string(parlist, 01027 "kmos.kmo_sci_red.obj_sky_table"); 01028 KMO_TRY_CHECK_ERROR_STATE(); 01029 KMO_TRY_EXIT_IF_ERROR( 01030 kmo_dfs_print_parameter_help(parlist, 01031 "kmos.kmo_sci_red.obj_sky_table")); 01032 KMO_TRY_EXIT_IF_ERROR( 01033 kmo_combine_pars_load(parlist, "kmos.kmo_sci_red", &cmethod, 01034 &cpos_rej, &cneg_rej, &citer, &cmin, &cmax, FALSE)); 01035 velo_offset = kmo_dfs_get_parameter_double(parlist, 01036 "kmos.kmo_sci_red.velocity_offset"); 01037 KMO_TRY_CHECK_ERROR_STATE(); 01038 01039 velo_corr = 1. + velo_offset * 1000. / CPL_PHYS_C; 01040 velo_corr_ptr = &velo_corr; 01041 KMO_TRY_EXIT_IF_ERROR( 01042 kmo_dfs_print_parameter_help(parlist, 01043 "kmos.kmo_sci_red.velocity_offset")); 01044 save_interims = kmo_dfs_get_parameter_bool(parlist, 01045 "kmos.kmo_sci_red.save_interims"); 01046 KMO_TRY_CHECK_ERROR_STATE(); 01047 KMO_TRY_ASSURE((save_interims == TRUE) || (save_interims == FALSE), 01048 CPL_ERROR_ILLEGAL_INPUT, "save_interims must be TRUE or FALSE"); 01049 KMO_TRY_ASSURE(!((save_interims == TRUE) && (sky_tweak == FALSE)), 01050 CPL_ERROR_ILLEGAL_INPUT, 01051 "Save_interims saves sky_tweak objects so sky_tweak must be enabled too"); 01052 KMO_TRY_EXIT_IF_ERROR( 01053 kmo_dfs_print_parameter_help(parlist, 01054 "kmos.kmo_sci_red.save_interims")); 01055 cpl_msg_info("", "-------------------------------------------"); 01056 01057 // assure that filters, grating and rotation offsets match for 01058 // XCAL, YCAL, LCAL and for data frame to reconstruct (except DARK 01059 // frames) 01060 /* Check if filter_id and grating_id match for all detectors */ 01061 KMO_TRY_EXIT_IF_ERROR( 01062 kmo_check_frameset_setup(frameset, SCIENCE, TRUE, FALSE, TRUE)); 01063 KMO_TRY_EXIT_IF_ERROR( 01064 kmo_check_frame_setup(frameset, SCIENCE, YCAL, TRUE, FALSE, TRUE)); 01065 KMO_TRY_EXIT_IF_ERROR( 01066 kmo_check_frame_setup(frameset, XCAL, YCAL, TRUE, FALSE, TRUE)); 01067 KMO_TRY_EXIT_IF_ERROR( 01068 kmo_check_frame_setup(frameset, XCAL, LCAL, TRUE, FALSE, TRUE)); 01069 if (has_master_flat) { 01070 KMO_TRY_EXIT_IF_ERROR(kmo_check_frame_setup(frameset, XCAL, 01071 MASTER_FLAT, TRUE, FALSE, TRUE)); 01072 } 01073 if (has_telluric) { 01074 KMO_TRY_EXIT_IF_ERROR(kmo_check_frame_setup(frameset, XCAL, 01075 TELLURIC, TRUE, FALSE, TRUE)); 01076 } 01077 if (has_oh_spec) { 01078 KMO_TRY_EXIT_IF_ERROR(kmo_check_oh_spec_setup(frameset, XCAL)); 01079 } 01080 01081 // check descriptors of all frames 01082 KMO_TRY_EXIT_IF_NULL(xcal_frame = kmo_dfs_get_frame(frameset, XCAL)); 01083 01084 desc1 = kmo_identify_fits_header(cpl_frame_get_filename(xcal_frame)); 01085 KMO_TRY_CHECK_ERROR_STATE(); 01086 01087 KMO_TRY_ASSURE((desc1.nr_ext % KMOS_NR_DETECTORS == 0) && 01088 (desc1.ex_badpix == FALSE) && 01089 (desc1.fits_type == f2d_fits) && 01090 (desc1.frame_type == detector_frame), 01091 CPL_ERROR_ILLEGAL_INPUT, 01092 "XCAL isn't in the correct format!!!"); 01093 01094 KMO_TRY_EXIT_IF_NULL(ycal_frame = kmo_dfs_get_frame(frameset, YCAL)); 01095 desc2 = kmo_identify_fits_header(cpl_frame_get_filename(ycal_frame)); 01096 KMO_TRY_CHECK_ERROR_STATE(); 01097 01098 KMO_TRY_ASSURE((desc1.nr_ext == desc2.nr_ext) && 01099 (desc1.ex_badpix == desc2.ex_badpix) && 01100 (desc1.fits_type == desc2.fits_type) && 01101 (desc1.frame_type == desc2.frame_type), 01102 CPL_ERROR_ILLEGAL_INPUT, 01103 "YCAL isn't in the correct format!!!"); 01104 kmo_free_fits_desc(&desc2); 01105 kmo_init_fits_desc(&desc2); 01106 01107 KMO_TRY_EXIT_IF_NULL(lcal_frame = kmo_dfs_get_frame(frameset, LCAL)); 01108 desc2 = kmo_identify_fits_header(cpl_frame_get_filename(lcal_frame)); 01109 KMO_TRY_CHECK_ERROR_STATE(); 01110 01111 KMO_TRY_ASSURE((desc2.nr_ext % KMOS_NR_DETECTORS == 0) && 01112 (desc1.ex_badpix == desc2.ex_badpix) && 01113 (desc1.fits_type == desc2.fits_type) && 01114 (desc1.frame_type == desc2.frame_type), 01115 CPL_ERROR_ILLEGAL_INPUT, 01116 "LCAL isn't in the correct format!!!"); 01117 kmo_free_fits_desc(&desc2); 01118 kmo_init_fits_desc(&desc2); 01119 01120 if (has_master_flat) { 01121 KMO_TRY_EXIT_IF_NULL(flat_frame = kmo_dfs_get_frame(frameset, 01122 MASTER_FLAT)); 01123 desc2=kmo_identify_fits_header(cpl_frame_get_filename(flat_frame)); 01124 KMO_TRY_CHECK_ERROR_STATE(); 01125 01126 KMO_TRY_ASSURE((desc2.nr_ext % (2*KMOS_NR_DETECTORS) == 0) && 01127 (desc1.ex_badpix == desc2.ex_badpix) && 01128 (desc1.fits_type == desc2.fits_type) && 01129 (desc1.frame_type == desc2.frame_type), 01130 CPL_ERROR_ILLEGAL_INPUT, 01131 "MASTER_FLAT isn't in the correct format!!!"); 01132 kmo_free_fits_desc(&desc2); 01133 kmo_init_fits_desc(&desc2); 01134 } 01135 01136 if (has_illum_corr) { 01137 KMO_TRY_EXIT_IF_NULL(illum_frame = kmo_dfs_get_frame(frameset, 01138 ILLUM_CORR)); 01139 desc2=kmo_identify_fits_header(cpl_frame_get_filename(illum_frame)); 01140 KMO_TRY_CHECK_ERROR_STATE(); 01141 KMO_TRY_ASSURE(((desc2.nr_ext == 24) || (desc2.nr_ext == 48)) && 01142 (desc2.ex_badpix == FALSE) && 01143 (desc2.fits_type == f2i_fits) && 01144 (desc2.frame_type == ifu_frame), 01145 CPL_ERROR_ILLEGAL_INPUT, 01146 "ILLUM_CORR isn't in the correct format!!!"); 01147 kmo_free_fits_desc(&desc2); 01148 kmo_init_fits_desc(&desc2); 01149 } 01150 01151 if (has_telluric) { 01152 KMO_TRY_EXIT_IF_NULL(telluric_frame = kmo_dfs_get_frame(frameset, 01153 TELLURIC)); 01154 desc_telluric=kmo_identify_fits_header( 01155 cpl_frame_get_filename(telluric_frame)); 01156 KMO_TRY_CHECK_ERROR_STATE(); 01157 KMO_TRY_ASSURE(((desc_telluric.nr_ext == 24) || 01158 (desc_telluric.nr_ext == 48)) && 01159 (desc_telluric.ex_badpix == FALSE) && 01160 (desc_telluric.fits_type == f1i_fits) && 01161 (desc_telluric.frame_type == ifu_frame), 01162 CPL_ERROR_ILLEGAL_INPUT, 01163 "TELLURIC isn't in the correct format!!!"); 01164 } 01165 kmo_free_fits_desc(&desc2); 01166 01167 KMO_TRY_EXIT_IF_NULL(tmp_frame = kmo_dfs_get_frame(frameset, SCIENCE)); 01168 while (tmp_frame != NULL ) { 01169 desc2 = kmo_identify_fits_header(cpl_frame_get_filename(tmp_frame)); 01170 KMO_TRY_CHECK_ERROR_STATE(); 01171 KMO_TRY_ASSURE((desc2.nr_ext == 3) && 01172 (desc2.ex_badpix == FALSE) && 01173 (desc2.fits_type == raw_fits) && 01174 (desc2.frame_type == detector_frame), 01175 CPL_ERROR_ILLEGAL_INPUT, 01176 "SCIENCE isn't in the correct format!!!"); 01177 kmo_free_fits_desc(&desc2); 01178 kmo_init_fits_desc(&desc2); 01179 01180 if (mapping_mode == NULL) { 01181 KMO_TRY_EXIT_IF_NULL( 01182 tmp_header = kmclipm_propertylist_load( 01183 cpl_frame_get_filename(tmp_frame), 0)); 01184 if (cpl_propertylist_has(tmp_header, TPL_ID)) { 01185 KMO_TRY_EXIT_IF_NULL(tmp_str = 01186 cpl_propertylist_get_string(tmp_header, TPL_ID)); 01187 if (strcmp(tmp_str, MAPPING8) == 0) { 01188 mapping_mode = cpl_sprintf("%s", "mapping8"); 01189 } 01190 if (strcmp(tmp_str, MAPPING24) == 0) { 01191 mapping_mode = cpl_sprintf("%s", "mapping24"); 01192 } 01193 } 01194 cpl_propertylist_delete(tmp_header); tmp_header = NULL; 01195 } 01196 tmp_frame = kmo_dfs_get_frame(frameset, NULL); 01197 KMO_TRY_CHECK_ERROR_STATE(); 01198 } 01199 01200 if (mapping_mode != NULL) { 01201 // we are in mapping mode 01202 if ((ifus != NULL) || (strcmp(name, "") != 0)) { 01203 cpl_msg_warning(__func__,\ 01204 "The SCIENCE frames have been taken in one of the " 01205 "mapping modes AND specific IFUs have been " 01206 "specified! --> Only processing these!"); 01207 } else { 01208 if (strcmp(smethod, "BCS") == 0) { 01209 extrapol_enum = BCS_NATURAL; 01210 cpl_msg_info(__func__, 01211 "Detected frames taken in mapping mode. " 01212 "Changing extrapolation mode to TRUE."); 01213 } 01214 } 01215 if (fast_mode) { 01216 cpl_msg_info(__func__, "Creating map in fast_mode."); 01217 } 01218 } else { 01219 if (fast_mode) { 01220 cpl_msg_info(__func__, 01221 "fast_mode has been selected but we aren't in " 01222 "mapping mode. The choice for fast_mode is ignored."); 01223 } 01224 } 01225 01226 KMO_TRY_EXIT_IF_NULL( 01227 suffix = kmo_dfs_get_suffix(xcal_frame, TRUE, FALSE)); 01228 01229 /* Verify that XCAL / YCAL were generated together */ 01230 KMO_TRY_EXIT_IF_ERROR(kmo_check_frame_setup_md5_xycal(frameset)); 01231 /* Verify that XCAL and YCAL / LCAL were generated together */ 01232 KMO_TRY_EXIT_IF_ERROR(kmo_check_frame_setup_md5(frameset)); 01233 /* b_start/b_end/b_samples used for LCAL and TELLURIC were the same */ 01234 KMO_TRY_EXIT_IF_ERROR(kmo_check_frame_setup_sampling(frameset)); 01235 01236 cpl_msg_info("", "Detected instrument setup: %s", suffix+1); 01237 cpl_msg_info("", "(grating 1, 2 & 3)"); 01238 01239 /* Check which IFUs are active for all frames */ 01240 KMO_TRY_EXIT_IF_NULL(unused_ifus_before = 01241 kmo_get_unused_ifus(frameset, 1, 1)); 01242 KMO_TRY_EXIT_IF_NULL(unused_ifus_after = 01243 kmo_duplicate_unused_ifus(unused_ifus_before)); 01244 kmo_print_unused_ifus(unused_ifus_before, FALSE); 01245 01246 /* Get bounds, setup grid, setup arm_name-struct */ 01247 /* Get left and right bounds of IFUs from XCAL */ 01248 KMO_TRY_EXIT_IF_NULL( 01249 tmp_header = kmo_dfs_load_primary_header(frameset, XCAL)); 01250 KMO_TRY_EXIT_IF_NULL(bounds = kmclipm_extract_bounds(tmp_header)); 01251 cpl_propertylist_delete(tmp_header); tmp_header = NULL; 01252 01253 /* Setup grid definition, wavelength start and end points will be */ 01254 /* set in the detector loop */ 01255 KMO_TRY_EXIT_IF_ERROR( 01256 kmclipm_setup_grid(&gd, imethod, neighborhoodRange, pix_scale, 0.)); 01257 01258 /* 01259 Create armNameStruct : Contains info about objects that need 01260 to be reconstructed and for each of them which sky need to be used 01261 Get valid STD frames with objects in it and associated sky 01262 exposures and get valid object names to process, either one object 01263 name across several SCIENCE frames, or all object names 01264 */ 01265 if (strcmp(fn_obj_sky_table, "") == 0) { 01266 KMO_TRY_EXIT_IF_NULL( 01267 arm_name_struct = kmo_create_armNameStruct(frameset, SCIENCE, 01268 ifus, name, unused_ifus_after, bounds, mapping_mode, 01269 no_subtract)); 01270 KMO_TRY_EXIT_IF_ERROR( 01271 kmo_save_objSkyStruct(arm_name_struct->obj_sky_struct)); 01272 } else { 01273 // read in obj/sky-table 01274 objSkyStruct *obj_sky_struct = NULL; 01275 01276 KMO_TRY_EXIT_IF_NULL( 01277 obj_sky_struct = kmo_read_objSkyStruct(fn_obj_sky_table, 01278 frameset, SCIENCE)); 01279 01280 /* Check if any sky-IFUs have been specified not beeing the */ 01281 /* same IFU# for objects. */ 01282 // In this case sky_tweak must be activated 01283 for (i = 0; i < obj_sky_struct->size; i++) { 01284 if (obj_sky_struct->table[i].objFrame != NULL) { 01285 for (jj = 0; jj < KMOS_NR_IFUS; jj++) { 01286 if ((obj_sky_struct->table[i].skyIfus[jj] > 0) && 01287 (sky_tweak == FALSE)) { 01288 kmo_print_objSkyStruct(obj_sky_struct); 01289 01290 cpl_msg_error("","*************************************************************************"); 01291 cpl_msg_error("","* The provided obj/sky-association-table (parameter --obj_sky_table) *"); 01292 cpl_msg_error("","* contains skies assigned to objects originating from different IFUs! *"); 01293 cpl_msg_error("","* In this case the parameter --sky_tweak has to be set by the user! *"); 01294 cpl_msg_error("","*************************************************************************"); 01295 01296 kmo_delete_objSkyStruct(obj_sky_struct); 01297 01298 KMO_TRY_ASSURE(1 == 0, CPL_ERROR_ILLEGAL_INPUT," "); 01299 } 01300 } 01301 } 01302 } 01303 01304 KMO_TRY_EXIT_IF_NULL( 01305 arm_name_struct = kmo_create_armNameStruct2(obj_sky_struct, 01306 frameset, SCIENCE, ifus, name, unused_ifus_after, bounds, 01307 mapping_mode, no_subtract)); 01308 } 01309 kmo_print_armNameStruct(frameset, arm_name_struct); 01310 01311 /* Check Telluric availability for each Object */ 01312 /* Why only mapping ? Not clear */ 01313 /* in mapping-mode check if for all IFUs there is either no */ 01314 /* telluric at all or the same number of tellurics than object names */ 01315 if ((has_telluric) && (mapping_mode != NULL)) { 01316 telluric_ok = TRUE; 01317 for (jj = 0; jj < arm_name_struct->nrNames; jj++) { 01318 if (!((arm_name_struct->telluricCnt[jj] == arm_name_struct->namesCnt[jj]) || 01319 (arm_name_struct->telluricCnt[jj] == 0))) { 01320 telluric_ok = FALSE; 01321 break; 01322 } 01323 } 01324 if (!telluric_ok) { 01325 KMO_TRY_ASSURE(1==0, CPL_ERROR_UNSUPPORTED_MODE, 01326 "Mosaics need a TELLURIC frame with at least a telluric correction per detector available! " 01327 "Omit the TELLURIC from your sof-file or choose another TELLURIC!"); 01328 } 01329 } 01330 01331 /* Load lcal-frames */ 01332 KMO_TRY_EXIT_IF_NULL(lcal = (cpl_image**)cpl_calloc(KMOS_NR_DETECTORS, 01333 sizeof(cpl_image*))); 01334 for (i = 0; i < KMOS_NR_DETECTORS; i++) { 01335 KMO_TRY_EXIT_IF_NULL(lcal[i] = kmo_dfs_load_image(frameset, LCAL, 01336 i+1, FALSE, FALSE, NULL)); 01337 } 01338 01339 nr_data_alloc = KMOS_NR_IFUS; 01340 KMO_TRY_EXIT_IF_NULL(cube_data = (cpl_imagelist**)cpl_calloc( 01341 nr_data_alloc, sizeof(cpl_imagelist*))); 01342 KMO_TRY_EXIT_IF_NULL(cube_noise = (cpl_imagelist**)cpl_calloc( 01343 nr_data_alloc, sizeof(cpl_imagelist*))); 01344 KMO_TRY_EXIT_IF_NULL(header_data = (cpl_propertylist**)cpl_calloc( 01345 nr_data_alloc, sizeof(cpl_propertylist*))); 01346 KMO_TRY_EXIT_IF_NULL(header_noise = (cpl_propertylist**)cpl_calloc( 01347 nr_data_alloc, sizeof(cpl_propertylist*))); 01348 01349 if (save_interims) { 01350 KMO_TRY_EXIT_IF_NULL(cube_interim_object=(cpl_imagelist**)cpl_calloc( 01351 nr_data_alloc, sizeof(cpl_imagelist*))); 01352 KMO_TRY_EXIT_IF_NULL(cube_interim_sky =(cpl_imagelist**)cpl_calloc( 01353 nr_data_alloc, sizeof(cpl_imagelist*))); 01354 KMO_TRY_EXIT_IF_NULL(header_sky = (cpl_propertylist**)cpl_calloc( 01355 nr_data_alloc, sizeof(cpl_propertylist*))); 01356 } 01357 01358 if (cpl_frameset_count_tags(frameset, SCIENCE) == 1) { 01359 no_combine = TRUE; 01360 cpl_msg_info(__func__, 01361 "--no_combine set to TRUE since there is 1 SCIENCE frame"); 01362 } 01363 01364 if (no_subtract) { 01365 no_combine = TRUE; 01366 cpl_msg_info(__func__, 01367 "--no_combine set to TRUE since --no_subtract is set"); 01368 } 01369 actual_msg_level = cpl_msg_get_level(); 01370 cpl_msg_info("", "-------------------------------------------"); 01371 01372 /* Check if input SCIENCE frames are really ALL observations */ 01373 /* If not, Omit the OH_SPEC, even if it is passed - issue a Warning */ 01374 if (has_oh_spec) { 01375 int is_all_obs = TRUE, 01376 has_all_origfile = TRUE; 01377 01378 KMO_TRY_EXIT_IF_NULL( 01379 tmp_frame = kmo_dfs_get_frame(frameset, SCIENCE)); 01380 while (tmp_frame != NULL ) { 01381 KMO_TRY_EXIT_IF_NULL(tmp_header = kmclipm_propertylist_load( 01382 cpl_frame_get_filename(tmp_frame), 0)); 01383 if (cpl_propertylist_has(tmp_header, ORIGFILE)) { 01384 KMO_TRY_EXIT_IF_NULL(tmp_str = 01385 cpl_propertylist_get_string(tmp_header, ORIGFILE)); 01386 if (strstr(tmp_str, "OBS") == NULL) { 01387 is_all_obs = FALSE; 01388 } 01389 } else { 01390 has_all_origfile = FALSE; 01391 } 01392 cpl_propertylist_delete(tmp_header); tmp_header = NULL; 01393 tmp_frame = kmo_dfs_get_frame(frameset, NULL); 01394 KMO_TRY_CHECK_ERROR_STATE(); 01395 } 01396 01397 if (has_all_origfile) { 01398 if (is_all_obs) { 01399 /* OBS-frame reconstruction - allow OH_SPEC */ 01400 KMO_TRY_EXIT_IF_NULL(ref_spectrum_frame = 01401 kmo_dfs_get_frame(frameset, OH_SPEC)); 01402 01403 /* Verify OH_SPEC */ 01404 /* TODO */ 01405 01406 } else { 01407 cpl_msg_warning(__func__, 01408 "Supplied OH_SPEC is ignored since a calibration " 01409 "frame is being used as SCIENCE frame."); 01410 } 01411 } else { 01412 cpl_msg_warning(__func__, 01413 "Supplied OH_SPEC is ignored since a calibration " 01414 "frame is being used as SCIENCE frame."); 01415 } 01416 } 01417 01418 /* Loop all science frames containing at least one object */ 01419 cpl_msg_info(__func__, "Reconstructing & saving cubes with objects"); 01420 for (sf = 0; sf < arm_name_struct->size; sf++) { 01421 KMO_TRY_EXIT_IF_NULL(fn_obj = cpl_frame_get_filename( 01422 arm_name_struct->obj_sky_struct->table[sf].objFrame)); 01423 KMO_TRY_EXIT_IF_NULL( 01424 main_header = kmclipm_propertylist_load(fn_obj, 0)); 01425 actual_msg_level = cpl_msg_get_level(); 01426 01427 /* Reconstruct science frame */ 01428 cpl_msg_info(__func__, " > processing frame: %s", fn_obj); 01429 for (ifu_nr = 1; ifu_nr <= KMOS_NR_IFUS; ifu_nr++) { 01430 sky_ifu_nr = ifu_nr; 01431 det_nr = (ifu_nr - 1)/KMOS_IFUS_PER_DETECTOR + 1; 01432 01433 KMO_TRY_ASSURE((det_nr >= 1) && (det_nr <= KMOS_NR_DETECTORS), 01434 CPL_ERROR_ILLEGAL_INPUT, 01435 "The provided ifu-numbers are incorrect! They " 01436 "must be between 1 and %d", KMOS_NR_IFUS); 01437 01438 /* Get subheader data */ 01439 KMO_TRY_EXIT_IF_NULL(header_data[ifu_nr-1] = 01440 kmclipm_propertylist_load(fn_obj, det_nr)); 01441 KMO_TRY_EXIT_IF_NULL(extname = kmo_extname_creator(ifu_frame, 01442 ifu_nr, EXT_DATA)); 01443 KMO_TRY_EXIT_IF_ERROR(kmclipm_update_property_string( 01444 header_data[ifu_nr-1], EXTNAME, extname, 01445 "FITS extension name")); 01446 cpl_free(extname); extname = NULL; 01447 01448 if (arm_name_struct->name_ids[ifu_nr-1+sf*KMOS_NR_IFUS] >= 1) { 01449 // IFU is valid 01450 01451 /* Fill do_sky_subtraction and sky_frame */ 01452 if ((arm_name_struct->obj_sky_struct->table[sf].skyFrames[ifu_nr-1] != NO_CORRESPONDING_SKYFRAME) && !no_subtract) { 01453 do_sky_subtraction = TRUE; 01454 if (no_subtract) { 01455 sky_frame = NULL; 01456 } else { 01457 sky_frame = arm_name_struct->obj_sky_struct->table[sf].skyFrames[ifu_nr-1]; 01458 KMO_TRY_EXIT_IF_NULL( 01459 fn_sky = cpl_frame_get_filename(sky_frame)); 01460 } 01461 01462 if (sky_tweak){ 01463 sky_as_object_frame = sky_frame; 01464 sky_frame = NULL; 01465 sky_ifu_nr = arm_name_struct->obj_sky_struct->table[sf].skyIfus[ifu_nr-1]; 01466 } 01467 01468 if (no_subtract) { 01469 cpl_msg_warning(__func__, 01470 " > Omit sky subtraction on IFU %d", 01471 ifu_nr); 01472 } else { 01473 if (sky_ifu_nr == ifu_nr) { 01474 cpl_msg_info(__func__, 01475 " > IFU %d (sky in frame: %s)", 01476 ifu_nr, fn_sky); 01477 } else { 01478 cpl_msg_info(__func__, 01479 " > IFU %d (sky in IFU %d of frame: %s)", 01480 ifu_nr, sky_ifu_nr, fn_sky); 01481 } 01482 } 01483 } else { 01484 do_sky_subtraction = FALSE; 01485 sky_frame = NULL; 01486 if (!no_subtract) { 01487 cpl_msg_warning(__func__, 01488 " > IFU %d with no corresponding sky frame", 01489 ifu_nr); 01490 } 01491 } 01492 01493 /* Get filter for this detector and setup grid definition using WAVE_BAND */ 01494 KMO_TRY_EXIT_IF_NULL(keyword = cpl_sprintf("%s%d%s", 01495 IFU_FILTID_PREFIX, det_nr, IFU_FILTID_POSTFIX)); 01496 KMO_TRY_EXIT_IF_NULL(filter_id = 01497 cpl_propertylist_get_string(main_header, keyword)); 01498 cpl_free(keyword); keyword = NULL; 01499 01500 /* TODO : Review print_once mechanism */ 01501 /* Used to print once per detector - problematic for parallelisation */ 01502 if (print_once) cpl_msg_set_level(CPL_MSG_WARNING); 01503 01504 KMO_TRY_EXIT_IF_NULL(band_table = kmo_dfs_load_table( 01505 frameset, WAVE_BAND, 1, 0)); 01506 KMO_TRY_EXIT_IF_ERROR(kmclipm_setup_grid_band_lcal(&gd, 01507 filter_id, band_table)); 01508 cpl_table_delete(band_table); band_table = NULL; 01509 01510 print_once = TRUE; 01511 cpl_msg_set_level(actual_msg_level); 01512 01513 /* calc WCS & update subheader */ 01514 KMO_TRY_EXIT_IF_ERROR(kmo_calc_wcs_gd(main_header, 01515 header_data[ifu_nr-1], ifu_nr, gd)); 01516 01517 /* Update some keywords */ 01518 KMO_TRY_EXIT_IF_ERROR( 01519 kmclipm_update_property_int(header_data[ifu_nr-1], 01520 NAXIS, 3, "number of data axes")); 01521 KMO_TRY_EXIT_IF_ERROR( 01522 kmclipm_update_property_int(header_data[ifu_nr-1], 01523 NAXIS1, gd.x.dim, "length of data axis 1")); 01524 KMO_TRY_EXIT_IF_ERROR( 01525 kmclipm_update_property_int(header_data[ifu_nr-1], 01526 NAXIS2, gd.y.dim, "length of data axis 2")); 01527 KMO_TRY_EXIT_IF_ERROR( 01528 kmclipm_update_property_int(header_data[ifu_nr-1], 01529 NAXIS3, gd.l.dim, "length of data axis 3")); 01530 01531 /* Option save_interim only applies if sky_tweak is used */ 01532 if (save_interims && (sky_as_object_frame != NULL)) { 01533 KMO_TRY_EXIT_IF_NULL( 01534 main_sky_header = kmclipm_propertylist_load( 01535 cpl_frame_get_filename( 01536 sky_as_object_frame), 0)); 01537 KMO_TRY_EXIT_IF_NULL( 01538 header_sky[ifu_nr-1]=kmclipm_propertylist_load( 01539 cpl_frame_get_filename( 01540 sky_as_object_frame), det_nr)); 01541 KMO_TRY_EXIT_IF_NULL(extname = kmo_extname_creator( 01542 ifu_frame, ifu_nr, EXT_DATA)); 01543 KMO_TRY_EXIT_IF_ERROR( 01544 kmclipm_update_property_string( 01545 header_sky[ifu_nr-1], EXTNAME, extname, 01546 "FITS extension name")); 01547 cpl_free(extname); extname = NULL; 01548 01549 KMO_TRY_EXIT_IF_ERROR(kmo_calc_wcs_gd(main_sky_header, 01550 header_sky[ifu_nr-1], ifu_nr, gd)); 01551 01552 KMO_TRY_EXIT_IF_ERROR(kmclipm_update_property_int( 01553 header_sky[ifu_nr-1], NAXIS, 3, 01554 "number of data axes")); 01555 KMO_TRY_EXIT_IF_ERROR(kmclipm_update_property_int( 01556 header_sky[ifu_nr-1], NAXIS1, gd.x.dim, 01557 "length of data axis 1")); 01558 KMO_TRY_EXIT_IF_ERROR(kmclipm_update_property_int( 01559 header_sky[ifu_nr-1], NAXIS2, gd.y.dim, 01560 "length of data axis 2")); 01561 KMO_TRY_EXIT_IF_ERROR(kmclipm_update_property_int( 01562 header_sky[ifu_nr-1], NAXIS3, gd.l.dim, 01563 "length of data axis 3")); 01564 cpl_propertylist_delete(main_sky_header); 01565 main_sky_header = NULL; 01566 } 01567 01568 /* Reconstruct object */ 01569 if (ref_spectrum_frame == NULL) { 01570 /* No lambda correction using OH lines */ 01571 KMO_TRY_EXIT_IF_ERROR( 01572 kmo_reconstruct_sci( 01573 ifu_nr, 01574 bounds[2*(ifu_nr-1)], 01575 bounds[2*(ifu_nr-1)+1], 01576 arm_name_struct->obj_sky_struct->table[sf].objFrame, 01577 SCIENCE, 01578 sky_frame, 01579 SCIENCE, 01580 flat_frame, 01581 xcal_frame, 01582 ycal_frame, 01583 lcal_frame, 01584 NULL, 01585 velo_corr_ptr, 01586 &gd, 01587 &cube_data[ifu_nr-1], 01588 &cube_noise[ifu_nr-1], 01589 flux, 01590 background, 01591 xcal_interpolation)); 01592 } else { 01593 /* Lambda correction using OH lines */ 01594 KMO_TRY_EXIT_IF_ERROR( 01595 kmo_reconstruct_sci( 01596 ifu_nr, 01597 bounds[2*(ifu_nr-1)], 01598 bounds[2*(ifu_nr-1)+1], 01599 arm_name_struct->obj_sky_struct->table[sf].objFrame, 01600 SCIENCE, 01601 NULL, 01602 NULL, 01603 flat_frame, 01604 xcal_frame, 01605 ycal_frame, 01606 lcal_frame, 01607 NULL, 01608 NULL, 01609 &gd, 01610 &cube_data[ifu_nr-1], 01611 &cube_noise[ifu_nr-1], 01612 FALSE, 01613 FALSE, 01614 xcal_interpolation)); 01615 if (cube_data[ifu_nr-1] != NULL) { 01616 KMO_TRY_EXIT_IF_NULL( 01617 oh_lcorr_coeffs = kmo_lcorr_get( 01618 cube_data[ifu_nr-1], header_data[ifu_nr-1], 01619 ref_spectrum_frame, gd, filter_id, ifu_nr)); 01620 cpl_imagelist_delete(cube_data[ifu_nr-1]); 01621 cube_data[ifu_nr-1] = NULL; 01622 if (cube_noise[ifu_nr-1] != NULL) { 01623 cpl_imagelist_delete(cube_noise[ifu_nr-1]); 01624 cube_noise[ifu_nr-1] = NULL; 01625 } 01626 01627 KMO_TRY_EXIT_IF_ERROR( 01628 kmo_reconstruct_sci( 01629 ifu_nr, 01630 bounds[2*(ifu_nr-1)], 01631 bounds[2*(ifu_nr-1)+1], 01632 arm_name_struct->obj_sky_struct->table[sf].objFrame, 01633 SCIENCE, 01634 sky_frame, 01635 SCIENCE, 01636 flat_frame, 01637 xcal_frame, 01638 ycal_frame, 01639 lcal_frame, 01640 oh_lcorr_coeffs, 01641 velo_corr_ptr, 01642 &gd, 01643 &cube_data[ifu_nr-1], 01644 &cube_noise[ifu_nr-1], 01645 flux, 01646 background, 01647 xcal_interpolation)); 01648 cpl_polynomial_delete(oh_lcorr_coeffs); 01649 oh_lcorr_coeffs = NULL; 01650 } 01651 } 01652 01653 /* If sky_tweak is set,reconstruct sky frame as object */ 01654 /* and use kmo_priv_sky_tweak to subtract */ 01655 /* a modified sky cube */ 01656 if (do_sky_subtraction && sky_tweak) { 01657 if (ref_spectrum_frame == NULL) { 01658 /* No lambda correction using OH lines */ 01659 KMO_TRY_EXIT_IF_ERROR( 01660 kmo_reconstruct_sci( 01661 sky_ifu_nr, 01662 bounds[2*(sky_ifu_nr-1)], 01663 bounds[2*(sky_ifu_nr-1)+1], 01664 sky_as_object_frame, 01665 SCIENCE, 01666 sky_frame, 01667 SCIENCE, 01668 flat_frame, 01669 xcal_frame, 01670 ycal_frame, 01671 lcal_frame, 01672 NULL, 01673 velo_corr_ptr, 01674 &gd, 01675 &sky_data, 01676 &sky_noise, 01677 flux, 01678 background, 01679 xcal_interpolation)); 01680 } else { 01681 /* Lambda correction using OH lines */ 01682 KMO_TRY_EXIT_IF_ERROR( 01683 kmo_reconstruct_sci( 01684 sky_ifu_nr, 01685 bounds[2*(sky_ifu_nr-1)], 01686 bounds[2*(sky_ifu_nr-1)+1], 01687 sky_as_object_frame, 01688 SCIENCE, 01689 NULL, 01690 NULL, 01691 flat_frame, 01692 xcal_frame, 01693 ycal_frame, 01694 lcal_frame, 01695 NULL, 01696 NULL, 01697 &gd, 01698 &sky_data, 01699 &sky_noise, 01700 FALSE, 01701 FALSE, 01702 xcal_interpolation)); 01703 if (sky_data != NULL) { 01704 KMO_TRY_EXIT_IF_NULL( 01705 oh_lcorr_coeffs = kmo_lcorr_get(sky_data, 01706 header_data[ifu_nr-1], 01707 ref_spectrum_frame, gd, filter_id, 01708 ifu_nr)); 01709 cpl_imagelist_delete(sky_data); sky_data = NULL; 01710 if (sky_noise != NULL) { 01711 cpl_imagelist_delete(sky_noise); 01712 sky_noise = NULL; 01713 } 01714 KMO_TRY_EXIT_IF_ERROR( 01715 kmo_reconstruct_sci( 01716 sky_ifu_nr, 01717 bounds[2*(sky_ifu_nr-1)], 01718 bounds[2*(sky_ifu_nr-1)+1], 01719 sky_as_object_frame, 01720 SCIENCE, 01721 sky_frame, 01722 SCIENCE, 01723 flat_frame, 01724 xcal_frame, 01725 ycal_frame, 01726 lcal_frame, 01727 oh_lcorr_coeffs, 01728 velo_corr_ptr, 01729 &gd, 01730 &sky_data, 01731 &sky_noise, 01732 flux, 01733 background, 01734 xcal_interpolation)); 01735 cpl_polynomial_delete(oh_lcorr_coeffs); 01736 oh_lcorr_coeffs = NULL; 01737 } 01738 } // end if (ref_spectrum_frame == NULL) 01739 01740 if (save_interims && (sky_as_object_frame != NULL)) { 01741 KMO_TRY_EXIT_IF_NULL(cube_interim_object[ifu_nr-1]= 01742 cpl_imagelist_duplicate(cube_data[ifu_nr-1])); 01743 KMO_TRY_EXIT_IF_NULL(cube_interim_sky[ifu_nr-1]= 01744 cpl_imagelist_duplicate(sky_data)); 01745 } 01746 01747 cpl_imagelist *tmp_object_cube = cube_data[ifu_nr-1]; 01748 KMO_TRY_EXIT_IF_NULL(cube_data[ifu_nr-1] = 01749 kmo_priv_sky_tweak (tmp_object_cube, sky_data, 01750 header_data[ifu_nr-1], .3, tbsub)); 01751 if (tmp_object_cube != NULL) { 01752 cpl_imagelist_delete(tmp_object_cube); 01753 tmp_object_cube = NULL; 01754 } 01755 if (sky_data != NULL) { 01756 cpl_imagelist_delete(sky_data); sky_data = NULL; 01757 } 01758 if (sky_noise != NULL) { 01759 cpl_imagelist_delete(sky_noise); sky_noise = NULL; 01760 } 01761 } // end if (do_sky_subtraction && sky_tweak) 01762 01763 /* Maintain flux constant in case the pixscale is diff */ 01764 /* For example, pixscale=0.1 => images 28x28 => scaling=4 */ 01765 KMO_TRY_EXIT_IF_NULL( 01766 tmpImg = cpl_imagelist_get(cube_data[ifu_nr-1], 0)); 01767 double scaling = (cpl_image_get_size_x(tmpImg)* 01768 cpl_image_get_size_y(tmpImg)) / 01769 (KMOS_SLITLET_X*KMOS_SLITLET_Y); 01770 KMO_TRY_EXIT_IF_ERROR( 01771 cpl_imagelist_divide_scalar(cube_data[ifu_nr-1], 01772 scaling)); 01773 if (cube_noise[ifu_nr-1] != NULL) { 01774 KMO_TRY_EXIT_IF_ERROR( 01775 cpl_imagelist_divide_scalar(cube_noise[ifu_nr-1], 01776 scaling)); 01777 } 01778 01779 /* Get object name */ 01780 KMO_TRY_EXIT_IF_NULL(keyword = cpl_sprintf("%s%d%s", 01781 IFU_NAME_PREFIX, ifu_nr, IFU_NAME_POSTFIX)); 01782 KMO_TRY_EXIT_IF_NULL(tmp_str = cpl_propertylist_get_string( 01783 header_data[ifu_nr-1], keyword)); 01784 cpl_free(keyword); keyword = NULL; 01785 01786 /* Divide cube by telluric correction */ 01787 if (has_telluric) { 01788 /* Check if the nb of occurences of the object name */ 01789 /* is the same as the number of found tellurics for */ 01790 /* this object (which can be on different arms) */ 01791 telluric_ok = FALSE; 01792 for (jj = 0; jj < arm_name_struct->nrNames; jj++) { 01793 if (((strcmp(arm_name_struct->names[jj], tmp_str) == 0) || 01794 (strcmp(arm_name_struct->names[jj], IFUS_USER_DEFINED) == 0)) && 01795 (arm_name_struct->telluricCnt[jj] == arm_name_struct->namesCnt[jj])) { 01796 telluric_ok = TRUE; 01797 break; 01798 } 01799 } 01800 01801 if (telluric_ok) { 01802 telluric_data = kmo_tweak_load_telluric(frameset, 01803 ifu_nr, FALSE, no_subtract); 01804 KMO_TRY_CHECK_ERROR_STATE(); 01805 if (telluric_data != NULL) { 01806 /* Get the index of the telluric noise */ 01807 index = kmo_identify_index_desc(desc_telluric, 01808 ifu_nr, TRUE); 01809 KMO_TRY_CHECK_ERROR_STATE(); 01810 if (desc_telluric.sub_desc[index-1].valid_data 01811 == TRUE) { 01812 // load noise if present 01813 telluric_noise = kmo_tweak_load_telluric( 01814 frameset,ifu_nr, TRUE, no_subtract); 01815 KMO_TRY_CHECK_ERROR_STATE(); 01816 } else { 01817 if (print_warning_once_tweak_std_noise && 01818 (cube_noise[ifu_nr-1] != NULL)) { 01819 cpl_msg_warning(__func__,"************************************************************"); 01820 cpl_msg_warning(__func__,"* Noise cubes were calculated, but won't be divided by *"); 01821 cpl_msg_warning(__func__,"* telluric error since it is missing. *"); 01822 cpl_msg_warning(__func__,"* In order to get a telluric with errors, execute *"); 01823 cpl_msg_warning(__func__,"* kmo_std_star with one of the nearest neighbour methods *"); 01824 cpl_msg_warning(__func__,"* (set --imethod to NN, lwNN or swNN) *"); 01825 cpl_msg_warning(__func__,"************************************************************"); 01826 print_warning_once_tweak_std_noise = 01827 FALSE; 01828 } 01829 } 01830 01831 KMO_TRY_EXIT_IF_ERROR(kmo_arithmetic_3D_1D( 01832 cube_data[ifu_nr-1], telluric_data, 01833 cube_noise[ifu_nr-1], 01834 telluric_noise, "/")); 01835 } 01836 } 01837 } 01838 01839 /* Divide cube by illumination correction */ 01840 if (has_illum_corr) { 01841 illum_data = kmo_dfs_load_image(frameset, ILLUM_CORR, 01842 ifu_nr, FALSE, FALSE, NULL); 01843 if (cpl_error_get_code() != CPL_ERROR_NONE) { 01844 cpl_msg_warning(__func__, 01845 "No illumination correction for IFU %d available! " 01846 "Proceeding anyway.", ifu_nr); 01847 cpl_error_reset(); 01848 } else { 01849 illum_noise = kmo_dfs_load_image(frameset, 01850 ILLUM_CORR, ifu_nr, TRUE, FALSE, NULL); 01851 if (cpl_error_get_code() != CPL_ERROR_NONE) { 01852 cpl_msg_warning(__func__, 01853 "No illumination correction for IFU %d available! " 01854 "Proceeding anyway.", ifu_nr); 01855 cpl_image_delete(illum_data); illum_data = NULL; 01856 cpl_error_reset(); 01857 } 01858 } 01859 01860 if (illum_data != NULL) { 01861 KMO_TRY_EXIT_IF_ERROR( 01862 kmo_arithmetic_3D_2D(cube_data[ifu_nr-1], 01863 illum_data, cube_noise[ifu_nr-1], 01864 illum_noise, "/")); 01865 cpl_image_delete(illum_data); illum_data = NULL; 01866 cpl_image_delete(illum_noise); illum_noise = NULL; 01867 } 01868 } 01869 01870 kmclipm_vector_delete(telluric_data); telluric_data = NULL; 01871 kmclipm_vector_delete(telluric_noise);telluric_noise= NULL; 01872 } else { 01873 // IFU is invalid 01874 } 01875 01876 // duplicate subheader data 01877 KMO_TRY_EXIT_IF_NULL(header_noise[ifu_nr-1] = 01878 cpl_propertylist_duplicate(header_data[ifu_nr-1])); 01879 KMO_TRY_EXIT_IF_NULL(extname = kmo_extname_creator(ifu_frame, 01880 ifu_nr, EXT_NOISE)); 01881 KMO_TRY_EXIT_IF_ERROR(kmclipm_update_property_string( 01882 header_noise[ifu_nr-1], EXTNAME, extname, 01883 "FITS extension name")); 01884 cpl_free(extname); extname = NULL; 01885 } // end for ifu_nr 01886 01887 /* Count number of reconstructed data- and noise-cubes */ 01888 for (ifu_nr = 1; ifu_nr <= nr_data_alloc; ifu_nr++) { 01889 if (cube_data[ifu_nr-1] != NULL) cube_counter_data++; 01890 if (cube_noise[ifu_nr-1] != NULL) cube_counter_noise++; 01891 } 01892 01893 /* Save reconstructed cubes of science frame */ 01894 if (cube_counter_data > 0) { 01895 cpl_msg_info(__func__, " > saving..."); 01896 01897 if (!suppress_extension) { 01898 fn_out = fn_obj; 01899 01900 int nr_found = 0; 01901 // remove any path-elements from filename and use it as 01902 // suffix 01903 split = kmo_strsplit(fn_out, "/", &nr_found); 01904 01905 fn_suffix = cpl_sprintf("_%s", split[nr_found-1]); 01906 kmo_strfreev(split); 01907 01908 // remove '.fits' at the end if there is any 01909 char *fff = fn_suffix; 01910 fff += strlen(fn_suffix)-5; 01911 if (strcmp(fff, ".fits") == 0) { 01912 fn_suffix[strlen(fn_suffix)-5] = '\0'; 01913 } 01914 } else { 01915 KMO_TRY_EXIT_IF_NULL( 01916 fn_suffix = cpl_sprintf("_%d", suppress_index++)); 01917 } 01918 01919 fn_out = RECONSTRUCTED_CUBE; 01920 fn_interim_object = INTERIM_OBJECT_CUBE; 01921 fn_interim_sky = INTERIM_OBJECT_SKY; 01922 01923 /* Create Primary Header */ 01924 KMO_TRY_EXIT_IF_ERROR(kmo_dfs_save_main_header(frameset, 01925 fn_out, fn_suffix, 01926 arm_name_struct->obj_sky_struct->table[sf].objFrame, 01927 NULL, parlist, cpl_func)); 01928 /* save intermediate products (only in sky tweak case) */ 01929 if (save_interims && (sky_as_object_frame != NULL)) { 01930 KMO_TRY_EXIT_IF_ERROR(kmo_dfs_save_main_header(frameset, 01931 fn_interim_object, fn_suffix, 01932 arm_name_struct->obj_sky_struct->table[sf].objFrame, 01933 NULL, parlist, cpl_func)); 01934 KMO_TRY_EXIT_IF_ERROR(kmo_dfs_save_main_header(frameset, 01935 fn_interim_sky, fn_suffix, 01936 arm_name_struct->obj_sky_struct->table[sf].objFrame, 01937 NULL, parlist, cpl_func)); 01938 } 01939 01940 /* Loop on IFUs */ 01941 for (ifu_nr = 1; ifu_nr <= KMOS_NR_IFUS; ifu_nr++) { 01942 /* Save data Extension */ 01943 KMO_TRY_EXIT_IF_ERROR(kmo_dfs_save_cube(cube_data[ifu_nr-1], 01944 fn_out,fn_suffix,header_data[ifu_nr-1], 0./0.)); 01945 01946 /* Save noise Extension */ 01947 if (cube_counter_noise > 0) { 01948 KMO_TRY_EXIT_IF_ERROR(kmo_dfs_save_cube( 01949 cube_noise[ifu_nr-1], fn_out, fn_suffix, 01950 header_noise[ifu_nr-1], 0./0.)); 01951 } 01952 01953 /* save intermediate products (only in sky tweak case */ 01954 if (save_interims && (sky_as_object_frame != NULL)) { 01955 KMO_TRY_EXIT_IF_ERROR(kmo_dfs_save_cube( 01956 cube_interim_object[ifu_nr-1], 01957 fn_interim_object, fn_suffix, 01958 header_data[ifu_nr-1], 0./0.)); 01959 KMO_TRY_EXIT_IF_ERROR(kmo_dfs_save_cube( 01960 cube_interim_sky[ifu_nr-1], fn_interim_sky, 01961 fn_suffix, header_sky[ifu_nr-1], 0./0.)); 01962 } 01963 01964 cpl_imagelist_delete(cube_data[ifu_nr-1]); 01965 cube_data[ifu_nr-1] = NULL; 01966 cpl_imagelist_delete(cube_noise[ifu_nr-1]); 01967 cube_noise[ifu_nr-1] = NULL; 01968 cpl_propertylist_delete(header_data[ifu_nr-1]); 01969 header_data[ifu_nr-1] = NULL; 01970 cpl_propertylist_delete(header_noise[ifu_nr-1]); 01971 header_noise[ifu_nr-1] = NULL; 01972 if (save_interims) { 01973 cpl_imagelist_delete(cube_interim_object[ifu_nr-1]); 01974 cube_interim_object[ifu_nr-1] = NULL; 01975 cpl_imagelist_delete(cube_interim_sky[ifu_nr-1]); 01976 cube_interim_sky[ifu_nr-1] = NULL; 01977 cpl_propertylist_delete(header_sky[ifu_nr-1]); 01978 header_sky[ifu_nr-1] = NULL; 01979 } 01980 } // end for ifu_nr 01981 cpl_free(fn_suffix); fn_suffix = NULL; 01982 } else { 01983 cpl_msg_info(__func__, " > all IFUs invalid, don't save"); 01984 for (ifu_nr = 1; ifu_nr <= KMOS_NR_IFUS; ifu_nr++) { 01985 cpl_propertylist_delete(header_data[ifu_nr-1]); 01986 header_data[ifu_nr-1] = NULL; 01987 cpl_propertylist_delete(header_noise[ifu_nr-1]); 01988 header_noise[ifu_nr-1] = NULL; 01989 } 01990 } // if (cube_counter_data > 0) { 01991 01992 cpl_propertylist_delete(main_header); main_header = NULL; 01993 } // end for sf (arm_name_struct->obj_sky_struct->size) 01994 cpl_free(cube_data); cube_data = NULL; 01995 cpl_free(cube_noise); cube_noise = NULL; 01996 cpl_free(header_data); header_data = NULL; 01997 cpl_free(header_noise); header_noise = NULL; 01998 if (save_interims) { 01999 cpl_free(cube_interim_object); cube_interim_object = NULL; 02000 cpl_free(cube_interim_sky); cube_interim_sky = NULL; 02001 cpl_free(header_sky); header_sky = NULL; 02002 } 02003 02004 kmo_print_unused_ifus(unused_ifus_after, TRUE); 02005 02006 cpl_msg_info("", "-------------------------------------------"); 02007 02008 if (lcal != NULL) { 02009 for (i = 0; i < KMOS_NR_DETECTORS; i++) { 02010 cpl_image_delete(lcal[i]); 02011 } 02012 } 02013 cpl_free(lcal); lcal = NULL; 02014 02015 /* Combine */ 02016 suppress_index = 0; 02017 if (!no_combine) { 02018 cpl_msg_info(__func__, "Combining reconstructed objects"); 02019 nr_reconstructed_frames = cpl_frameset_count_tags(frameset, 02020 RECONSTRUCTED_CUBE); 02021 if ((mapping_mode == NULL) || ((mapping_mode != NULL) && 02022 ((ifus != NULL) || (strcmp(name, "") != 0)))) { 02023 // loop all available objects 02024 for (i = 0; i < arm_name_struct->nrNames; i++) { 02025 cpl_msg_info(__func__, 02026 " > object: %s", arm_name_struct->names[i]); 02027 nr_data_alloc = arm_name_struct->namesCnt[i]; 02028 KMO_TRY_EXIT_IF_NULL(cube_data=(cpl_imagelist**)cpl_calloc( 02029 nr_data_alloc, sizeof(cpl_imagelist*))); 02030 KMO_TRY_EXIT_IF_NULL(cube_noise=(cpl_imagelist**)cpl_calloc( 02031 nr_data_alloc, sizeof(cpl_imagelist*))); 02032 KMO_TRY_EXIT_IF_NULL(header_data= 02033 (cpl_propertylist**)cpl_calloc(nr_data_alloc, 02034 sizeof(cpl_propertylist*))); 02035 KMO_TRY_EXIT_IF_NULL(header_noise= 02036 (cpl_propertylist**)cpl_calloc(nr_data_alloc, 02037 sizeof(cpl_propertylist*))); 02038 02039 // setup cube-list and header-list for kmo_priv_combine() 02040 cube_counter_data = 0; 02041 cube_counter_noise = 0; 02042 KMO_TRY_EXIT_IF_NULL(tmp_frame = kmo_dfs_get_frame(frameset, 02043 RECONSTRUCTED_CUBE)); 02044 while (tmp_frame != NULL ) { 02045 KMO_TRY_EXIT_IF_NULL( 02046 fn_reconstr = cpl_frame_get_filename(tmp_frame)); 02047 KMO_TRY_EXIT_IF_NULL(tmp_header = 02048 kmclipm_propertylist_load(fn_reconstr, 0)); 02049 kmo_free_fits_desc(&desc1); 02050 kmo_init_fits_desc(&desc1); 02051 desc1 = kmo_identify_fits_header(fn_reconstr); 02052 02053 for (ifu_nr = 1; ifu_nr <= KMOS_NR_IFUS; ifu_nr++) { 02054 // check if object-name equals the one in our list 02055 KMO_TRY_EXIT_IF_NULL(keyword = cpl_sprintf("%s%d%s", 02056 IFU_NAME_PREFIX, ifu_nr, 02057 IFU_NAME_POSTFIX)); 02058 KMO_TRY_EXIT_IF_NULL(tmp_str = 02059 cpl_propertylist_get_string(tmp_header, 02060 keyword)); 02061 cpl_free(keyword); keyword = NULL; 02062 02063 if ((strcmp(arm_name_struct->names[i],tmp_str)==0) 02064 || (strcmp(arm_name_struct->names[i], 02065 IFUS_USER_DEFINED) == 0)) { 02066 // found object-IFU with matching name 02067 // load data & subheader 02068 index = kmo_identify_index(fn_reconstr, ifu_nr, 02069 FALSE); 02070 KMO_TRY_CHECK_ERROR_STATE(); 02071 02072 if (desc1.sub_desc[index-1].valid_data) { 02073 KMO_TRY_EXIT_IF_NULL( 02074 cube_data[cube_counter_data] = 02075 kmclipm_imagelist_load(fn_reconstr, 02076 CPL_TYPE_FLOAT, index)); 02077 /* Set cubes borders (1 pixel) to Nan to avoid jumps in combined cube */ 02078 if (edge_nan) { 02079 KMO_TRY_EXIT_IF_ERROR(kmo_edge_nan( 02080 cube_data[cube_counter_data], 02081 ifu_nr)); 02082 } 02083 02084 KMO_TRY_EXIT_IF_NULL( 02085 header_data[cube_counter_data] = 02086 kmclipm_propertylist_load( 02087 fn_reconstr, index)); 02088 cpl_propertylist_update_string( 02089 header_data[cube_counter_data], 02090 "ESO PRO FRNAME", fn_reconstr); 02091 cpl_propertylist_update_int( 02092 header_data[cube_counter_data], 02093 "ESO PRO IFUNR", ifu_nr); 02094 cube_counter_data++; 02095 } 02096 02097 // load noise & subheader (if existing) 02098 if (desc1.ex_noise) { 02099 index = kmo_identify_index(fn_reconstr, 02100 ifu_nr, TRUE); 02101 KMO_TRY_CHECK_ERROR_STATE(); 02102 02103 if (desc1.sub_desc[index-1].valid_data) { 02104 KMO_TRY_EXIT_IF_NULL( 02105 cube_noise[cube_counter_noise] = 02106 kmclipm_imagelist_load( 02107 fn_reconstr, CPL_TYPE_FLOAT, 02108 index)); 02109 if (edge_nan) { 02110 KMO_TRY_EXIT_IF_ERROR( 02111 kmo_edge_nan(cube_noise[cube_counter_noise], ifu_nr)); 02112 } 02113 KMO_TRY_EXIT_IF_NULL( 02114 header_noise[cube_counter_noise] = 02115 kmclipm_propertylist_load( 02116 fn_reconstr, index)); 02117 cube_counter_noise++; 02118 } 02119 } 02120 cpl_error_reset(); 02121 } // end if found obj 02122 } // end for ifu_nr 02123 02124 cpl_propertylist_delete(tmp_header); tmp_header = NULL; 02125 tmp_frame = kmo_dfs_get_frame(frameset, NULL); 02126 KMO_TRY_CHECK_ERROR_STATE(); 02127 } // end while-loop RECONSTRUCTED_CUBE frames 02128 02129 if (cube_counter_data > 1) { 02130 if (cube_counter_data == cube_counter_noise) { 02131 KMO_TRY_EXIT_IF_ERROR( 02132 kmo_priv_combine(cube_data, 02133 cube_noise, 02134 header_data, 02135 header_noise, 02136 cube_counter_data, 02137 cube_counter_noise, 02138 arm_name_struct->names[i], 02139 "", 02140 comb_method, 02141 smethod, 02142 fmethod, 02143 filename, 02144 cmethod, 02145 cpos_rej, 02146 cneg_rej, 02147 citer, 02148 cmin, 02149 cmax, 02150 extrapol_enum, 02151 flux, 02152 &combined_data, 02153 &combined_noise, 02154 &exp_mask)); 02155 } else if (cube_counter_noise == 0) { 02156 KMO_TRY_EXIT_IF_ERROR( 02157 kmo_priv_combine(cube_data, 02158 NULL, 02159 header_data, 02160 header_noise, 02161 cube_counter_data, 02162 cube_counter_noise, 02163 arm_name_struct->names[i], 02164 "", 02165 comb_method, 02166 smethod, 02167 fmethod, 02168 filename, 02169 cmethod, 02170 cpos_rej, 02171 cneg_rej, 02172 citer, 02173 cmin, 02174 cmax, 02175 extrapol_enum, 02176 flux, 02177 &combined_data, 02178 &combined_noise, 02179 &exp_mask)); 02180 } else { 02181 KMO_TRY_ASSURE(1 == 0, CPL_ERROR_ILLEGAL_INPUT, 02182 "The number of cube-data and cube-noise " 02183 "isn't the same (%d vs. %d)!", 02184 cube_counter_data, cube_counter_noise); 02185 } 02186 } else if (cube_counter_data == 1) { 02187 cpl_msg_warning(__func__, 02188 "There is only one reconstructed cube with " 02189 "this object! Saving it as it is."); 02190 KMO_TRY_EXIT_IF_NULL(combined_data = 02191 cpl_imagelist_duplicate(cube_data[0])); 02192 KMO_TRY_EXIT_IF_NULL(tmpImg = 02193 cpl_imagelist_get(combined_data, 0)); 02194 KMO_TRY_EXIT_IF_NULL(exp_mask = cpl_image_new( 02195 cpl_image_get_size_x(tmpImg), 02196 cpl_image_get_size_y(tmpImg), 02197 CPL_TYPE_FLOAT)); 02198 KMO_TRY_EXIT_IF_ERROR(kmo_image_fill(exp_mask, 1.)); 02199 02200 if (cube_noise[0] != NULL) { 02201 KMO_TRY_EXIT_IF_NULL( 02202 combined_noise = cpl_imagelist_duplicate( 02203 cube_noise[0])); 02204 } 02205 } else { 02206 KMO_TRY_ASSURE(1==0, CPL_ERROR_ILLEGAL_INPUT, 02207 "No cubes found with this object name!"); 02208 } // end if (cube_counter_data > 1) 02209 02210 fn_out = COMBINED_CUBE; 02211 fn_out_mask = EXP_MASK; 02212 if (!suppress_extension) { 02213 char tmp_suffix[1024]; 02214 tmp_suffix[0] = '\0'; 02215 02216 if (arm_name_struct->telluricCnt[i] == 02217 arm_name_struct->namesCnt[i]) { 02218 strcat(tmp_suffix, "_telluric"); 02219 } 02220 if (has_illum_corr) strcat(tmp_suffix, "_illum"); 02221 if (sky_tweak) strcat(tmp_suffix, "_skytweak"); 02222 02223 if (strlen(tmp_suffix) > 0) { 02224 KMO_TRY_EXIT_IF_NULL( 02225 fn_suffix = cpl_sprintf("_%s_%s", 02226 arm_name_struct->names[i], tmp_suffix)); 02227 } else { 02228 KMO_TRY_EXIT_IF_NULL( 02229 fn_suffix = cpl_sprintf("_%s", 02230 arm_name_struct->names[i])); 02231 } 02232 } else { 02233 KMO_TRY_EXIT_IF_NULL( 02234 fn_suffix = cpl_sprintf("_%d", suppress_index++)); 02235 } 02236 02237 // save combined cube 02238 KMO_TRY_EXIT_IF_NULL(tmp_frame = 02239 kmo_dfs_get_frame(frameset, RECONSTRUCTED_CUBE)); 02240 KMO_TRY_EXIT_IF_ERROR(kmo_dfs_save_main_header(frameset, 02241 fn_out, fn_suffix, tmp_frame, NULL, parlist, 02242 cpl_func)); 02243 KMO_TRY_EXIT_IF_ERROR(kmo_dfs_save_main_header(frameset, 02244 fn_out_mask, fn_suffix, tmp_frame, NULL, 02245 parlist, cpl_func)); 02246 KMO_TRY_EXIT_IF_ERROR(kmo_dfs_save_cube(combined_data, 02247 fn_out, fn_suffix, header_data[0], 0./0.)); 02248 KMO_TRY_EXIT_IF_ERROR(kmo_dfs_save_image(exp_mask, 02249 fn_out_mask, fn_suffix, header_data[0], 0./0.)); 02250 02251 if (header_noise[0] == NULL) { 02252 KMO_TRY_EXIT_IF_NULL(header_noise[0] = 02253 cpl_propertylist_duplicate(header_data[0])); 02254 02255 KMO_TRY_EXIT_IF_NULL(tmp_str = 02256 cpl_propertylist_get_string(header_data[0], 02257 EXTNAME)); 02258 KMO_TRY_EXIT_IF_ERROR(kmo_extname_extractor(tmp_str, 02259 &ft, &tmp_int, content)); 02260 KMO_TRY_EXIT_IF_NULL(extname = kmo_extname_creator( 02261 ifu_frame, tmp_int, EXT_NOISE)); 02262 KMO_TRY_EXIT_IF_ERROR(kmclipm_update_property_string( 02263 header_noise[0], EXTNAME, extname, 02264 "FITS extension name")); 02265 cpl_free(extname); extname = NULL; 02266 } 02267 KMO_TRY_EXIT_IF_ERROR(kmo_dfs_save_cube(combined_noise, 02268 fn_out, fn_suffix, header_noise[0], 0./0.)); 02269 02270 for (jj = 0; jj < nr_data_alloc; jj++) { 02271 cpl_imagelist_delete(cube_data[jj]); 02272 cube_data[jj] = NULL; 02273 cpl_imagelist_delete(cube_noise[jj]); 02274 cube_noise[jj] = NULL; 02275 cpl_propertylist_delete(header_data[jj]); 02276 header_data[jj] = NULL; 02277 cpl_propertylist_delete(header_noise[jj]); 02278 header_noise[jj] = NULL; 02279 } 02280 cpl_free(cube_data); cube_data = NULL; 02281 cpl_free(cube_noise); cube_noise = NULL; 02282 cpl_free(header_data); header_data = NULL; 02283 cpl_free(header_noise); header_noise = NULL; 02284 cpl_free(fn_suffix); fn_suffix = NULL; 02285 cpl_imagelist_delete(combined_data); combined_data = NULL; 02286 cpl_imagelist_delete(combined_noise); combined_noise = NULL; 02287 cpl_image_delete(exp_mask); exp_mask = NULL; 02288 } // for i = nr_avail_obj_names 02289 } else { 02290 // we are in mapping_mode 02291 nr_data_alloc = nr_reconstructed_frames*KMOS_NR_IFUS; 02292 KMO_TRY_EXIT_IF_NULL(cube_data = (cpl_imagelist**)cpl_calloc( 02293 nr_data_alloc, sizeof(cpl_imagelist*))); 02294 KMO_TRY_EXIT_IF_NULL(cube_noise = (cpl_imagelist**)cpl_calloc( 02295 nr_data_alloc, sizeof(cpl_imagelist*))); 02296 KMO_TRY_EXIT_IF_NULL(header_data=(cpl_propertylist**)cpl_calloc( 02297 nr_data_alloc, sizeof(cpl_propertylist*))); 02298 KMO_TRY_EXIT_IF_NULL(header_noise=(cpl_propertylist**)cpl_calloc( 02299 nr_data_alloc, sizeof(cpl_propertylist*))); 02300 02301 cube_counter_data = 0; 02302 cube_counter_noise = 0; 02303 KMO_TRY_EXIT_IF_NULL(tmp_frame = 02304 kmo_dfs_get_frame(frameset, RECONSTRUCTED_CUBE)); 02305 while (tmp_frame != NULL ) { 02306 KMO_TRY_EXIT_IF_NULL( 02307 fn_reconstr = cpl_frame_get_filename(tmp_frame)); 02308 KMO_TRY_EXIT_IF_NULL( 02309 tmp_header = kmclipm_propertylist_load(fn_reconstr, 0)); 02310 02311 kmo_free_fits_desc(&desc1); 02312 kmo_init_fits_desc(&desc1); 02313 desc1 = kmo_identify_fits_header(fn_reconstr); 02314 for (ifu_nr = 1; ifu_nr <= KMOS_NR_IFUS; ifu_nr++) { 02315 index = kmo_identify_index(fn_reconstr, ifu_nr, FALSE); 02316 KMO_TRY_CHECK_ERROR_STATE(); 02317 02318 if (desc1.sub_desc[index-1].valid_data) { 02319 KMO_TRY_EXIT_IF_NULL(cube_data[cube_counter_data] = 02320 kmclipm_imagelist_load(fn_reconstr, 02321 CPL_TYPE_FLOAT, index)); 02322 if (edge_nan) { 02323 KMO_TRY_EXIT_IF_ERROR( 02324 kmo_edge_nan(cube_data[cube_counter_data], 02325 ifu_nr)); 02326 } 02327 02328 if (fast_mode) { 02329 KMO_TRY_EXIT_IF_NULL(tmpImg = 02330 cpl_imagelist_collapse_median_create( 02331 cube_data[cube_counter_data])); 02332 KMO_TRY_EXIT_IF_NULL( 02333 tmpCube = cpl_imagelist_new()); 02334 KMO_TRY_EXIT_IF_ERROR( 02335 cpl_imagelist_set(tmpCube, tmpImg, 0)); 02336 cpl_imagelist_delete(cube_data[cube_counter_data]); 02337 cube_data[cube_counter_data] = tmpCube; 02338 } 02339 02340 KMO_TRY_EXIT_IF_NULL( 02341 header_data[cube_counter_data] = 02342 kmclipm_propertylist_load(fn_reconstr, index)); 02343 cpl_propertylist_update_string( 02344 header_data[cube_counter_data], 02345 "ESO PRO FRNAME", fn_reconstr); 02346 cpl_propertylist_update_int( 02347 header_data[cube_counter_data], 02348 "ESO PRO IFUNR", ifu_nr); 02349 cube_counter_data++; 02350 } 02351 02352 // load noise & subheader (if existing) 02353 if (desc1.ex_noise) { 02354 index = kmo_identify_index(fn_reconstr,ifu_nr,TRUE); 02355 KMO_TRY_CHECK_ERROR_STATE(); 02356 if (desc1.sub_desc[index-1].valid_data) { 02357 KMO_TRY_EXIT_IF_NULL( 02358 cube_noise[cube_counter_noise] = 02359 kmclipm_imagelist_load(fn_reconstr, 02360 CPL_TYPE_FLOAT, index)); 02361 02362 if (edge_nan) { 02363 KMO_TRY_EXIT_IF_ERROR(kmo_edge_nan( 02364 cube_noise[cube_counter_noise], 02365 ifu_nr)); 02366 } 02367 02368 if (fast_mode) { 02369 KMO_TRY_EXIT_IF_NULL(tmpImg = 02370 cpl_imagelist_collapse_median_create(cube_noise[cube_counter_noise])); 02371 KMO_TRY_EXIT_IF_NULL( 02372 tmpCube = cpl_imagelist_new()); 02373 KMO_TRY_EXIT_IF_ERROR( 02374 cpl_imagelist_set(tmpCube, tmpImg, 0)); 02375 cpl_imagelist_delete(cube_noise[cube_counter_noise]); 02376 cube_noise[cube_counter_noise] = tmpCube; 02377 } 02378 KMO_TRY_EXIT_IF_NULL( 02379 header_noise[cube_counter_noise] = 02380 kmclipm_propertylist_load(fn_reconstr, 02381 index)); 02382 cube_counter_noise++; 02383 } 02384 } 02385 cpl_error_reset(); 02386 } // end for ifu_nr 02387 02388 cpl_propertylist_delete(tmp_header); tmp_header = NULL; 02389 tmp_frame = kmo_dfs_get_frame(frameset, NULL); 02390 KMO_TRY_CHECK_ERROR_STATE(); 02391 } // end while-loop RECONSTRUCTED_CUBE frames 02392 02393 if (cube_counter_data > 1) { 02394 if (cube_counter_data == cube_counter_noise) { 02395 KMO_TRY_EXIT_IF_ERROR( 02396 kmo_priv_combine(cube_data, 02397 cube_noise, 02398 header_data, 02399 header_noise, 02400 cube_counter_data, 02401 cube_counter_noise, 02402 mapping_mode, 02403 "", 02404 comb_method, 02405 smethod, 02406 fmethod, 02407 filename, 02408 cmethod, 02409 cpos_rej, 02410 cneg_rej, 02411 citer, 02412 cmin, 02413 cmax, 02414 extrapol_enum, 02415 flux, 02416 &combined_data, 02417 &combined_noise, 02418 NULL)); 02419 } else if (cube_counter_noise == 0) { 02420 KMO_TRY_EXIT_IF_ERROR( 02421 kmo_priv_combine(cube_data, 02422 NULL, 02423 header_data, 02424 header_noise, 02425 cube_counter_data, 02426 cube_counter_noise, 02427 mapping_mode, 02428 "", 02429 comb_method, 02430 smethod, 02431 fmethod, 02432 filename, 02433 cmethod, 02434 cpos_rej, 02435 cneg_rej, 02436 citer, 02437 cmin, 02438 cmax, 02439 extrapol_enum, 02440 flux, 02441 &combined_data, 02442 &combined_noise, 02443 NULL)); 02444 } else { 02445 KMO_TRY_ASSURE(1 == 0, CPL_ERROR_ILLEGAL_INPUT, 02446 "The number of cube-data and cube-noise " 02447 "isn't the same (%d vs. %d)!", 02448 cube_counter_data, cube_counter_noise); 02449 } 02450 } else { 02451 cpl_msg_warning(__func__, 02452 "There is only one reconstructed cube - Save it"); 02453 KMO_TRY_EXIT_IF_NULL( 02454 combined_data = cpl_imagelist_duplicate(cube_data[0])); 02455 02456 if (cube_noise[0] != NULL) { 02457 KMO_TRY_EXIT_IF_NULL( 02458 combined_noise = cpl_imagelist_duplicate( 02459 cube_noise[0])); 02460 } 02461 } 02462 02463 fn_out = COMBINED_CUBE; 02464 KMO_TRY_EXIT_IF_NULL( 02465 fn_suffix = cpl_sprintf("_%s", mapping_mode)); 02466 02467 // save combined cube 02468 KMO_TRY_EXIT_IF_NULL(tmp_frame = kmo_dfs_get_frame(frameset, 02469 RECONSTRUCTED_CUBE)); 02470 KMO_TRY_EXIT_IF_ERROR( 02471 kmo_dfs_save_main_header(frameset, fn_out, fn_suffix, 02472 tmp_frame, NULL, parlist, cpl_func)); 02473 02474 KMO_TRY_EXIT_IF_ERROR( 02475 kmo_dfs_save_cube(combined_data, fn_out, fn_suffix, 02476 header_data[0], 0./0.)); 02477 02478 if (header_noise[0] == NULL) { 02479 KMO_TRY_EXIT_IF_NULL( 02480 header_noise[0] = 02481 cpl_propertylist_duplicate(header_data[0])); 02482 02483 KMO_TRY_EXIT_IF_NULL( 02484 tmp_str = cpl_propertylist_get_string(header_data[0], 02485 EXTNAME)); 02486 KMO_TRY_EXIT_IF_ERROR( 02487 kmo_extname_extractor(tmp_str, &ft, &tmp_int, content)); 02488 KMO_TRY_EXIT_IF_NULL( 02489 extname = kmo_extname_creator(ifu_frame, tmp_int, 02490 EXT_NOISE)); 02491 KMO_TRY_EXIT_IF_ERROR( 02492 kmclipm_update_property_string(header_noise[0], EXTNAME, 02493 extname, "FITS extension name")); 02494 cpl_free(extname); extname = NULL; 02495 } 02496 KMO_TRY_EXIT_IF_ERROR( 02497 kmo_dfs_save_cube(combined_noise, fn_out, fn_suffix, 02498 header_noise[0], 0./0.)); 02499 02500 for (i = 0; i < nr_data_alloc; i++) { 02501 cpl_imagelist_delete(cube_data[i]); cube_data[i] = NULL; 02502 cpl_imagelist_delete(cube_noise[i]); cube_noise[i] = NULL; 02503 cpl_propertylist_delete(header_data[i]); 02504 header_data[i] = NULL; 02505 cpl_propertylist_delete(header_noise[i]); 02506 header_noise[i] = NULL; 02507 } 02508 cpl_free(cube_data); cube_data = NULL; 02509 cpl_free(cube_noise); cube_noise = NULL; 02510 cpl_free(header_data); header_data = NULL; 02511 cpl_free(header_noise); header_noise = NULL; 02512 cpl_free(fn_suffix); fn_suffix = NULL; 02513 cpl_imagelist_delete(combined_data); combined_data = NULL; 02514 cpl_imagelist_delete(combined_noise); combined_noise = NULL; 02515 } // if mapping_mode 02516 } else { 02517 cpl_msg_info("", "Reconstructed objects are not combined"); 02518 } // if (!no_combine) 02519 cpl_msg_info("", "-------------------------------------------"); 02520 } 02521 KMO_CATCH 02522 { 02523 KMO_CATCH_MSG(); 02524 ret_val = -1; 02525 } 02526 if (cube_data != NULL) { 02527 for (ifu_nr = 1; ifu_nr <= nr_data_alloc; ifu_nr++) { 02528 cpl_imagelist_delete(cube_data[ifu_nr-1]); 02529 cube_data[ifu_nr-1] = NULL; 02530 } 02531 } 02532 cpl_free(cube_data); cube_data = NULL; 02533 if (cube_noise != NULL) { 02534 for (ifu_nr = 1; ifu_nr <= nr_data_alloc; ifu_nr++) { 02535 cpl_imagelist_delete(cube_noise[ifu_nr-1]); 02536 cube_noise[ifu_nr-1] = NULL; 02537 } 02538 } 02539 cpl_free(cube_noise); cube_noise = NULL; 02540 if (header_data != NULL) { 02541 for (ifu_nr = 1; ifu_nr <= nr_data_alloc; ifu_nr++) { 02542 cpl_propertylist_delete(header_data[ifu_nr-1]); 02543 header_data[ifu_nr-1] = NULL; 02544 } 02545 } 02546 cpl_free(header_data); header_data = NULL; 02547 if (header_noise != NULL) { 02548 for (ifu_nr = 1; ifu_nr <= nr_data_alloc; ifu_nr++) { 02549 cpl_propertylist_delete(header_noise[ifu_nr-1]); 02550 header_noise[ifu_nr-1] = NULL; 02551 } 02552 } 02553 cpl_free(header_noise); header_noise = NULL; 02554 02555 02556 kmo_free_fits_desc(&desc1); 02557 kmo_free_fits_desc(&desc2); 02558 kmo_free_fits_desc(&desc_telluric); 02559 02560 cpl_vector_delete(ifus); ifus = NULL; 02561 cpl_free(mapping_mode); mapping_mode = NULL; 02562 if (unused_ifus_before != NULL) { 02563 kmo_free_unused_ifus(unused_ifus_before); unused_ifus_before = NULL; 02564 } 02565 if (unused_ifus_after != NULL) { 02566 kmo_free_unused_ifus(unused_ifus_after); unused_ifus_after = NULL; 02567 } 02568 if (bounds != NULL) { 02569 cpl_free(bounds); bounds = NULL; 02570 } 02571 02572 // frees for the case of errors 02573 kmclipm_vector_delete(telluric_data); telluric_data = NULL; 02574 kmclipm_vector_delete(telluric_noise); telluric_noise = NULL; 02575 cpl_image_delete(illum_data); illum_data = NULL; 02576 cpl_image_delete(illum_noise); illum_noise = NULL; 02577 cpl_propertylist_delete(tmp_header); tmp_header = NULL; 02578 cpl_table_delete(band_table); band_table = NULL; 02579 cpl_propertylist_delete(main_header); main_header = NULL; 02580 if (lcal != NULL) { 02581 for (i = 0; i < KMOS_NR_DETECTORS; i++) { 02582 cpl_image_delete(lcal[i]); 02583 } 02584 } 02585 cpl_free(lcal); lcal = NULL; 02586 cpl_free(fn_suffix); fn_suffix = NULL; 02587 cpl_free(suffix); suffix = NULL; 02588 02589 kmo_delete_armNameStruct(arm_name_struct); 02590 02591 return ret_val; 02592 } 02593