vimos_science.c

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_8_6 $
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 }

Generated on Fri Mar 4 09:46:01 2011 for FORS Pipeline Reference Manual by  doxygen 1.4.7