FORS Pipeline Reference Manual 4.9.20
fors_align_sky_lss.c
00001 /* $Id: fors_align_sky_lss.c,v 1.6 2013/02/28 15:12:57 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/02/28 15:12:57 $
00024  * $Revision: 1.6 $
00025  * $Name: fors-4_9_20 $
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_align_sky_lss_create(cpl_plugin *);
00038 static int fors_align_sky_lss_exec(cpl_plugin *);
00039 static int fors_align_sky_lss_destroy(cpl_plugin *);
00040 static int fors_align_sky_lss(cpl_parameterlist *, cpl_frameset *);
00041 
00042 static char fors_align_sky_lss_description[] =
00043 "This recipe is used to align the wavelength solution based on the arc\n"
00044 "lamp exposure on a set of sky lines observed on a scientific exposure.\n"
00045 "The input scientific frames are produced by the recipes fors_remove_bias\n"
00046 "and fors_flatfield. An input catalog of sky lines can be specified, or\n"
00047 "an internal one is used.\n"
00048 "\n"
00049 "This recipe should be applied to LSS or long-slit like data (MOS/MXU with\n"
00050 "all slits at the same offset). For multi-slit MOS/MXU data use recipe\n"
00051 "fors_align_sky instead. Please refer to the FORS PIpeline User's Manual\n"
00052 "for more details.\n"
00053 "\n"
00054 "In the table below the MXU acronym can be alternatively read as MOS and\n"
00055 "LSS, and SCI as STD.\n\n"
00056 "Input files:\n\n"
00057 "  DO category:               Type:       Explanation:         Required:\n"
00058 "  SCIENCE_UNBIAS_MXU\n"
00059 "  or SCIENCE_UNFLAT_MXU\n"
00060 "  or STANDARD_UNBIAS_MXU\n"
00061 "  or STANDARD_UNFLAT_MXU     Calib       Frame with sky lines    Y\n"
00062 "  DISP_COEFF_MXU             Calib       Dispersion solution     Y\n"
00063 "  SLIT_LOCATION_MXU          Calib       Slit location on CCD    Y\n"
00064 "  MASTER_SKYLINECAT          Calib       Catalog of sky lines    .\n"
00065 "  GRISM_TABLE                Calib       Grism table             .\n\n"
00066 "Output files:\n\n"
00067 "  DO category:               Data type:  Explanation:\n"
00068 "  SKY_SHIFTS_LONG_SCI_MXU    FITS table  Observed sky lines offsets\n"
00069 "  WAVELENGTH_MAP_SCI_MXU     FITS image  Wavelength mapped on CCD\n"
00070 "  DISP_COEFF_SCI_MXU         FITS image  Upgraded dispersion solution\n\n";
00071 
00072 #define fors_align_sky_lss_exit(message)          \
00073 {                                             \
00074 if (message) cpl_msg_error(recipe, message);  \
00075 cpl_image_delete(wavemap);                    \
00076 cpl_image_delete(rainbow);                    \
00077 cpl_image_delete(smapped);                    \
00078 cpl_table_delete(grism_table);                \
00079 cpl_table_delete(maskslits);                  \
00080 cpl_table_delete(wavelengths);                \
00081 cpl_table_delete(offsets);                    \
00082 cpl_table_delete(slits);                      \
00083 cpl_table_delete(idscoeff);                   \
00084 cpl_vector_delete(lines);                     \
00085 cpl_propertylist_delete(header);              \
00086 cpl_msg_indent_less();                        \
00087 return -1;                                    \
00088 }
00089 
00090 #define fors_align_sky_lss_exit_memcheck(message)   \
00091 {                                               \
00092 if (message) cpl_msg_info(recipe, message);     \
00093 printf("free wavemap (%p)\n", wavemap);         \
00094 cpl_image_delete(wavemap);                      \
00095 printf("free rainbow (%p)\n", rainbow);         \
00096 cpl_image_delete(rainbow);                      \
00097 printf("free smapped (%p)\n", smapped);         \
00098 cpl_image_delete(smapped);                      \
00099 printf("free grism_table (%p)\n", grism_table); \
00100 cpl_table_delete(grism_table);                  \
00101 printf("free maskslits (%p)\n", maskslits);     \
00102 cpl_table_delete(maskslits);                    \
00103 printf("free wavelengths (%p)\n", wavelengths); \
00104 cpl_table_delete(wavelengths);                  \
00105 printf("free offsets (%p)\n", offsets);         \
00106 cpl_table_delete(offsets);                      \
00107 printf("free idscoeff (%p)\n", idscoeff);       \
00108 cpl_table_delete(idscoeff);                     \
00109 printf("free slits (%p)\n", slits);             \
00110 cpl_table_delete(slits);                        \
00111 printf("free lines (%p)\n", lines);             \
00112 cpl_vector_delete(lines);                       \
00113 printf("free header (%p)\n", header);           \
00114 cpl_propertylist_delete(header);                \
00115 cpl_msg_indent_less();                          \
00116 return 0;                                       \
00117 }
00118 
00119 
00131 int cpl_plugin_get_info(cpl_pluginlist *list)
00132 {
00133     cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe );
00134     cpl_plugin *plugin = &recipe->interface;
00135 
00136     cpl_plugin_init(plugin,
00137                     CPL_PLUGIN_API,
00138                     FORS_BINARY_VERSION,
00139                     CPL_PLUGIN_TYPE_RECIPE,
00140                     "fors_align_sky_lss",
00141                     "Upgrade wavelength solution using sky lines",
00142                     fors_align_sky_lss_description,
00143                     "Carlo Izzo",
00144                     PACKAGE_BUGREPORT,
00145     "This file is currently part of the FORS Instrument Pipeline\n"
00146     "Copyright (C) 2002-2010 European Southern Observatory\n\n"
00147     "This program is free software; you can redistribute it and/or modify\n"
00148     "it under the terms of the GNU General Public License as published by\n"
00149     "the Free Software Foundation; either version 2 of the License, or\n"
00150     "(at your option) any later version.\n\n"
00151     "This program is distributed in the hope that it will be useful,\n"
00152     "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
00153     "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
00154     "GNU General Public License for more details.\n\n"
00155     "You should have received a copy of the GNU General Public License\n"
00156     "along with this program; if not, write to the Free Software Foundation,\n"
00157     "Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\n",
00158                     fors_align_sky_lss_create,
00159                     fors_align_sky_lss_exec,
00160                     fors_align_sky_lss_destroy);
00161 
00162     cpl_pluginlist_append(list, plugin);
00163     
00164     return 0;
00165 }
00166 
00167 
00178 static int fors_align_sky_lss_create(cpl_plugin *plugin)
00179 {
00180     cpl_recipe    *recipe;
00181     cpl_parameter *p;
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 (empty) parameters list in the cpl_recipe object 
00194      */
00195 
00196     recipe->parameters = cpl_parameterlist_new(); 
00197 
00198     /*
00199      * Dispersion
00200      */
00201 
00202     p = cpl_parameter_new_value("fors.fors_align_sky_lss.dispersion",
00203                                 CPL_TYPE_DOUBLE,
00204                                 "Expected spectral dispersion (Angstrom/pixel)",
00205                                 "fors.fors_align_sky_lss",
00206                                 0.0);
00207     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "dispersion");
00208     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00209     cpl_parameterlist_append(recipe->parameters, p);
00210 
00211     /*
00212      * Start wavelength for spectral extraction
00213      */
00214 
00215     p = cpl_parameter_new_value("fors.fors_align_sky_lss.startwavelength",
00216                                 CPL_TYPE_DOUBLE,
00217                                 "Start wavelength in spectral extraction",
00218                                 "fors.fors_align_sky_lss",
00219                                 0.0);
00220     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "startwavelength");
00221     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00222     cpl_parameterlist_append(recipe->parameters, p);
00223 
00224     /*
00225      * End wavelength for spectral extraction
00226      */
00227 
00228     p = cpl_parameter_new_value("fors.fors_align_sky_lss.endwavelength",
00229                                 CPL_TYPE_DOUBLE,
00230                                 "End wavelength in spectral extraction",
00231                                 "fors.fors_align_sky_lss",
00232                                 0.0);
00233     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "endwavelength");
00234     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00235     cpl_parameterlist_append(recipe->parameters, p);
00236 
00237     /*
00238      * Sky lines alignment
00239      */
00240 
00241     p = cpl_parameter_new_value("fors.fors_align_sky_lss.skyalign",
00242                                 CPL_TYPE_INT,
00243                                 "Polynomial order for sky lines alignment",
00244                                 "fors.fors_align_sky_lss",
00245                                 0);
00246     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "skyalign");
00247     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00248     cpl_parameterlist_append(recipe->parameters, p);
00249 
00250     /*
00251      * Line catalog table column containing the sky reference wavelengths
00252      */
00253     
00254     p = cpl_parameter_new_value("fors.fors_align_sky_lss.wcolumn",
00255                                 CPL_TYPE_STRING,
00256                                 "Name of sky line catalog table column "
00257                                 "with wavelengths",
00258                                 "fors.fors_align_sky_lss",
00259                                 "WLEN");
00260     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcolumn");
00261     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00262     cpl_parameterlist_append(recipe->parameters, p);
00263 
00264     return 0;
00265 }
00266 
00267 
00276 static int fors_align_sky_lss_exec(cpl_plugin *plugin)
00277 {
00278     cpl_recipe *recipe;
00279     
00280     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00281         recipe = (cpl_recipe *)plugin;
00282     else 
00283         return -1;
00284 
00285     return fors_align_sky_lss(recipe->parameters, recipe->frames);
00286 }
00287 
00288 
00297 static int fors_align_sky_lss_destroy(cpl_plugin *plugin)
00298 {
00299     cpl_recipe *recipe;
00300     
00301     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00302         recipe = (cpl_recipe *)plugin;
00303     else 
00304         return -1;
00305 
00306     cpl_parameterlist_delete(recipe->parameters); 
00307 
00308     return 0;
00309 }
00310 
00311 
00321 static int fors_align_sky_lss(cpl_parameterlist *parlist, 
00322                                cpl_frameset *frameset)
00323 {
00324 
00325     const char *recipe = "fors_align_sky_lss";
00326 
00327 
00328     /*
00329      * Input parameters
00330      */
00331 
00332     double      dispersion;
00333     double      startwavelength;
00334     double      endwavelength;
00335     int         skyalign;
00336     const char *wcolumn;
00337 
00338     /*
00339      * CPL objects
00340      */
00341 
00342     cpl_image        *rainbow     = NULL;
00343     cpl_image        *wavemap     = NULL;
00344     cpl_image        *smapped     = NULL;
00345     cpl_image        *dummy       = NULL;
00346     cpl_table        *grism_table = NULL;
00347     cpl_table        *wavelengths = NULL;
00348     cpl_table        *slits       = NULL;
00349     cpl_table        *idscoeff    = NULL;
00350     cpl_table        *maskslits   = NULL;
00351     cpl_table        *offsets     = NULL;
00352     cpl_vector       *lines       = NULL;
00353     cpl_propertylist *header      = NULL;
00354 
00355     /*
00356      * Auxiliary variables
00357      */
00358 
00359     char        version[80];
00360     const char *slit_location_tag;
00361     const char *rectified_tag;
00362     const char *wavemap_tag;
00363     const char *shifts_tag;
00364     const char *disp_ali_tag;
00365     const char *disp_coeff_tag;
00366     int         nframes;
00367     int         rebin;
00368     int         nslits;
00369     int         nlines;
00370     int         nx, ny;
00371     int         ccd_xsize, ccd_ysize;
00372     int         first_row, last_row;
00373     int         ylow, yhig;
00374     int         highres;
00375     int         treat_as_lss;
00376     int         i;
00377     double      reference;
00378     double     *xpos;
00379     double      mxpos;
00380     double     *line;
00381     int         mxu, mos, lss;
00382     int         rec_scib;
00383     int         rec_stdb;
00384     int         rec_scif;
00385     int         rec_stdf;
00386     int         nslits_out_det = 0;
00387 
00388     char       *instrume = NULL;
00389 
00390 
00391     cpl_msg_set_indentation(2);
00392 
00393     if (dfs_files_dont_exist(frameset))
00394         fors_align_sky_lss_exit(NULL);
00395 
00396 
00397     /*
00398      * Get configuration parameters
00399      */
00400 
00401     cpl_msg_info(recipe, "Recipe %s configuration parameters:", recipe);
00402     cpl_msg_indent_more();
00403     
00404     if (cpl_frameset_count_tags(frameset, "GRISM_TABLE") > 1)
00405         fors_align_sky_lss_exit("Too many in input: GRISM_TABLE"); 
00406 
00407     grism_table = dfs_load_table(frameset, "GRISM_TABLE", 1);
00408 
00409     dispersion = dfs_get_parameter_double(parlist,
00410                     "fors.fors_align_sky_lss.dispersion", grism_table);
00411 
00412     if (dispersion <= 0.0)
00413         fors_align_sky_lss_exit("Invalid spectral dispersion value");
00414 
00415     startwavelength = dfs_get_parameter_double(parlist,
00416                     "fors.fors_align_sky_lss.startwavelength", grism_table);
00417     if (startwavelength > 1.0)
00418         if (startwavelength < 3000.0 || startwavelength > 13000.0)
00419             fors_align_sky_lss_exit("Invalid wavelength");
00420 
00421     endwavelength = dfs_get_parameter_double(parlist,
00422                     "fors.fors_align_sky_lss.endwavelength", grism_table);
00423     if (endwavelength > 1.0) {
00424         if (endwavelength < 3000.0 || endwavelength > 13000.0)
00425             fors_align_sky_lss_exit("Invalid wavelength");
00426         if (startwavelength < 1.0)
00427             fors_align_sky_lss_exit("Invalid wavelength interval");
00428     }
00429 
00430     if (startwavelength > 1.0)
00431         if (endwavelength - startwavelength <= 0.0)
00432             fors_align_sky_lss_exit("Invalid wavelength interval");
00433 
00434     skyalign = dfs_get_parameter_int(parlist,
00435                     "fors.fors_align_sky_lss.skyalign", NULL);
00436 
00437     if (skyalign < 0)
00438         fors_align_sky_lss_exit("Invalid polynomial degree");
00439     if (skyalign > 2)
00440         fors_align_sky_lss_exit("Max polynomial degree for sky alignment is 2");
00441 
00442     wcolumn = dfs_get_parameter_string(parlist,
00443                     "fors.fors_align_sky_lss.wcolumn", NULL);
00444 
00445     cpl_table_delete(grism_table); grism_table = NULL;
00446 
00447     if (cpl_error_get_code())
00448         fors_align_sky_lss_exit("Failure reading the configuration parameters");
00449 
00450 
00451     cpl_msg_indent_less();
00452     cpl_msg_info(recipe, "Check input set-of-frames:");
00453     cpl_msg_indent_more();
00454 
00455     mxu  = cpl_frameset_count_tags(frameset, "SLIT_LOCATION_MXU");
00456     mos  = cpl_frameset_count_tags(frameset, "SLIT_LOCATION_MOS");
00457     lss  = cpl_frameset_count_tags(frameset, "SLIT_LOCATION_LSS");
00458 
00459     nframes = mos + mxu + lss;
00460 
00461     if (nframes == 0) {
00462         fors_align_sky_lss_exit("Missing input slit location table");
00463     }
00464     if (nframes > 1) {
00465         cpl_msg_error(recipe, 
00466                       "Too many input slit location tables (%d > 1)", nframes);
00467         fors_align_sky_lss_exit(NULL);
00468     }
00469 
00470     if (mxu) {
00471         rec_scib = cpl_frameset_count_tags(frameset, "SCIENCE_UNBIAS_MXU");
00472         rec_stdb = cpl_frameset_count_tags(frameset, "STANDARD_UNBIAS_MXU");
00473         rec_scif = cpl_frameset_count_tags(frameset, "SCIENCE_UNFLAT_MXU");
00474         rec_stdf = cpl_frameset_count_tags(frameset, "STANDARD_UNFLAT_MXU");
00475     }
00476     else if (mos) {
00477         rec_scib = cpl_frameset_count_tags(frameset, "SCIENCE_UNBIAS_MOS");
00478         rec_stdb = cpl_frameset_count_tags(frameset, "STANDARD_UNBIAS_MOS");
00479         rec_scif = cpl_frameset_count_tags(frameset, "SCIENCE_UNFLAT_MOS");
00480         rec_stdf = cpl_frameset_count_tags(frameset, "STANDARD_UNFLAT_MOS");
00481     }
00482     else {
00483         rec_scib = cpl_frameset_count_tags(frameset, "SCIENCE_UNBIAS_LSS");
00484         rec_stdb = cpl_frameset_count_tags(frameset, "STANDARD_UNBIAS_LSS");
00485         rec_scif = cpl_frameset_count_tags(frameset, "SCIENCE_UNFLAT_LSS");
00486         rec_stdf = cpl_frameset_count_tags(frameset, "STANDARD_UNFLAT_LSS");
00487     }
00488 
00489     nframes = rec_scib + rec_stdb + rec_scif + rec_stdf;
00490 
00491     if (nframes == 0) {
00492         fors_align_sky_lss_exit("Missing input scientific spectra");
00493     }
00494     if (nframes > 1) {
00495         cpl_msg_error(recipe, "Too many input scientific spectra (%d > 1)", 
00496                       nframes);
00497         fors_align_sky_lss_exit(NULL);
00498     }
00499 
00500     if (cpl_frameset_count_tags(frameset, "MASTER_SKYLINECAT") > 1)
00501         fors_align_sky_lss_exit("Too many in input: MASTER_SKYLINECAT");
00502 
00503     if (rec_scib) {
00504         if (mxu) {
00505             rectified_tag = "SCIENCE_UNBIAS_MXU";
00506             wavemap_tag   = "WAVELENGTH_MAP_SCI_MXU";
00507             shifts_tag    = "SKY_SHIFTS_LONG_SCI_MXU";
00508             disp_ali_tag  = "DISP_COEFF_SCI_MXU";
00509         }
00510         else if (mos) {
00511             rectified_tag = "SCIENCE_UNBIAS_MOS";
00512             wavemap_tag   = "WAVELENGTH_MAP_SCI_MOS";
00513             shifts_tag    = "SKY_SHIFTS_LONG_SCI_MOS";
00514             disp_ali_tag  = "DISP_COEFF_SCI_MOS";
00515         }
00516         else {
00517             rectified_tag = "SCIENCE_UNBIAS_LSS";
00518             wavemap_tag   = "WAVELENGTH_MAP_SCI_LSS";
00519             shifts_tag    = "SKY_SHIFTS_LONG_SCI_LSS";
00520             disp_ali_tag  = "DISP_COEFF_SCI_LSS";
00521         }
00522     }
00523     else if (rec_stdb) {
00524         if (mxu) {
00525             rectified_tag = "STANDARD_UNBIAS_MXU";
00526             wavemap_tag   = "WAVELENGTH_MAP_STD_MXU";
00527             shifts_tag    = "SKY_SHIFTS_LONG_STD_MXU";
00528             disp_ali_tag  = "DISP_COEFF_STD_MXU";
00529         }
00530         else if (mos) {
00531             rectified_tag = "STANDARD_UNBIAS_MOS";
00532             wavemap_tag   = "WAVELENGTH_MAP_STD_MOS";
00533             shifts_tag    = "SKY_SHIFTS_LONG_STD_MOS";
00534             disp_ali_tag  = "DISP_COEFF_STD_MOS";
00535         }
00536         else { 
00537             rectified_tag = "STANDARD_UNBIAS_LSS";
00538             wavemap_tag   = "WAVELENGTH_MAP_STD_LSS";
00539             shifts_tag    = "SKY_SHIFTS_LONG_STD_LSS";
00540             disp_ali_tag  = "DISP_COEFF_STD_LSS";
00541         }
00542     }
00543     else if (rec_scif) {
00544         if (mxu) {
00545             rectified_tag = "SCIENCE_UNFLAT_MXU";
00546             wavemap_tag   = "WAVELENGTH_MAP_SCI_MXU";
00547             shifts_tag    = "SKY_SHIFTS_LONG_SCI_MXU";
00548             disp_ali_tag  = "DISP_COEFF_SCI_MXU";
00549         }
00550         else if (mos) {   
00551             rectified_tag = "SCIENCE_UNFLAT_MOS";
00552             wavemap_tag   = "WAVELENGTH_MAP_SCI_MOS";
00553             shifts_tag    = "SKY_SHIFTS_LONG_SCI_MOS";
00554             disp_ali_tag  = "DISP_COEFF_SCI_MOS";
00555         }
00556         else {
00557             rectified_tag = "SCIENCE_UNFLAT_LSS";
00558             wavemap_tag   = "WAVELENGTH_MAP_SCI_LSS";
00559             shifts_tag    = "SKY_SHIFTS_LONG_SCI_LSS";
00560             disp_ali_tag  = "DISP_COEFF_SCI_LSS";
00561         }
00562     }
00563     else if (rec_stdf) {
00564         if (mxu) {
00565             rectified_tag = "STANDARD_UNFLAT_MXU";
00566             wavemap_tag   = "WAVELENGTH_MAP_STD_MXU";
00567             shifts_tag    = "SKY_SHIFTS_LONG_STD_MXU";
00568             disp_ali_tag  = "DISP_COEFF_STD_MXU";
00569         }
00570         else if (mos) {   
00571             rectified_tag = "STANDARD_UNFLAT_MOS";
00572             wavemap_tag   = "WAVELENGTH_MAP_STD_MOS";
00573             shifts_tag    = "SKY_SHIFTS_LONG_STD_MOS";
00574             disp_ali_tag  = "DISP_COEFF_STD_MOS";
00575         }
00576         else {
00577             rectified_tag = "STANDARD_UNFLAT_LSS";
00578             wavemap_tag   = "WAVELENGTH_MAP_STD_LSS";
00579             shifts_tag    = "SKY_SHIFTS_LONG_STD_LSS";
00580             disp_ali_tag  = "DISP_COEFF_STD_LSS";
00581         }
00582     }
00583 
00584     nframes = cpl_frameset_count_tags(frameset, rectified_tag);
00585 
00586     if (nframes == 0) {
00587         cpl_msg_error(recipe, "Missing input %s", rectified_tag);
00588         fors_align_sky_lss_exit(NULL);
00589     }
00590     if (nframes > 1) {
00591         cpl_msg_error(recipe, "Too many input %s (%d > 1)", rectified_tag,
00592                       nframes);
00593         fors_align_sky_lss_exit(NULL);
00594     }
00595 
00596 
00597     if (mxu) {
00598         disp_coeff_tag    = "DISP_COEFF_MXU";
00599         slit_location_tag = "SLIT_LOCATION_MXU";
00600     }
00601     else if (mos) {
00602         disp_coeff_tag    = "DISP_COEFF_MOS";
00603         slit_location_tag = "SLIT_LOCATION_MOS";
00604     }
00605     else {
00606         disp_coeff_tag    = "DISP_COEFF_LSS";
00607         slit_location_tag = "SLIT_LOCATION_LSS";
00608     }
00609 
00610     nframes = cpl_frameset_count_tags(frameset, disp_coeff_tag);
00611 
00612     if (nframes == 0) {
00613         cpl_msg_error(recipe, "Missing input %s", disp_coeff_tag);
00614         fors_align_sky_lss_exit(NULL);
00615     }
00616     if (nframes > 1) {
00617         cpl_msg_error(recipe, "Too many input %s (%d > 1)", disp_coeff_tag,
00618                       nframes);
00619         fors_align_sky_lss_exit(NULL);
00620     }
00621 
00622 
00623     header = dfs_load_header(frameset, rectified_tag, 0);
00624 
00625     if (header == NULL)
00626         fors_align_sky_lss_exit("Cannot load scientific frame header");
00627 
00628     if (mos || mxu) {
00629         if (mos)
00630             maskslits = mos_load_slits_fors_mos(header, &nslits_out_det);
00631         else
00632             maskslits = mos_load_slits_fors_mxu(header);
00633 
00634         /*
00635          * Check if all slits have the same X offset: if not, abort!
00636          */
00637 
00638         treat_as_lss = fors_mos_is_lss_like(maskslits, nslits_out_det);
00639 
00640         cpl_table_delete(maskslits); maskslits = NULL;
00641 
00642         if (!treat_as_lss)
00643             fors_align_sky_lss_exit("This is not an LSS observation. "
00644                                     "Please use recipe fors_align_sky");
00645     }
00646 
00647     if (!dfs_equal_keyword(frameset, "ESO INS GRIS1 ID"))
00648         fors_align_sky_lss_exit("Input frames are not from the same grism");
00649 
00650     if (!dfs_equal_keyword(frameset, "ESO INS FILT1 ID"))
00651         fors_align_sky_lss_exit("Input frames are not from the same filter");
00652 
00653     if (!dfs_equal_keyword(frameset, "ESO DET CHIP1 ID"))
00654         fors_align_sky_lss_exit("Input frames are not from the same chip");
00655 
00656 
00657     /*
00658      * Get the reference wavelength and the rebin factor along the
00659      * dispersion direction from the reference frame
00660      */
00661 
00662     instrume = (char *)cpl_propertylist_get_string(header, "INSTRUME");
00663     if (instrume == NULL)
00664         fors_align_sky_lss_exit("Missing keyword INSTRUME in reference frame "
00665                             "header");
00666 
00667     if (instrume[4] == '1')
00668         snprintf(version, 80, "%s/%s", "fors1", VERSION);
00669     if (instrume[4] == '2')
00670         snprintf(version, 80, "%s/%s", "fors2", VERSION);
00671 
00672     reference = cpl_propertylist_get_double(header, "ESO INS GRIS1 WLEN");
00673 
00674     if (cpl_error_get_code() != CPL_ERROR_NONE)
00675         fors_align_sky_lss_exit("Missing keyword ESO INS GRIS1 WLEN "
00676                             "in reference frame header");
00677 
00678     if (reference < 3000.0)   /* Perhaps in nanometers... */
00679         reference *= 10;
00680 
00681     if (reference < 3000.0 || reference > 13000.0) {
00682         cpl_msg_error(recipe, "Invalid central wavelength %.2f read from "
00683                       "keyword ESO INS GRIS1 WLEN in reference frame header",
00684                       reference);
00685         fors_align_sky_lss_exit(NULL);
00686     }
00687 
00688     cpl_msg_info(recipe, "The central wavelength is: %.2f", reference);
00689 
00690     rebin = cpl_propertylist_get_int(header, "ESO DET WIN1 BINX");
00691 
00692     if (cpl_error_get_code() != CPL_ERROR_NONE)
00693         fors_align_sky_lss_exit("Missing keyword ESO DET WIN1 BINX "
00694                             "in reference frame header");
00695 
00696     if (rebin != 1) {
00697         dispersion *= rebin;
00698         cpl_msg_warning(recipe, "The rebin factor is %d, and therefore the "
00699                         "working dispersion used is %f A/pixel", rebin,
00700                         dispersion);
00701     }
00702 
00703 
00704     cpl_msg_indent_less();
00705     cpl_msg_info(recipe, "Load input frames...");
00706     cpl_msg_indent_more();
00707 
00708     smapped = dfs_load_image(frameset, rectified_tag, CPL_TYPE_FLOAT, 0, 0);
00709     if (smapped == NULL)
00710         fors_align_sky_lss_exit("Cannot load input scientific frame");
00711 
00712     slits = dfs_load_table(frameset, slit_location_tag, 1);
00713     if (slits == NULL)
00714         fors_align_sky_lss_exit("Cannot load slits location table");
00715 
00716     first_row = cpl_table_get_double(slits, "ybottom", 0, NULL);
00717     last_row = cpl_table_get_double(slits, "ytop", 0, NULL);
00718 
00719     ylow = first_row + 1;
00720     yhig = last_row + 1;
00721 
00722     ccd_xsize = cpl_image_get_size_x(smapped);
00723     ccd_ysize = cpl_image_get_size_x(smapped);
00724     dummy = cpl_image_extract(smapped, 1, ylow, ccd_xsize, yhig);
00725     cpl_image_delete(smapped); smapped = dummy;
00726     nx = ccd_xsize;
00727     ny = cpl_image_get_size_y(smapped);
00728 
00729     cpl_table_delete(slits); slits = NULL;
00730 
00731     idscoeff = dfs_load_table(frameset, disp_coeff_tag, 1);
00732     if (idscoeff == NULL)
00733         fors_align_sky_lss_exit("Cannot load dispersion solution");
00734 
00735     wavelengths = dfs_load_table(frameset, "MASTER_SKYLINECAT", 1);
00736 
00737     if (wavelengths) {
00738 
00739         /*
00740          * Cast the wavelengths into a (double precision) CPL vector
00741          */
00742 
00743         nlines = cpl_table_get_nrow(wavelengths);
00744 
00745         if (nlines == 0)
00746             fors_align_sky_lss_exit("Empty input sky line catalog");
00747 
00748         if (cpl_table_has_column(wavelengths, wcolumn) != 1) {
00749             cpl_msg_error(recipe, "Missing column %s in input line "
00750                           "catalog table", wcolumn);
00751             fors_align_sky_lss_exit(NULL);
00752         }
00753 
00754         line = cpl_malloc(nlines * sizeof(double));
00755 
00756         for (i = 0; i < nlines; i++)
00757             line[i] = cpl_table_get(wavelengths, wcolumn, i, NULL);
00758 
00759         cpl_table_delete(wavelengths); wavelengths = NULL;
00760 
00761         lines = cpl_vector_wrap(nlines, line);
00762     }
00763     else {
00764         cpl_msg_info(recipe, "No sky line catalog found in input - fine!");
00765     }
00766 
00767     if (skyalign) {
00768         cpl_msg_info(recipe, "Align wavelength solution to reference "
00769         "skylines applying %d order residual fit...", skyalign);
00770     }
00771     else {
00772         cpl_msg_info(recipe, "Align wavelength solution to reference "
00773         "skylines applying median offset...");
00774     }
00775 
00776     if (dispersion > 1.0)
00777         highres = 0;
00778     else
00779         highres = 1;
00780 
00781     rainbow = mos_map_idscoeff(idscoeff, nx, reference, startwavelength,
00782                                endwavelength);
00783 
00784     offsets = mos_wavelength_align_lss(smapped, reference,
00785                                        startwavelength, endwavelength,
00786                                        idscoeff, lines, highres,
00787                                        skyalign, rainbow, 4);
00788 
00789     cpl_vector_delete(lines); lines = NULL;
00790     cpl_image_delete(smapped); smapped = NULL;
00791 
00792     if (offsets) {
00793         if (dfs_save_table(frameset, offsets, shifts_tag, NULL,
00794                            parlist, recipe, version))
00795             fors_align_sky_lss_exit(NULL);
00796 
00797         cpl_table_delete(offsets); offsets = NULL;
00798     }
00799     else
00800         fors_align_sky_lss_exit("Alignment of the wavelength solution "
00801                         "to reference sky lines could not be done!");
00802 
00803     if (dfs_save_table(frameset, idscoeff, disp_ali_tag, NULL,
00804                        parlist, recipe, version))
00805         fors_align_sky_lss_exit(NULL);
00806 
00807     cpl_table_delete(idscoeff); idscoeff = NULL;
00808 
00809     wavemap = cpl_image_new(ccd_xsize, ccd_ysize, CPL_TYPE_FLOAT);
00810     cpl_image_copy(wavemap, rainbow, 1, ylow);
00811 
00812     cpl_image_delete(rainbow); rainbow = NULL;
00813 
00814     if (dfs_save_image(frameset, wavemap, wavemap_tag,
00815                        header, parlist, recipe, version))
00816         fors_align_sky_lss_exit(NULL);
00817 
00818     cpl_image_delete(wavemap); wavemap = NULL;
00819     cpl_propertylist_delete(header); header = NULL;
00820 
00821     return 0;
00822 }