FORS Pipeline Reference Manual 4.9.9
|
00001 /* $Id: fors_pmos_calib.c,v 1.34 2010/09/14 07:38:16 cizzo Exp $ 00002 * 00003 * This file is part of the FORS Data Reduction Pipeline 00004 * Copyright (C) 2002-2010 European Southern Observatory 00005 * 00006 * This program is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00019 */ 00020 00021 /* 00022 * $Author: cizzo $ 00023 * $Date: 2010/09/14 07:38:16 $ 00024 * $Revision: 1.34 $ 00025 * $Name: fors-4_9_9 $ 00026 */ 00027 00028 #ifdef HAVE_CONFIG_H 00029 #include <config.h> 00030 #endif 00031 00032 #include <math.h> 00033 #include <string.h> 00034 #include <ctype.h> 00035 #include <cpl.h> 00036 #include <moses.h> 00037 #include <fors_stack.h> 00038 #include <fors_dfs.h> 00039 #include <fors_qc.h> 00040 00041 #define OFFSET 50 00042 #define TOLERANCE 10 00043 00044 static int fors_pmos_calib_create(cpl_plugin *); 00045 static int fors_pmos_calib_exec(cpl_plugin *); 00046 static int fors_pmos_calib_destroy(cpl_plugin *); 00047 static int fors_pmos_calib(cpl_parameterlist *, cpl_frameset *); 00048 00049 static char fors_pmos_calib_description[] = 00050 "This recipe is used to identify reference lines on PMOS arc lamp\n" 00051 "exposures, and trace the spectral edges on the corresponding flat field\n" 00052 "exposures. This information is used to determine the spectral extraction\n" 00053 "mask to be applied in the scientific data reduction, performed with the\n" 00054 "recipe fors_science.\n" 00055 "This recipe accepts both FORS1 and FORS2 frames. The input arc lamps and\n" 00056 "flat field exposures are assumed to be obtained quasi-simultaneously, so\n" 00057 "that they would be described by exactly the same instrument distortions.\n" 00058 "A line catalog must be specified, containing the wavelengths of the\n" 00059 "reference arc lamp lines used for the wavelength calibration. A grism\n" 00060 "table (typically depending on the instrument mode, and in particular on\n" 00061 "the grism used) may also be specified: this table contains a default\n" 00062 "recipe parameter setting to control the way spectra are extracted for\n" 00063 "a specific instrument mode, as it is used for automatic run of the\n" 00064 "pipeline on Paranal and in Garching. If this table is specified, it\n" 00065 "will modify the default recipe parameter setting, with the exception of\n" 00066 "those parameters which have been explicitly modifyed on the command line.\n" 00067 "If a grism table is not specified, the input recipe parameters values\n" 00068 "will always be read from the command line, or from an esorex configuration\n" 00069 "file if present, or from their generic default values (that are rarely\n" 00070 "meaningful). Finally a master bias frame must be input to this recipe.\n" 00071 "The products SPECTRA_DETECTION_PMOS, SLIT_MAP_PMOS, and DISP_RESIDUALS_PMOS,\n" 00072 "are just created if the --check parameter is set to true.\n" 00073 "The MASTER_DISTORTION_TABLE is marked as required, but it is not so if all\n" 00074 "slits have different offsets, and in the case of FORS1 observations made\n" 00075 "with the old TK2048EB4-1 1604 chip read in windowed mode (2048x400)\n\n" 00076 "Input files:\n\n" 00077 " DO category: Type: Explanation: Required:\n" 00078 " SCREEN_FLAT_PMOS Raw Flat field exposures Y\n" 00079 " LAMP_PMOS Raw Arc lamp exposure Y\n" 00080 " MASTER_BIAS or BIAS Calib Bias frame Y\n" 00081 " MASTER_LINECAT Calib Line catalog Y\n" 00082 " GRISM_TABLE Calib Grism table .\n" 00083 " MASTER_DISTORTION_TABLE Calib Master distortions table Y\n\n" 00084 "Output files:\n\n" 00085 " DO category: Data type: Explanation:\n" 00086 " MASTER_SCREEN_FLAT_PMOS FITS image Combined (sum) flat field\n" 00087 " MASTER_NORM_FLAT_PMOS FITS image Normalised flat field\n" 00088 " MAPPED_SCREEN_FLAT_PMOS FITS image Wavelength calibrated flat field\n" 00089 " MAPPED_NORM_FLAT_PMOS FITS image Wavelength calibrated normalised flat\n" 00090 " REDUCED_LAMP_PMOS FITS image Wavelength calibrated arc spectrum\n" 00091 " DISP_COEFF_PMOS FITS table Inverse dispersion coefficients\n" 00092 " DISP_RESIDUALS_PMOS FITS image Residuals in wavelength calibration\n" 00093 " DISP_RESIDUALS_TABLE_PMOS FITS table Residuals in wavelength calibration\n" 00094 " DELTA_IMAGE_PMOS FITS image Offset vs linear wavelength calib\n" 00095 " WAVELENGTH_MAP_PMOS FITS image Wavelength for each pixel on CCD\n" 00096 " SPECTRA_DETECTION_PMOS FITS image Check for preliminary detection\n" 00097 " SLIT_MAP_PMOS FITS image Map of central wavelength on CCD\n" 00098 " CURV_TRACES_PMOS FITS table Spectral curvature traces\n" 00099 " CURV_COEFF_PMOS FITS table Spectral curvature coefficients\n" 00100 " SPATIAL_MAP_PMOS FITS image Spatial position along slit on CCD\n" 00101 " SPECTRAL_RESOLUTION_PMOS FITS table Resolution at reference arc lines\n" 00102 " SLIT_LOCATION_PMOS FITS table Slits on product frames and CCD\n\n"; 00103 00104 #define fors_pmos_calib_exit(message) \ 00105 { \ 00106 if (message) cpl_msg_error(recipe, message); \ 00107 cpl_free(instrume); \ 00108 cpl_free(pipefile); \ 00109 cpl_free(fiterror); \ 00110 cpl_free(fitlines); \ 00111 cpl_image_delete(bias); \ 00112 cpl_image_delete(master_bias); \ 00113 cpl_image_delete(coordinate); \ 00114 cpl_image_delete(checkwave); \ 00115 cpl_image_delete(flat); \ 00116 cpl_image_delete(master_flat); \ 00117 cpl_image_delete(added_flat); \ 00118 cpl_image_delete(norm_flat); \ 00119 cpl_image_delete(mapped_flat); \ 00120 cpl_image_delete(mapped_nflat); \ 00121 cpl_image_delete(rainbow); \ 00122 cpl_image_delete(rectified); \ 00123 cpl_image_delete(residual); \ 00124 cpl_image_delete(smo_flat); \ 00125 cpl_image_delete(spatial); \ 00126 cpl_image_delete(spectra); \ 00127 cpl_image_delete(wavemap); \ 00128 cpl_image_delete(delta); \ 00129 cpl_image_delete(rect_flat); \ 00130 cpl_image_delete(rect_nflat); \ 00131 cpl_image_delete(mapped_flat); \ 00132 cpl_image_delete(mapped_nflat); \ 00133 cpl_mask_delete(refmask); \ 00134 cpl_propertylist_delete(header); \ 00135 cpl_propertylist_delete(save_header); \ 00136 cpl_propertylist_delete(qclist); \ 00137 cpl_table_delete(grism_table); \ 00138 cpl_table_delete(idscoeff); \ 00139 cpl_table_delete(idscoeff_all); \ 00140 cpl_table_delete(restable); \ 00141 cpl_table_delete(maskslits); \ 00142 cpl_table_delete(overscans); \ 00143 cpl_table_delete(traces); \ 00144 cpl_table_delete(polytraces); \ 00145 cpl_table_delete(slits); \ 00146 cpl_table_delete(restab); \ 00147 cpl_table_delete(global); \ 00148 cpl_table_delete(wavelengths); \ 00149 cpl_vector_delete(lines); \ 00150 cpl_msg_indent_less(); \ 00151 return -1; \ 00152 } 00153 00154 #define fors_pmos_calib_exit_memcheck(message) \ 00155 { \ 00156 if (message) cpl_msg_info(recipe, message); \ 00157 printf("free instrume (%p)\n", instrume); \ 00158 cpl_free(instrume); \ 00159 printf("free pipefile (%p)\n", pipefile); \ 00160 cpl_free(pipefile); \ 00161 printf("free fiterror (%p)\n", fiterror); \ 00162 cpl_free(fiterror); \ 00163 printf("free fitlines (%p)\n", fitlines); \ 00164 cpl_free(fitlines); \ 00165 printf("free bias (%p)\n", bias); \ 00166 cpl_image_delete(bias); \ 00167 printf("free master_bias (%p)\n", master_bias); \ 00168 cpl_image_delete(master_bias); \ 00169 printf("free coordinate (%p)\n", coordinate); \ 00170 cpl_image_delete(coordinate); \ 00171 printf("free checkwave (%p)\n", checkwave); \ 00172 cpl_image_delete(checkwave); \ 00173 printf("free flat (%p)\n", flat); \ 00174 cpl_image_delete(flat); \ 00175 printf("free master_flat (%p)\n", master_flat); \ 00176 cpl_image_delete(master_flat); \ 00177 printf("free norm_flat (%p)\n", norm_flat); \ 00178 cpl_image_delete(norm_flat); \ 00179 printf("free mapped_flat (%p)\n", mapped_flat); \ 00180 cpl_image_delete(mapped_flat); \ 00181 printf("free mapped_nflat (%p)\n", mapped_nflat); \ 00182 cpl_image_delete(mapped_nflat); \ 00183 printf("free rainbow (%p)\n", rainbow); \ 00184 cpl_image_delete(rainbow); \ 00185 printf("free rectified (%p)\n", rectified); \ 00186 cpl_image_delete(rectified); \ 00187 printf("free residual (%p)\n", residual); \ 00188 cpl_image_delete(residual); \ 00189 printf("free smo_flat (%p)\n", smo_flat); \ 00190 cpl_image_delete(smo_flat); \ 00191 printf("free spatial (%p)\n", spatial); \ 00192 cpl_image_delete(spatial); \ 00193 printf("free spectra (%p)\n", spectra); \ 00194 cpl_image_delete(spectra); \ 00195 printf("free wavemap (%p)\n", wavemap); \ 00196 cpl_image_delete(wavemap); \ 00197 printf("free delta (%p)\n", delta); \ 00198 cpl_image_delete(delta); \ 00199 printf("free rect_flat (%p)\n", rect_flat); \ 00200 cpl_image_delete(rect_flat); \ 00201 printf("free rect_nflat (%p)\n", rect_nflat); \ 00202 cpl_image_delete(rect_nflat); \ 00203 printf("free refmask (%p)\n", refmask); \ 00204 cpl_mask_delete(refmask); \ 00205 printf("free header (%p)\n", header); \ 00206 cpl_propertylist_delete(header); \ 00207 printf("free save_header (%p)\n", save_header); \ 00208 cpl_propertylist_delete(save_header); \ 00209 printf("free qclist (%p)\n", qclist); \ 00210 cpl_propertylist_delete(qclist); \ 00211 printf("free grism_table (%p)\n", grism_table); \ 00212 cpl_table_delete(grism_table); \ 00213 printf("free idscoeff (%p)\n", idscoeff); \ 00214 cpl_table_delete(idscoeff); \ 00215 printf("free idscoeff_all (%p)\n", idscoeff_all); \ 00216 cpl_table_delete(idscoeff_all); \ 00217 printf("free restable (%p)\n", restable); \ 00218 cpl_table_delete(restable); \ 00219 printf("free maskslits (%p)\n", maskslits); \ 00220 cpl_table_delete(maskslits); \ 00221 printf("free overscans (%p)\n", overscans); \ 00222 cpl_table_delete(overscans); \ 00223 printf("free traces (%p)\n", traces); \ 00224 cpl_table_delete(traces); \ 00225 printf("free polytraces (%p)\n", polytraces); \ 00226 cpl_table_delete(polytraces); \ 00227 printf("free slits (%p)\n", slits); \ 00228 cpl_table_delete(slits); \ 00229 printf("free restab (%p)\n", restab); \ 00230 cpl_table_delete(restab); \ 00231 printf("free global (%p)\n", global); \ 00232 cpl_table_delete(global); \ 00233 printf("free wavelengths (%p)\n", wavelengths); \ 00234 cpl_table_delete(wavelengths); \ 00235 printf("free lines (%p)\n", lines); \ 00236 cpl_vector_delete(lines); \ 00237 cpl_msg_indent_less(); \ 00238 return 0; \ 00239 } 00240 00241 00253 int cpl_plugin_get_info(cpl_pluginlist *list) 00254 { 00255 cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe ); 00256 cpl_plugin *plugin = &recipe->interface; 00257 00258 cpl_plugin_init(plugin, 00259 CPL_PLUGIN_API, 00260 FORS_BINARY_VERSION, 00261 CPL_PLUGIN_TYPE_RECIPE, 00262 "fors_pmos_calib", 00263 "Determination of the extraction mask", 00264 fors_pmos_calib_description, 00265 "Carlo Izzo", 00266 PACKAGE_BUGREPORT, 00267 "This file is currently part of the FORS Instrument Pipeline\n" 00268 "Copyright (C) 2002-2010 European Southern Observatory\n\n" 00269 "This program is free software; you can redistribute it and/or modify\n" 00270 "it under the terms of the GNU General Public License as published by\n" 00271 "the Free Software Foundation; either version 2 of the License, or\n" 00272 "(at your option) any later version.\n\n" 00273 "This program is distributed in the hope that it will be useful,\n" 00274 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" 00275 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" 00276 "GNU General Public License for more details.\n\n" 00277 "You should have received a copy of the GNU General Public License\n" 00278 "along with this program; if not, write to the Free Software Foundation,\n" 00279 "Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\n", 00280 fors_pmos_calib_create, 00281 fors_pmos_calib_exec, 00282 fors_pmos_calib_destroy); 00283 00284 cpl_pluginlist_append(list, plugin); 00285 00286 return 0; 00287 } 00288 00289 00300 static int fors_pmos_calib_create(cpl_plugin *plugin) 00301 { 00302 cpl_recipe *recipe; 00303 cpl_parameter *p; 00304 00305 00306 /* 00307 * Check that the plugin is part of a valid recipe 00308 */ 00309 00310 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00311 recipe = (cpl_recipe *)plugin; 00312 else 00313 return -1; 00314 00315 /* 00316 * Create the parameters list in the cpl_recipe object 00317 */ 00318 00319 recipe->parameters = cpl_parameterlist_new(); 00320 00321 00322 /* 00323 * Dispersion 00324 */ 00325 00326 p = cpl_parameter_new_value("fors.fors_pmos_calib.dispersion", 00327 CPL_TYPE_DOUBLE, 00328 "Expected spectral dispersion (Angstrom/pixel)", 00329 "fors.fors_pmos_calib", 00330 0.0); 00331 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "dispersion"); 00332 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00333 cpl_parameterlist_append(recipe->parameters, p); 00334 00335 /* 00336 * Peak detection level 00337 */ 00338 00339 p = cpl_parameter_new_value("fors.fors_pmos_calib.peakdetection", 00340 CPL_TYPE_DOUBLE, 00341 "Initial peak detection threshold (ADU)", 00342 "fors.fors_pmos_calib", 00343 0.0); 00344 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "peakdetection"); 00345 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00346 cpl_parameterlist_append(recipe->parameters, p); 00347 00348 /* 00349 * Degree of wavelength calibration polynomial 00350 */ 00351 00352 p = cpl_parameter_new_value("fors.fors_pmos_calib.wdegree", 00353 CPL_TYPE_INT, 00354 "Degree of wavelength calibration polynomial", 00355 "fors.fors_pmos_calib", 00356 0); 00357 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wdegree"); 00358 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00359 cpl_parameterlist_append(recipe->parameters, p); 00360 00361 /* 00362 * Reference lines search radius 00363 */ 00364 00365 p = cpl_parameter_new_value("fors.fors_pmos_calib.wradius", 00366 CPL_TYPE_INT, 00367 "Search radius if iterating pattern-matching " 00368 "with first-guess method", 00369 "fors.fors_pmos_calib", 00370 4); 00371 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wradius"); 00372 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00373 cpl_parameterlist_append(recipe->parameters, p); 00374 00375 /* 00376 * Rejection threshold in dispersion relation polynomial fitting 00377 */ 00378 00379 p = cpl_parameter_new_value("fors.fors_pmos_calib.wreject", 00380 CPL_TYPE_DOUBLE, 00381 "Rejection threshold in dispersion " 00382 "relation fit (pixel)", 00383 "fors.fors_pmos_calib", 00384 0.7); 00385 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wreject"); 00386 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00387 cpl_parameterlist_append(recipe->parameters, p); 00388 00389 /* 00390 * Line catalog table column containing the reference wavelengths 00391 */ 00392 00393 p = cpl_parameter_new_value("fors.fors_pmos_calib.wcolumn", 00394 CPL_TYPE_STRING, 00395 "Name of line catalog table column " 00396 "with wavelengths", 00397 "fors.fors_pmos_calib", 00398 "WLEN"); 00399 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcolumn"); 00400 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00401 cpl_parameterlist_append(recipe->parameters, p); 00402 00403 /* 00404 * Degree of spectral curvature polynomial 00405 */ 00406 00407 p = cpl_parameter_new_value("fors.fors_pmos_calib.cdegree", 00408 CPL_TYPE_INT, 00409 "Degree of spectral curvature polynomial", 00410 "fors.fors_pmos_calib", 00411 0); 00412 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "cdegree"); 00413 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00414 cpl_parameterlist_append(recipe->parameters, p); 00415 00416 /* 00417 * Curvature solution interpolation 00418 */ 00419 00420 p = cpl_parameter_new_value("fors.fors_pmos_calib.cmode", 00421 CPL_TYPE_INT, 00422 "Interpolation mode of curvature solution " 00423 "(0 = no " 00424 "interpolation, 1 = fill gaps, 2 = global " 00425 "model)", 00426 "fors.fors_pmos_calib", 00427 1); 00428 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "cmode"); 00429 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00430 cpl_parameterlist_append(recipe->parameters, p); 00431 00432 /* 00433 * Start wavelength for spectral extraction 00434 */ 00435 00436 p = cpl_parameter_new_value("fors.fors_pmos_calib.startwavelength", 00437 CPL_TYPE_DOUBLE, 00438 "Start wavelength in spectral extraction", 00439 "fors.fors_pmos_calib", 00440 0.0); 00441 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "startwavelength"); 00442 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00443 cpl_parameterlist_append(recipe->parameters, p); 00444 00445 /* 00446 * End wavelength for spectral extraction 00447 */ 00448 00449 p = cpl_parameter_new_value("fors.fors_pmos_calib.endwavelength", 00450 CPL_TYPE_DOUBLE, 00451 "End wavelength in spectral extraction", 00452 "fors.fors_pmos_calib", 00453 0.0); 00454 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "endwavelength"); 00455 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00456 cpl_parameterlist_append(recipe->parameters, p); 00457 00458 /* 00459 * Flat field frames stack parameters 00460 */ 00461 00462 fors_stack_define_parameters(recipe->parameters, "fors.fors_pmos_calib", 00463 "average"); 00464 00465 /* 00466 * Degree of flat field fitting polynomial along dispersion direction 00467 */ 00468 00469 p = cpl_parameter_new_value("fors.fors_pmos_calib.ddegree", 00470 CPL_TYPE_INT, 00471 "Degree of flat field fitting polynomial " 00472 "along dispersion direction", 00473 "fors.fors_pmos_calib", 00474 -1); 00475 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "ddegree"); 00476 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00477 cpl_parameterlist_append(recipe->parameters, p); 00478 00479 /* 00480 * Smooth box radius for flat field along dispersion direction 00481 */ 00482 00483 p = cpl_parameter_new_value("fors.fors_pmos_calib.dradius", 00484 CPL_TYPE_INT, 00485 "Smooth box radius for flat field along " 00486 "dispersion direction", 00487 "fors.fors_pmos_calib", 00488 10); 00489 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "dradius"); 00490 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00491 cpl_parameterlist_append(recipe->parameters, p); 00492 00493 /* 00494 * Computation of QC1 parameters 00495 */ 00496 00497 p = cpl_parameter_new_value("fors.fors_pmos_calib.qc", 00498 CPL_TYPE_BOOL, 00499 "Compute QC1 parameters", 00500 "fors.fors_pmos_calib", 00501 TRUE); 00502 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "qc"); 00503 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00504 cpl_parameterlist_append(recipe->parameters, p); 00505 00506 /* 00507 * Create check products 00508 */ 00509 00510 p = cpl_parameter_new_value("fors.fors_pmos_calib.check", 00511 CPL_TYPE_BOOL, 00512 "Create intermediate products", 00513 "fors.fors_pmos_calib", 00514 FALSE); 00515 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "check"); 00516 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00517 cpl_parameterlist_append(recipe->parameters, p); 00518 00519 return 0; 00520 } 00521 00522 00531 static int fors_pmos_calib_exec(cpl_plugin *plugin) 00532 { 00533 cpl_recipe *recipe; 00534 00535 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00536 recipe = (cpl_recipe *)plugin; 00537 else 00538 return -1; 00539 00540 return fors_pmos_calib(recipe->parameters, recipe->frames); 00541 } 00542 00543 00552 static int fors_pmos_calib_destroy(cpl_plugin *plugin) 00553 { 00554 cpl_recipe *recipe; 00555 00556 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00557 recipe = (cpl_recipe *)plugin; 00558 else 00559 return -1; 00560 00561 cpl_parameterlist_delete(recipe->parameters); 00562 00563 return 0; 00564 } 00565 00566 00576 static int fors_pmos_calib(cpl_parameterlist *parlist, cpl_frameset *frameset) 00577 { 00578 00579 const char *recipe = "fors_pmos_calib"; 00580 00581 00582 /* 00583 * Input parameters 00584 */ 00585 00586 double dispersion; 00587 double peakdetection; 00588 int wdegree; 00589 int wradius; 00590 double wreject; 00591 const char *wcolumn; 00592 int cdegree; 00593 int cmode; 00594 double startwavelength; 00595 double endwavelength; 00596 int ddegree; 00597 int dradius; 00598 int qc; 00599 int check; 00600 const char *stack_method; 00601 int min_reject; 00602 int max_reject; 00603 double klow; 00604 double khigh; 00605 int kiter; 00606 00607 00608 /* 00609 * CPL objects 00610 */ 00611 00612 cpl_imagelist *biases = NULL; 00613 cpl_image *bias = NULL; 00614 cpl_image *master_bias = NULL; 00615 cpl_image *multi_bias = NULL; 00616 cpl_image *flat = NULL; 00617 cpl_image *master_flat = NULL; 00618 cpl_image *added_flat = NULL; 00619 cpl_image *trace_flat = NULL; 00620 cpl_image *smo_flat = NULL; 00621 cpl_image *norm_flat = NULL; 00622 cpl_image *spectra = NULL; 00623 cpl_image *wavemap = NULL; 00624 cpl_image *delta = NULL; 00625 cpl_image *residual = NULL; 00626 cpl_image *checkwave = NULL; 00627 cpl_image *rectified = NULL; 00628 cpl_image *dummy = NULL; 00629 cpl_image *add_dummy = NULL; 00630 cpl_image *refimage = NULL; 00631 cpl_image *coordinate = NULL; 00632 cpl_image *rainbow = NULL; 00633 cpl_image *spatial = NULL; 00634 cpl_image *rect_flat = NULL; 00635 cpl_image *rect_nflat = NULL; 00636 cpl_image *mapped_flat = NULL; 00637 cpl_image *mapped_nflat = NULL; 00638 00639 cpl_mask *refmask = NULL; 00640 00641 cpl_table *grism_table = NULL; 00642 cpl_table *overscans = NULL; 00643 cpl_table *wavelengths = NULL; 00644 cpl_table *idscoeff = NULL; 00645 cpl_table *idscoeff_all = NULL; 00646 cpl_table *restable = NULL; 00647 cpl_table *slits = NULL; 00648 cpl_table *positions = NULL; 00649 cpl_table *maskslits = NULL; 00650 cpl_table *traces = NULL; 00651 cpl_table *polytraces = NULL; 00652 cpl_table *restab = NULL; 00653 cpl_table *global = NULL; 00654 00655 cpl_vector *lines = NULL; 00656 00657 cpl_propertylist *header_dist = NULL; 00658 cpl_propertylist *header = NULL; 00659 cpl_propertylist *save_header = NULL; 00660 cpl_propertylist *qclist = NULL; 00661 00662 /* 00663 * Auxiliary variables 00664 */ 00665 00666 char version[80]; 00667 const char *arc_tag; 00668 const char *flat_tag; 00669 const char *master_screen_flat_tag; 00670 const char *master_norm_flat_tag; 00671 const char *reduced_lamp_tag; 00672 const char *disp_residuals_tag; 00673 const char *disp_coeff_tag; 00674 const char *wavelength_map_tag; 00675 const char *spectra_detection_tag; 00676 const char *spectral_resolution_tag; 00677 const char *slit_map_tag; 00678 const char *curv_traces_tag; 00679 const char *curv_coeff_tag; 00680 const char *spatial_map_tag; 00681 const char *slit_location_tag; 00682 const char *master_distortion_tag = "MASTER_DISTORTION_TABLE"; 00683 const char *disp_residuals_table_tag; 00684 const char *delta_image_tag; 00685 const char *mapped_screen_flat_tag; 00686 const char *mapped_norm_flat_tag; 00687 const char *keyname; 00688 int pmos; 00689 int same_offset = 0; 00690 int nslits; 00691 float *data; 00692 double *xpos; 00693 double mxpos; 00694 double mean_rms; 00695 double mean_rms_err; 00696 double alltime; 00697 int nflats; 00698 int nbias; 00699 int nlines; 00700 int rebin, rebin_dist; 00701 double *line; 00702 double *fiterror = NULL; 00703 int *fitlines = NULL; 00704 int nx, ny; 00705 double reference; 00706 double gain; 00707 int ccd_xsize, ccd_ysize; 00708 int i, j; 00709 00710 char *instrume = NULL; 00711 char *pipefile = NULL; 00712 00713 /* 00714 * Variables just related to bagoo 00715 */ 00716 00717 int bagoo = 0; 00718 int doit = 0; 00719 double blevel = 0.0; 00720 double ron = 0.0; 00721 00722 snprintf(version, 80, "%s-%s", PACKAGE, PACKAGE_VERSION); 00723 00724 cpl_msg_set_indentation(2); 00725 00726 if (dfs_files_dont_exist(frameset)) 00727 fors_pmos_calib_exit(NULL); 00728 00729 fors_dfs_set_groups(frameset); 00730 00731 /* 00732 * Get configuration parameters 00733 */ 00734 00735 cpl_msg_info(recipe, "Recipe %s configuration parameters:", recipe); 00736 cpl_msg_indent_more(); 00737 00738 if (cpl_frameset_count_tags(frameset, "GRISM_TABLE") > 1) 00739 fors_pmos_calib_exit("Too many in input: GRISM_TABLE"); 00740 00741 grism_table = dfs_load_table(frameset, "GRISM_TABLE", 1); 00742 00743 dispersion = dfs_get_parameter_double(parlist, 00744 "fors.fors_pmos_calib.dispersion", grism_table); 00745 00746 if (dispersion <= 0.0) 00747 fors_pmos_calib_exit("Invalid spectral dispersion value"); 00748 00749 peakdetection = dfs_get_parameter_double(parlist, 00750 "fors.fors_pmos_calib.peakdetection", grism_table); 00751 if (peakdetection <= 0.0) 00752 fors_pmos_calib_exit("Invalid peak detection level"); 00753 00754 wdegree = dfs_get_parameter_int(parlist, 00755 "fors.fors_pmos_calib.wdegree", grism_table); 00756 00757 if (wdegree < 1) 00758 fors_pmos_calib_exit("Invalid polynomial degree"); 00759 00760 if (wdegree > 5) 00761 fors_pmos_calib_exit("Max allowed polynomial degree is 5"); 00762 00763 wradius = dfs_get_parameter_int(parlist, 00764 "fors.fors_pmos_calib.wradius", NULL); 00765 00766 if (wradius < 0) 00767 fors_pmos_calib_exit("Invalid search radius"); 00768 00769 wreject = dfs_get_parameter_double(parlist, 00770 "fors.fors_pmos_calib.wreject", NULL); 00771 00772 if (wreject <= 0.0) 00773 fors_pmos_calib_exit("Invalid rejection threshold"); 00774 00775 wcolumn = dfs_get_parameter_string(parlist, 00776 "fors.fors_pmos_calib.wcolumn", NULL); 00777 00778 cdegree = dfs_get_parameter_int(parlist, 00779 "fors.fors_pmos_calib.cdegree", grism_table); 00780 00781 if (cdegree < 1) 00782 fors_pmos_calib_exit("Invalid polynomial degree"); 00783 00784 if (cdegree > 5) 00785 fors_pmos_calib_exit("Max allowed polynomial degree is 5"); 00786 00787 cmode = dfs_get_parameter_int(parlist, "fors.fors_pmos_calib.cmode", NULL); 00788 00789 if (cmode < 0 || cmode > 2) 00790 fors_pmos_calib_exit("Invalid curvature solution interpolation mode"); 00791 00792 startwavelength = dfs_get_parameter_double(parlist, 00793 "fors.fors_pmos_calib.startwavelength", grism_table); 00794 if (startwavelength > 1.0) 00795 if (startwavelength < 3000.0 || startwavelength > 13000.0) 00796 fors_pmos_calib_exit("Invalid wavelength"); 00797 00798 endwavelength = dfs_get_parameter_double(parlist, 00799 "fors.fors_pmos_calib.endwavelength", grism_table); 00800 if (endwavelength > 1.0) { 00801 if (endwavelength < 3000.0 || endwavelength > 13000.0) 00802 fors_pmos_calib_exit("Invalid wavelength"); 00803 if (startwavelength < 1.0) 00804 fors_pmos_calib_exit("Invalid wavelength interval"); 00805 } 00806 00807 if (startwavelength > 1.0) 00808 if (endwavelength - startwavelength <= 0.0) 00809 fors_pmos_calib_exit("Invalid wavelength interval"); 00810 00811 stack_method = dfs_get_parameter_string(parlist, 00812 "fors.fors_pmos_calib.stack_method", 00813 NULL); 00814 00815 if (strcmp(stack_method, "minmax") == 0) { 00816 min_reject = dfs_get_parameter_int(parlist, 00817 "fors.fors_pmos_calib.minrejection", NULL); 00818 if (min_reject < 0) 00819 fors_pmos_calib_exit("Invalid number of lower rejections"); 00820 00821 max_reject = dfs_get_parameter_int(parlist, 00822 "fors.fors_pmos_calib.maxrejection", NULL); 00823 if (max_reject < 0) 00824 fors_pmos_calib_exit("Invalid number of upper rejections"); 00825 } 00826 00827 if (strcmp(stack_method, "ksigma") == 0) { 00828 klow = dfs_get_parameter_double(parlist, 00829 "fors.fors_pmos_calib.klow", NULL); 00830 if (klow < 0.1) 00831 fors_pmos_calib_exit("Invalid lower K-sigma"); 00832 00833 khigh = dfs_get_parameter_double(parlist, 00834 "fors.fors_pmos_calib.khigh", NULL); 00835 if (khigh < 0.1) 00836 fors_pmos_calib_exit("Invalid lower K-sigma"); 00837 00838 kiter = dfs_get_parameter_int(parlist, 00839 "fors.fors_pmos_calib.kiter", NULL); 00840 if (kiter < 1) 00841 fors_pmos_calib_exit("Invalid number of iterations"); 00842 } 00843 00844 ddegree = dfs_get_parameter_int(parlist, 00845 "fors.fors_pmos_calib.ddegree", NULL); 00846 dradius = dfs_get_parameter_int(parlist, 00847 "fors.fors_pmos_calib.dradius", NULL); 00848 00849 if (dradius < 1) 00850 fors_pmos_calib_exit("Invalid smoothing box radius"); 00851 00852 qc = dfs_get_parameter_bool(parlist, "fors.fors_pmos_calib.qc", NULL); 00853 00854 check = dfs_get_parameter_bool(parlist, "fors.fors_pmos_calib.check", NULL); 00855 00856 cpl_table_delete(grism_table); grism_table = NULL; 00857 00858 if (cpl_error_get_code()) 00859 fors_pmos_calib_exit("Failure getting the configuration parameters"); 00860 00861 00862 /* 00863 * Check input set-of-frames 00864 */ 00865 00866 cpl_msg_indent_less(); 00867 cpl_msg_info(recipe, "Check input set-of-frames:"); 00868 cpl_msg_indent_more(); 00869 00870 { 00871 cpl_frameset *subframeset = cpl_frameset_duplicate(frameset); 00872 cpl_frameset_erase(subframeset, "BIAS"); 00873 cpl_frameset_erase(subframeset, "MASTER_BIAS"); 00874 00875 if (!dfs_equal_keyword(subframeset, "ESO INS GRIS1 ID")) 00876 fors_pmos_calib_exit("Input frames are not from the same grism"); 00877 00878 if (!dfs_equal_keyword(subframeset, "ESO INS FILT1 ID")) 00879 fors_pmos_calib_exit("Input frames are not from the same filter"); 00880 00881 if (!dfs_equal_keyword(subframeset, "ESO DET CHIP1 ID")) 00882 fors_pmos_calib_exit("Input frames are not from the same chip"); 00883 00884 cpl_frameset_delete(subframeset); 00885 } 00886 00887 pmos = cpl_frameset_count_tags(frameset, "LAMP_PMOS"); 00888 00889 if (pmos == 0) 00890 fors_pmos_calib_exit("Missing input arc lamp frame"); 00891 00892 if (pmos) { 00893 cpl_msg_info(recipe, "PMOS data found"); 00894 arc_tag = "LAMP_PMOS"; 00895 flat_tag = "SCREEN_FLAT_PMOS"; 00896 master_screen_flat_tag = "MASTER_SCREEN_FLAT_PMOS"; 00897 master_norm_flat_tag = "MASTER_NORM_FLAT_PMOS"; 00898 reduced_lamp_tag = "REDUCED_LAMP_PMOS"; 00899 disp_residuals_tag = "DISP_RESIDUALS_PMOS"; 00900 disp_coeff_tag = "DISP_COEFF_PMOS"; 00901 wavelength_map_tag = "WAVELENGTH_MAP_PMOS"; 00902 spectra_detection_tag = "SPECTRA_DETECTION_PMOS"; 00903 spectral_resolution_tag = "SPECTRAL_RESOLUTION_PMOS"; 00904 slit_map_tag = "SLIT_MAP_PMOS"; 00905 curv_traces_tag = "CURV_TRACES_PMOS"; 00906 curv_coeff_tag = "CURV_COEFF_PMOS"; 00907 spatial_map_tag = "SPATIAL_MAP_PMOS"; 00908 slit_location_tag = "SLIT_LOCATION_PMOS"; 00909 disp_residuals_table_tag = "DISP_RESIDUALS_TABLE_PMOS"; 00910 delta_image_tag = "DELTA_IMAGE_PMOS"; 00911 mapped_screen_flat_tag = "MAPPED_SCREEN_FLAT_PMOS"; 00912 mapped_norm_flat_tag = "MAPPED_NORM_FLAT_PMOS"; 00913 } 00914 00915 nbias = 0; 00916 if (cpl_frameset_count_tags(frameset, "MASTER_BIAS") == 0) { 00917 if (cpl_frameset_count_tags(frameset, "BIAS") == 0) 00918 fors_pmos_calib_exit("Missing required input: MASTER_BIAS or BIAS"); 00919 nbias = cpl_frameset_count_tags(frameset, "BIAS"); 00920 } 00921 00922 if (cpl_frameset_count_tags(frameset, "MASTER_BIAS") > 1) 00923 fors_pmos_calib_exit("Too many in input: MASTER_BIAS"); 00924 00925 if (cpl_frameset_count_tags(frameset, "MASTER_LINECAT") == 0) 00926 fors_pmos_calib_exit("Missing required input: MASTER_LINECAT"); 00927 00928 if (cpl_frameset_count_tags(frameset, "MASTER_LINECAT") > 1) 00929 fors_pmos_calib_exit("Too many in input: MASTER_LINECAT"); 00930 00931 if (cpl_frameset_count_tags(frameset, "MASTER_LINECAT") == 0) 00932 fors_pmos_calib_exit("Missing required input: MASTER_LINECAT"); 00933 00934 if (cpl_frameset_count_tags(frameset, "MASTER_LINECAT") > 1) 00935 fors_pmos_calib_exit("Too many in input: MASTER_LINECAT"); 00936 00937 /* 00938 if (cpl_frameset_count_tags(frameset, master_distortion_tag) == 0) 00939 fors_pmos_calib_exit("Missing required input: MASTER_DISTORTION_TABLE"); 00940 */ 00941 00942 if (cpl_frameset_count_tags(frameset, master_distortion_tag) > 1) 00943 fors_pmos_calib_exit("Too many in input: MASTER_DISTORTION_TABLE"); 00944 00945 nflats = cpl_frameset_count_tags(frameset, flat_tag); 00946 00947 if (nflats < 1) { 00948 cpl_msg_error(recipe, "Missing required input: %s", flat_tag); 00949 fors_pmos_calib_exit(NULL); 00950 } 00951 00952 cpl_msg_indent_less(); 00953 00954 if (nflats > 1) 00955 cpl_msg_info(recipe, "Load %d flat field frames and stack them " 00956 "with method \"%s\"", nflats, stack_method); 00957 else 00958 cpl_msg_info(recipe, "Load flat field exposure..."); 00959 00960 cpl_msg_indent_more(); 00961 00962 header = dfs_load_header(frameset, flat_tag, 0); 00963 00964 if (header == NULL) 00965 fors_pmos_calib_exit("Cannot load flat field frame header"); 00966 00967 alltime = cpl_propertylist_get_double(header, "EXPTIME"); 00968 00969 if (cpl_error_get_code() != CPL_ERROR_NONE) 00970 fors_pmos_calib_exit("Missing keyword EXPTIME in flat field " 00971 "frame header"); 00972 00973 cpl_propertylist_delete(header); 00974 00975 for (i = 1; i < nflats; i++) { 00976 00977 header = dfs_load_header(frameset, NULL, 0); 00978 00979 if (header == NULL) 00980 fors_pmos_calib_exit("Cannot load flat field frame header"); 00981 00982 alltime += cpl_propertylist_get_double(header, "EXPTIME"); 00983 00984 if (cpl_error_get_code() != CPL_ERROR_NONE) 00985 fors_pmos_calib_exit("Missing keyword EXPTIME in flat field " 00986 "frame header"); 00987 00988 cpl_propertylist_delete(header); 00989 00990 } 00991 00992 if (bagoo) { 00993 char *montecarlo = getenv("MONTECARLO"); 00994 00995 if (montecarlo) 00996 doit = atoi(montecarlo); 00997 00998 if (doit) { 00999 master_bias = dfs_load_image(frameset, "MASTER_BIAS", 01000 CPL_TYPE_FLOAT, 0, 1); 01001 if (master_bias == NULL) 01002 fors_pmos_calib_exit("Cannot load master bias"); 01003 01004 blevel = cpl_image_get_mean(master_bias); 01005 01006 cpl_image_delete(master_bias); 01007 } 01008 } 01009 01010 master_flat = dfs_load_image(frameset, flat_tag, CPL_TYPE_FLOAT, 0, 0); 01011 01012 if (master_flat == NULL) 01013 fors_pmos_calib_exit("Cannot load flat field"); 01014 01015 if (doit) { 01016 header = dfs_load_header(frameset, flat_tag, 0); 01017 01018 gain = cpl_propertylist_get_double(header, "ESO DET OUT1 CONAD"); 01019 01020 if (cpl_error_get_code() != CPL_ERROR_NONE) 01021 fors_pmos_calib_exit("Missing keyword ESO DET OUT1 CONAD " 01022 "in flat field frame header"); 01023 01024 ron = cpl_propertylist_get_double(header, "ESO DET OUT1 RON"); 01025 01026 if (cpl_error_get_code() != CPL_ERROR_NONE) 01027 fors_pmos_calib_exit("Missing keyword ESO DET OUT1 RON " 01028 "in flat field frame header"); 01029 01030 cpl_propertylist_delete(header); 01031 01032 ron /= gain; // RON converted from electrons to ADU 01033 01034 mos_randomise_image(master_flat, ron, gain, blevel); 01035 } 01036 01037 ny = cpl_image_get_size_y(master_flat); 01038 01039 if (nflats > 1) { 01040 if (strcmp(stack_method, "average") == 0) { 01041 for (i = 1; i < nflats; i++) { 01042 flat = dfs_load_image(frameset, NULL, CPL_TYPE_FLOAT, 0, 0); 01043 if (flat) { 01044 if (doit) { 01045 mos_randomise_image(flat, ron, gain, blevel); 01046 } 01047 cpl_image_add(master_flat, flat); 01048 cpl_image_delete(flat); flat = NULL; 01049 } 01050 else 01051 fors_pmos_calib_exit("Cannot load flat field"); 01052 } 01053 01054 /*** 01055 if (nflats > 1) 01056 cpl_image_divide_scalar(master_flat, nflats); 01057 ***/ 01058 01059 } 01060 else { 01061 cpl_imagelist *flatlist = NULL; 01062 double rflux, flux; 01063 01064 added_flat = cpl_image_duplicate(master_flat); 01065 01066 flatlist = cpl_imagelist_new(); 01067 cpl_imagelist_set(flatlist, master_flat, 01068 cpl_imagelist_get_size(flatlist)); 01069 01070 /* 01071 * Stacking with rejection requires normalization 01072 * at the same flux. We normalise according to mean 01073 * flux. This is equivalent to determining the 01074 * flux ratio for each image as the average of the 01075 * flux ratio of all pixels weighted on the actual 01076 * flux of each pixel. 01077 */ 01078 01079 rflux = cpl_image_get_mean(master_flat); 01080 01081 for (i = 1; i < nflats; i++) { 01082 flat = dfs_load_image(frameset, NULL, CPL_TYPE_FLOAT, 0, 0); 01083 if (flat) { 01084 if (doit) { 01085 mos_randomise_image(flat, ron, gain, blevel); 01086 } 01087 cpl_image_add(added_flat, flat); 01088 flux = cpl_image_get_mean(flat); 01089 cpl_image_multiply_scalar(flat, rflux / flux); 01090 cpl_imagelist_set(flatlist, flat, 01091 cpl_imagelist_get_size(flatlist)); 01092 } 01093 else { 01094 fors_pmos_calib_exit("Cannot load flat field"); 01095 } 01096 } 01097 01098 if (strcmp(stack_method, "median") == 0) { 01099 master_flat = cpl_imagelist_collapse_median_create(flatlist); 01100 } 01101 01102 if (strcmp(stack_method, "minmax") == 0) { 01103 master_flat = cpl_imagelist_collapse_minmax_create(flatlist, 01104 min_reject, 01105 max_reject); 01106 } 01107 01108 if (strcmp(stack_method, "ksigma") == 0) { 01109 master_flat = mos_ksigma_stack(flatlist, 01110 klow, khigh, kiter, NULL); 01111 } 01112 } 01113 } 01114 01115 01116 /* 01117 * Get the reference wavelength and the rebin factor along the 01118 * dispersion direction from the arc lamp exposure 01119 */ 01120 01121 header = dfs_load_header(frameset, arc_tag, 0); 01122 01123 if (header == NULL) 01124 fors_pmos_calib_exit("Cannot load arc lamp header"); 01125 01126 instrume = (char *)cpl_propertylist_get_string(header, "INSTRUME"); 01127 if (instrume == NULL) 01128 fors_pmos_calib_exit("Missing keyword INSTRUME in arc lamp header"); 01129 01130 instrume = cpl_strdup(instrume); 01131 01132 if (instrume[4] == '1') 01133 snprintf(version, 80, "%s/%s", "fors1", VERSION); 01134 if (instrume[4] == '2') 01135 snprintf(version, 80, "%s/%s", "fors2", VERSION); 01136 01137 reference = cpl_propertylist_get_double(header, "ESO INS GRIS1 WLEN"); 01138 01139 if (cpl_error_get_code() != CPL_ERROR_NONE) 01140 fors_pmos_calib_exit("Missing keyword ESO INS GRIS1 WLEN in arc lamp " 01141 "frame header"); 01142 01143 if (reference < 3000.0) /* Perhaps in nanometers... */ 01144 reference *= 10; 01145 01146 if (reference < 3000.0 || reference > 13000.0) { 01147 cpl_msg_error(recipe, "Invalid central wavelength %.2f read from " 01148 "keyword ESO INS GRIS1 WLEN in arc lamp frame header", 01149 reference); 01150 fors_pmos_calib_exit(NULL); 01151 } 01152 01153 cpl_msg_info(recipe, "The central wavelength is: %.2f", reference); 01154 01155 rebin = cpl_propertylist_get_int(header, "ESO DET WIN1 BINX"); 01156 01157 if (cpl_error_get_code() != CPL_ERROR_NONE) 01158 fors_pmos_calib_exit("Missing keyword ESO DET WIN1 BINX in arc lamp " 01159 "frame header"); 01160 01161 if (rebin != 1) { 01162 dispersion *= rebin; 01163 cpl_msg_warning(recipe, "The rebin factor is %d, and therefore the " 01164 "working dispersion used is %f A/pixel", rebin, 01165 dispersion); 01166 } 01167 01168 gain = cpl_propertylist_get_double(header, "ESO DET OUT1 CONAD"); 01169 01170 if (cpl_error_get_code() != CPL_ERROR_NONE) 01171 fors_pmos_calib_exit("Missing keyword ESO DET OUT1 CONAD in arc lamp " 01172 "frame header"); 01173 01174 cpl_msg_info(recipe, "The gain factor is: %.2f e-/ADU", gain); 01175 01176 if (pmos) { 01177 cpl_msg_info(recipe, "Produce mask slit position table..."); 01178 01179 maskslits = mos_load_slits_fors_mos(header); 01180 01181 /* 01182 * Check if all slits have the same X offset: in such case, 01183 * treat the observation as a long-slit one! 01184 */ 01185 01186 mxpos = cpl_table_get_column_median(maskslits, "xtop"); 01187 xpos = cpl_table_get_data_double(maskslits, "xtop"); 01188 nslits = cpl_table_get_nrow(maskslits); 01189 01190 same_offset = 1; 01191 for (i = 0; i < nslits; i++) { 01192 if (fabs(mxpos-xpos[i]) > 0.01) { 01193 same_offset = 0; 01194 break; 01195 } 01196 } 01197 01198 if (same_offset) { 01199 cpl_msg_info(recipe, "All slits have same offset: %.2f", mxpos); 01200 } 01201 else { 01202 cpl_msg_info(recipe, "All slits have different offsets"); 01203 } 01204 01205 if (ny != 400 && ny != 500) { 01206 if (cpl_frameset_count_tags(frameset, 01207 master_distortion_tag) == 0) 01208 fors_pmos_calib_exit( 01209 "Missing required input: MASTER_DISTORTION_TABLE"); 01210 01211 header_dist = dfs_load_header(frameset, 01212 master_distortion_tag, 0); 01213 rebin_dist = cpl_propertylist_get_int(header_dist, 01214 "ESO DET WIN1 BINX"); 01215 cpl_propertylist_delete(header_dist); 01216 } 01217 } 01218 01219 /* Leave the header on for the next step... */ 01220 01221 01222 /* 01223 * Remove the master bias 01224 */ 01225 01226 if (nbias) { 01227 01228 /* 01229 * Set of raw BIASes in input, need to create master bias! 01230 */ 01231 01232 cpl_msg_info(recipe, "Generate the master from input raw biases..."); 01233 01234 if (nbias > 1) { 01235 01236 biases = cpl_imagelist_new(); 01237 01238 bias = dfs_load_image(frameset, "BIAS", CPL_TYPE_FLOAT, 0, 0); 01239 01240 if (bias == NULL) 01241 fors_pmos_calib_exit("Cannot load bias frame"); 01242 01243 cpl_imagelist_set(biases, bias, 0); 01244 01245 for (i = 1; i < nbias; i++) { 01246 bias = dfs_load_image(frameset, NULL, CPL_TYPE_FLOAT, 0, 0); 01247 if (bias) 01248 cpl_imagelist_set(biases, bias, i); 01249 else 01250 fors_pmos_calib_exit("Cannot load bias frame"); 01251 } 01252 01253 master_bias = cpl_imagelist_collapse_median_create(biases); 01254 01255 cpl_imagelist_delete(biases); 01256 } 01257 else { 01258 master_bias = dfs_load_image(frameset, "BIAS", 01259 CPL_TYPE_FLOAT, 0, 1); 01260 if (master_bias == NULL) 01261 fors_pmos_calib_exit("Cannot load bias"); 01262 } 01263 01264 } 01265 else { 01266 master_bias = dfs_load_image(frameset, "MASTER_BIAS", 01267 CPL_TYPE_FLOAT, 0, 1); 01268 if (master_bias == NULL) 01269 fors_pmos_calib_exit("Cannot load master bias"); 01270 } 01271 01272 cpl_msg_info(recipe, "Remove the master bias..."); 01273 01274 overscans = mos_load_overscans_fors(header); 01275 cpl_propertylist_delete(header); header = NULL; 01276 01277 if (nbias) { 01278 int xlow = cpl_table_get_int(overscans, "xlow", 0, NULL); 01279 int ylow = cpl_table_get_int(overscans, "ylow", 0, NULL); 01280 int xhig = cpl_table_get_int(overscans, "xhig", 0, NULL); 01281 int yhig = cpl_table_get_int(overscans, "yhig", 0, NULL); 01282 dummy = cpl_image_extract(master_bias, xlow+1, ylow+1, xhig, yhig); 01283 cpl_image_delete(master_bias); master_bias = dummy; 01284 01285 if (dfs_save_image(frameset, master_bias, "MASTER_BIAS", 01286 NULL, parlist, recipe, version)) 01287 fors_pmos_calib_exit(NULL); 01288 } 01289 01290 if (nflats > 1) { 01291 multi_bias = cpl_image_multiply_scalar_create(master_bias, nflats); 01292 dummy = mos_remove_bias(master_flat, multi_bias, overscans); 01293 if (added_flat) 01294 add_dummy = mos_remove_bias(added_flat, multi_bias, overscans); 01295 cpl_image_delete(multi_bias); 01296 } 01297 else { 01298 dummy = mos_remove_bias(master_flat, master_bias, overscans); 01299 } 01300 cpl_image_delete(master_flat); 01301 master_flat = dummy; 01302 01303 if (master_flat == NULL) 01304 fors_pmos_calib_exit("Cannot remove bias from flat field"); 01305 01306 if (added_flat) { 01307 cpl_image_delete(added_flat); 01308 added_flat = add_dummy; 01309 01310 if (added_flat == NULL) 01311 fors_pmos_calib_exit("Cannot remove bias from added flat field"); 01312 01313 trace_flat = added_flat; 01314 } 01315 else 01316 trace_flat = master_flat; 01317 01318 wavelengths = dfs_load_table(frameset, "MASTER_LINECAT", 1); 01319 01320 if (wavelengths == NULL) 01321 fors_pmos_calib_exit("Cannot load line catalog"); 01322 01323 /* 01324 * Cast the wavelengths into a (double precision) CPL vector 01325 */ 01326 01327 nlines = cpl_table_get_nrow(wavelengths); 01328 01329 if (nlines == 0) 01330 fors_pmos_calib_exit("Empty input line catalog"); 01331 01332 if (cpl_table_has_column(wavelengths, wcolumn) != 1) { 01333 cpl_msg_error(recipe, "Missing column %s in input line catalog table", 01334 wcolumn); 01335 fors_pmos_calib_exit(NULL); 01336 } 01337 01338 line = cpl_malloc(nlines * sizeof(double)); 01339 01340 for (i = 0; i < nlines; i++) 01341 line[i] = cpl_table_get(wavelengths, wcolumn, i, NULL); 01342 01343 lines = cpl_vector_wrap(nlines, line); 01344 01345 for (j = 0; j < pmos; j++) { 01346 int k; 01347 01348 cpl_msg_indent_less(); 01349 cpl_msg_info(recipe, "Processing arc lamp nb %d out of %d ...", 01350 j + 1, pmos); 01351 cpl_msg_indent_more(); 01352 01353 cpl_msg_info(recipe, "Load arc lamp exposure..."); 01354 cpl_msg_indent_more(); 01355 01356 spectra = dfs_load_image(frameset, arc_tag, CPL_TYPE_FLOAT, 0, 0); 01357 01358 /* 01359 * FIXME: Horrible workaround to avoid the problem because of the 01360 * multiple encapsulation of cpl_frameset_find() in different 01361 * loading functions 01362 */ 01363 for (k = 0; k < j; k ++) { 01364 cpl_image_delete(spectra); 01365 spectra = dfs_load_image(frameset, NULL, CPL_TYPE_FLOAT, 0, 0); 01366 } 01367 01368 if (spectra == NULL) 01369 fors_pmos_calib_exit("Cannot load arc lamp exposure"); 01370 01371 if (doit) { 01372 mos_randomise_image(spectra, ron, gain, blevel); 01373 } 01374 01375 cpl_msg_info(recipe, "Remove the master bias..."); 01376 01377 dummy = mos_remove_bias(spectra, master_bias, overscans); 01378 cpl_image_delete(spectra); spectra = dummy; 01379 01380 if (spectra == NULL) 01381 fors_pmos_calib_exit("Cannot remove bias from arc lamp exposure"); 01382 01383 cpl_msg_indent_less(); 01384 cpl_msg_info(recipe, "Load input line catalog..."); 01385 cpl_msg_indent_more(); 01386 01387 /* 01388 * Here the PMOS calibration is carried out. 01389 */ 01390 01391 if (mos_saturation_process(spectra)) 01392 fors_pmos_calib_exit("Cannot process saturation"); 01393 01394 if (mos_subtract_background(spectra)) 01395 fors_pmos_calib_exit("Cannot subtract the background"); 01396 01397 if (!j) { 01398 /* 01399 * Detecting spectra on the CCD 01400 */ 01401 01402 cpl_msg_indent_less(); 01403 cpl_msg_info(recipe, "Detecting spectra on CCD..."); 01404 cpl_msg_indent_more(); 01405 01406 ccd_xsize = nx = cpl_image_get_size_x(spectra); 01407 ccd_ysize = ny = cpl_image_get_size_y(spectra); 01408 01409 refmask = cpl_mask_new(nx, ny); 01410 01411 checkwave = 01412 mos_wavelength_calibration_raw(spectra, lines, dispersion, 01413 peakdetection, wradius, 01414 wdegree, wreject, reference, 01415 &startwavelength, &endwavelength, 01416 NULL, NULL, NULL, NULL, NULL, 01417 NULL, refmask); 01418 01419 if (checkwave == NULL) 01420 fors_pmos_calib_exit("Wavelength calibration failure."); 01421 01422 /* 01423 * Save check image to disk 01424 */ 01425 01426 header = cpl_propertylist_new(); 01427 cpl_propertylist_update_double(header, "CRPIX1", 1.0); 01428 cpl_propertylist_update_double(header, "CRPIX2", 1.0); 01429 cpl_propertylist_update_double(header, "CRVAL1", 01430 startwavelength + dispersion/2); 01431 cpl_propertylist_update_double(header, "CRVAL2", 1.0); 01432 /* cpl_propertylist_update_double(header, "CDELT1", dispersion); 01433 cpl_propertylist_update_double(header, "CDELT2", 1.0); */ 01434 cpl_propertylist_update_double(header, "CD1_1", dispersion); 01435 cpl_propertylist_update_double(header, "CD1_2", 0.0); 01436 cpl_propertylist_update_double(header, "CD2_1", 0.0); 01437 cpl_propertylist_update_double(header, "CD2_2", 1.0); 01438 cpl_propertylist_update_string(header, "CTYPE1", "LINEAR"); 01439 cpl_propertylist_update_string(header, "CTYPE2", "PIXEL"); 01440 01441 if (check) { 01442 if (!j) { 01443 if(dfs_save_image_null(frameset, parlist, 01444 spectra_detection_tag, 01445 recipe, version)) { 01446 fors_pmos_calib_exit(NULL); 01447 } 01448 } 01449 01450 if (dfs_save_image_ext(checkwave, 01451 spectra_detection_tag, header)) { 01452 fors_pmos_calib_exit(NULL); 01453 } 01454 } 01455 01456 cpl_image_delete(checkwave); checkwave = NULL; 01457 cpl_propertylist_delete(header); header = NULL; 01458 01459 if (cpl_mask_is_empty(refmask)) 01460 fors_pmos_calib_exit("Wavelength calibration failure."); 01461 01462 if (mos_refmask_find_gaps(refmask, trace_flat, -1.0)) 01463 fors_pmos_calib_exit("The gaps could not be found"); 01464 01465 cpl_msg_info(recipe, 01466 "Locate slits at reference wavelength on CCD..."); 01467 slits = mos_locate_spectra(refmask); 01468 01469 if (!slits) { 01470 cpl_msg_error(cpl_error_get_where(), cpl_error_get_message()); 01471 fors_pmos_calib_exit("No slits could be detected!"); 01472 } 01473 01474 if (same_offset) { 01475 if (ny != 400 && ny != 500) { 01476 float rescale = (float) rebin_dist / rebin; 01477 if (mos_check_slits(slits, rescale)) { 01478 fors_pmos_calib_exit("Some slits are missing. " 01479 "Cannot recover!"); 01480 } 01481 } 01482 } 01483 01484 refimage = cpl_image_new_from_mask(refmask); 01485 cpl_mask_delete(refmask); refmask = NULL; 01486 01487 if (check) { 01488 if (!j) { 01489 if(dfs_save_image_null(frameset, parlist, 01490 slit_map_tag, 01491 recipe, version)) { 01492 fors_pmos_calib_exit(NULL); 01493 } 01494 } 01495 01496 save_header = dfs_load_header(frameset, arc_tag, 0); 01497 01498 for (k = 0; k < j; k ++) { 01499 cpl_propertylist_delete(save_header); 01500 save_header = dfs_load_header(frameset, NULL, 0); 01501 } 01502 01503 if (dfs_save_image_ext(refimage, slit_map_tag, save_header)) { 01504 fors_pmos_calib_exit(NULL); 01505 } 01506 cpl_propertylist_delete(save_header); save_header = NULL; 01507 } 01508 01509 cpl_image_delete(refimage); refimage = NULL; 01510 01511 // if (same_offset == 0) { 01512 01513 same_offset = 1; // Added, see next line comment. 01514 if (0) { // This part is eliminated: a successful 01515 // pattern matching would identify just 01516 // one of the two beams!!! It needs to be FIXED. 01517 01518 /* 01519 * Attempt slit identification: this recipe may continue even 01520 * in case of failed identification (i.e., the position table 01521 * is not produced, but an error is not set). In case of 01522 * failure, the spectra would be still extracted, even if they 01523 * would not be associated to slits on the mask. 01524 * 01525 * The reason for making the slit identification an user option 01526 * (via the parameter slit_ident) is to offer the possibility 01527 * to avoid identifications that are only apparently successful 01528 * as it would happen in the case of an incorrect slit 01529 * description in the data header. 01530 */ 01531 01532 cpl_msg_indent_less(); 01533 cpl_msg_info(recipe, 01534 "Attempt slit identification (optional)..."); 01535 cpl_msg_indent_more(); 01536 01537 positions = mos_identify_slits(slits, maskslits, NULL); 01538 01539 if (positions) { 01540 cpl_table_delete(slits); 01541 slits = positions; 01542 01543 /* 01544 * Eliminate slits which are not _entirely_ inside the CCD 01545 */ 01546 01547 cpl_table_and_selected_double(slits, 01548 "ytop", CPL_GREATER_THAN, ny); 01549 cpl_table_or_selected_double(slits, 01550 "ybottom", CPL_LESS_THAN, 0); 01551 cpl_table_erase_selected(slits); 01552 01553 nslits = cpl_table_get_nrow(slits); 01554 01555 if (nslits == 0) 01556 fors_pmos_calib_exit("No slits found on the CCD"); 01557 01558 cpl_msg_info(recipe, 01559 "%d slits are entirely contained in CCD", 01560 nslits); 01561 } 01562 else { 01563 same_offset = 1; /* FIXLANDER slit_ident = 0; */ 01564 cpl_msg_info(recipe, 01565 "Global distortion model cannot be computed"); 01566 if (cpl_error_get_code() != CPL_ERROR_NONE) { 01567 fors_pmos_calib_exit(NULL); 01568 } 01569 } 01570 } 01571 01572 01573 if (ny == 400 || ny == 500) { 01574 01575 /* 01576 * For the FORS1 special case (old chip 2048x400 readout) 01577 * keep the central slits only 01578 */ 01579 01580 nslits = cpl_table_get_nrow(slits); 01581 01582 if (nslits > 4) { 01583 cpl_table_unselect_all(slits); 01584 for (k = 0; k < cpl_table_get_nrow(slits); k++) { 01585 double jump = cpl_table_get(slits, "ytop", k, NULL) 01586 - cpl_table_get(slits, "ybottom", k, NULL); 01587 if (jump < 50.) { 01588 cpl_table_select_row(slits, k); 01589 } 01590 } 01591 cpl_table_erase_selected(slits); 01592 nslits = cpl_table_get_nrow(slits); 01593 } 01594 01595 if (nslits == 0) 01596 fors_pmos_calib_exit("No slits found on the CCD"); 01597 01598 if (nslits == 4) { 01599 cpl_table_unselect_all(slits); 01600 cpl_table_select_row(slits, 0); 01601 cpl_table_select_row(slits, cpl_table_get_nrow(slits)-1); 01602 cpl_table_erase_selected(slits); 01603 } 01604 01605 cpl_msg_info(recipe, 01606 "%d slits are entirely contained in CCD", nslits); 01607 } 01608 else { 01609 cpl_table_unselect_all(slits); 01610 for (k = 0; k < cpl_table_get_nrow(slits); k++) { 01611 double jump = cpl_table_get(slits, "ytop", k, NULL) 01612 - cpl_table_get(slits, "ybottom", k, NULL); 01613 if (jump < 10.) { 01614 cpl_table_select_row(slits, k); 01615 } 01616 } 01617 cpl_table_erase_selected(slits); 01618 nslits = cpl_table_get_nrow(slits); 01619 } 01620 01621 01622 /* 01623 * Determination of spectral curvature 01624 */ 01625 01626 cpl_msg_indent_less(); 01627 cpl_msg_info(recipe, "Determining spectral curvature..."); 01628 cpl_msg_indent_more(); 01629 01630 cpl_msg_info(recipe, "Tracing master flat field spectra edges..."); 01631 traces = mos_trace_flat(trace_flat, slits, reference, 01632 startwavelength, endwavelength, dispersion); 01633 01634 if (!traces) 01635 fors_pmos_calib_exit("Tracing failure"); 01636 01637 cpl_image_delete(added_flat); added_flat = NULL; 01638 01639 cpl_msg_info(recipe, "Fitting flat field spectra edges..."); 01640 polytraces = mos_poly_trace(slits, traces, cdegree); 01641 01642 if (!polytraces) 01643 fors_pmos_calib_exit("Trace fitting failure"); 01644 01645 if (cmode) { 01646 cpl_msg_info(recipe, 01647 "Computing global spectral curvature model..."); 01648 mos_global_trace(slits, polytraces, cmode); 01649 } 01650 01651 if (!j) { 01652 if(dfs_save_image_null(frameset, parlist, curv_traces_tag, 01653 recipe, version)) { 01654 fors_pmos_calib_exit(NULL); 01655 } 01656 } 01657 01658 if (dfs_save_table_ext(traces, curv_traces_tag, NULL)) { 01659 fors_pmos_calib_exit(NULL); 01660 } 01661 01662 cpl_table_delete(traces); traces = NULL; 01663 01664 coordinate = cpl_image_new(nx, ny, CPL_TYPE_FLOAT); 01665 01666 } 01667 // 01668 spatial = mos_spatial_calibration(spectra, slits, polytraces, 01669 reference, 01670 startwavelength, endwavelength, 01671 dispersion, 0, j ? NULL: coordinate); 01672 01673 if (!j) { 01674 // 01675 if (same_offset) { /* FIXLANDER It was !slit_ident */ 01676 cpl_image_delete(spectra); spectra = NULL; 01677 } 01678 01679 /* 01680 * Flat field normalisation is done directly on the master flat 01681 * field (without spatial rectification first). The spectral 01682 * curvature model may be provided in input, in future releases. 01683 */ 01684 01685 cpl_msg_indent_less(); 01686 cpl_msg_info(recipe, "Perform flat field normalisation..."); 01687 cpl_msg_indent_more(); 01688 01689 norm_flat = cpl_image_duplicate(master_flat); 01690 01691 smo_flat = mos_normalise_flat(norm_flat, coordinate, slits, 01692 polytraces, reference, 01693 startwavelength, endwavelength, 01694 dispersion, dradius, ddegree); 01695 01696 /* This may be a product */ 01697 cpl_image_delete(smo_flat); smo_flat = NULL; 01698 01699 01700 save_header = dfs_load_header(frameset, flat_tag, 0); 01701 cpl_propertylist_update_int(save_header, "ESO PRO DATANCOM", 01702 nflats); 01703 01704 rect_flat = mos_spatial_calibration(master_flat, slits, polytraces, 01705 reference, startwavelength, 01706 endwavelength, dispersion, 0, 01707 NULL); 01708 rect_nflat = mos_spatial_calibration(norm_flat, slits, polytraces, 01709 reference, startwavelength, 01710 endwavelength, dispersion, 0, 01711 NULL); 01712 01713 01714 if (dfs_save_image(frameset, master_flat, master_screen_flat_tag, 01715 save_header, parlist, recipe, version)) 01716 fors_pmos_calib_exit(NULL); 01717 01718 01719 if (dfs_save_image(frameset, norm_flat, master_norm_flat_tag, 01720 save_header, parlist, recipe, version)) 01721 fors_pmos_calib_exit(NULL); 01722 01723 cpl_image_delete(norm_flat); norm_flat = NULL; 01724 cpl_propertylist_delete(save_header); save_header = NULL; 01725 01726 } 01727 01728 01729 /* 01730 * Final wavelength calibration of spectra having their curvature 01731 * removed 01732 */ 01733 01734 cpl_msg_indent_less(); 01735 cpl_msg_info(recipe, "Perform final wavelength calibration..."); 01736 cpl_msg_indent_more(); 01737 01738 nx = cpl_image_get_size_x(spatial); 01739 ny = cpl_image_get_size_y(spatial); 01740 01741 idscoeff = cpl_table_new(ny); 01742 restable = cpl_table_new(nlines); 01743 rainbow = cpl_image_new(nx, ny, CPL_TYPE_FLOAT); 01744 if (check) 01745 residual = cpl_image_new(nx, ny, CPL_TYPE_FLOAT); 01746 fiterror = cpl_calloc(ny, sizeof(double)); 01747 fitlines = cpl_calloc(ny, sizeof(int)); 01748 01749 rectified = mos_wavelength_calibration_final(spatial, slits, lines, 01750 dispersion, peakdetection, 01751 wradius, wdegree, wreject, 01752 reference, 01753 &startwavelength, 01754 &endwavelength, fitlines, 01755 fiterror, idscoeff, 01756 rainbow, 01757 residual, restable); 01758 01759 if (rectified == NULL) 01760 fors_pmos_calib_exit("Wavelength calibration failure."); 01761 01762 if (!j) { 01763 if(dfs_save_image_null(frameset, parlist, disp_residuals_table_tag, 01764 recipe, version)) { 01765 fors_pmos_calib_exit(NULL); 01766 } 01767 } 01768 01769 header = dfs_load_header(frameset, arc_tag, 0); 01770 01771 for (k = 0; k < j; k ++) { 01772 cpl_propertylist_delete(header); 01773 header = dfs_load_header(frameset, NULL, 0); 01774 } 01775 01776 if (dfs_save_table_ext(restable, disp_residuals_table_tag, header)) { 01777 fors_pmos_calib_exit(NULL); 01778 } 01779 01780 cpl_propertylist_delete(header); 01781 01782 cpl_table_delete(restable); restable = NULL; 01783 01784 cpl_table_wrap_double(idscoeff, fiterror, "error"); fiterror = NULL; 01785 cpl_table_set_column_unit(idscoeff, "error", "pixel"); 01786 cpl_table_wrap_int(idscoeff, fitlines, "nlines"); fitlines = NULL; 01787 01788 for (i = 0; i < ny; i++) 01789 if (!cpl_table_is_valid(idscoeff, "c0", i)) 01790 cpl_table_set_invalid(idscoeff, "error", i); 01791 01792 delta = mos_map_pixel(idscoeff, reference, startwavelength, 01793 endwavelength, dispersion, 2); 01794 01795 header = dfs_load_header(frameset, arc_tag, 0); 01796 01797 for (k = 0; k < j; k ++) { 01798 cpl_propertylist_delete(header); 01799 header = dfs_load_header(frameset, NULL, 0); 01800 } 01801 01802 cpl_propertylist_update_double(header, "CRPIX1", 1.0); 01803 cpl_propertylist_update_double(header, "CRPIX2", 1.0); 01804 cpl_propertylist_update_double(header, "CRVAL1", 01805 startwavelength + dispersion/2); 01806 cpl_propertylist_update_double(header, "CRVAL2", 1.0); 01807 /* cpl_propertylist_update_double(header, "CDELT1", dispersion); 01808 cpl_propertylist_update_double(header, "CDELT2", 1.0); */ 01809 cpl_propertylist_update_double(header, "CD1_1", dispersion); 01810 cpl_propertylist_update_double(header, "CD1_2", 0.0); 01811 cpl_propertylist_update_double(header, "CD2_1", 0.0); 01812 cpl_propertylist_update_double(header, "CD2_2", 1.0); 01813 cpl_propertylist_update_string(header, "CTYPE1", "LINEAR"); 01814 cpl_propertylist_update_string(header, "CTYPE2", "PIXEL"); 01815 01816 if (!j) { 01817 if(dfs_save_image_null(frameset, parlist, delta_image_tag, 01818 recipe, version)) { 01819 fors_pmos_calib_exit(NULL); 01820 } 01821 } 01822 01823 if (dfs_save_image_ext(delta, delta_image_tag, header)) { 01824 fors_pmos_calib_exit(NULL); 01825 } 01826 01827 cpl_image_delete(delta); delta = NULL; 01828 cpl_propertylist_delete(header); header = NULL; 01829 01830 mean_rms = mos_distortions_rms(rectified, lines, startwavelength, 01831 dispersion, 6, 0); 01832 01833 cpl_msg_info(recipe, "Mean residual: %f pixel", mean_rms); 01834 01835 mean_rms = cpl_table_get_column_mean(idscoeff, "error"); 01836 mean_rms_err = cpl_table_get_column_stdev(idscoeff, "error"); 01837 01838 cpl_msg_info(recipe, "Mean model accuracy: %f pixel (%f A)", 01839 mean_rms, mean_rms * dispersion); 01840 01841 restab = mos_resolution_table(rectified, startwavelength, dispersion, 01842 60000, lines); 01843 01844 if (restab) { 01845 cpl_msg_info(recipe, "Mean spectral resolution: %.2f", 01846 cpl_table_get_column_mean(restab, "resolution")); 01847 cpl_msg_info(recipe, 01848 "Mean reference lines FWHM: %.2f +/- %.2f pixel", 01849 cpl_table_get_column_mean(restab, "fwhm") / dispersion, 01850 cpl_table_get_column_mean(restab, "fwhm_rms") / dispersion); 01851 01852 cpl_table_duplicate_column(restab, "dlambda", 01853 restab, "fwhm"); 01854 cpl_table_multiply_scalar(restab, "dlambda", dispersion); 01855 cpl_table_duplicate_column(restab, "dlambda_rms", 01856 restab, "fwhm_rms"); 01857 cpl_table_multiply_scalar(restab, "dlambda_rms", dispersion); 01858 01859 if (qc) { 01860 01861 header = dfs_load_header(frameset, arc_tag, 0); 01862 01863 for (k = 0; k < j; k ++) { 01864 cpl_propertylist_delete(header); 01865 header = dfs_load_header(frameset, NULL, 0); 01866 } 01867 01868 if (header == NULL) 01869 fors_pmos_calib_exit("Cannot reload arc lamp header"); 01870 01871 qclist = cpl_propertylist_new(); 01872 01873 fors_qc_start_group(qclist, "2.0", instrume); 01874 01875 01876 /* 01877 * QC1 group header 01878 */ 01879 01880 if (fors_qc_write_string("PRO.CATG", spectral_resolution_tag, 01881 "Product category", instrume)) 01882 fors_pmos_calib_exit("Cannot write product category to " 01883 "QC log file"); 01884 01885 if (fors_qc_keyword_to_paf(header, "ESO DPR TYPE", NULL, 01886 "DPR type", instrume)) 01887 fors_pmos_calib_exit("Missing keyword DPR TYPE in arc " 01888 "lamp header"); 01889 01890 if (fors_qc_keyword_to_paf(header, "ESO TPL ID", NULL, 01891 "Template", instrume)) 01892 fors_pmos_calib_exit("Missing keyword TPL ID in arc " 01893 "lamp header"); 01894 01895 if (fors_qc_keyword_to_paf(header, "ESO INS GRIS1 NAME", NULL, 01896 "Grism name", instrume)) 01897 fors_pmos_calib_exit("Missing keyword INS GRIS1 NAME in " 01898 "arc lamp header"); 01899 01900 if (fors_qc_keyword_to_paf(header, "ESO INS GRIS1 ID", NULL, 01901 "Grism identifier", instrume)) 01902 fors_pmos_calib_exit("Missing keyword INS GRIS1 ID in arc " 01903 "lamp header"); 01904 01905 if (cpl_propertylist_has(header, "ESO INS FILT1 NAME")) 01906 fors_qc_keyword_to_paf(header, "ESO INS FILT1 NAME", NULL, 01907 "Filter name", instrume); 01908 01909 if (fors_qc_keyword_to_paf(header, "ESO INS COLL NAME", NULL, 01910 "Collimator name", instrume)) 01911 fors_pmos_calib_exit("Missing keyword INS COLL NAME in arc " 01912 "lamp header"); 01913 01914 if (fors_qc_keyword_to_paf(header, "ESO DET CHIP1 ID", NULL, 01915 "Chip identifier", instrume)) 01916 fors_pmos_calib_exit("Missing keyword DET CHIP1 ID in arc " 01917 "lamp header"); 01918 01919 if (fors_qc_keyword_to_paf(header, "ARCFILE", NULL, 01920 "Archive name of input data", 01921 instrume)) 01922 fors_pmos_calib_exit("Missing keyword ARCFILE in arc " 01923 "lamp header"); 01924 01925 cpl_propertylist_delete(header); header = NULL; 01926 01927 pipefile = dfs_generate_filename_tfits(spectral_resolution_tag); 01928 if (fors_qc_write_string("PIPEFILE", pipefile, 01929 "Pipeline product name", instrume)) 01930 fors_pmos_calib_exit("Cannot write PIPEFILE to QC logfile"); 01931 cpl_free(pipefile); pipefile = NULL; 01932 01933 01934 /* 01935 * QC1 parameters 01936 */ 01937 01938 keyname = "QC.PMOS.RESOLUTION"; 01939 01940 if (fors_qc_write_qc_double(qclist, 01941 cpl_table_get_column_mean(restab, 01942 "resolution"), 01943 keyname, 01944 "Angstrom", 01945 "Mean spectral resolution", 01946 instrume)) { 01947 fors_pmos_calib_exit("Cannot write mean spectral " 01948 "resolution to QC log file"); 01949 } 01950 01951 keyname = "QC.PMOS.RESOLUTION.RMS"; 01952 01953 if (fors_qc_write_qc_double(qclist, 01954 cpl_table_get_column_stdev(restab, 01955 "resolution"), 01956 keyname, 01957 "Angstrom", 01958 "Scatter of spectral resolution", 01959 instrume)) { 01960 fors_pmos_calib_exit("Cannot write spectral resolution " 01961 "scatter to QC log file"); 01962 } 01963 01964 keyname = "QC.PMOS.RESOLUTION.NWAVE"; 01965 01966 if (fors_qc_write_qc_int(qclist, cpl_table_get_nrow(restab) - 01967 cpl_table_count_invalid(restab, 01968 "resolution"), 01969 keyname, 01970 NULL, 01971 "Number of examined wavelengths " 01972 "for resolution computation", 01973 instrume)) { 01974 fors_pmos_calib_exit("Cannot write number of lines used " 01975 "in spectral resolution computation " 01976 "to QC log file"); 01977 } 01978 01979 keyname = "QC.PMOS.RESOLUTION.MEANRMS"; 01980 01981 if (fors_qc_write_qc_double(qclist, 01982 cpl_table_get_column_mean(restab, 01983 "resolution_rms"), 01984 keyname, NULL, 01985 "Mean error on spectral " 01986 "resolution computation", 01987 instrume)) { 01988 fors_pmos_calib_exit("Cannot write mean error in " 01989 "spectral resolution computation " 01990 "to QC log file"); 01991 } 01992 01993 keyname = "QC.PMOS.RESOLUTION.NLINES"; 01994 01995 if (fors_qc_write_qc_int(qclist, 01996 cpl_table_get_column_mean(restab, 01997 "nlines") * 01998 cpl_table_get_nrow(restab), 01999 keyname, NULL, 02000 "Number of lines for spectral " 02001 "resolution computation", 02002 instrume)) { 02003 fors_pmos_calib_exit("Cannot write number of examined " 02004 "wavelengths in spectral resolution " 02005 "computation to QC log file"); 02006 } 02007 02008 fors_qc_end_group(); 02009 02010 } 02011 02012 if (!j) { 02013 if(dfs_save_image_null(frameset, parlist, 02014 spectral_resolution_tag, 02015 recipe, version)) { 02016 fors_pmos_calib_exit(NULL); 02017 } 02018 } 02019 02020 header = dfs_load_header(frameset, arc_tag, 0); 02021 02022 for (k = 0; k < j; k ++) { 02023 cpl_propertylist_delete(header); 02024 header = dfs_load_header(frameset, NULL, 0); 02025 } 02026 02027 cpl_propertylist_append(header, qclist); 02028 02029 if (dfs_save_table_ext(restab, spectral_resolution_tag, header)) { 02030 fors_pmos_calib_exit(NULL); 02031 } 02032 02033 cpl_table_delete(restab); restab = NULL; 02034 cpl_propertylist_delete(qclist); qclist = NULL; 02035 cpl_propertylist_delete(header); header = NULL; 02036 02037 } 02038 else 02039 fors_pmos_calib_exit("Cannot compute the spectral " 02040 "resolution table"); 02041 02042 if (!j) { 02043 if(dfs_save_image_null(frameset, parlist, disp_coeff_tag, 02044 recipe, version)) { 02045 fors_pmos_calib_exit(NULL); 02046 } 02047 } 02048 02049 header = dfs_load_header(frameset, arc_tag, 0); 02050 02051 for (k = 0; k < j; k ++) { 02052 cpl_propertylist_delete(header); 02053 header = dfs_load_header(frameset, NULL, 0); 02054 } 02055 02056 if (dfs_save_table_ext(idscoeff, disp_coeff_tag, header)) { 02057 fors_pmos_calib_exit(NULL); 02058 } 02059 02060 cpl_propertylist_delete(header); 02061 02062 if (!j) { 02063 mapped_flat = mos_wavelength_calibration(rect_flat, reference, 02064 startwavelength, 02065 endwavelength, 02066 dispersion, idscoeff, 0); 02067 02068 mapped_nflat = mos_wavelength_calibration(rect_nflat, reference, 02069 startwavelength, 02070 endwavelength, 02071 dispersion, idscoeff, 0); 02072 02073 cpl_image_delete(rect_flat); rect_flat = NULL; 02074 cpl_image_delete(rect_nflat); rect_nflat = NULL; 02075 } 02076 02077 /* Global removed */ 02078 02079 cpl_table_delete(idscoeff); idscoeff = NULL; 02080 02081 header = dfs_load_header(frameset, arc_tag, 0); 02082 02083 for (k = 0; k < j; k ++) { 02084 cpl_propertylist_delete(header); 02085 header = dfs_load_header(frameset, NULL, 0); 02086 } 02087 02088 cpl_propertylist_update_double(header, "CRPIX1", 1.0); 02089 cpl_propertylist_update_double(header, "CRPIX2", 1.0); 02090 cpl_propertylist_update_double(header, "CRVAL1", 02091 startwavelength + dispersion/2); 02092 cpl_propertylist_update_double(header, "CRVAL2", 1.0); 02093 /* cpl_propertylist_update_double(header, "CDELT1", dispersion); 02094 cpl_propertylist_update_double(header, "CDELT2", 1.0); */ 02095 cpl_propertylist_update_double(header, "CD1_1", dispersion); 02096 cpl_propertylist_update_double(header, "CD1_2", 0.0); 02097 cpl_propertylist_update_double(header, "CD2_1", 0.0); 02098 cpl_propertylist_update_double(header, "CD2_2", 1.0); 02099 cpl_propertylist_update_string(header, "CTYPE1", "LINEAR"); 02100 cpl_propertylist_update_string(header, "CTYPE2", "PIXEL"); 02101 cpl_propertylist_update_int(header, "ESO PRO DATANCOM", 1); 02102 02103 if (!j) { 02104 if(dfs_save_image_null(frameset, parlist, reduced_lamp_tag, 02105 recipe, version)) { 02106 fors_pmos_calib_exit(NULL); 02107 } 02108 } 02109 02110 if (dfs_save_image_ext(rectified, reduced_lamp_tag, header)) { 02111 fors_pmos_calib_exit(NULL); 02112 } 02113 02114 cpl_image_delete(rectified); rectified = NULL; 02115 02116 cpl_propertylist_update_int(header, "ESO PRO DATANCOM", nflats); 02117 02118 if (!j) { 02119 if (dfs_save_image(frameset, mapped_flat, mapped_screen_flat_tag, 02120 header, parlist, recipe, version)) 02121 fors_pmos_calib_exit(NULL); 02122 cpl_image_delete(mapped_flat); mapped_flat = NULL; 02123 02124 if (dfs_save_image(frameset, mapped_nflat, mapped_norm_flat_tag, 02125 header, parlist, recipe, version)) 02126 fors_pmos_calib_exit(NULL); 02127 cpl_image_delete(mapped_nflat); mapped_nflat = NULL; 02128 } 02129 02130 cpl_propertylist_delete(header); header = NULL; 02131 02132 if (check) { 02133 save_header = dfs_load_header(frameset, arc_tag, 0); 02134 for (k = 0; k < j; k ++) { 02135 cpl_propertylist_delete(save_header); 02136 save_header = dfs_load_header(frameset, NULL, 0); 02137 } 02138 02139 cpl_propertylist_update_double(save_header, "CRPIX2", 1.0); 02140 cpl_propertylist_update_double(save_header, "CRVAL2", 1.0); 02141 /* cpl_propertylist_update_double(save_header, "CDELT2", 1.0); */ 02142 cpl_propertylist_update_double(save_header, "CD1_1", 1.0); 02143 cpl_propertylist_update_double(save_header, "CD1_2", 0.0); 02144 cpl_propertylist_update_double(save_header, "CD2_1", 0.0); 02145 cpl_propertylist_update_double(save_header, "CD2_2", 1.0); 02146 cpl_propertylist_update_string(save_header, "CTYPE1", "LINEAR"); 02147 cpl_propertylist_update_string(save_header, "CTYPE2", "PIXEL"); 02148 02149 if (!j) { 02150 if(dfs_save_image_null(frameset, parlist, disp_residuals_tag, 02151 recipe, version)) { 02152 fors_pmos_calib_exit(NULL); 02153 } 02154 } 02155 02156 if (dfs_save_image_ext(residual, disp_residuals_tag, save_header)) { 02157 fors_pmos_calib_exit(NULL); 02158 } 02159 02160 cpl_image_delete(residual); residual = NULL; 02161 cpl_propertylist_delete(save_header); save_header = NULL; 02162 } 02163 02164 wavemap = mos_map_wavelengths(coordinate, rainbow, slits, polytraces, 02165 reference, startwavelength, endwavelength, 02166 dispersion); 02167 02168 cpl_image_delete(rainbow); rainbow = NULL; 02169 02170 save_header = dfs_load_header(frameset, arc_tag, 0); 02171 02172 for (k = 0; k < j; k ++) { 02173 cpl_propertylist_delete(save_header); 02174 save_header = dfs_load_header(frameset, NULL, 0); 02175 } 02176 02177 if (qc) { 02178 fors_qc_start_group(save_header, "2.0", instrume); 02179 02180 /* 02181 * QC1 group header 02182 */ 02183 02184 if (fors_qc_write_string("PRO.CATG", wavelength_map_tag, 02185 "Product category", instrume)) 02186 fors_pmos_calib_exit("Cannot write product category to " 02187 "QC log file"); 02188 02189 if (fors_qc_keyword_to_paf(save_header, "ESO DPR TYPE", NULL, 02190 "DPR type", instrume)) 02191 fors_pmos_calib_exit("Missing keyword DPR TYPE in arc " 02192 "lamp header"); 02193 02194 if (fors_qc_keyword_to_paf(save_header, "ESO TPL ID", NULL, 02195 "Template", instrume)) 02196 fors_pmos_calib_exit("Missing keyword TPL ID in arc " 02197 "lamp header"); 02198 02199 if (fors_qc_keyword_to_paf(save_header, "ESO INS GRIS1 NAME", NULL, 02200 "Grism name", instrume)) 02201 fors_pmos_calib_exit("Missing keyword INS GRIS1 NAME in arc " 02202 "lamp header"); 02203 02204 if (fors_qc_keyword_to_paf(save_header, "ESO INS GRIS1 ID", NULL, 02205 "Grism identifier", instrume)) 02206 fors_pmos_calib_exit("Missing keyword INS GRIS1 ID in arc " 02207 "lamp header"); 02208 02209 if (cpl_propertylist_has(save_header, "ESO INS FILT1 NAME")) 02210 fors_qc_keyword_to_paf(save_header, "ESO INS FILT1 NAME", NULL, 02211 "Filter name", instrume); 02212 02213 if (fors_qc_keyword_to_paf(save_header, "ESO INS COLL NAME", NULL, 02214 "Collimator name", instrume)) 02215 fors_pmos_calib_exit("Missing keyword INS COLL NAME in arc " 02216 "lamp header"); 02217 02218 if (fors_qc_keyword_to_paf(save_header, "ESO DET CHIP1 ID", NULL, 02219 "Chip identifier", instrume)) 02220 fors_pmos_calib_exit("Missing keyword DET CHIP1 ID in arc " 02221 "lamp header"); 02222 02223 if (fors_qc_keyword_to_paf(save_header, "ESO DET WIN1 BINX", NULL, 02224 "Binning factor along X", instrume)) 02225 fors_pmos_calib_exit("Missing keyword ESO DET WIN1 BINX " 02226 "in frame header"); 02227 02228 if (fors_qc_keyword_to_paf(save_header, "ESO DET WIN1 BINY", NULL, 02229 "Binning factor along Y", instrume)) 02230 fors_pmos_calib_exit("Missing keyword ESO DET WIN1 BINY " 02231 "in frame header"); 02232 02233 if (fors_qc_keyword_to_paf(save_header, "ARCFILE", NULL, 02234 "Archive name of input data", 02235 instrume)) 02236 fors_pmos_calib_exit("Missing keyword ARCFILE in arc " 02237 "lamp header"); 02238 02239 pipefile = dfs_generate_filename(wavelength_map_tag); 02240 if (fors_qc_write_string("PIPEFILE", pipefile, 02241 "Pipeline product name", instrume)) 02242 fors_pmos_calib_exit("Cannot write PIPEFILE to QC log file"); 02243 cpl_free(pipefile); pipefile = NULL; 02244 02245 02246 /* 02247 * QC1 parameters 02248 */ 02249 02250 if (fors_qc_write_qc_double(save_header, 02251 mean_rms, 02252 "QC.WAVE.ACCURACY", 02253 "pixel", 02254 "Mean accuracy of wavecalib model", 02255 instrume)) { 02256 fors_pmos_calib_exit("Cannot write mean wavelength calibration " 02257 "accuracy to QC log file"); 02258 } 02259 02260 02261 if (fors_qc_write_qc_double(save_header, 02262 mean_rms_err, 02263 "QC.WAVE.ACCURACY.ERROR", 02264 "pixel", 02265 "Error on accuracy of wavecalib model", 02266 instrume)) { 02267 fors_pmos_calib_exit("Cannot write error on wavelength " 02268 "calibration accuracy to QC log file"); 02269 } 02270 02271 if (same_offset && fabs(mxpos) < 0.05) { 02272 /* Only if same offset is 0.0 */ 02273 02274 data = cpl_image_get_data(wavemap); 02275 02276 if (fors_qc_write_qc_double(save_header, 02277 data[nx/2 + ccd_ysize*nx/2], 02278 "QC.PMOS.CENTRAL.WAVELENGTH", 02279 "Angstrom", 02280 "Wavelength at CCD center", 02281 instrume)) { 02282 fors_pmos_calib_exit("Cannot write central wavelength " 02283 "to QC log file"); 02284 } 02285 } 02286 02287 fors_qc_end_group(); 02288 02289 } 02290 02291 if (!j) { 02292 if(dfs_save_image_null(frameset, parlist, wavelength_map_tag, 02293 recipe, version)) { 02294 fors_pmos_calib_exit(NULL); 02295 } 02296 } 02297 02298 if (dfs_save_image_ext(wavemap, wavelength_map_tag, save_header)) { 02299 fors_pmos_calib_exit(NULL); 02300 } 02301 02302 cpl_image_delete(wavemap); wavemap = NULL; 02303 02304 cpl_propertylist_erase_regexp(save_header, "^ESO QC ", 0); 02305 02306 cpl_propertylist_delete(save_header); save_header = NULL; 02307 02308 cpl_msg_indent_less(); 02309 02310 } 02311 02312 if (dfs_save_image(frameset, coordinate, spatial_map_tag, save_header, 02313 parlist, recipe, version)) 02314 fors_pmos_calib_exit(NULL); 02315 02316 cpl_image_delete(coordinate); coordinate = NULL; 02317 cpl_propertylist_delete(save_header); save_header = NULL; 02318 02319 header = NULL; 02320 02321 if (qc) { 02322 02323 double maxpos, maxneg, maxcurve, maxslope; 02324 02325 header = dfs_load_header(frameset, arc_tag, 0); 02326 02327 fors_qc_start_group(header, "2.0", instrume); 02328 02329 /* 02330 * QC1 group header 02331 */ 02332 02333 if (fors_qc_write_string("PRO.CATG", curv_coeff_tag, 02334 "Product category", instrume)) 02335 fors_pmos_calib_exit("Cannot write product category to " 02336 "QC log file"); 02337 02338 if (fors_qc_keyword_to_paf(header, "ESO DPR TYPE", NULL, 02339 "DPR type", instrume)) 02340 fors_pmos_calib_exit("Missing keyword DPR TYPE in arc " 02341 "lamp header"); 02342 02343 if (fors_qc_keyword_to_paf(header, "ESO TPL ID", NULL, 02344 "Template", instrume)) 02345 fors_pmos_calib_exit("Missing keyword TPL ID in arc " 02346 "lamp header"); 02347 if (fors_qc_keyword_to_paf(header, "ARCFILE", NULL, 02348 "Archive name of input data", 02349 instrume)) 02350 fors_pmos_calib_exit("Missing keyword ARCFILE in arc " 02351 "lamp header"); 02352 02353 pipefile = dfs_generate_filename(curv_coeff_tag); 02354 if (fors_qc_write_string("PIPEFILE", pipefile, 02355 "Pipeline product name", instrume)) 02356 fors_pmos_calib_exit("Cannot write PIPEFILE to QC log file"); 02357 cpl_free(pipefile); pipefile = NULL; 02358 02359 /* 02360 * QC1 parameters 02361 */ 02362 02363 maxpos = fabs(cpl_table_get_column_max(polytraces, "c2")); 02364 maxneg = fabs(cpl_table_get_column_min(polytraces, "c2")); 02365 maxcurve = maxpos > maxneg ? maxpos : maxneg; 02366 if (fors_qc_write_qc_double(header, 02367 maxcurve, 02368 "QC.TRACE.MAX.CURVATURE", 02369 "Y pixel / X pixel ^2", 02370 "Max observed curvature in spectral tracing", 02371 instrume)) { 02372 fors_pmos_calib_exit("Cannot write max observed curvature in " 02373 "spectral tracing to QC log file"); 02374 } 02375 02376 maxpos = fabs(cpl_table_get_column_max(polytraces, "c1")); 02377 maxneg = fabs(cpl_table_get_column_min(polytraces, "c1")); 02378 maxslope = maxpos > maxneg ? maxpos : maxneg; 02379 02380 if (fors_qc_write_qc_double(header, 02381 maxslope, 02382 "QC.TRACE.MAX.SLOPE", 02383 "Y pixel / X pixel", 02384 "Max observed slope in spectral tracing", 02385 instrume)) { 02386 fors_pmos_calib_exit("Cannot write max observed slope in spectral " 02387 "tracing to QC log file"); 02388 } 02389 02390 fors_qc_end_group(); 02391 } 02392 02393 if (dfs_save_table(frameset, polytraces, curv_coeff_tag, header, 02394 parlist, recipe, version)) { 02395 fors_pmos_calib_exit(NULL); 02396 } 02397 02398 cpl_propertylist_delete(header); header = NULL; 02399 cpl_table_delete(polytraces); polytraces = NULL; 02400 02401 /* FIXLANDER It was slit_ident == 0 and 02402 it was in a different place above in the code */ 02403 02404 if (same_offset) { 02405 cpl_table *globaltbl; 02406 cpl_table *slitpos; 02407 double *l_ytop; 02408 int *l_id; 02409 int npairs; 02410 double *ytop = cpl_table_get_data_double(slits, "ytop"); 02411 double *ybot = cpl_table_get_data_double(slits, "ybottom"); 02412 int k; 02413 // int *p_id; 02414 02415 /* Just in case it has been modified */ 02416 nslits = cpl_table_get_nrow(slits); 02417 02418 cpl_table_new_column(slits, "pair_id", CPL_TYPE_INT); 02419 // p_id = cpl_table_get_data_int(slits, "pair_id"); 02420 02421 if (ccd_ysize == 400 || ccd_ysize == 500) { 02422 02423 /* 02424 * Special case with old FORS1 chip 02425 */ 02426 02427 l_ytop = cpl_malloc(sizeof(double)); 02428 l_ytop[0] = 255.0; 02429 l_id = cpl_malloc(sizeof(double)); 02430 l_id[0] = 10; 02431 npairs = 1; 02432 } 02433 else { 02434 globaltbl = dfs_load_table(frameset, master_distortion_tag, 1); 02435 slitpos = mos_build_slit_location(globaltbl, maskslits, ccd_ysize); 02436 l_ytop = cpl_table_get_data_double(slitpos, "ytop"); 02437 l_id = cpl_table_get_data_int(slitpos, "slit_id"); 02438 npairs = cpl_table_get_nrow(slitpos); 02439 if (rebin_dist != rebin) { 02440 float rescale = (float)rebin_dist / rebin; 02441 for (i = 0; i < npairs; i++) { 02442 l_ytop[i] *= rescale; 02443 } 02444 } 02445 } 02446 02447 for (k = 0; k < npairs; k++) { 02448 int h; 02449 02450 for (h = 0; h < nslits; h++) { 02451 02452 if (l_ytop[k] < ytop[h] && l_ytop[k] > ybot[h]) { 02453 if (h + 1 < nslits) { 02454 cpl_table_set_int(slits, "pair_id", h, l_id[k]); 02455 cpl_table_set_int(slits, "pair_id", h + 1, l_id[k]); 02456 } 02457 } 02458 } 02459 } 02460 02461 /* %%% */ 02462 02463 cpl_table_fill_invalid_int(slits, "pair_id", -1); 02464 02465 if (ccd_ysize == 400 || ccd_ysize == 500) { 02466 cpl_free(l_ytop); 02467 cpl_free(l_id); 02468 } 02469 else { 02470 cpl_table_delete(slitpos); slitpos = NULL; 02471 cpl_table_delete(globaltbl); globaltbl = NULL; 02472 02473 cpl_table_delete(maskslits); maskslits = NULL; 02474 } 02475 } 02476 02477 if (dfs_save_table(frameset, slits, slit_location_tag, NULL, 02478 parlist, recipe, version)) { 02479 fors_pmos_calib_exit(NULL); 02480 } 02481 02482 cpl_table_delete(slits); slits = NULL; 02483 02484 cpl_image_delete(spatial); spatial = NULL; 02485 02486 cpl_free(instrume); instrume = NULL; 02487 02488 cpl_table_delete(overscans); overscans = NULL; 02489 cpl_image_delete(master_bias); master_bias = NULL; 02490 cpl_image_delete(master_flat); master_flat = NULL; 02491 02492 cpl_table_delete(wavelengths); wavelengths = NULL; 02493 cpl_vector_delete(lines); lines = NULL; 02494 02495 if (cpl_error_get_code()) { 02496 cpl_msg_error(cpl_error_get_where(), cpl_error_get_message()); 02497 fors_pmos_calib_exit(NULL); 02498 } 02499 02500 return 0; 02501 }