FORS Pipeline Reference Manual 4.9.9
|
00001 /* $Id: vimos_science.c,v 1.22 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.22 $ 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 <vimos_science_impl.h> 00035 #include <cpl.h> 00036 #include <moses.h> 00037 #include <fors_stack.h> 00038 #include <fors_tools.h> 00039 #include <fors_dfs.h> 00040 #include <fors_qc.h> 00041 00042 static int vimos_science_create(cpl_plugin *); 00043 static int vimos_science_exec(cpl_plugin *); 00044 static int vimos_science_destroy(cpl_plugin *); 00045 static int vimos_science(cpl_parameterlist *, cpl_frameset *); 00046 00047 static char vimos_science_description[] = 00048 "This recipe is used to reduce scientific spectra using the extraction\n" 00049 "mask and the products created by the recipe vimos_calib. The spectra are\n" 00050 "bias subtracted, flat fielded (if a normalised flat field is specified)\n" 00051 "and remapped eliminating the optical distortions. The wavelength calibration\n" 00052 "can be optionally upgraded using a number of sky lines: if no sky lines\n" 00053 "catalog of wavelengths is specified, an internal one is used instead.\n" 00054 "If the alignment to the sky lines is performed, the input dispersion\n" 00055 "coefficients table is upgraded and saved to disk, and a new CCD wavelengths\n" 00056 "map is created. A grism table (typically depending on the grism used)\n" 00057 "may also be specified: this table contains a default recipe parameter\n" 00058 "setting to control the way spectra are extracted for a specific instrument\n" 00059 "mode, as it is used for automatic run of the pipeline on Paranal and in\n" 00060 "Garching. If this table is specified, it will modify the default recipe\n" 00061 "parameter setting, with the exception of those parameters which have been\n" 00062 "explicitly modifyed on the command line. If a grism table is not specified,\n" 00063 "the input recipe parameters values will always be read from the command\n" 00064 "line, or from an esorex configuration file if present, or from their\n" 00065 "generic default values (that are rarely meaningful).\n" 00066 "MOS_SLIT_LOCATION and MOS_CURV_COEFF tables are not (yet) expected for\n" 00067 "long-slit-like data.\n" 00068 "Only in case of a standard star exposure input, the atmospheric extinction\n" 00069 "table and a table with the physical fluxes of the observed standard star\n" 00070 "must be specified in input.\n\n" 00071 "Input files:\n\n" 00072 " DO category: Type: Explanation: Required:\n" 00073 " MOS_SCIENCE Raw Scientific exposure Y\n" 00074 " or MOS_STANDARD Raw Standard star exposure Y\n" 00075 "\n" 00076 " MASTER_BIAS Calib Master bias Y\n" 00077 " SKY_LINE_CATALOG Calib Sky lines catalog .\n" 00078 " MOS_MASTER_SCREEN_FLAT Calib Normalised flat field .\n" 00079 " MOS_DISP_COEFF Calib Inverse dispersion Y\n" 00080 " MOS_CURV_COEFF Calib Spectral curvature Y\n" 00081 " MOS_SLIT_LOCATION Calib Slits positions table Y\n" 00082 " GRISM_TABLE Calib Grism table .\n" 00083 "\n" 00084 " In case MOS_STANDARD is specified in input,\n" 00085 "\n" 00086 " EXTINCT_TABLE Calib Atmospheric extinction Y\n" 00087 " STD_FLUX_TABLE Calib Standard star flux Y\n" 00088 "\n" 00089 "Output files:\n\n" 00090 " DO category: Data type: Explanation:\n" 00091 " MOS_SCIENCE_REDUCED FITS image Extracted scientific spectra\n" 00092 " or MOS_STANDARD_REDUCED FITS image Extracted standard star spectrum\n" 00093 " MOS_SKY_REDUCED FITS image Extracted sky spectra\n" 00094 " MOS_ERROR_REDUCED FITS image Errors on extracted spectra\n" 00095 "\n" 00096 " MOS_UNMAPPED_SCIENCE FITS image Sky subtracted scientific spectra\n" 00097 " or MOS_UNMAPPED_STANDARD FITS image Sky subtracted standard spectrum\n" 00098 "\n" 00099 " MOS_SCIENCE_EXTRACTED FITS image Rectified scientific spectra\n" 00100 " or MOS_STANDARD_EXTRACTED FITS image Rectified standard star spectrum\n" 00101 "\n" 00102 " MOS_SCIENCE_SKY_EXTRACTED FITS image Rectified science spectra with sky\n" 00103 "or MOS_STANDARD_SKY_EXTRACTED FITS image Rectified std spectrum with sky\n" 00104 "\n" 00105 " MOS_SCIENCE_SKY FITS image Rectified sky spectra\n" 00106 " MOS_UNMAPPED_SKY FITS image Sky on CCD\n" 00107 " MOS_GLOBAL_SKY_SPECTRUM FITS table Global sky spectrum\n" 00108 " OBJECT_TABLE FITS table Positions of detected objects\n" 00109 "\n" 00110 " Only if the sky-alignment of the wavelength solution is requested:\n" 00111 " MOS_SKYLINES_OFFSETS_LONG FITS table Sky lines offsets (LSS-like data)\n" 00112 "or MOS_SKYLINES_OFFSETS_SLIT FITS table Sky lines offsets (MOS-like data)\n" 00113 " MOS_DISP_COEFF_SKY FITS table Upgraded dispersion coefficients\n" 00114 " MOS_WAVELENGTH_MAP_SKY FITS image Upgraded wavelength map\n" 00115 "\n" 00116 " Only if a MOS_STANDARD is specified in input:\n" 00117 " MOS_SPECPHOT_TABLE FITS table Efficiency and response curves\n\n"; 00118 00130 int cpl_plugin_get_info(cpl_pluginlist *list) 00131 { 00132 cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe ); 00133 cpl_plugin *plugin = &recipe->interface; 00134 00135 cpl_plugin_init(plugin, 00136 CPL_PLUGIN_API, 00137 FORS_BINARY_VERSION, 00138 CPL_PLUGIN_TYPE_RECIPE, 00139 "vimos_science", 00140 "Extraction of scientific spectra", 00141 vimos_science_description, 00142 "Carlo Izzo", 00143 PACKAGE_BUGREPORT, 00144 "This file is currently part of the FORS Instrument Pipeline\n" 00145 "Copyright (C) 2002-2010 European Southern Observatory\n\n" 00146 "This program is free software; you can redistribute it and/or modify\n" 00147 "it under the terms of the GNU General Public License as published by\n" 00148 "the Free Software Foundation; either version 2 of the License, or\n" 00149 "(at your option) any later version.\n\n" 00150 "This program is distributed in the hope that it will be useful,\n" 00151 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" 00152 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" 00153 "GNU General Public License for more details.\n\n" 00154 "You should have received a copy of the GNU General Public License\n" 00155 "along with this program; if not, write to the Free Software Foundation,\n" 00156 "Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\n", 00157 vimos_science_create, 00158 vimos_science_exec, 00159 vimos_science_destroy); 00160 00161 cpl_pluginlist_append(list, plugin); 00162 00163 return 0; 00164 } 00165 00166 00177 static int vimos_science_create(cpl_plugin *plugin) 00178 { 00179 cpl_recipe *recipe; 00180 cpl_parameter *p; 00181 00182 00183 /* 00184 * Check that the plugin is part of a valid recipe 00185 */ 00186 00187 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00188 recipe = (cpl_recipe *)plugin; 00189 else 00190 return -1; 00191 00192 /* 00193 * Create the parameters list in the cpl_recipe object 00194 */ 00195 00196 recipe->parameters = cpl_parameterlist_new(); 00197 00198 00199 /* 00200 * Dispersion 00201 */ 00202 00203 p = cpl_parameter_new_value("fors.vimos_science.dispersion", 00204 CPL_TYPE_DOUBLE, 00205 "Resampling step (Angstrom/pixel)", 00206 "fors.vimos_science", 00207 0.0); 00208 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "dispersion"); 00209 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00210 cpl_parameterlist_append(recipe->parameters, p); 00211 00212 /* 00213 * Sky lines alignment 00214 */ 00215 00216 p = cpl_parameter_new_value("fors.vimos_science.skyalign", 00217 CPL_TYPE_INT, 00218 "Polynomial order for sky lines alignment, " 00219 "or -1 to avoid alignment", 00220 "fors.vimos_science", 00221 0); 00222 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "skyalign"); 00223 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00224 cpl_parameterlist_append(recipe->parameters, p); 00225 00226 /* 00227 * Line catalog table column containing the sky reference wavelengths 00228 */ 00229 00230 p = cpl_parameter_new_value("fors.vimos_science.wcolumn", 00231 CPL_TYPE_STRING, 00232 "Name of sky line catalog table column " 00233 "with wavelengths", 00234 "fors.vimos_science", 00235 "WLEN"); 00236 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcolumn"); 00237 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00238 cpl_parameterlist_append(recipe->parameters, p); 00239 00240 /* 00241 * Start wavelength for spectral extraction 00242 */ 00243 00244 p = cpl_parameter_new_value("fors.vimos_science.startwavelength", 00245 CPL_TYPE_DOUBLE, 00246 "Start wavelength in spectral extraction", 00247 "fors.vimos_science", 00248 0.0); 00249 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "startwavelength"); 00250 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00251 cpl_parameterlist_append(recipe->parameters, p); 00252 00253 /* 00254 * End wavelength for spectral extraction 00255 */ 00256 00257 p = cpl_parameter_new_value("fors.vimos_science.endwavelength", 00258 CPL_TYPE_DOUBLE, 00259 "End wavelength in spectral extraction", 00260 "fors.vimos_science", 00261 0.0); 00262 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "endwavelength"); 00263 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00264 cpl_parameterlist_append(recipe->parameters, p); 00265 00266 /* 00267 * Reference wavelength for wavelength calibration 00268 */ 00269 00270 p = cpl_parameter_new_value("fors.vimos_science.reference", 00271 CPL_TYPE_DOUBLE, 00272 "Reference wavelength for calibration", 00273 "fors.vimos_science", 00274 0.0); 00275 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "reference"); 00276 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00277 cpl_parameterlist_append(recipe->parameters, p); 00278 00279 /* 00280 * Flux conservation 00281 */ 00282 00283 p = cpl_parameter_new_value("fors.vimos_science.flux", 00284 CPL_TYPE_BOOL, 00285 "Apply flux conservation", 00286 "fors.vimos_science", 00287 TRUE); 00288 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "flux"); 00289 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00290 cpl_parameterlist_append(recipe->parameters, p); 00291 00292 /* 00293 * Apply flat field 00294 */ 00295 00296 p = cpl_parameter_new_value("fors.vimos_science.flatfield", 00297 CPL_TYPE_BOOL, 00298 "Apply flat field", 00299 "fors.vimos_science", 00300 TRUE); 00301 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "flatfield"); 00302 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00303 cpl_parameterlist_append(recipe->parameters, p); 00304 00305 /* 00306 * Global sky subtraction 00307 */ 00308 00309 p = cpl_parameter_new_value("fors.vimos_science.skyglobal", 00310 CPL_TYPE_BOOL, 00311 "Subtract global sky spectrum from CCD", 00312 "fors.vimos_science", 00313 FALSE); 00314 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "skyglobal"); 00315 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00316 cpl_parameterlist_append(recipe->parameters, p); 00317 00318 /* 00319 * Local sky subtraction on extracted spectra 00320 */ 00321 00322 p = cpl_parameter_new_value("fors.vimos_science.skymedian", 00323 CPL_TYPE_BOOL, 00324 "Sky subtraction from extracted slit spectra", 00325 "fors.vimos_science", 00326 FALSE); 00327 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "skymedian"); 00328 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00329 cpl_parameterlist_append(recipe->parameters, p); 00330 00331 /* 00332 * Local sky subtraction on CCD spectra 00333 */ 00334 00335 p = cpl_parameter_new_value("fors.vimos_science.skylocal", 00336 CPL_TYPE_BOOL, 00337 "Sky subtraction from CCD slit spectra", 00338 "fors.vimos_science", 00339 TRUE); 00340 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "skylocal"); 00341 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00342 cpl_parameterlist_append(recipe->parameters, p); 00343 00344 /* 00345 * Cosmic rays removal 00346 */ 00347 00348 p = cpl_parameter_new_value("fors.vimos_science.cosmics", 00349 CPL_TYPE_BOOL, 00350 "Eliminate cosmic rays hits (only if global " 00351 "or local sky subtraction is also requested)", 00352 "fors.vimos_science", 00353 TRUE); 00354 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "cosmics"); 00355 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00356 cpl_parameterlist_append(recipe->parameters, p); 00357 00358 /* 00359 * Slit margin 00360 */ 00361 00362 p = cpl_parameter_new_value("fors.vimos_science.slit_margin", 00363 CPL_TYPE_INT, 00364 "Number of pixels to exclude at each slit " 00365 "in object detection and extraction", 00366 "fors.vimos_science", 00367 3); 00368 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "slit_margin"); 00369 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00370 cpl_parameterlist_append(recipe->parameters, p); 00371 00372 /* 00373 * Extraction radius 00374 */ 00375 00376 p = cpl_parameter_new_value("fors.vimos_science.ext_radius", 00377 CPL_TYPE_INT, 00378 "Maximum extraction radius for detected " 00379 "objects (pixel)", 00380 "fors.vimos_science", 00381 6); 00382 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "ext_radius"); 00383 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00384 cpl_parameterlist_append(recipe->parameters, p); 00385 00386 /* 00387 * Contamination radius 00388 */ 00389 00390 p = cpl_parameter_new_value("fors.vimos_science.cont_radius", 00391 CPL_TYPE_INT, 00392 "Minimum distance at which two objects " 00393 "of equal luminosity do not contaminate " 00394 "each other (pixel)", 00395 "fors.vimos_science", 00396 0); 00397 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "cont_radius"); 00398 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00399 cpl_parameterlist_append(recipe->parameters, p); 00400 00401 /* 00402 * Object extraction method 00403 */ 00404 00405 p = cpl_parameter_new_value("fors.vimos_science.ext_mode", 00406 CPL_TYPE_INT, 00407 "Object extraction method: 0 = aperture, " 00408 "1 = Horne optimal extraction", 00409 "fors.vimos_science", 00410 1); 00411 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "ext_mode"); 00412 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00413 cpl_parameterlist_append(recipe->parameters, p); 00414 00415 /* 00416 * Normalise output by exposure time 00417 */ 00418 00419 p = cpl_parameter_new_value("fors.vimos_science.time_normalise", 00420 CPL_TYPE_BOOL, 00421 "Normalise output spectra by the exposure time", 00422 "fors.vimos_science", 00423 TRUE); 00424 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "time_normalise"); 00425 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00426 cpl_parameterlist_append(recipe->parameters, p); 00427 00428 /* 00429 * Look for a standard star in any frame classified as MOS_STANDARD 00430 */ 00431 00432 p = cpl_parameter_new_value("fors.vimos_science.anyframe", 00433 CPL_TYPE_BOOL, 00434 "Look for a standard star in any frame " 00435 "classified as MOS_STANDARD", 00436 "fors.vimos_science", 00437 FALSE); 00438 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "anyframe"); 00439 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00440 cpl_parameterlist_append(recipe->parameters, p); 00441 00442 00443 /* 00444 * Order of polynomial modeling the instrument response. 00445 */ 00446 00447 p = cpl_parameter_new_value("fors.vimos_science.response", 00448 CPL_TYPE_INT, 00449 "Order of polynomial modeling the " 00450 "instrument response", 00451 "fors.vimos_science", 00452 5); 00453 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "response"); 00454 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00455 cpl_parameterlist_append(recipe->parameters, p); 00456 00457 00458 /* 00459 * Type of alignment of dithered frames 00460 */ 00461 00462 p = cpl_parameter_new_enum("fors.vimos_science.alignment", 00463 CPL_TYPE_STRING, 00464 "Type of alignment of dithered frames, " 00465 "either to the nearest neighbour pixel " 00466 "or to fractions of pixel", 00467 "fors.vimos_science", 00468 "integer", 2, 00469 "integer", "float"); 00470 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "alignment"); 00471 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00472 cpl_parameterlist_append(recipe->parameters, p); 00473 00474 00475 /* 00476 * Stacking method of dithered frames 00477 */ 00478 00479 fors_stack_define_parameters(recipe->parameters, 00480 "fors.vimos_science", "average"); 00481 00482 00483 /* 00484 * Fringing correction 00485 */ 00486 00487 p = cpl_parameter_new_value("fors.vimos_science.fringing", 00488 CPL_TYPE_BOOL, 00489 "Apply fringing correction " 00490 "(only for dithered observations)", 00491 "fors.vimos_science", 00492 TRUE); 00493 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "fringing"); 00494 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00495 cpl_parameterlist_append(recipe->parameters, p); 00496 00497 00498 /* 00499 * Computation of QC1 parameters 00500 */ 00501 00502 p = cpl_parameter_new_value("fors.vimos_science.qc", 00503 CPL_TYPE_BOOL, 00504 "Compute QC1 parameters", 00505 "fors.vimos_science", 00506 TRUE); 00507 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "qc"); 00508 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00509 cpl_parameterlist_append(recipe->parameters, p); 00510 00511 00512 return 0; 00513 } 00514 00515 00524 static int vimos_science_exec(cpl_plugin *plugin) 00525 { 00526 cpl_recipe *recipe; 00527 00528 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00529 recipe = (cpl_recipe *)plugin; 00530 else 00531 return -1; 00532 00533 return vimos_science(recipe->parameters, recipe->frames); 00534 } 00535 00536 00545 static int vimos_science_destroy(cpl_plugin *plugin) 00546 { 00547 cpl_recipe *recipe; 00548 00549 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00550 recipe = (cpl_recipe *)plugin; 00551 else 00552 return -1; 00553 00554 cpl_parameterlist_delete(recipe->parameters); 00555 00556 return 0; 00557 } 00558 00559 00569 static int vimos_science(cpl_parameterlist *parlist, cpl_frameset *frameset) 00570 { 00571 const char *science_tag = "MOS_SCIENCE"; 00572 int mos = cpl_frameset_count_tags(frameset, science_tag); 00573 00574 if (mos > 1) { 00575 char version[80]; 00576 const char *curv_coeff_tag = "MOS_CURV_COEFF"; 00577 const char *slit_location_tag = "MOS_SLIT_LOCATION"; 00578 const char *disp_coeff_tag = "MOS_DISP_COEFF"; 00579 const char *unmapped_science_tag = "MOS_UNMAPPED_SCIENCE"; 00580 const char *mapped_science_tag = "MOS_SCIENCE_EXTRACTED"; 00581 const char *object_table_tag = "OBJECT_TABLE"; 00582 const char *unmapped_sky_tag = "MOS_UNMAPPED_SKY"; 00583 const char *mapped_sky_tag = "MOS_SCIENCE_SKY"; 00584 const char *reduced_science_tag = "MOS_SCIENCE_REDUCED"; 00585 const char *reduced_sky_tag = "MOS_SKY_REDUCED"; 00586 const char *reduced_error_tag = "MOS_ERROR_REDUCED"; 00587 const char *stack_method; 00588 const char *alignment; 00589 double refwave; 00590 double startwavelength; 00591 double endwavelength; 00592 double dispersion; 00593 int flux; 00594 int fringing; 00595 int cosmics; 00596 int slit_margin; 00597 int ext_radius; 00598 int cont_radius; 00599 int ext_mode; 00600 int rotate = 1; 00601 int rotate_back = -1; 00602 cpl_frameset *work = cpl_frameset_duplicate(frameset); 00603 cpl_frame **mos_science = cpl_calloc(mos, sizeof(cpl_frame*)); 00604 cpl_parameter *param; 00605 cpl_table *reference = NULL; 00606 cpl_table *objects = NULL; 00607 cpl_image **images = NULL; 00608 cpl_image *image = NULL; 00609 cpl_image *sky_image = NULL; 00610 cpl_imagelist *imagelist = NULL; 00611 cpl_image *fringes = NULL; 00612 cpl_image *stacked = NULL; 00613 cpl_image *mapped = NULL; 00614 cpl_image *smapped = NULL; 00615 cpl_image *sky_stacked = NULL; 00616 cpl_image *sky_mapped = NULL; 00617 cpl_image *sky_smapped = NULL; 00618 cpl_table *polytraces = NULL; 00619 cpl_table *idscoeff = NULL; 00620 cpl_table *slits = NULL; 00621 cpl_table *grism_table = NULL; 00622 cpl_propertylist *header = NULL; 00623 char *name; 00624 double offset; 00625 double gain; 00626 double ron; 00627 int time_normal; 00628 int min_reject; 00629 int max_reject; 00630 double klow; 00631 double khigh; 00632 int kiter; 00633 int int_alignment = 0; 00634 int status; 00635 int nx, ny; 00636 int i; 00637 00638 00639 snprintf(version, 80, "%s-%s", PACKAGE, PACKAGE_VERSION); 00640 00641 grism_table = dfs_load_table(frameset, "GRISM_TABLE", 1); 00642 00643 flux = dfs_get_parameter_bool(parlist, "fors.vimos_science.flux", NULL); 00644 00645 cosmics = dfs_get_parameter_bool(parlist, 00646 "fors.vimos_science.cosmics", NULL); 00647 00648 dispersion = dfs_get_parameter_double(parlist, 00649 "fors.vimos_science.dispersion", grism_table); 00650 00651 refwave = dfs_get_parameter_double(parlist, 00652 "fors.vimos_science.reference", grism_table); 00653 00654 startwavelength = dfs_get_parameter_double(parlist, 00655 "fors.vimos_science.startwavelength", grism_table); 00656 00657 endwavelength = dfs_get_parameter_double(parlist, 00658 "fors.vimos_science.endwavelength", grism_table); 00659 00660 alignment = dfs_get_parameter_string(parlist, 00661 "fors.vimos_science.alignment", NULL); 00662 00663 if (strcmp(alignment, "integer") == 0) { 00664 int_alignment = 1; 00665 } 00666 00667 stack_method = dfs_get_parameter_string(parlist, 00668 "fors.vimos_science.stack_method", NULL); 00669 00670 if (strcmp(stack_method, "minmax") == 0) { 00671 min_reject = dfs_get_parameter_int(parlist, 00672 "fors.vimos_science.minrejection", NULL); 00673 if (min_reject < 0) { 00674 cpl_msg_error("vimos_science", 00675 "Invalid number of lower rejections"); 00676 return -1; 00677 } 00678 00679 max_reject = dfs_get_parameter_int(parlist, 00680 "fors.vimos_science.maxrejection", NULL); 00681 00682 if (max_reject < 0) { 00683 cpl_msg_error("vimos_science", 00684 "Invalid number of upper rejections"); 00685 return -1; 00686 } 00687 } 00688 00689 if (strcmp(stack_method, "ksigma") == 0) { 00690 klow = dfs_get_parameter_double(parlist, 00691 "fors.vimos_science.klow", NULL); 00692 if (klow < 0.1) { 00693 cpl_msg_error("vimos_science", 00694 "Invalid lower K-sigma"); 00695 return -1; 00696 } 00697 00698 khigh = dfs_get_parameter_double(parlist, 00699 "fors.vimos_science.khigh", NULL); 00700 if (khigh < 0.1) { 00701 cpl_msg_error("vimos_science", 00702 "Invalid lower K-sigma"); 00703 return -1; 00704 } 00705 00706 kiter = dfs_get_parameter_int(parlist, 00707 "fors.vimos_science.kiter", NULL); 00708 if (kiter < 1) { 00709 cpl_msg_error("vimos_science", 00710 "Invalid number of iterations"); 00711 return -1; 00712 } 00713 } 00714 00715 slit_margin = dfs_get_parameter_int(parlist, 00716 "fors.vimos_science.slit_margin", 00717 NULL); 00718 ext_radius = dfs_get_parameter_int(parlist, 00719 "fors.vimos_science.ext_radius", 00720 NULL); 00721 cont_radius = dfs_get_parameter_int(parlist, 00722 "fors.vimos_science.cont_radius", 00723 NULL); 00724 ext_mode = dfs_get_parameter_int(parlist, 00725 "fors.vimos_science.ext_mode", 00726 NULL); 00727 00728 fringing = dfs_get_parameter_bool(parlist, 00729 "fors.vimos_science.fringing", NULL); 00730 00731 cpl_table_delete(grism_table); grism_table = NULL; 00732 00733 00734 /* 00735 * Disable time normalisation for single runs 00736 */ 00737 00738 param = cpl_parameterlist_find(parlist, 00739 "fors.vimos_science.time_normalise"); 00740 time_normal = cpl_parameter_get_bool(param); 00741 cpl_parameter_set_bool(param, 0); 00742 00743 00744 /* 00745 * Collect all scientific frames from input SOF 00746 */ 00747 00748 mos_science[0] = cpl_frameset_find(frameset, science_tag); 00749 for (i = 1; i < mos; i++) { 00750 mos_science[i] = cpl_frameset_find(frameset, NULL); 00751 } 00752 00753 00754 /* 00755 * Process scientific frames one at a time 00756 */ 00757 00758 for (i = 0; i < mos; i++) { 00759 cpl_frameset_erase(work, science_tag); 00760 cpl_frameset_insert(work, cpl_frame_duplicate(mos_science[i])); 00761 vimos_science_impl(work, parlist); 00762 00763 00764 /* 00765 * Cleanup work SOF from products 00766 * (not really necessary, but clean) 00767 */ 00768 00769 cpl_frameset_erase(work, "MOS_SKYLINES_OFFSETS_SLIT"); 00770 cpl_frameset_erase(work, "MOS_SCIENCE_SKY_EXTRACTED"); 00771 cpl_frameset_erase(work, "MOS_UNMAPPED_SKY"); 00772 cpl_frameset_erase(work, "MOS_UNMAPPED_SCIENCE"); 00773 cpl_frameset_erase(work, "MOS_WAVELENGTH_MAP_SKY"); 00774 cpl_frameset_erase(work, "MOS_SCIENCE_SKY"); 00775 cpl_frameset_erase(work, "OBJECT_TABLE"); 00776 cpl_frameset_erase(work, "MOS_SCIENCE_REDUCED"); 00777 cpl_frameset_erase(work, "MOS_SKY_REDUCED"); 00778 cpl_frameset_erase(work, "MOS_ERROR_REDUCED"); 00779 cpl_frameset_erase(work, "MOS_DISP_COEFF_SKY"); 00780 cpl_frameset_erase(work, "MOS_SCIENCE_EXTRACTED"); 00781 00782 00783 /* 00784 * Of all products, only keep the object tables, the 00785 * unmapped sky, and the unmapped science. 00786 */ 00787 00788 name = cpl_sprintf("object_table_%d.fits", i); 00789 status = rename("object_table.fits", name); 00790 cpl_free(name); 00791 name = cpl_sprintf("mos_unmapped_sky_%d.fits", i); 00792 status |= rename("mos_unmapped_sky.fits", name); 00793 cpl_free(name); 00794 name = cpl_sprintf("mos_unmapped_science_%d.fits", i); 00795 status |= rename("mos_unmapped_science.fits", name); 00796 cpl_free(name); 00797 00798 if (status) { 00799 cpl_msg_error("vimos_science", "Cannot rename product."); 00800 cpl_free(mos_science); 00801 cpl_frameset_delete(work); 00802 return -1; 00803 } 00804 } 00805 00806 cpl_free(mos_science); 00807 cpl_frameset_delete(work); 00808 00809 if (fringing) { 00810 00811 /* 00812 * Produce fringing map by median stacking 00813 */ 00814 00815 imagelist = cpl_imagelist_new(); 00816 00817 for (i = 0; i < mos; i++) { 00818 name = cpl_sprintf("mos_unmapped_science_%d.fits", i); 00819 image = cpl_image_load(name, CPL_TYPE_FLOAT, 0, 0); 00820 cpl_imagelist_set(imagelist, image, 00821 cpl_imagelist_get_size(imagelist)); 00822 } 00823 00824 fringes = cpl_imagelist_collapse_median_create(imagelist); 00825 cpl_imagelist_delete(imagelist); 00826 cpl_image_save(fringes, "fringes.fits", 00827 CPL_BPP_IEEE_FLOAT, NULL, CPL_IO_DEFAULT); 00828 00829 } 00830 00831 00832 /* 00833 * Now stack all frames and extract final objects 00834 */ 00835 00836 reference = cpl_table_load("object_table_0.fits", 1, 1); 00837 stacked = cpl_image_load("mos_unmapped_science_0.fits", 00838 CPL_TYPE_FLOAT, 0, 0); 00839 sky_stacked = cpl_image_load("mos_unmapped_sky_0.fits", 00840 CPL_TYPE_FLOAT, 0, 0); 00841 if (fringing) { 00842 cpl_image_subtract(stacked, fringes); 00843 cpl_image_add(sky_stacked, fringes); 00844 } 00845 00846 // Added just for eliminating wcs like in other images 00847 cpl_image_save(stacked, "mos_unmapped_science_0.fits", 00848 CPL_BPP_IEEE_FLOAT, NULL, CPL_IO_DEFAULT); 00849 // end of debug line 00850 00851 for (i = 1; i < mos; i++) { 00852 name = cpl_sprintf("object_table_%d.fits", i); 00853 objects = cpl_table_load(name, 1, 1); 00854 cpl_free(name); 00855 if (mos_compute_offset(reference, objects, &offset)) { 00856 cpl_msg_error("vimos_science", "Cannot compute offset."); 00857 cpl_table_delete(objects); 00858 return -1; 00859 } 00860 cpl_table_delete(objects); 00861 name = cpl_sprintf("mos_unmapped_science_%d.fits", i); 00862 image = cpl_image_load(name, CPL_TYPE_FLOAT, 0, 0); 00863 00864 if (fringing) { 00865 cpl_image_subtract(image, fringes); 00866 } 00867 00868 cpl_msg_info("vimos_science", 00869 "Frame %d offset relative " 00870 "to frame 1: %.2f pix\n", i + 1, offset); 00871 00872 if (int_alignment) { 00873 offset = floor(offset + 0.5); 00874 cpl_msg_info("vimos_science", 00875 "Nearest neighbour offset applied is " 00876 "%.0f pix\n", offset); 00877 } 00878 00879 mos_image_shift(image, offset, 0.0); 00880 cpl_image_save(image, name, CPL_BPP_IEEE_FLOAT, 00881 NULL, CPL_IO_DEFAULT); 00882 cpl_free(name); 00883 00884 /* 00885 * Here stacking sky frames, they are always averaged 00886 */ 00887 00888 name = cpl_sprintf("mos_unmapped_sky_%d.fits", i); 00889 sky_image = cpl_image_load(name, CPL_TYPE_FLOAT, 0, 0); 00890 00891 if (fringing) { 00892 cpl_image_add(sky_image, fringes); 00893 } 00894 00895 mos_image_shift(sky_image, offset, 0.0); 00896 cpl_free(name); 00897 cpl_image_add(sky_stacked, sky_image); 00898 cpl_image_delete(sky_image); 00899 00900 if (strcmp(stack_method, "average") == 0) { 00901 cpl_image_add(stacked, image); 00902 cpl_image_delete(image); 00903 } 00904 else { 00905 if (i == 1) { 00906 imagelist = cpl_imagelist_new(); 00907 cpl_imagelist_set(imagelist, stacked, 00908 cpl_imagelist_get_size(imagelist)); 00909 } 00910 cpl_imagelist_set(imagelist, image, 00911 cpl_imagelist_get_size(imagelist)); 00912 } 00913 } 00914 cpl_table_delete(reference); 00915 00916 cpl_image_divide_scalar(sky_stacked, mos); 00917 00918 if (fringing) { 00919 cpl_image_delete(fringes); 00920 } 00921 00922 if (strcmp(stack_method, "average") == 0) { 00923 cpl_image_divide_scalar(stacked, mos); 00924 } 00925 00926 if (strcmp(stack_method, "median") == 0) { 00927 stacked = cpl_imagelist_collapse_median_create(imagelist); 00928 cpl_imagelist_delete(imagelist); 00929 } 00930 00931 if (strcmp(stack_method, "minmax") == 0) { 00932 stacked = cpl_imagelist_collapse_minmax_create(imagelist, 00933 min_reject, 00934 max_reject); 00935 cpl_imagelist_delete(imagelist); 00936 } 00937 00938 if (strcmp(stack_method, "ksigma") == 0) { 00939 stacked = mos_ksigma_stack(imagelist, klow, khigh, kiter, NULL); 00940 cpl_imagelist_delete(imagelist); 00941 } 00942 00943 header = dfs_load_header(frameset, science_tag, 0); 00944 00945 gain = cpl_propertylist_get_double(header, "ESO DET OUT1 CONAD"); 00946 ron = cpl_propertylist_get_double(header, "ESO DET OUT1 RON"); 00947 ron /= gain; /* Convert from electrons to ADU */ 00948 00949 if (dfs_save_image(frameset, stacked, unmapped_science_tag, 00950 header, parlist, "vimos_science", version)) { 00951 cpl_image_delete(stacked); 00952 cpl_image_delete(sky_stacked); 00953 cpl_propertylist_delete(header); 00954 cpl_table_delete(slits); 00955 return -1; 00956 } 00957 00958 if (dfs_save_image(frameset, sky_stacked, unmapped_sky_tag, 00959 header, parlist, "vimos_science", version)) { 00960 cpl_image_delete(stacked); 00961 cpl_image_delete(sky_stacked); 00962 cpl_propertylist_delete(header); 00963 cpl_table_delete(slits); 00964 return -1; 00965 } 00966 00967 cpl_parameter_set_bool(param, time_normal); 00968 00969 cpl_image_turn(stacked, rotate); 00970 cpl_image_turn(sky_stacked, rotate); 00971 00972 nx = cpl_image_get_size_x(stacked); 00973 ny = cpl_image_get_size_y(stacked); 00974 00975 polytraces = dfs_load_table(frameset, curv_coeff_tag, 1); 00976 00977 slits = dfs_load_table(frameset, slit_location_tag, 1); 00978 mos_rotate_slits(slits, -rotate, nx, ny); 00979 00980 // FIXME: Qui potremmo tirare su una tabella allineata al cielo, se esiste. 00981 idscoeff = dfs_load_table(frameset, disp_coeff_tag, 1); 00982 00983 cpl_msg_indent_less(); 00984 cpl_msg_info("vimos_science", 00985 "Processing stacked scientific spectra..."); 00986 cpl_msg_indent_more(); 00987 00988 smapped = mos_spatial_calibration(stacked, slits, polytraces, refwave, 00989 startwavelength, endwavelength, 00990 dispersion, flux, NULL); 00991 00992 cpl_image_delete(stacked); 00993 00994 sky_smapped = mos_spatial_calibration(sky_stacked, slits, polytraces, 00995 refwave, startwavelength, 00996 endwavelength, dispersion, 00997 flux, NULL); 00998 00999 cpl_image_delete(sky_stacked); 01000 cpl_table_delete(polytraces); 01001 01002 mapped = mos_wavelength_calibration(smapped, refwave, 01003 startwavelength, endwavelength, 01004 dispersion, idscoeff, flux); 01005 01006 cpl_image_delete(smapped); 01007 01008 sky_mapped = mos_wavelength_calibration(sky_smapped, refwave, 01009 startwavelength, endwavelength, 01010 dispersion, idscoeff, flux); 01011 cpl_table_delete(idscoeff); 01012 01013 cpl_propertylist_update_double(header, "CRPIX1", 1.0); 01014 cpl_propertylist_update_double(header, "CRPIX2", 1.0); 01015 cpl_propertylist_update_double(header, "CRVAL1", 01016 startwavelength + dispersion/2); 01017 cpl_propertylist_update_double(header, "CRVAL2", 1.0); 01018 cpl_propertylist_update_double(header, "CD1_1", dispersion); 01019 cpl_propertylist_update_double(header, "CD1_2", 0.0); 01020 cpl_propertylist_update_double(header, "CD2_1", 0.0); 01021 cpl_propertylist_update_double(header, "CD2_2", 1.0); 01022 cpl_propertylist_update_string(header, "CTYPE1", "LINEAR"); 01023 cpl_propertylist_update_string(header, "CTYPE2", "PIXEL"); 01024 01025 // Later, when you have alltime 01026 // if (time_normal) { 01027 // image = cpl_image_divide_scalar_create(mapped, alltime); 01028 // if (dfs_save_image(frameset, image, mapped_science_sky_tag, header, 01029 // parlist, recipe, version)) 01030 // vimos_science_exit(NULL); 01031 // cpl_image_delete(image); image = NULL; 01032 // } 01033 // else { 01034 01035 if (dfs_save_image(frameset, mapped, mapped_science_tag, 01036 header, parlist, "vimos_science", version)) { 01037 cpl_propertylist_delete(header); 01038 cpl_image_delete(mapped); 01039 cpl_image_delete(sky_mapped); 01040 cpl_table_delete(slits); 01041 return -1; 01042 } 01043 01044 if (dfs_save_image(frameset, sky_mapped, mapped_sky_tag, 01045 header, parlist, "vimos_science", version)) { 01046 cpl_propertylist_delete(header); 01047 cpl_image_delete(mapped); 01048 cpl_image_delete(sky_mapped); 01049 cpl_table_delete(slits); 01050 return -1; 01051 } 01052 // } 01053 01054 cpl_msg_indent_less(); 01055 cpl_msg_info("vimos_science", "Final object detection..."); 01056 cpl_msg_indent_more(); 01057 01058 if (cosmics || strcmp(stack_method, "average")) { 01059 image = mos_detect_objects(mapped, slits, slit_margin, ext_radius, 01060 cont_radius); 01061 } 01062 else { 01063 cpl_image *mapped_cleaned = cpl_image_duplicate(mapped); 01064 mos_clean_cosmics(mapped_cleaned, gain, -1., -1.); 01065 image = mos_detect_objects(mapped_cleaned, slits, slit_margin, 01066 ext_radius, cont_radius); 01067 01068 cpl_image_delete(mapped_cleaned); 01069 } 01070 01071 cpl_image_delete(image); 01072 01073 mos_rotate_slits(slits, rotate, ny, nx); 01074 if (dfs_save_table(frameset, slits, object_table_tag, NULL, parlist, 01075 "vimos_science", version)) { 01076 cpl_propertylist_delete(header); 01077 cpl_image_delete(mapped); 01078 cpl_image_delete(sky_mapped); 01079 cpl_table_delete(slits); 01080 return -1; 01081 } 01082 01083 cpl_msg_indent_less(); 01084 cpl_msg_info("vimos_science", "Final object extraction..."); 01085 cpl_msg_indent_more(); 01086 01087 images = mos_extract_objects(mapped, sky_mapped, slits, 01088 ext_mode, ron, gain, mos); 01089 01090 cpl_image_delete(mapped); 01091 cpl_image_delete(sky_mapped); 01092 cpl_table_delete(slits); 01093 01094 if (images) { 01095 // if (time_normalise) 01096 // cpl_image_divide_scalar(images[0], alltime); 01097 01098 if (dfs_save_image(frameset, images[0], reduced_science_tag, 01099 header, parlist, "vimos_science", version)) { 01100 cpl_image_delete(images[0]); 01101 cpl_image_delete(images[1]); 01102 cpl_image_delete(images[2]); 01103 cpl_free(images); 01104 cpl_propertylist_delete(header); 01105 return -1; 01106 } 01107 01108 cpl_image_delete(images[0]); 01109 01110 // if (time_normalise) 01111 // cpl_image_divide_scalar(images[1], alltime); 01112 01113 if (dfs_save_image(frameset, images[1], reduced_sky_tag, header, 01114 parlist, "vimos_science", version)) { 01115 cpl_image_delete(images[1]); 01116 cpl_image_delete(images[2]); 01117 cpl_free(images); 01118 cpl_propertylist_delete(header); 01119 return -1; 01120 } 01121 01122 cpl_image_delete(images[1]); 01123 01124 // if (time_normalise) 01125 // cpl_image_divide_scalar(images[2], alltime); 01126 01127 if (dfs_save_image(frameset, images[2], reduced_error_tag, header, 01128 parlist, "vimos_science", version)) { 01129 cpl_image_delete(images[2]); 01130 cpl_free(images); 01131 cpl_propertylist_delete(header); 01132 return -1; 01133 } 01134 01135 cpl_image_delete(images[2]); 01136 01137 cpl_free(images); 01138 } 01139 else { 01140 cpl_msg_warning("vimos_science", "No objects found: the products " 01141 "%s, %s, and %s are not created", 01142 reduced_science_tag, reduced_sky_tag, 01143 reduced_error_tag); 01144 } 01145 01146 cpl_propertylist_delete(header); 01147 01148 return 0; 01149 } 01150 01151 return vimos_science_impl(frameset, parlist); 01152 }