fors_wave_calib_lss.c

00001 /* $Id: fors_wave_calib_lss.c,v 1.10 2013-09-09 12:25:33 cgarcia 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: cgarcia $
00023  * $Date: 2013-09-09 12:25:33 $
00024  * $Revision: 1.10 $
00025  * $Name: not supported by cvs2svn $
00026  */
00027 
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031 
00032 #include <math.h>
00033 #include <cpl.h>
00034 #include <moses.h>
00035 #include <fors_dfs.h>
00036 
00037 static int fors_wave_calib_lss_create(cpl_plugin *);
00038 static int fors_wave_calib_lss_exec(cpl_plugin *);
00039 static int fors_wave_calib_lss_destroy(cpl_plugin *);
00040 static int fors_wave_calib_lss(cpl_parameterlist *, cpl_frameset *);
00041 
00042 static char fors_wave_calib_lss_description[] =
00043 "This recipe is used to wavelength calibrate one long slit spectrum, i.e.,\n"
00044 "a FORS spectral obtained either in LSS mode or in MOS/MXU mode with all\n"
00045 "slits at the same offset. A pattern-matching algorithm is applied as in\n"
00046 "recipe fors_detect_spectra. For more details on this data reduction\n"
00047 "strategy please refer to the FORS Pipeline User's Manual.\n"
00048 "\n"
00049 "Note that specifying an input GRISM_TABLE will set some of the recipe\n"
00050 "configuration parameters to default values valid for a particular grism.\n"
00051 "\n"
00052 "In the table below the LSS acronym can be alternatively read as MOS or\n"
00053 "MXU.\n\n"
00054 "Input files:\n\n"
00055 "  DO category:               Type:       Explanation:         Required:\n"
00056 "  LAMP_UNBIAS_LSS            Calib       Arc lamp exposure       Y\n"
00057 "  MASTER_LINECAT             Calib       Line catalog            Y\n"
00058 "  GRISM_TABLE                Calib       Grism table             .\n\n"
00059 "Output files:\n\n"
00060 "  DO category:               Data type:  Explanation:\n"
00061 "  REDUCED_LAMP_LSS           FITS image  Calibrated arc lamp exposure\n"
00062 "  DISP_COEFF_LSS             FITS table  Inverse dispersion coefficients\n"
00063 "  DISP_RESIDUALS_LSS         FITS image  Image of modeling residuals\n"
00064 "  WAVELENGTH_MAP_LSS         FITS image  Wavelengths mapped on CCD\n"
00065 "  SLIT_LOCATION_LSS          FITS image  Background subtracted arc frame\n"
00066 "  SPECTRAL_RESOLUTION_LSS    FITS table  Spectral resolution table\n\n";
00067 
00068 #define fors_wave_calib_lss_exit(message)     \
00069 {                                             \
00070 if ((const char *)message != NULL) cpl_msg_error(recipe, message);  \
00071 cpl_image_delete(spectra);                    \
00072 cpl_image_delete(residual);                   \
00073 cpl_image_delete(rectified);                  \
00074 cpl_image_delete(wavemap);                    \
00075 cpl_table_delete(grism_table);                \
00076 cpl_table_delete(wavelengths);                \
00077 cpl_table_delete(maskslits);                  \
00078 cpl_table_delete(idscoeff);                   \
00079 cpl_table_delete(idscoeff_all);               \
00080 cpl_table_delete(restab);                     \
00081 cpl_table_delete(slits);                      \
00082 cpl_vector_delete(lines);                     \
00083 cpl_propertylist_delete(header);              \
00084 cpl_propertylist_delete(save_header);         \
00085 cpl_msg_indent_less();                        \
00086 return -1;                                    \
00087 }
00088 
00089 #define fors_wave_calib_lss_exit_memcheck(message)  \
00090 {                                                   \
00091 if ((const char *)message != NULL) cpl_msg_info(recipe, message);         \
00092 printf("free spectra (%p)\n", spectra);             \
00093 cpl_image_delete(spectra);                          \
00094 printf("free residual (%p)\n", residual);           \
00095 cpl_image_delete(residual);                         \
00096 printf("free rectified (%p)\n", rectified);         \
00097 cpl_image_delete(rectified);                        \
00098 printf("free wavemap (%p)\n", wavemap);             \
00099 cpl_image_delete(wavemap);                          \
00100 printf("free grism_table (%p)\n", grism_table);     \
00101 cpl_table_delete(grism_table);                      \
00102 printf("free wavelengths (%p)\n", wavelengths);     \
00103 cpl_table_delete(wavelengths);                      \
00104 printf("free maskslits (%p)\n", maskslits);         \
00105 cpl_table_delete(maskslits);                        \
00106 printf("free idscoeff (%p)\n", idscoeff);           \
00107 cpl_table_delete(idscoeff);                         \
00108 printf("free idscoeff_all (%p)\n", idscoeff_all);   \
00109 cpl_table_delete(idscoeff_all);                     \
00110 printf("free restab (%p)\n", restab);               \
00111 cpl_table_delete(restab);                           \
00112 printf("free slits (%p)\n", slits);                 \
00113 cpl_table_delete(slits);                            \
00114 printf("free lines (%p)\n", lines);                 \
00115 cpl_vector_delete(lines);                           \
00116 printf("free header (%p)\n", header);               \
00117 cpl_propertylist_delete(header);                    \
00118 printf("free save_header (%p)\n", save_header);     \
00119 cpl_propertylist_delete(save_header);               \
00120 cpl_msg_indent_less();                              \
00121 return 0;                                           \
00122 }
00123 
00124 
00136 int cpl_plugin_get_info(cpl_pluginlist *list)
00137 {
00138     cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe );
00139     cpl_plugin *plugin = &recipe->interface;
00140 
00141     cpl_plugin_init(plugin,
00142                     CPL_PLUGIN_API,
00143                     FORS_BINARY_VERSION,
00144                     CPL_PLUGIN_TYPE_RECIPE,
00145                     "fors_wave_calib_lss",
00146                     "Derive dispersion relation from long-slit arc lamp frame",
00147                     fors_wave_calib_lss_description,
00148                     "Carlo Izzo",
00149                     PACKAGE_BUGREPORT,
00150     "This file is currently part of the FORS Instrument Pipeline\n"
00151     "Copyright (C) 2002-2010 European Southern Observatory\n\n"
00152     "This program is free software; you can redistribute it and/or modify\n"
00153     "it under the terms of the GNU General Public License as published by\n"
00154     "the Free Software Foundation; either version 2 of the License, or\n"
00155     "(at your option) any later version.\n\n"
00156     "This program is distributed in the hope that it will be useful,\n"
00157     "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
00158     "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
00159     "GNU General Public License for more details.\n\n"
00160     "You should have received a copy of the GNU General Public License\n"
00161     "along with this program; if not, write to the Free Software Foundation,\n"
00162     "Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\n",
00163                     fors_wave_calib_lss_create,
00164                     fors_wave_calib_lss_exec,
00165                     fors_wave_calib_lss_destroy);
00166 
00167     cpl_pluginlist_append(list, plugin);
00168     
00169     return 0;
00170 }
00171 
00172 
00183 static int fors_wave_calib_lss_create(cpl_plugin *plugin)
00184 {
00185     cpl_recipe    *recipe;
00186     cpl_parameter *p;
00187 
00188     /* 
00189      * Check that the plugin is part of a valid recipe 
00190      */
00191 
00192     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00193         recipe = (cpl_recipe *)plugin;
00194     else 
00195         return -1;
00196 
00197     /* 
00198      * Create the (empty) parameters list in the cpl_recipe object 
00199      */
00200 
00201     recipe->parameters = cpl_parameterlist_new(); 
00202 
00203     /*
00204      * Dispersion
00205      */
00206 
00207     p = cpl_parameter_new_value("fors.fors_wave_calib_lss.dispersion",
00208                                 CPL_TYPE_DOUBLE,
00209                                 "Expected spectral dispersion (Angstrom/pixel)",
00210                                 "fors.fors_wave_calib_lss",
00211                                 0.0);
00212     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "dispersion");
00213     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00214     cpl_parameterlist_append(recipe->parameters, p);
00215 
00216     /*
00217      * Peak detection level
00218      */
00219 
00220     p = cpl_parameter_new_value("fors.fors_wave_calib_lss.peakdetection",
00221                                 CPL_TYPE_DOUBLE,
00222                                 "Initial peak detection threshold (ADU)",
00223                                 "fors.fors_wave_calib_lss",
00224                                 0.0);
00225     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "peakdetection");
00226     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00227     cpl_parameterlist_append(recipe->parameters, p);
00228 
00229     /*
00230      * Degree of wavelength calibration polynomial
00231      */
00232 
00233     p = cpl_parameter_new_value("fors.fors_wave_calib_lss.wdegree",
00234                                 CPL_TYPE_INT,
00235                                 "Degree of wavelength calibration polynomial",
00236                                 "fors.fors_wave_calib_lss",
00237                                 0);
00238     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wdegree");
00239     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00240     cpl_parameterlist_append(recipe->parameters, p);
00241 
00242     /*
00243      * Reference lines search radius
00244      */
00245 
00246     p = cpl_parameter_new_value("fors.fors_wave_calib_lss.wradius",
00247                                 CPL_TYPE_INT,
00248                                 "Search radius if iterating pattern-matching "
00249                                 "with first-guess method",
00250                                 "fors.fors_wave_calib_lss",
00251                                 4);
00252     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wradius");
00253     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00254     cpl_parameterlist_append(recipe->parameters, p);
00255 
00256     /*
00257      * Rejection threshold in dispersion relation polynomial fitting
00258      */
00259 
00260     p = cpl_parameter_new_value("fors.fors_wave_calib_lss.wreject",
00261                                 CPL_TYPE_DOUBLE,
00262                                 "Rejection threshold in dispersion "
00263                                 "relation fit (pixel)",
00264                                 "fors.fors_wave_calib_lss",
00265                                 0.7);
00266     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wreject");
00267     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00268     cpl_parameterlist_append(recipe->parameters, p);
00269 
00270     /*
00271      * Line catalog table column containing the reference wavelengths
00272      */
00273 
00274     p = cpl_parameter_new_value("fors.fors_wave_calib_lss.wcolumn",
00275                                 CPL_TYPE_STRING,
00276                                 "Name of line catalog table column "
00277                                 "with wavelengths",
00278                                 "fors.fors_wave_calib_lss",
00279                                 "WLEN");
00280     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcolumn");
00281     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00282     cpl_parameterlist_append(recipe->parameters, p);
00283 
00284     /*
00285      * Start wavelength for spectral extraction
00286      */
00287 
00288     p = cpl_parameter_new_value("fors.fors_wave_calib_lss.startwavelength",
00289                                 CPL_TYPE_DOUBLE,
00290                                 "Start wavelength in spectral extraction",
00291                                 "fors.fors_wave_calib_lss",
00292                                 0.0);
00293     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "startwavelength");
00294     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00295     cpl_parameterlist_append(recipe->parameters, p);
00296 
00297     /*
00298      * End wavelength for spectral extraction
00299      */
00300 
00301     p = cpl_parameter_new_value("fors.fors_wave_calib_lss.endwavelength",
00302                                 CPL_TYPE_DOUBLE,
00303                                 "End wavelength in spectral extraction",
00304                                 "fors.fors_wave_calib_lss",
00305                                 0.0);
00306     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "endwavelength");
00307     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00308     cpl_parameterlist_append(recipe->parameters, p);
00309 
00310     /*
00311      * Wavelength solution interpolation
00312      */
00313  
00314     p = cpl_parameter_new_value("fors.fors_wave_calib_lss.wmode",
00315                                 CPL_TYPE_INT,
00316                                 "Interpolation mode of wavelength solution "
00317                                 "(0 = no interpolation, 1 = fill gaps, "
00318                                 "2 = global model)",
00319                                 "fors.fors_wave_calib_lss",
00320                                 2);
00321     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wmode");
00322     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00323     cpl_parameterlist_append(recipe->parameters, p);
00324 
00325     return 0;
00326 }
00327 
00328 
00337 static int fors_wave_calib_lss_exec(cpl_plugin *plugin)
00338 {
00339     cpl_recipe *recipe;
00340     
00341     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00342         recipe = (cpl_recipe *)plugin;
00343     else 
00344         return -1;
00345 
00346     return fors_wave_calib_lss(recipe->parameters, recipe->frames);
00347 }
00348 
00349 
00358 static int fors_wave_calib_lss_destroy(cpl_plugin *plugin)
00359 {
00360     cpl_recipe *recipe;
00361     
00362     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00363         recipe = (cpl_recipe *)plugin;
00364     else 
00365         return -1;
00366 
00367     cpl_parameterlist_delete(recipe->parameters); 
00368 
00369     return 0;
00370 }
00371 
00372 
00382 static int fors_wave_calib_lss(cpl_parameterlist *parlist, 
00383                                cpl_frameset *frameset)
00384 {
00385 
00386     const char *recipe = "fors_wave_calib_lss";
00387 
00388 
00389     /*
00390      * Input parameters
00391      */
00392 
00393     double      dispersion;
00394     double      peakdetection;
00395     int         wdegree;
00396     int         wradius;
00397     double      wreject;
00398     int         wmode;
00399     const char *wcolumn;
00400     double      startwavelength;
00401     double      endwavelength;
00402 
00403     /*
00404      * CPL objects
00405      */
00406 
00407     cpl_image        *spectra      = NULL;
00408     cpl_image        *rectified    = NULL;
00409     cpl_image        *wavemap      = NULL;
00410     cpl_image        *residual     = NULL;
00411     cpl_image        *dummy        = NULL;
00412     cpl_table        *grism_table  = NULL;
00413     cpl_table        *wavelengths  = NULL;
00414     cpl_table        *slits        = NULL;
00415     cpl_table        *idscoeff     = NULL;
00416     cpl_table        *idscoeff_all = NULL;
00417     cpl_table        *maskslits    = NULL;
00418     cpl_table        *restab       = NULL;
00419     cpl_vector       *lines        = NULL;
00420     cpl_propertylist *header       = NULL;
00421     cpl_propertylist *save_header  = NULL;
00422 
00423     /*
00424      * Auxiliary variables
00425      */
00426 
00427     char        version[80];
00428     const char *arc_tag;
00429     const char *reduced_lamp_tag;
00430     const char *wavelength_map_tag;
00431     const char *disp_residuals_tag;
00432     const char *disp_coeff_tag;
00433     const char *slit_location_tag;
00434     const char *spectral_resolution_tag;
00435     int         mxu;
00436     int         mos;
00437     int         lss;
00438     int         treat_as_lss = 0;
00439     double      mean_rms;
00440     int         narc;
00441     int         nlines;
00442     int         rebin;
00443     double     *line;
00444     double     *fiterror = NULL;
00445     int        *fitlines = NULL;
00446     int         nx, ny;
00447     int         first_row, last_row;
00448     int         ylow, yhig;
00449     double      reference;
00450     int         i;
00451 
00452     char       *instrume = NULL;
00453 
00454 
00455     cpl_msg_set_indentation(2);
00456 
00457     /*
00458      * Get configuration parameters
00459      */
00460 
00461     cpl_msg_info(recipe, "Recipe %s configuration parameters:", recipe);
00462     cpl_msg_indent_more();
00463     
00464     if (cpl_frameset_count_tags(frameset, "GRISM_TABLE") > 1)
00465         fors_wave_calib_lss_exit("Too many in input: GRISM_TABLE"); 
00466 
00467     grism_table = dfs_load_table(frameset, "GRISM_TABLE", 1);
00468 
00469     dispersion = dfs_get_parameter_double(parlist,
00470                     "fors.fors_wave_calib_lss.dispersion", grism_table);
00471 
00472     if (dispersion <= 0.0)
00473         fors_wave_calib_lss_exit("Invalid spectral dispersion value");
00474 
00475     peakdetection = dfs_get_parameter_double(parlist,
00476                     "fors.fors_wave_calib_lss.peakdetection", grism_table);
00477     if (peakdetection <= 0.0)
00478         fors_wave_calib_lss_exit("Invalid peak detection level");
00479 
00480     wdegree = dfs_get_parameter_int(parlist,
00481                     "fors.fors_wave_calib_lss.wdegree", grism_table);
00482 
00483     if (wdegree < 1)
00484         fors_wave_calib_lss_exit("Invalid polynomial degree");
00485 
00486     if (wdegree > 5)
00487         fors_wave_calib_lss_exit("Max allowed polynomial degree is 5");
00488 
00489     wradius = dfs_get_parameter_int(parlist, 
00490                                     "fors.fors_wave_calib_lss.wradius", NULL);
00491 
00492     if (wradius < 0)
00493         fors_wave_calib_lss_exit("Invalid search radius");
00494 
00495     wreject = dfs_get_parameter_double(parlist, 
00496                                     "fors.fors_wave_calib_lss.wreject", NULL);
00497 
00498     if (wreject <= 0.0)
00499         fors_wave_calib_lss_exit("Invalid rejection threshold");
00500 
00501     wmode = dfs_get_parameter_int(parlist, 
00502                                     "fors.fors_wave_calib_lss.wmode", NULL);
00503 
00504     if (wmode < 0 || wmode > 2)
00505         fors_wave_calib_lss_exit("Invalid interpolation mode");
00506 
00507     wcolumn = dfs_get_parameter_string(parlist, 
00508                                     "fors.fors_wave_calib_lss.wcolumn", NULL);
00509 
00510     startwavelength = dfs_get_parameter_double(parlist,
00511                     "fors.fors_wave_calib_lss.startwavelength", grism_table);
00512     if (startwavelength > 1.0)
00513         if (startwavelength < 3000.0 || startwavelength > 13000.0)
00514             fors_wave_calib_lss_exit("Invalid wavelength");
00515 
00516     endwavelength = dfs_get_parameter_double(parlist,
00517                     "fors.fors_wave_calib_lss.endwavelength", grism_table);
00518     if (endwavelength > 1.0) {
00519         if (endwavelength < 3000.0 || endwavelength > 13000.0)
00520             fors_wave_calib_lss_exit("Invalid wavelength");
00521         if (startwavelength < 1.0)
00522             fors_wave_calib_lss_exit("Invalid wavelength interval");
00523     }
00524 
00525     if (startwavelength > 1.0)
00526         if (endwavelength - startwavelength <= 0.0)
00527             fors_wave_calib_lss_exit("Invalid wavelength interval");
00528 
00529     cpl_table_delete(grism_table); grism_table = NULL;
00530 
00531     if (cpl_error_get_code())
00532         fors_wave_calib_lss_exit("Failure reading the configuration "
00533                                  "parameters");
00534 
00535 
00536     cpl_msg_indent_less();
00537     cpl_msg_info(recipe, "Check input set-of-frames:");
00538     cpl_msg_indent_more();
00539 
00540     if (cpl_frameset_count_tags(frameset, "MASTER_LINECAT") == 0)
00541         fors_wave_calib_lss_exit("Missing required input: MASTER_LINECAT");
00542 
00543     if (cpl_frameset_count_tags(frameset, "MASTER_LINECAT") > 1)
00544         fors_wave_calib_lss_exit("Too many in input: MASTER_LINECAT");
00545 
00546     mxu = cpl_frameset_count_tags(frameset, "LAMP_UNBIAS_MXU");
00547     mos = cpl_frameset_count_tags(frameset, "LAMP_UNBIAS_MOS");
00548     lss = cpl_frameset_count_tags(frameset, "LAMP_UNBIAS_LSS");
00549 
00550     narc = mxu + mos + lss;
00551 
00552     if (narc == 0) {
00553         fors_wave_calib_lss_exit("Missing input long-slit arc lamp frame");
00554     }
00555     if (narc > 1) {
00556         cpl_msg_error(recipe, "Too many input arc lamp frames (%d > 1)", narc);
00557         fors_wave_calib_lss_exit(NULL);
00558     }
00559 
00560     if (mxu) {
00561         arc_tag                 = "LAMP_UNBIAS_MXU";
00562         slit_location_tag       = "SLIT_LOCATION_MXU";
00563         reduced_lamp_tag        = "REDUCED_LAMP_MXU";
00564         disp_residuals_tag      = "DISP_RESIDUALS_MXU";
00565         disp_coeff_tag          = "DISP_COEFF_MXU";
00566         wavelength_map_tag      = "WAVELENGTH_MAP_MXU";
00567         spectral_resolution_tag = "SPECTRAL_RESOLUTION_MXU";
00568     }
00569     else if (mos) {
00570         arc_tag                 = "LAMP_UNBIAS_MOS";
00571         slit_location_tag       = "SLIT_LOCATION_MOS";
00572         reduced_lamp_tag        = "REDUCED_LAMP_MOS";
00573         disp_residuals_tag      = "DISP_RESIDUALS_MOS";
00574         disp_coeff_tag          = "DISP_COEFF_MOS";
00575         wavelength_map_tag      = "WAVELENGTH_MAP_MOS";
00576         spectral_resolution_tag = "SPECTRAL_RESOLUTION_MOS";
00577     }
00578     else if (lss) {
00579         arc_tag                 = "LAMP_UNBIAS_LSS";
00580         slit_location_tag       = "SLIT_LOCATION_LSS";
00581         reduced_lamp_tag        = "REDUCED_LAMP_LSS";
00582         disp_residuals_tag      = "DISP_RESIDUALS_LSS";
00583         disp_coeff_tag          = "DISP_COEFF_LSS";
00584         wavelength_map_tag      = "WAVELENGTH_MAP_LSS";
00585         spectral_resolution_tag = "SPECTRAL_RESOLUTION_LSS";
00586     }
00587 
00588 
00589     if (!dfs_equal_keyword(frameset, "ESO INS GRIS1 ID"))
00590         cpl_msg_warning(cpl_func,"Input frames are not from the same grism");
00591 
00592     if (!dfs_equal_keyword(frameset, "ESO INS FILT1 ID"))
00593         cpl_msg_warning(cpl_func,"Input frames are not from the same filter");
00594 
00595     if (!dfs_equal_keyword(frameset, "ESO DET CHIP1 ID"))
00596         cpl_msg_warning(cpl_func,"Input frames are not from the same chip");
00597 
00598 
00599     /*
00600      * Get the reference wavelength and the rebin factor along the
00601      * dispersion direction from the arc lamp exposure
00602      */
00603 
00604     header = dfs_load_header(frameset, arc_tag, 0);
00605 
00606     if (header == NULL)
00607         fors_wave_calib_lss_exit("Cannot load arc lamp header");
00608 
00609     instrume = (char *)cpl_propertylist_get_string(header, "INSTRUME");
00610     if (instrume == NULL)
00611         fors_wave_calib_lss_exit("Missing keyword INSTRUME in arc lamp header");
00612 
00613     if (instrume[4] == '1')
00614         snprintf(version, 80, "%s/%s", "fors1", VERSION);
00615     if (instrume[4] == '2')
00616         snprintf(version, 80, "%s/%s", "fors2", VERSION);
00617 
00618     reference = cpl_propertylist_get_double(header, "ESO INS GRIS1 WLEN");
00619 
00620     if (cpl_error_get_code() != CPL_ERROR_NONE)
00621         fors_wave_calib_lss_exit("Missing keyword ESO INS GRIS1 WLEN "
00622                                  "in arc lamp frame header");
00623 
00624     if (reference < 3000.0)   /* Perhaps in nanometers... */
00625         reference *= 10;
00626 
00627     if (reference < 3000.0 || reference > 13000.0) {
00628         cpl_msg_error(recipe, "Invalid central wavelength %.2f read from "
00629                       "keyword ESO INS GRIS1 WLEN in arc lamp frame header",
00630                       reference);
00631         fors_wave_calib_lss_exit(NULL);
00632     }
00633 
00634     cpl_msg_info(recipe, "The central wavelength is: %.2f", reference);
00635 
00636     rebin = cpl_propertylist_get_int(header, "ESO DET WIN1 BINX");
00637 
00638     if (cpl_error_get_code() != CPL_ERROR_NONE)
00639         fors_wave_calib_lss_exit("Missing keyword ESO DET WIN1 BINX "
00640                                  "in arc lamp frame header");
00641 
00642     if (rebin != 1) {
00643         dispersion *= rebin;
00644         cpl_msg_warning(recipe, "The rebin factor is %d, and therefore the "
00645                         "working dispersion used is %f A/pixel", rebin,
00646                         dispersion);
00647     }
00648 
00649 
00650     if (mos || mxu) {
00651 
00652         int nslits_out_det = 0;
00653 
00654         /*
00655          * Check if all slits have the same X offset. If not, this is the
00656          * wrong recipe...
00657          */
00658 
00659         if (mos)
00660             maskslits = mos_load_slits_fors_mos(header, &nslits_out_det);
00661         else
00662             maskslits = mos_load_slits_fors_mxu(header);
00663 
00664         treat_as_lss = fors_mos_is_lss_like(maskslits, nslits_out_det);
00665 
00666         cpl_table_delete(maskslits); maskslits = NULL;
00667 
00668         if (!treat_as_lss)
00669             fors_wave_calib_lss_exit("Input data are not long-slit data");
00670     }
00671 
00672 
00673     cpl_msg_indent_less();
00674     cpl_msg_info(recipe, "Load arc lamp exposure...");
00675     cpl_msg_indent_more();
00676 
00677     spectra = dfs_load_image(frameset, arc_tag, CPL_TYPE_FLOAT, 0, 0);
00678 
00679     if (spectra == NULL)
00680         fors_wave_calib_lss_exit("Cannot load arc lamp exposure");
00681 
00682 
00683     cpl_msg_indent_less();
00684     cpl_msg_info(recipe, "Load input line catalog...");
00685     cpl_msg_indent_more();
00686 
00687     wavelengths = dfs_load_table(frameset, "MASTER_LINECAT", 1);
00688 
00689     if (wavelengths == NULL)
00690         fors_wave_calib_lss_exit("Cannot load line catalog");
00691 
00692 
00693     /*
00694      * Cast the wavelengths into a (double precision) CPL vector
00695      */
00696 
00697     nlines = cpl_table_get_nrow(wavelengths);
00698 
00699     if (nlines == 0)
00700         fors_wave_calib_lss_exit("Empty input line catalog");
00701 
00702     if (cpl_table_has_column(wavelengths, wcolumn) != 1) {
00703         cpl_msg_error(recipe, "Missing column %s in input line catalog table",
00704                       wcolumn);
00705         fors_wave_calib_lss_exit(NULL);
00706     }
00707 
00708     line = cpl_malloc(nlines * sizeof(double));
00709 
00710     for (i = 0; i < nlines; i++)
00711         line[i] = cpl_table_get(wavelengths, wcolumn, i, NULL);
00712 
00713     cpl_table_delete(wavelengths); wavelengths = NULL;
00714 
00715     lines = cpl_vector_wrap(nlines, line);
00716 
00717 
00718     cpl_msg_indent_less();
00719     cpl_msg_info(recipe, "Perform wavelength calibration...");
00720     cpl_msg_indent_more();
00721 
00722     nx = cpl_image_get_size_x(spectra);
00723     ny = cpl_image_get_size_y(spectra);
00724 
00725     wavemap = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
00726     idscoeff_all = cpl_table_new(ny);
00727 
00728     if (mos_saturation_process(spectra))
00729     fors_wave_calib_lss_exit("Cannot process saturation");
00730 
00731     if (mos_subtract_background(spectra))
00732     fors_wave_calib_lss_exit("Cannot subtract the background");
00733 
00734     rectified = mos_wavelength_calibration_raw(spectra, lines, dispersion,
00735                                                peakdetection, wradius,
00736                                                wdegree, wreject, reference,
00737                                                &startwavelength,
00738                                                &endwavelength, NULL,
00739                                                NULL, idscoeff_all, wavemap,
00740                                                NULL, NULL, NULL, NULL);
00741 
00742     if (rectified == NULL)
00743         fors_wave_calib_lss_exit("Wavelength calibration failure.");
00744 
00745     cpl_image_delete(rectified); rectified = NULL;
00746 
00747     first_row = 0;
00748     while (!cpl_table_is_valid(idscoeff_all, "c0", first_row))
00749         first_row++;
00750 
00751     last_row = ny - 1;
00752     while (!cpl_table_is_valid(idscoeff_all, "c0", last_row))
00753         last_row--;
00754 
00755     ylow = first_row + 1;
00756     yhig = last_row + 1;
00757 
00758     dummy = cpl_image_extract(spectra, 1, ylow, nx, yhig);
00759     cpl_image_delete(spectra); spectra = dummy;
00760 
00761     ny = cpl_image_get_size_y(spectra);
00762 
00763     residual = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
00764 
00765     fiterror = cpl_calloc(ny, sizeof(double));
00766     fitlines = cpl_calloc(ny, sizeof(int));
00767     idscoeff = cpl_table_new(ny);
00768 
00769     if (mos_saturation_process(spectra))
00770     fors_wave_calib_lss_exit("Cannot process saturation");
00771 
00772     if (mos_subtract_background(spectra))
00773     fors_wave_calib_lss_exit("Cannot subtract the background");
00774 
00775     rectified = mos_wavelength_calibration_raw(spectra, lines, dispersion,
00776                                                peakdetection, wradius,
00777                                                wdegree, wreject, reference,
00778                                                &startwavelength,
00779                                                &endwavelength, fitlines,
00780                                                fiterror, idscoeff, NULL,
00781                                                residual, NULL, NULL, NULL);
00782 
00783     if (rectified == NULL)
00784         fors_wave_calib_lss_exit("Wavelength calibration failure.");
00785 
00786     /*
00787      * A dummy slit locations table
00788      */
00789 
00790     slits = cpl_table_new(1);
00791     cpl_table_new_column(slits, "slit_id", CPL_TYPE_INT);
00792     cpl_table_new_column(slits, "xtop", CPL_TYPE_DOUBLE);
00793     cpl_table_new_column(slits, "ytop", CPL_TYPE_DOUBLE);
00794     cpl_table_new_column(slits, "xbottom", CPL_TYPE_DOUBLE);
00795     cpl_table_new_column(slits, "ybottom", CPL_TYPE_DOUBLE);
00796     cpl_table_new_column(slits, "position", CPL_TYPE_INT);
00797     cpl_table_new_column(slits, "length", CPL_TYPE_INT);
00798     cpl_table_set_column_unit(slits, "xtop", "pixel");
00799     cpl_table_set_column_unit(slits, "ytop", "pixel");
00800     cpl_table_set_column_unit(slits, "xbottom", "pixel");
00801     cpl_table_set_column_unit(slits, "ybottom", "pixel");
00802     cpl_table_set_column_unit(slits, "position", "pixel");
00803     cpl_table_set_column_unit(slits, "length", "pixel");
00804     cpl_table_set_int(slits, "slit_id", 0, 0);
00805     cpl_table_set_double(slits, "xtop", 0, 0);
00806     cpl_table_set_double(slits, "ytop", 0, last_row);
00807     cpl_table_set_double(slits, "xbottom", 0, 0);
00808     cpl_table_set_double(slits, "ybottom", 0, first_row);
00809     cpl_table_set_int(slits, "position", 0, 0);
00810     cpl_table_set_int(slits, "length", 0, ny);
00811 
00812     if (dfs_save_table(frameset, slits, slit_location_tag, NULL,
00813                        parlist, recipe, version))
00814         fors_wave_calib_lss_exit(NULL);
00815 
00816     cpl_table_delete(slits); slits = NULL;
00817 
00818     if (wmode) {
00819         cpl_image_delete(rectified); rectified = NULL;
00820         cpl_image_delete(wavemap); wavemap = NULL;
00821 
00822         /*
00823          * Wavemap is intentionally NULL in the next two calls
00824          */
00825 
00826         mos_interpolate_wavecalib(idscoeff, wavemap, wmode, 2);
00827         mos_interpolate_wavecalib(idscoeff_all, wavemap, wmode, 2);
00828 
00829         wavemap = mos_map_idscoeff(idscoeff_all, nx, reference,
00830                                    startwavelength, endwavelength);
00831         rectified = mos_wavelength_calibration(spectra, reference,
00832                                                startwavelength,
00833                                                endwavelength, dispersion,
00834                                                idscoeff, 0);
00835     }
00836 
00837     cpl_table_delete(idscoeff_all); idscoeff_all = NULL;
00838 
00839     cpl_table_wrap_double(idscoeff, fiterror, "error"); fiterror = NULL;
00840     cpl_table_set_column_unit(idscoeff, "error", "pixel");
00841     cpl_table_wrap_int(idscoeff, fitlines, "nlines"); fitlines = NULL;
00842 
00843     for (i = 0; i < ny; i++)
00844         if (!cpl_table_is_valid(idscoeff, "c0", i))
00845             cpl_table_set_invalid(idscoeff, "error", i);
00846 
00847     cpl_msg_info(recipe, "Valid solutions found: %d out of %d rows",
00848                  ny - cpl_table_count_invalid(idscoeff, "c0"), ny);
00849 
00850     cpl_image_delete(spectra); spectra = NULL;
00851 
00852     mean_rms = mos_distortions_rms(rectified, lines, startwavelength,
00853                                    dispersion, 6, 0);
00854 
00855     cpl_msg_info(recipe, "Mean residual: %f pixel", mean_rms);
00856 
00857     mean_rms = cpl_table_get_column_mean(idscoeff, "error");
00858 
00859     cpl_msg_info(recipe, "Mean model accuracy: %f pixel (%f A)",
00860                  mean_rms, mean_rms * dispersion);
00861 
00862     restab = mos_resolution_table(rectified, startwavelength, dispersion,
00863                                   60000, lines);
00864 
00865     if (restab) {
00866         cpl_msg_info(recipe, "Mean spectral resolution: %.2f",
00867               cpl_table_get_column_mean(restab, "resolution"));
00868         cpl_msg_info(recipe,
00869               "Mean reference lines FWHM: %.2f +/- %.2f pixel",
00870               cpl_table_get_column_mean(restab, "fwhm") / dispersion,
00871               cpl_table_get_column_mean(restab, "fwhm_rms") / dispersion);
00872 
00873         if (dfs_save_table(frameset, restab, spectral_resolution_tag,
00874                            NULL, parlist, recipe, version))
00875             fors_wave_calib_lss_exit(NULL);
00876 
00877         cpl_table_delete(restab); restab = NULL;
00878 
00879     }
00880     else
00881         fors_wave_calib_lss_exit("Cannot compute the spectral "
00882                                  "resolution table");
00883 
00884     cpl_vector_delete(lines); lines = NULL;
00885 
00886 
00887     /*
00888      * Save rectified arc lamp spectrum to disk
00889      */
00890 
00891     save_header = cpl_propertylist_new();
00892     cpl_propertylist_update_double(save_header, "CRPIX1", 1.0);
00893     cpl_propertylist_update_double(save_header, "CRPIX2", 1.0);
00894     cpl_propertylist_update_double(save_header, "CRVAL1",
00895                                    startwavelength + dispersion/2);
00896     cpl_propertylist_update_double(save_header, "CRVAL2", 1.0);
00897     /* cpl_propertylist_update_double(save_header, "CDELT1", dispersion);
00898     cpl_propertylist_update_double(save_header, "CDELT2", 1.0); */
00899     cpl_propertylist_update_double(save_header, "CD1_1", dispersion);
00900     cpl_propertylist_update_double(save_header, "CD1_2", 0.0);
00901     cpl_propertylist_update_double(save_header, "CD2_1", 0.0);
00902     cpl_propertylist_update_double(save_header, "CD2_2", 1.0);
00903     cpl_propertylist_update_string(save_header, "CTYPE1", "LINEAR");
00904     cpl_propertylist_update_string(save_header, "CTYPE2", "PIXEL");
00905     cpl_propertylist_update_int(save_header, "ESO PRO DATANCOM", 1);
00906 
00907     if (dfs_save_image(frameset, rectified, reduced_lamp_tag, save_header,
00908                        parlist, recipe, version))
00909         fors_wave_calib_lss_exit(NULL);
00910 
00911     cpl_image_delete(rectified); rectified = NULL;
00912     cpl_propertylist_delete(save_header); save_header = NULL;
00913 
00914     if (dfs_save_table(frameset, idscoeff, disp_coeff_tag, NULL,
00915                        parlist, recipe, version))
00916         fors_wave_calib_lss_exit(NULL);
00917 
00918     cpl_table_delete(idscoeff); idscoeff = NULL;
00919 
00920     if (dfs_save_image(frameset, wavemap, wavelength_map_tag, header,
00921                        parlist, recipe, version))
00922         fors_wave_calib_lss_exit(NULL);
00923 
00924     cpl_image_delete(wavemap); wavemap = NULL;
00925     cpl_propertylist_delete(header); header = NULL;
00926     header = cpl_propertylist_new();
00927 
00928     cpl_propertylist_update_double(header, "CRPIX2", 1.0);
00929     cpl_propertylist_update_double(header, "CRVAL2", 1.0);
00930     /* cpl_propertylist_update_double(header, "CDELT2", 1.0); */
00931     cpl_propertylist_update_double(header, "CD1_1", 1.0);
00932     cpl_propertylist_update_double(header, "CD1_2", 0.0);
00933     cpl_propertylist_update_double(header, "CD2_1", 0.0);
00934     cpl_propertylist_update_double(header, "CD2_2", 1.0);
00935     cpl_propertylist_update_string(header, "CTYPE1", "LINEAR");
00936     cpl_propertylist_update_string(header, "CTYPE2", "PIXEL");
00937 
00938     if (dfs_save_image(frameset, residual, disp_residuals_tag, header,
00939                        parlist, recipe, version))
00940         fors_wave_calib_lss_exit(NULL);
00941 
00942     cpl_image_delete(residual); residual = NULL;
00943     cpl_propertylist_delete(header); header = NULL;
00944 
00945     return 0;
00946 }

Generated on 12 Feb 2016 for FORS Pipeline Reference Manual by  doxygen 1.6.1