CRIRES Pipeline Reference Manual  2.3.2
crires_util_wlcalib.c
00001 /* $Id: crires_util_wlcalib.c,v 1.69 2012-09-20 12:06:34 yjung Exp $
00002  *
00003  * This file is part of the crires Pipeline
00004  * Copyright (C) 2002,2003 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  */
00020 
00021 /*
00022  * $Author: yjung $
00023  * $Date: 2012-09-20 12:06:34 $
00024  * $Revision: 1.69 $
00025  * $Name: not supported by cvs2svn $
00026  */
00027 
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031 
00032 /*-----------------------------------------------------------------------------
00033                                 Includes
00034  -----------------------------------------------------------------------------*/
00035 
00036 #include "crires_recipe.h"
00037 
00038 #include "irplib_wlxcorr.h"
00039 #include "crires_wlcalib.h"
00040 #include "crires_wlestimate.h"
00041 
00042 /*-----------------------------------------------------------------------------
00043                                 Define
00044  -----------------------------------------------------------------------------*/
00045 
00046 #define RECIPE_STRING "crires_util_wlcalib"
00047 
00048 /*-----------------------------------------------------------------------------
00049                             Functions prototypes
00050  -----------------------------------------------------------------------------*/
00051 
00052 static int crires_util_wlcalib_save(const cpl_imagelist *, const cpl_table **, 
00053         const cpl_table **, const cpl_parameterlist *, cpl_frameset *) ;
00054 
00055 static char crires_util_wlcalib_description[] = 
00056 "This recipe accepts 2 parameters:\n"
00057 "First parameter:   the extracted spectrum in pixels.\n"
00058 "                   (PRO TYPE = "CRIRES_PROTYPE_SPEC_PIX")\n"
00059 "Second parameter:  the table with the lines catalog.\n"
00060 "                   (PRO TYPE = "CRIRES_PROTYPE_CATALOG")\n"
00061 "\n"
00062 "This recipe produces 2 files:\n"
00063 "First product:     the image with the wavelength values.\n"
00064 "                   (PRO TYPE = "CRIRES_PROTYPE_WL_MAP")\n"
00065 "Second product:    the table with the wavelength polynomial coefficients.\n"
00066 "                   (PRO TYPE = "CRIRES_PROTYPE_WL_POLY")\n" ;
00067 
00068 CRIRES_RECIPE_DEFINE(crires_util_wlcalib,
00069         CRIRES_PARAM_WAVES          |
00070         CRIRES_PARAM_DISPLAY        |
00071         CRIRES_PARAM_WL_LOG         |
00072         CRIRES_PARAM_WL_NOLIMIT     |
00073         CRIRES_PARAM_WL_ERROR       |
00074         CRIRES_PARAM_XC_LIMIT       |
00075         CRIRES_PARAM_WL_NBSAMPLES   |
00076         CRIRES_PARAM_DEGREE         |
00077         CRIRES_PARAM_WL_CLEAN       |
00078         CRIRES_PARAM_LINES          |
00079         CRIRES_PARAM_FIRST_PLOTTED  |
00080         CRIRES_PARAM_LAST_PLOTTED,
00081         "Wavelength calibration of a spectrum",
00082         crires_util_wlcalib_description) ;
00083 
00084 /*-----------------------------------------------------------------------------
00085                             Static variables
00086  -----------------------------------------------------------------------------*/
00087 
00088 static struct {
00089     /* Inputs */
00090     double                  wstart[CRIRES_NB_DETECTORS] ;
00091     double                  wstop[CRIRES_NB_DETECTORS] ;
00092     int                     display ;
00093     int                     degree ;
00094     int                     wl_nolimit ;
00095     int                     wl_log ;
00096     double                  wl_err ;
00097     int                     wl_nsamples ;
00098     int                     wl_clean ;
00099     double                  wl_xclimit ;
00100     int                     use_ppm ;
00101     int                     slitw ;
00102     int                     fwhm ;
00103     const char          *   lines ;
00104     int                     first_plotted_line ;
00105     int                     last_plotted_line ;
00106     /* Output */
00107     int                     win_mode ;
00108     crires_illum_period     period ;
00109     double                  qc_wlcent[CRIRES_NB_DETECTORS] ;
00110     double                  qc_wldisp[CRIRES_NB_DETECTORS] ;
00111     double                  qc_wlxc[CRIRES_NB_DETECTORS] ;
00112 } crires_util_wlcalib_config ;
00113 
00114 /*-----------------------------------------------------------------------------
00115                                 Functions code
00116  -----------------------------------------------------------------------------*/
00117 
00118 /*----------------------------------------------------------------------------*/
00125 /*----------------------------------------------------------------------------*/
00126 static int crires_util_wlcalib(
00127         cpl_frameset            *   frameset,
00128         const cpl_parameterlist *   parlist)
00129 {
00130     cpl_table           *   ext_spec ;
00131     const char          *   fname ;
00132     cpl_propertylist    *   plist ;
00133     double                  wmin, wmax ;
00134     cpl_vector          *   spec ;
00135     double              *   pspec ;
00136     cpl_polynomial      *   phdisp ;
00137     cpl_polynomial      *   poly_sol ;
00138     cpl_matrix          *   samppos ;
00139     cpl_size                mindeg, maxdeg ;
00140     cpl_bivector        *   lines_biv ;
00141     cpl_table           *   cat ;
00142     double                  val ;
00143     cpl_table           *   real_sol ;
00144     int                     nrows, spec_pos ;
00145     cpl_bivector        *   cat_biv ;
00146     double              *   cat_biv_x ;
00147     double              *   cat_biv_y ;
00148     const char          *   sval ;
00149     cpl_frame           *   fr ;
00150     cpl_polynomial      *   disp_poly ;
00151     cpl_table           *   wl_infos[CRIRES_NB_DETECTORS] ;
00152     cpl_table           *   wl_tab[CRIRES_NB_DETECTORS] ;
00153     cpl_imagelist       *   wl_map ;
00154     int                     i, j ;
00155     
00156     /* Initialise */
00157     for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
00158         crires_util_wlcalib_config.qc_wlcent[i] = -1.0 ;
00159         crires_util_wlcalib_config.qc_wldisp[i] = -1.0 ;
00160         crires_util_wlcalib_config.qc_wlxc[i] = -1.0 ;
00161         wl_tab[i] = NULL ;
00162         wl_infos[i] = NULL ;
00163     }
00164     crires_util_wlcalib_config.lines = NULL ;
00165     crires_util_wlcalib_config.use_ppm = 0 ;
00166     crires_util_wlcalib_config.slitw = 2 ;
00167     crires_util_wlcalib_config.fwhm = 2 ;
00168     
00169     /* Retrieve input parameters */
00170     sval = crires_parameterlist_get_string(parlist, RECIPE_STRING,
00171             CRIRES_PARAM_WAVES) ;
00172     if (sscanf(sval, "%lg,%lg,%lg,%lg,%lg,%lg,%lg,%lg",
00173                     &crires_util_wlcalib_config.wstart[0],
00174                     &crires_util_wlcalib_config.wstop[0],
00175                     &crires_util_wlcalib_config.wstart[1],
00176                     &crires_util_wlcalib_config.wstop[1],
00177                     &crires_util_wlcalib_config.wstart[2],
00178                     &crires_util_wlcalib_config.wstop[2],
00179                     &crires_util_wlcalib_config.wstart[3],
00180                 &crires_util_wlcalib_config.wstop[3])!=2*CRIRES_NB_DETECTORS){
00181         return -1 ;
00182     }
00183     crires_util_wlcalib_config.display = crires_parameterlist_get_int(parlist,
00184             RECIPE_STRING, CRIRES_PARAM_DISPLAY) ;
00185     crires_util_wlcalib_config.degree = crires_parameterlist_get_int(parlist,
00186             RECIPE_STRING, CRIRES_PARAM_DEGREE) ;
00187     crires_util_wlcalib_config.wl_log = crires_parameterlist_get_bool(parlist,
00188             RECIPE_STRING, CRIRES_PARAM_WL_LOG) ;
00189     crires_util_wlcalib_config.wl_nolimit = crires_parameterlist_get_bool(
00190             parlist, RECIPE_STRING, CRIRES_PARAM_WL_NOLIMIT) ;
00191     crires_util_wlcalib_config.wl_err = crires_parameterlist_get_double(parlist,
00192             RECIPE_STRING, CRIRES_PARAM_WL_ERROR) ;
00193     crires_util_wlcalib_config.wl_xclimit = crires_parameterlist_get_double(
00194             parlist, RECIPE_STRING, CRIRES_PARAM_XC_LIMIT) ;
00195     crires_util_wlcalib_config.wl_nsamples = crires_parameterlist_get_int(
00196             parlist, RECIPE_STRING, CRIRES_PARAM_WL_NBSAMPLES) ;
00197     crires_util_wlcalib_config.wl_clean = crires_parameterlist_get_bool(parlist,
00198             RECIPE_STRING, CRIRES_PARAM_WL_CLEAN) ;
00199     crires_util_wlcalib_config.lines = crires_parameterlist_get_string(parlist, 
00200             RECIPE_STRING, CRIRES_PARAM_LINES) ;
00201     crires_util_wlcalib_config.first_plotted_line=crires_parameterlist_get_int(
00202             parlist, RECIPE_STRING, CRIRES_PARAM_FIRST_PLOTTED) ;
00203     crires_util_wlcalib_config.last_plotted_line=crires_parameterlist_get_int(
00204             parlist, RECIPE_STRING, CRIRES_PARAM_LAST_PLOTTED) ;
00205 
00206     /* Identify the RAW and CALIB frames in the input frameset */
00207     if (crires_dfs_set_groups(frameset, NULL)) {
00208         cpl_msg_error(__func__, "Cannot identify RAW and CALIB frames") ;
00209         return -1 ;
00210     }
00211     
00212     /* Check that we have 2 files in input */
00213     if (cpl_frameset_get_size(frameset) != 2) {
00214         cpl_msg_error(__func__, "Expects 2 files in input") ;
00215         return -1 ;
00216     }
00217 
00218     /* Get the detector illumination period */
00219     fr = cpl_frameset_get_position(frameset, 0);
00220     crires_util_wlcalib_config.period =
00221         crires_get_detector_illum_period(cpl_frame_get_filename(fr)) ;
00222     if (crires_util_wlcalib_config.period == CRIRES_ILLUM_UNKNOWN) {
00223         cpl_msg_error(__func__,
00224                 "Cannot determine the detector illumination period") ;
00225         return -1 ;
00226     }
00227 
00228     /* Windowing mode ? */
00229     if ((plist=cpl_propertylist_load(cpl_frame_get_filename(fr), 0)) == NULL)
00230         return -1 ;
00231     sval = crires_pfits_get_ncorrs(plist) ;
00232     if (!strcmp(sval, "FowlerNsampGRstWin")) {
00233         crires_util_wlcalib_config.period = CRIRES_ILLUM_FULL_DETECTOR ;
00234         crires_util_wlcalib_config.win_mode = 1 ;
00235     } else {
00236         crires_util_wlcalib_config.win_mode = 0 ;
00237     }
00238     cpl_propertylist_delete(plist) ;
00239     
00240     /* Display the Detector illumination */
00241     crires_display_detector_illum(crires_util_wlcalib_config.period) ;
00242 
00243     /* Load the second file */
00244     cpl_msg_info(__func__, "Second frame validity check") ;
00245     cpl_msg_indent_more() ;
00246     fr = cpl_frameset_get_position(frameset, 1);
00247     cat = crires_load_table_check(cpl_frame_get_filename(fr), 1,
00248             CRIRES_PROTYPE_CATALOG, -1, -1, 0) ;
00249     if (cat == NULL) {
00250         cpl_msg_error(__func__, "Second frame is incorrect") ;
00251         cpl_msg_indent_less() ;
00252         return -1 ;
00253     }
00254     cpl_msg_indent_less() ;
00255     
00256     /* Create the catalog spectrum in a bivector */
00257     nrows = cpl_table_get_nrow(cat) ;
00258     cat_biv = cpl_bivector_new(nrows) ;
00259     cat_biv_x = cpl_bivector_get_x_data(cat_biv) ;
00260     cat_biv_y = cpl_bivector_get_y_data(cat_biv) ;
00261     for (i=0 ; i<nrows ; i++) {
00262         cat_biv_x[i] = cpl_table_get(cat, CRIRES_COL_WAVELENGTH, i, NULL) ;
00263         val = cpl_table_get(cat, CRIRES_COL_EMISSION, i, NULL) ;
00264         if (crires_util_wlcalib_config.wl_log && val > 0)
00265             cat_biv_y[i] = log10(val) ;
00266         else 
00267             cat_biv_y[i] = val ;
00268     }
00269     cpl_table_delete(cat) ;
00270 
00271     /* Get the raw file name */
00272     fr = cpl_frameset_get_position(frameset, 0);
00273     fname = cpl_frame_get_filename(fr) ;
00274 
00275     /* Get the Minimum and Maximum wavelengths */
00276     if (crires_util_wlcalib_config.wl_nolimit == 0) {
00277         plist = cpl_propertylist_load(fname, 0) ;
00278         wmin = crires_pfits_get_wlen_min(plist) ;
00279         wmax = crires_pfits_get_wlen_max(plist) ;
00280         cpl_propertylist_delete(plist) ;
00281         if (cpl_error_get_code()) {
00282             wmin = wmax = -1.0 ;
00283             cpl_error_reset() ;
00284         }
00285     } else {
00286         wmin = wmax = -1.0 ;
00287     }
00288 
00289     /* Loop on the spectra to calibrate */
00290     for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
00291         /* Skip some detectors in windowing mode */
00292         if ((i==0 || i==CRIRES_NB_DETECTORS-1) &&
00293                 (crires_util_wlcalib_config.win_mode == 1)) {
00294             continue ;
00295         }
00296 
00297         cpl_msg_info(__func__, "Wavelength calibration for chip %d", i+1) ;
00298         /* Load the first file in table */
00299         cpl_msg_info(__func__, "Load the extracted table") ;
00300         cpl_msg_indent_more() ;
00301         if ((ext_spec=crires_load_table_check(fname, i+1, 
00302                     CRIRES_PROTYPE_SPEC_PIX, -1, -1, 0)) == NULL) {
00303             cpl_msg_warning(__func__, "Empty extension") ;
00304             cpl_msg_indent_less() ;
00305             continue ;
00306         }
00307         cpl_msg_indent_less() ;
00308         
00309         /* Get the Wavlength estimation */
00310         cpl_msg_info(__func__, "Wavelength estimation") ;
00311         cpl_msg_indent_more() ;
00312         if ((phdisp = crires_wlestimate_compute(
00313                         crires_util_wlcalib_config.wstart[i],
00314                         crires_util_wlcalib_config.wstop[i])) == NULL) {
00315             if ((phdisp = crires_wlestimate_get(fname, i+1)) == NULL) {
00316                 cpl_msg_error(__func__, "Cannot get the wavelength estimate") ;
00317                 cpl_msg_indent_less() ;
00318                 cpl_table_delete(ext_spec) ;
00319                 continue ;
00320             }
00321         }
00322         cpl_msg_indent_less() ;
00323 
00324         /* Convert to vector */
00325         nrows = cpl_table_get_nrow(ext_spec) ;
00326         spec = cpl_vector_new(nrows) ;
00327         pspec = cpl_vector_get_data(spec) ;
00328         for (j=0 ; j<nrows ; j++) {
00329             pspec[j] = cpl_table_get(ext_spec, CRIRES_COL_EXTRACT_INT_RECT, j, 
00330                     NULL);
00331         }
00332         cpl_table_delete(ext_spec) ;
00333 
00334         /* Wavelength calibration */
00335         cpl_msg_info(__func__, "Wavelength calibration computation") ;
00336         cpl_msg_indent_more() ;
00337         if ((disp_poly = crires_wlcalib_engine(spec, cat_biv, phdisp,
00338                         crires_util_wlcalib_config.slitw, 
00339                         crires_util_wlcalib_config.fwhm,
00340                         crires_util_wlcalib_config.degree,
00341                         wmin, wmax,
00342                         crires_util_wlcalib_config.wl_err,
00343                         crires_util_wlcalib_config.wl_nsamples,
00344                         crires_util_wlcalib_config.wl_clean, 
00345                         crires_util_wlcalib_config.wl_xclimit,
00346                         crires_util_wlcalib_config.use_ppm, 
00347                         (i+1==crires_util_wlcalib_config.display),
00348                         crires_util_wlcalib_config.first_plotted_line,
00349                         crires_util_wlcalib_config.last_plotted_line,
00350                         &((crires_util_wlcalib_config.qc_wlxc)[i]),
00351                         NULL)) == NULL) {
00352             cpl_msg_error(__func__, 
00353                     "Wavelength calibration failed - use estimate") ;
00354             disp_poly = cpl_polynomial_duplicate(phdisp) ;
00355             crires_util_wlcalib_config.qc_wlxc[i] = -1.0 ;
00356         }
00357         cpl_msg_indent_less() ;
00358         
00359         /* Compute the QC parameters */
00360         crires_util_wlcalib_config.qc_wlcent[i] = 
00361             cpl_polynomial_eval_1d(disp_poly, (double)512, NULL) ;
00362         crires_util_wlcalib_config.qc_wldisp[i] = 
00363             (cpl_polynomial_eval_1d(disp_poly, (double)1024, NULL) -
00364              cpl_polynomial_eval_1d(disp_poly, (double)1, NULL)) / 1023 ;
00365         
00366         /* Plot the result */
00367         if (crires_util_wlcalib_config.display==i+1) {
00368             /* Compute the solution from the passed associated lines if passed*/
00369             poly_sol = NULL ;
00370             if (crires_util_wlcalib_config.lines != NULL && 
00371                     crires_util_wlcalib_config.lines[0] != (char)0) {
00372                 lines_biv = 
00373                     cpl_bivector_read((char*)crires_util_wlcalib_config.lines);
00374                 if ((lines_biv != NULL) && 
00375         (cpl_bivector_get_size(lines_biv)>crires_util_wlcalib_config.degree)) {
00376                     poly_sol = cpl_polynomial_new(1);
00377                     samppos = cpl_matrix_wrap(1, 
00378                             cpl_bivector_get_size(lines_biv),
00379                             cpl_bivector_get_x_data(lines_biv)) ;
00380                     mindeg = 1 ;
00381                     maxdeg = (cpl_size)crires_util_wlcalib_config.degree ;
00382                     cpl_polynomial_fit(poly_sol,
00383                             samppos, NULL,
00384                             cpl_bivector_get_y(lines_biv),
00385                             NULL, CPL_FALSE, 
00386                             &mindeg,
00387                             &maxdeg) ;
00388                     cpl_matrix_unwrap(samppos) ;
00389                 }
00390                 if (lines_biv != NULL) cpl_bivector_delete(lines_biv) ;
00391             } 
00392             irplib_wlxcorr_plot_solution(phdisp, disp_poly, poly_sol, 1, 1024);
00393             if (poly_sol != NULL) {
00394                 real_sol = irplib_wlxcorr_gen_spc_table(spec, cat_biv,
00395                         crires_util_wlcalib_config.slitw, 
00396                         crires_util_wlcalib_config.fwhm,
00397                         phdisp, poly_sol) ;
00398                 irplib_wlxcorr_plot_spc_table(real_sol, "Real",
00399                         crires_util_wlcalib_config.first_plotted_line,
00400                         crires_util_wlcalib_config.last_plotted_line) ;
00401                 cpl_table_delete(real_sol) ;
00402             }
00403             if (poly_sol != NULL) cpl_polynomial_delete(poly_sol) ;
00404         }
00405 
00406         /* Compute the products */
00407         wl_infos[i] = irplib_wlxcorr_gen_spc_table(spec, cat_biv, 
00408                 crires_util_wlcalib_config.slitw, 
00409                 crires_util_wlcalib_config.fwhm, 
00410                 phdisp, disp_poly) ;
00411 
00412         /* Free */
00413         cpl_vector_delete(spec) ;
00414         cpl_polynomial_delete(phdisp) ;
00415 
00416         /* Create the table */
00417         if (crires_util_wlcalib_config.qc_wlxc[i] > 0)
00418             spec_pos = crires_get_y_spec_position(fname, i+1) ;
00419         else 
00420             spec_pos = -1 ;
00421         wl_tab[i] = crires_wlcalib_gen_wltab_one(
00422                 (const cpl_polynomial *)disp_poly, 
00423                 spec_pos, 
00424                 crires_util_wlcalib_config.qc_wlxc[i]) ;
00425         cpl_polynomial_delete(disp_poly) ;
00426     }
00427     cpl_bivector_delete(cat_biv) ;
00428       
00429     /* Reconstruct chips in windowing mode using detector 2 */
00430     if (crires_util_wlcalib_config.win_mode == 1) {
00431         if (wl_tab[1] != NULL) {
00432             wl_tab[0] = cpl_table_duplicate(wl_tab[1]) ;
00433             cpl_table_set_size(wl_tab[0], 0) ;
00434             wl_tab[CRIRES_NB_DETECTORS-1] = cpl_table_duplicate(wl_tab[0]) ;
00435         }
00436         if (wl_infos[1] != NULL) {
00437             wl_infos[0] = cpl_table_duplicate(wl_infos[1]) ;
00438             cpl_table_set_size(wl_infos[0], 0) ;
00439             wl_infos[CRIRES_NB_DETECTORS-1] = cpl_table_duplicate(wl_infos[0]) ;
00440         }
00441     }
00442 
00443     /* Create the Map */
00444     if ((wl_map = crires_wlcalib_gen_wlmap((const cpl_table **)wl_tab)) 
00445             == NULL) {
00446         cpl_msg_error(__func__, "Cannot create WL Map") ;
00447         for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
00448             if (wl_tab[i] != NULL) cpl_table_delete(wl_tab[i]) ;
00449             if (wl_infos[i] != NULL) cpl_table_delete(wl_infos[i]) ;
00450         }
00451         return -1 ;
00452     }
00453 
00454     /* Save the result */
00455     cpl_msg_info(__func__, "Save the products") ;
00456     cpl_msg_indent_more() ;
00457     if (crires_util_wlcalib_save(wl_map, (const cpl_table **)wl_tab, 
00458                 (const cpl_table **)wl_infos, parlist, frameset) == -1) {
00459         cpl_msg_error(__func__, "Cannot save products");
00460         cpl_msg_indent_less() ;
00461         cpl_imagelist_delete(wl_map) ;
00462         for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
00463             if (wl_tab[i] != NULL) cpl_table_delete(wl_tab[i]) ;
00464             if (wl_infos[i] != NULL) cpl_table_delete(wl_infos[i]) ;
00465         }
00466         return -1 ;
00467     }
00468     cpl_msg_indent_less() ;
00469     cpl_imagelist_delete(wl_map) ;
00470     for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
00471         if (wl_tab[i] != NULL) cpl_table_delete(wl_tab[i]) ;
00472         if (wl_infos[i] != NULL) cpl_table_delete(wl_infos[i]) ;
00473     }
00474 
00475     /* Return */
00476     if (cpl_error_get_code()) return -1 ;
00477     else return 0 ;
00478 }
00479 
00480 /*----------------------------------------------------------------------------*/
00490 /*----------------------------------------------------------------------------*/
00491 static int crires_util_wlcalib_save(
00492         const cpl_imagelist     *   ilist,
00493         const cpl_table         **  tab,
00494         const cpl_table         **  xctab,
00495         const cpl_parameterlist *   parlist,
00496         cpl_frameset            *   set)
00497 {
00498     cpl_propertylist    **  qclists ;
00499     const cpl_frame     *   ref_frame ;
00500     cpl_propertylist    *   inputlist ;
00501     const char          *   recipe_name = "crires_util_wlcalib" ;
00502     int                     i ;
00503 
00504     /* Get the reference frame */
00505     ref_frame = irplib_frameset_get_first_from_group(set, CPL_FRAME_GROUP_RAW) ;
00506 
00507     /* Create the QC lists */
00508     qclists = cpl_malloc(CRIRES_NB_DETECTORS * sizeof(cpl_propertylist*)) ;
00509     for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
00510         qclists[i] = cpl_propertylist_new() ;
00511         cpl_propertylist_append_double(qclists[i], "ESO QC CENTWL", 
00512                 crires_util_wlcalib_config.qc_wlcent[i]) ;
00513         cpl_propertylist_append_double(qclists[i], "ESO QC DISPWL", 
00514                 crires_util_wlcalib_config.qc_wldisp[i]) ;
00515         cpl_propertylist_append_double(qclists[i], "ESO QC XCORR", 
00516                 crires_util_wlcalib_config.qc_wlxc[i]) ;
00517 
00518         /* Propagate some keywords from input raw frame extensions */
00519         inputlist = cpl_propertylist_load_regexp(
00520                 cpl_frame_get_filename(ref_frame), i+1,
00521                 CRIRES_HEADER_EXT_FORWARD, 0) ;
00522         cpl_propertylist_copy_property_regexp(qclists[i], inputlist, 
00523                 CRIRES_HEADER_EXT_FORWARD, 0) ;
00524         cpl_propertylist_delete(inputlist) ;
00525     }
00526 
00527     /* Write the image */
00528     crires_image_save(set,
00529             parlist,
00530             set,
00531             ilist,
00532             recipe_name,
00533             CRIRES_WL_MAP_IMA,
00534             CRIRES_PROTYPE_WL_MAP,
00535             crires_util_wlcalib_config.period,
00536             NULL,
00537             (const cpl_propertylist **)qclists,
00538             PACKAGE "/" PACKAGE_VERSION,
00539             "crires_util_wlcalib_ima.fits") ;
00540 
00541     /* Write the table */
00542     crires_table_save(set,
00543             parlist,
00544             set,
00545             tab,
00546             recipe_name,
00547             CRIRES_CALPRO_WAVE,
00548             CRIRES_PROTYPE_WL_POLY,
00549             NULL,
00550             (const cpl_propertylist **)qclists,
00551             PACKAGE "/" PACKAGE_VERSION,
00552             "crires_util_wlcalib_tab.fits") ;
00553 
00554     if (xctab[0] != NULL) {
00555         /* Write the table */
00556         crires_table_save(set,
00557                 parlist,
00558                 set,
00559                 xctab,
00560                 recipe_name,
00561                 CRIRES_WL_XCORR_TAB,
00562                 CRIRES_PROTYPE_XCORR,
00563                 NULL,
00564                 (const cpl_propertylist **)qclists,
00565                 PACKAGE "/" PACKAGE_VERSION,
00566                 "crires_util_wlcalib_xctab.fits") ;
00567     }
00568 
00569     /* Free and return */
00570     for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
00571         cpl_propertylist_delete(qclists[i]) ;
00572     }
00573     cpl_free(qclists) ;
00574     return  0;
00575 }