fors_wave_calib_lss.c

00001 /* $Id: fors_wave_calib_lss.c,v 1.7 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.7 $
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 <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 (message) 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 (message) 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     int         nslits;
00440     double      mean_rms;
00441     double     *xpos;
00442     double      mxpos;
00443     int         narc;
00444     int         nlines;
00445     int         rebin;
00446     double     *line;
00447     double     *fiterror = NULL;
00448     int        *fitlines = NULL;
00449     int         nx, ny;
00450     int         first_row, last_row;
00451     int         ylow, yhig;
00452     double      reference;
00453     int         i;
00454 
00455     char       *instrume = NULL;
00456 
00457 
00458     cpl_msg_set_indentation(2);
00459 
00460     if (dfs_files_dont_exist(frameset))
00461         fors_wave_calib_lss_exit(NULL);
00462 
00463 
00464     /*
00465      * Get configuration parameters
00466      */
00467 
00468     cpl_msg_info(recipe, "Recipe %s configuration parameters:", recipe);
00469     cpl_msg_indent_more();
00470     
00471     if (cpl_frameset_count_tags(frameset, "GRISM_TABLE") > 1)
00472         fors_wave_calib_lss_exit("Too many in input: GRISM_TABLE"); 
00473 
00474     grism_table = dfs_load_table(frameset, "GRISM_TABLE", 1);
00475 
00476     dispersion = dfs_get_parameter_double(parlist,
00477                     "fors.fors_wave_calib_lss.dispersion", grism_table);
00478 
00479     if (dispersion <= 0.0)
00480         fors_wave_calib_lss_exit("Invalid spectral dispersion value");
00481 
00482     peakdetection = dfs_get_parameter_double(parlist,
00483                     "fors.fors_wave_calib_lss.peakdetection", grism_table);
00484     if (peakdetection <= 0.0)
00485         fors_wave_calib_lss_exit("Invalid peak detection level");
00486 
00487     wdegree = dfs_get_parameter_int(parlist,
00488                     "fors.fors_wave_calib_lss.wdegree", grism_table);
00489 
00490     if (wdegree < 1)
00491         fors_wave_calib_lss_exit("Invalid polynomial degree");
00492 
00493     if (wdegree > 5)
00494         fors_wave_calib_lss_exit("Max allowed polynomial degree is 5");
00495 
00496     wradius = dfs_get_parameter_int(parlist, 
00497                                     "fors.fors_wave_calib_lss.wradius", NULL);
00498 
00499     if (wradius < 0)
00500         fors_wave_calib_lss_exit("Invalid search radius");
00501 
00502     wreject = dfs_get_parameter_double(parlist, 
00503                                     "fors.fors_wave_calib_lss.wreject", NULL);
00504 
00505     if (wreject <= 0.0)
00506         fors_wave_calib_lss_exit("Invalid rejection threshold");
00507 
00508     wmode = dfs_get_parameter_int(parlist, 
00509                                     "fors.fors_wave_calib_lss.wmode", NULL);
00510 
00511     if (wmode < 0 || wmode > 2)
00512         fors_wave_calib_lss_exit("Invalid interpolation mode");
00513 
00514     wcolumn = dfs_get_parameter_string(parlist, 
00515                                     "fors.fors_wave_calib_lss.wcolumn", NULL);
00516 
00517     startwavelength = dfs_get_parameter_double(parlist,
00518                     "fors.fors_wave_calib_lss.startwavelength", grism_table);
00519     if (startwavelength > 1.0)
00520         if (startwavelength < 3000.0 || startwavelength > 13000.0)
00521             fors_wave_calib_lss_exit("Invalid wavelength");
00522 
00523     endwavelength = dfs_get_parameter_double(parlist,
00524                     "fors.fors_wave_calib_lss.endwavelength", grism_table);
00525     if (endwavelength > 1.0) {
00526         if (endwavelength < 3000.0 || endwavelength > 13000.0)
00527             fors_wave_calib_lss_exit("Invalid wavelength");
00528         if (startwavelength < 1.0)
00529             fors_wave_calib_lss_exit("Invalid wavelength interval");
00530     }
00531 
00532     if (startwavelength > 1.0)
00533         if (endwavelength - startwavelength <= 0.0)
00534             fors_wave_calib_lss_exit("Invalid wavelength interval");
00535 
00536     cpl_table_delete(grism_table); grism_table = NULL;
00537 
00538     if (cpl_error_get_code())
00539         fors_wave_calib_lss_exit("Failure reading the configuration "
00540                                  "parameters");
00541 
00542 
00543     cpl_msg_indent_less();
00544     cpl_msg_info(recipe, "Check input set-of-frames:");
00545     cpl_msg_indent_more();
00546 
00547     if (cpl_frameset_count_tags(frameset, "MASTER_LINECAT") == 0)
00548         fors_wave_calib_lss_exit("Missing required input: MASTER_LINECAT");
00549 
00550     if (cpl_frameset_count_tags(frameset, "MASTER_LINECAT") > 1)
00551         fors_wave_calib_lss_exit("Too many in input: MASTER_LINECAT");
00552 
00553     mxu = cpl_frameset_count_tags(frameset, "LAMP_UNBIAS_MXU");
00554     mos = cpl_frameset_count_tags(frameset, "LAMP_UNBIAS_MOS");
00555     lss = cpl_frameset_count_tags(frameset, "LAMP_UNBIAS_LSS");
00556 
00557     narc = mxu + mos + lss;
00558 
00559     if (narc == 0) {
00560         fors_wave_calib_lss_exit("Missing input long-slit arc lamp frame");
00561     }
00562     if (narc > 1) {
00563         cpl_msg_error(recipe, "Too many input arc lamp frames (%d > 1)", narc);
00564         fors_wave_calib_lss_exit(NULL);
00565     }
00566 
00567     if (mxu) {
00568         arc_tag                 = "LAMP_UNBIAS_MXU";
00569         slit_location_tag       = "SLIT_LOCATION_MXU";
00570         reduced_lamp_tag        = "REDUCED_LAMP_MXU";
00571         disp_residuals_tag      = "DISP_RESIDUALS_MXU";
00572         disp_coeff_tag          = "DISP_COEFF_MXU";
00573         wavelength_map_tag      = "WAVELENGTH_MAP_MXU";
00574         spectral_resolution_tag = "SPECTRAL_RESOLUTION_MXU";
00575     }
00576     else if (mos) {
00577         arc_tag                 = "LAMP_UNBIAS_MOS";
00578         slit_location_tag       = "SLIT_LOCATION_MOS";
00579         reduced_lamp_tag        = "REDUCED_LAMP_MOS";
00580         disp_residuals_tag      = "DISP_RESIDUALS_MOS";
00581         disp_coeff_tag          = "DISP_COEFF_MOS";
00582         wavelength_map_tag      = "WAVELENGTH_MAP_MOS";
00583         spectral_resolution_tag = "SPECTRAL_RESOLUTION_MOS";
00584     }
00585     else if (lss) {
00586         arc_tag                 = "LAMP_UNBIAS_LSS";
00587         slit_location_tag       = "SLIT_LOCATION_LSS";
00588         reduced_lamp_tag        = "REDUCED_LAMP_LSS";
00589         disp_residuals_tag      = "DISP_RESIDUALS_LSS";
00590         disp_coeff_tag          = "DISP_COEFF_LSS";
00591         wavelength_map_tag      = "WAVELENGTH_MAP_LSS";
00592         spectral_resolution_tag = "SPECTRAL_RESOLUTION_LSS";
00593     }
00594 
00595 
00596     if (!dfs_equal_keyword(frameset, "ESO INS GRIS1 ID"))
00597         fors_wave_calib_lss_exit("Input frames are not from the same grism");
00598 
00599     if (!dfs_equal_keyword(frameset, "ESO INS FILT1 ID"))
00600         fors_wave_calib_lss_exit("Input frames are not from the same filter");
00601 
00602     if (!dfs_equal_keyword(frameset, "ESO DET CHIP1 ID"))
00603         fors_wave_calib_lss_exit("Input frames are not from the same chip");
00604 
00605 
00606     /*
00607      * Get the reference wavelength and the rebin factor along the
00608      * dispersion direction from the arc lamp exposure
00609      */
00610 
00611     header = dfs_load_header(frameset, arc_tag, 0);
00612 
00613     if (header == NULL)
00614         fors_wave_calib_lss_exit("Cannot load arc lamp header");
00615 
00616     instrume = (char *)cpl_propertylist_get_string(header, "INSTRUME");
00617     if (instrume == NULL)
00618         fors_wave_calib_lss_exit("Missing keyword INSTRUME in arc lamp header");
00619 
00620     if (instrume[4] == '1')
00621         snprintf(version, 80, "%s/%s", "fors1", VERSION);
00622     if (instrume[4] == '2')
00623         snprintf(version, 80, "%s/%s", "fors2", VERSION);
00624 
00625     reference = cpl_propertylist_get_double(header, "ESO INS GRIS1 WLEN");
00626 
00627     if (cpl_error_get_code() != CPL_ERROR_NONE)
00628         fors_wave_calib_lss_exit("Missing keyword ESO INS GRIS1 WLEN "
00629                                  "in arc lamp frame header");
00630 
00631     if (reference < 3000.0)   /* Perhaps in nanometers... */
00632         reference *= 10;
00633 
00634     if (reference < 3000.0 || reference > 13000.0) {
00635         cpl_msg_error(recipe, "Invalid central wavelength %.2f read from "
00636                       "keyword ESO INS GRIS1 WLEN in arc lamp frame header",
00637                       reference);
00638         fors_wave_calib_lss_exit(NULL);
00639     }
00640 
00641     cpl_msg_info(recipe, "The central wavelength is: %.2f", reference);
00642 
00643     rebin = cpl_propertylist_get_int(header, "ESO DET WIN1 BINX");
00644 
00645     if (cpl_error_get_code() != CPL_ERROR_NONE)
00646         fors_wave_calib_lss_exit("Missing keyword ESO DET WIN1 BINX "
00647                                  "in arc lamp frame header");
00648 
00649     if (rebin != 1) {
00650         dispersion *= rebin;
00651         cpl_msg_warning(recipe, "The rebin factor is %d, and therefore the "
00652                         "working dispersion used is %f A/pixel", rebin,
00653                         dispersion);
00654     }
00655 
00656 
00657     if (mos || mxu) {
00658 
00659         /*
00660          * Check if all slits have the same X offset. If not, this is the
00661          * wrong recipe...
00662          */
00663 
00664         if (mos)
00665             maskslits = mos_load_slits_fors_mos(header);
00666         else
00667             maskslits = mos_load_slits_fors_mxu(header);
00668 
00669         mxpos = cpl_table_get_column_median(maskslits, "xtop");
00670         xpos = cpl_table_get_data_double(maskslits, "xtop");
00671         nslits = cpl_table_get_nrow(maskslits);
00672 
00673         treat_as_lss = 1;
00674         for (i = 0; i < nslits; i++) {
00675             if (fabs(mxpos-xpos[i]) > 0.01) {
00676                 treat_as_lss = 0;
00677                 break;
00678             }
00679         }
00680 
00681         cpl_table_delete(maskslits); maskslits = NULL;
00682 
00683         if (!treat_as_lss)
00684             fors_wave_calib_lss_exit("Input data are not long-slit data");
00685     }
00686 
00687 
00688     cpl_msg_indent_less();
00689     cpl_msg_info(recipe, "Load arc lamp exposure...");
00690     cpl_msg_indent_more();
00691 
00692     spectra = dfs_load_image(frameset, arc_tag, CPL_TYPE_FLOAT, 0, 0);
00693 
00694     if (spectra == NULL)
00695         fors_wave_calib_lss_exit("Cannot load arc lamp exposure");
00696 
00697 
00698     cpl_msg_indent_less();
00699     cpl_msg_info(recipe, "Load input line catalog...");
00700     cpl_msg_indent_more();
00701 
00702     wavelengths = dfs_load_table(frameset, "MASTER_LINECAT", 1);
00703 
00704     if (wavelengths == NULL)
00705         fors_wave_calib_lss_exit("Cannot load line catalog");
00706 
00707 
00708     /*
00709      * Cast the wavelengths into a (double precision) CPL vector
00710      */
00711 
00712     nlines = cpl_table_get_nrow(wavelengths);
00713 
00714     if (nlines == 0)
00715         fors_wave_calib_lss_exit("Empty input line catalog");
00716 
00717     if (cpl_table_has_column(wavelengths, wcolumn) != 1) {
00718         cpl_msg_error(recipe, "Missing column %s in input line catalog table",
00719                       wcolumn);
00720         fors_wave_calib_lss_exit(NULL);
00721     }
00722 
00723     line = cpl_malloc(nlines * sizeof(double));
00724 
00725     for (i = 0; i < nlines; i++)
00726         line[i] = cpl_table_get(wavelengths, wcolumn, i, NULL);
00727 
00728     cpl_table_delete(wavelengths); wavelengths = NULL;
00729 
00730     lines = cpl_vector_wrap(nlines, line);
00731 
00732 
00733     cpl_msg_indent_less();
00734     cpl_msg_info(recipe, "Perform wavelength calibration...");
00735     cpl_msg_indent_more();
00736 
00737     nx = cpl_image_get_size_x(spectra);
00738     ny = cpl_image_get_size_y(spectra);
00739 
00740     wavemap = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
00741     idscoeff_all = cpl_table_new(ny);
00742 
00743     if (mos_saturation_process(spectra))
00744     fors_wave_calib_lss_exit("Cannot process saturation");
00745 
00746     if (mos_subtract_background(spectra))
00747     fors_wave_calib_lss_exit("Cannot subtract the background");
00748 
00749     rectified = mos_wavelength_calibration_raw(spectra, lines, dispersion,
00750                                                peakdetection, wradius,
00751                                                wdegree, wreject, reference,
00752                                                &startwavelength,
00753                                                &endwavelength, NULL,
00754                                                NULL, idscoeff_all, wavemap,
00755                                                NULL, NULL, NULL);
00756 
00757     if (rectified == NULL)
00758         fors_wave_calib_lss_exit("Wavelength calibration failure.");
00759 
00760     cpl_image_delete(rectified); rectified = NULL;
00761 
00762     first_row = 0;
00763     while (!cpl_table_is_valid(idscoeff_all, "c0", first_row))
00764         first_row++;
00765 
00766     last_row = ny - 1;
00767     while (!cpl_table_is_valid(idscoeff_all, "c0", last_row))
00768         last_row--;
00769 
00770     ylow = first_row + 1;
00771     yhig = last_row + 1;
00772 
00773     dummy = cpl_image_extract(spectra, 1, ylow, nx, yhig);
00774     cpl_image_delete(spectra); spectra = dummy;
00775 
00776     ny = cpl_image_get_size_y(spectra);
00777 
00778     residual = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
00779 
00780     fiterror = cpl_calloc(ny, sizeof(double));
00781     fitlines = cpl_calloc(ny, sizeof(int));
00782     idscoeff = cpl_table_new(ny);
00783 
00784     if (mos_saturation_process(spectra))
00785     fors_wave_calib_lss_exit("Cannot process saturation");
00786 
00787     if (mos_subtract_background(spectra))
00788     fors_wave_calib_lss_exit("Cannot subtract the background");
00789 
00790     rectified = mos_wavelength_calibration_raw(spectra, lines, dispersion,
00791                                                peakdetection, wradius,
00792                                                wdegree, wreject, reference,
00793                                                &startwavelength,
00794                                                &endwavelength, fitlines,
00795                                                fiterror, idscoeff, NULL,
00796                                                residual, NULL, NULL);
00797 
00798     if (rectified == NULL)
00799         fors_wave_calib_lss_exit("Wavelength calibration failure.");
00800 
00801     /*
00802      * A dummy slit locations table
00803      */
00804 
00805     slits = cpl_table_new(1);
00806     cpl_table_new_column(slits, "slit_id", CPL_TYPE_INT);
00807     cpl_table_new_column(slits, "xtop", CPL_TYPE_DOUBLE);
00808     cpl_table_new_column(slits, "ytop", CPL_TYPE_DOUBLE);
00809     cpl_table_new_column(slits, "xbottom", CPL_TYPE_DOUBLE);
00810     cpl_table_new_column(slits, "ybottom", CPL_TYPE_DOUBLE);
00811     cpl_table_new_column(slits, "position", CPL_TYPE_INT);
00812     cpl_table_new_column(slits, "length", CPL_TYPE_INT);
00813     cpl_table_set_column_unit(slits, "xtop", "pixel");
00814     cpl_table_set_column_unit(slits, "ytop", "pixel");
00815     cpl_table_set_column_unit(slits, "xbottom", "pixel");
00816     cpl_table_set_column_unit(slits, "ybottom", "pixel");
00817     cpl_table_set_column_unit(slits, "position", "pixel");
00818     cpl_table_set_column_unit(slits, "length", "pixel");
00819     cpl_table_set_int(slits, "slit_id", 0, 0);
00820     cpl_table_set_double(slits, "xtop", 0, 0);
00821     cpl_table_set_double(slits, "ytop", 0, last_row);
00822     cpl_table_set_double(slits, "xbottom", 0, 0);
00823     cpl_table_set_double(slits, "ybottom", 0, first_row);
00824     cpl_table_set_int(slits, "position", 0, 0);
00825     cpl_table_set_int(slits, "length", 0, ny);
00826 
00827     if (dfs_save_table(frameset, slits, slit_location_tag, NULL,
00828                        parlist, recipe, version))
00829         fors_wave_calib_lss_exit(NULL);
00830 
00831     cpl_table_delete(slits); slits = NULL;
00832 
00833     if (wmode) {
00834         cpl_image_delete(rectified); rectified = NULL;
00835         cpl_image_delete(wavemap); wavemap = NULL;
00836 
00837         /*
00838          * Wavemap is intentionally NULL in the next two calls
00839          */
00840 
00841         mos_interpolate_wavecalib(idscoeff, wavemap, wmode, 2);
00842         mos_interpolate_wavecalib(idscoeff_all, wavemap, wmode, 2);
00843 
00844         wavemap = mos_map_idscoeff(idscoeff_all, nx, reference,
00845                                    startwavelength, endwavelength);
00846         rectified = mos_wavelength_calibration(spectra, reference,
00847                                                startwavelength,
00848                                                endwavelength, dispersion,
00849                                                idscoeff, 0);
00850     }
00851 
00852     cpl_table_delete(idscoeff_all); idscoeff_all = NULL;
00853 
00854     cpl_table_wrap_double(idscoeff, fiterror, "error"); fiterror = NULL;
00855     cpl_table_set_column_unit(idscoeff, "error", "pixel");
00856     cpl_table_wrap_int(idscoeff, fitlines, "nlines"); fitlines = NULL;
00857 
00858     for (i = 0; i < ny; i++)
00859         if (!cpl_table_is_valid(idscoeff, "c0", i))
00860             cpl_table_set_invalid(idscoeff, "error", i);
00861 
00862     cpl_msg_info(recipe, "Valid solutions found: %d out of %d rows",
00863                  ny - cpl_table_count_invalid(idscoeff, "c0"), ny);
00864 
00865     cpl_image_delete(spectra); spectra = NULL;
00866 
00867     mean_rms = mos_distortions_rms(rectified, lines, startwavelength,
00868                                    dispersion, 6, 0);
00869 
00870     cpl_msg_info(recipe, "Mean residual: %f pixel", mean_rms);
00871 
00872     mean_rms = cpl_table_get_column_mean(idscoeff, "error");
00873 
00874     cpl_msg_info(recipe, "Mean model accuracy: %f pixel (%f A)",
00875                  mean_rms, mean_rms * dispersion);
00876 
00877     restab = mos_resolution_table(rectified, startwavelength, dispersion,
00878                                   60000, lines);
00879 
00880     if (restab) {
00881         cpl_msg_info(recipe, "Mean spectral resolution: %.2f",
00882               cpl_table_get_column_mean(restab, "resolution"));
00883         cpl_msg_info(recipe,
00884               "Mean reference lines FWHM: %.2f +/- %.2f pixel",
00885               cpl_table_get_column_mean(restab, "fwhm") / dispersion,
00886               cpl_table_get_column_mean(restab, "fwhm_rms") / dispersion);
00887 
00888         if (dfs_save_table(frameset, restab, spectral_resolution_tag,
00889                            NULL, parlist, recipe, version))
00890             fors_wave_calib_lss_exit(NULL);
00891 
00892         cpl_table_delete(restab); restab = NULL;
00893 
00894     }
00895     else
00896         fors_wave_calib_lss_exit("Cannot compute the spectral "
00897                                  "resolution table");
00898 
00899     cpl_vector_delete(lines); lines = NULL;
00900 
00901 
00902     /*
00903      * Save rectified arc lamp spectrum to disk
00904      */
00905 
00906     save_header = cpl_propertylist_new();
00907     cpl_propertylist_update_double(save_header, "CRPIX1", 1.0);
00908     cpl_propertylist_update_double(save_header, "CRPIX2", 1.0);
00909     cpl_propertylist_update_double(save_header, "CRVAL1",
00910                                    startwavelength + dispersion/2);
00911     cpl_propertylist_update_double(save_header, "CRVAL2", 1.0);
00912     /* cpl_propertylist_update_double(save_header, "CDELT1", dispersion);
00913     cpl_propertylist_update_double(save_header, "CDELT2", 1.0); */
00914     cpl_propertylist_update_double(save_header, "CD1_1", dispersion);
00915     cpl_propertylist_update_double(save_header, "CD1_2", 0.0);
00916     cpl_propertylist_update_double(save_header, "CD2_1", 0.0);
00917     cpl_propertylist_update_double(save_header, "CD2_2", 1.0);
00918     cpl_propertylist_update_string(save_header, "CTYPE1", "LINEAR");
00919     cpl_propertylist_update_string(save_header, "CTYPE2", "PIXEL");
00920     cpl_propertylist_update_int(save_header, "ESO PRO DATANCOM", 1);
00921 
00922     if (dfs_save_image(frameset, rectified, reduced_lamp_tag, save_header,
00923                        parlist, recipe, version))
00924         fors_wave_calib_lss_exit(NULL);
00925 
00926     cpl_image_delete(rectified); rectified = NULL;
00927     cpl_propertylist_delete(save_header); save_header = NULL;
00928 
00929     if (dfs_save_table(frameset, idscoeff, disp_coeff_tag, NULL,
00930                        parlist, recipe, version))
00931         fors_wave_calib_lss_exit(NULL);
00932 
00933     cpl_table_delete(idscoeff); idscoeff = NULL;
00934 
00935     if (dfs_save_image(frameset, wavemap, wavelength_map_tag, header,
00936                        parlist, recipe, version))
00937         fors_wave_calib_lss_exit(NULL);
00938 
00939     cpl_image_delete(wavemap); wavemap = NULL;
00940     cpl_propertylist_delete(header); header = NULL;
00941     header = cpl_propertylist_new();
00942 
00943     cpl_propertylist_update_double(header, "CRPIX2", 1.0);
00944     cpl_propertylist_update_double(header, "CRVAL2", 1.0);
00945     /* cpl_propertylist_update_double(header, "CDELT2", 1.0); */
00946     cpl_propertylist_update_double(header, "CD1_1", 1.0);
00947     cpl_propertylist_update_double(header, "CD1_2", 0.0);
00948     cpl_propertylist_update_double(header, "CD2_1", 0.0);
00949     cpl_propertylist_update_double(header, "CD2_2", 1.0);
00950     cpl_propertylist_update_string(header, "CTYPE1", "LINEAR");
00951     cpl_propertylist_update_string(header, "CTYPE2", "PIXEL");
00952 
00953     if (dfs_save_image(frameset, residual, disp_residuals_tag, header,
00954                        parlist, recipe, version))
00955         fors_wave_calib_lss_exit(NULL);
00956 
00957     cpl_image_delete(residual); residual = NULL;
00958     cpl_propertylist_delete(header); header = NULL;
00959 
00960     return 0;
00961 }

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