CRIRES Pipeline Reference Manual  2.3.2
crires_util_extract.c
00001 /* $Id: crires_util_extract.c,v 1.70 2012-10-09 08:18:01 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-10-09 08:18:01 $
00024  * $Revision: 1.70 $
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 "crires_extract.h"
00039 
00040 /*-----------------------------------------------------------------------------
00041                                 Define
00042  -----------------------------------------------------------------------------*/
00043 
00044 #define RECIPE_STRING "crires_util_extract"
00045 
00046 /*-----------------------------------------------------------------------------
00047                             Functions prototypes
00048  -----------------------------------------------------------------------------*/
00049 
00050 static int crires_util_extract_save(const cpl_table **, const cpl_imagelist *, 
00051         const cpl_imagelist *, const cpl_parameterlist *, cpl_frameset *) ;
00052 
00053 static char crires_util_extract_description[] = 
00054 "This recipe accepts 1 parameter (optionally a 2nd one):\n"
00055 "First parameter:   the combined image.\n" 
00056 "                   (PRO TYPE = "CRIRES_PROTYPE_COMBINED")\n"
00057 "Second parameter (optional):   the contribution map.\n" 
00058 "                   (PRO TYPE = "CRIRES_PROTYPE_CONTRIB")\n"
00059 "\n"
00060 "This recipe produces 3 files:\n"
00061 "First product:     the image of the profile of the spectrum\n"
00062 "                   (PRO TYPE = "CRIRES_PROTYPE_PROFILE")\n"
00063 "Second product:    the table of the extracted spectrum in pixels\n"
00064 "                   (PRO TYPE = "CRIRES_PROTYPE_SPEC_PIX")\n"
00065 "Third product:     the maps of the background\n"
00066 "                   (PRO TYPE = "CRIRES_PROTYPE_BGD_MAP")\n" ;
00067 
00068 CRIRES_RECIPE_DEFINE(crires_util_extract,
00069         CRIRES_PARAM_DISPLAY        |
00070         CRIRES_PARAM_EXTR_MODE      |
00071         CRIRES_PARAM_HOR_SIZE       |
00072         CRIRES_PARAM_SPEC_HSIZE     |
00073         CRIRES_PARAM_KAPPA          |
00074         CRIRES_PARAM_CLOSING_HSIZE  |
00075         CRIRES_PARAM_CLEAN_RATE     |
00076         CRIRES_PARAM_TOT_NDIT       |
00077         CRIRES_PARAM_Y_POS_CHIP1    |
00078         CRIRES_PARAM_Y_POS_CHIP2    |
00079         CRIRES_PARAM_Y_POS_CHIP3    |
00080         CRIRES_PARAM_Y_POS_CHIP4    |
00081         CRIRES_PARAM_Y_WIDTH        |
00082         CRIRES_PARAM_SPEC_ZONE      |
00083         CRIRES_PARAM_REJECT,
00084         "Spectrum extraction routine",
00085         crires_util_extract_description) ;
00086 
00087 /*-----------------------------------------------------------------------------
00088                             Static variables
00089  -----------------------------------------------------------------------------*/
00090 
00091 static struct {
00092     /* Inputs */
00093     /* mode : 1=spec ; 2=lines */
00094     int                 mode ;
00095     double              kappa ;         /* mode = 1 */
00096     int                 closing_hs ;    /* mode = 1 */
00097     double              clean_rate ;    /* mode = 1 */
00098     double              tot_ndit ;      /* mode = 1 */
00099     int                 box_hor_size ;  /* mode = 1 */
00100     int                 spec_hsize ;    /* mode = 1 */
00101     const char      *   y_pos_c1 ;      /* mode = 2 */
00102     const char      *   y_pos_c2 ;      /* mode = 2 */
00103     const char      *   y_pos_c3 ;      /* mode = 2 */
00104     const char      *   y_pos_c4 ;      /* mode = 2 */
00105     int                 y_width ;       /* mode = 2 */
00106     int                 extr_spec_starty ;  /* mode = 1 */
00107     int                 extr_spec_stopy ;   /* mode = 1 */
00108     int                 rej_right ;     /* All modes */
00109     int                 rej_left ;      /* All modes */
00110     int                 display ;       /* All modes */
00111     /* Outputs */
00112     int                 win_mode ;
00113     crires_illum_period period ;
00114     int                 qc_specpos[CRIRES_NB_DETECTORS] ;
00115     int                 qc_specwrec[CRIRES_NB_DETECTORS] ;
00116     int                 qc_specwopt[CRIRES_NB_DETECTORS] ;
00117     double              qc_specoptmed[CRIRES_NB_DETECTORS] ;
00118     double              qc_s2nmed[CRIRES_NB_DETECTORS] ;
00119     double              qc_fwhm_comb_pix[CRIRES_NB_DETECTORS] ;
00120     double              qc_fwhm_comb_as[CRIRES_NB_DETECTORS] ;
00121     double              qc_fwhm_prof_pix[CRIRES_NB_DETECTORS] ;
00122     double              qc_fwhm_prof_as[CRIRES_NB_DETECTORS] ;
00123     double              qc_fwhm_diff[CRIRES_NB_DETECTORS] ;
00124 } crires_util_extract_config ;
00125 
00126 /*-----------------------------------------------------------------------------
00127                                 Functions code
00128  -----------------------------------------------------------------------------*/
00129 
00130 /*----------------------------------------------------------------------------*/
00137 /*----------------------------------------------------------------------------*/
00138 static int crires_util_extract(
00139         cpl_frameset            *   frameset,
00140         const cpl_parameterlist *   parlist) 
00141 {
00142     const char          *   sval ;
00143     const char          *   y_pos ;
00144     cpl_imagelist       *   imlist ;
00145     cpl_propertylist    *   plist ;
00146     cpl_imagelist       *   contrib ;
00147     cpl_image           *   contribution_map ;
00148     cpl_frame           *   fr ;
00149     cpl_imagelist       *   profile ;
00150     cpl_image           *   prof[CRIRES_NB_DETECTORS] ;
00151     cpl_imagelist       *   bgmaps ;
00152     cpl_image           *   bgmap[CRIRES_NB_DETECTORS] ;
00153     cpl_table           *   ext[CRIRES_NB_DETECTORS] ;
00154     cpl_vector          *   ext_vec ;
00155     cpl_vector          *   ypos_vec ;
00156     int                     ly, nexp, starty, stopy ;
00157     int                     i, j ;
00158     
00159     /* Initialise */
00160     for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
00161         crires_util_extract_config.qc_specpos[i] = -1 ;
00162         crires_util_extract_config.qc_specwrec[i] = -1 ;
00163         crires_util_extract_config.qc_specwopt[i] = -1 ;
00164         crires_util_extract_config.qc_specoptmed[i] = -1.0 ;
00165         crires_util_extract_config.qc_s2nmed[i] = -1.0 ;
00166         crires_util_extract_config.qc_fwhm_comb_pix[i] = -1.0 ;
00167         crires_util_extract_config.qc_fwhm_comb_as[i] = -1.0 ;
00168         crires_util_extract_config.qc_fwhm_prof_pix[i] = -1.0 ;
00169         crires_util_extract_config.qc_fwhm_prof_as[i] = -1.0 ;
00170         crires_util_extract_config.qc_fwhm_diff[i] = -1.0 ;
00171         ext[i] = NULL ;
00172         prof[i] = NULL ;
00173         bgmap[i] = NULL ;
00174     }
00175     ly = -1 ;
00176     
00177     /* Retrieve input parameters */
00178     crires_util_extract_config.display = crires_parameterlist_get_int(parlist,
00179             RECIPE_STRING, CRIRES_PARAM_DISPLAY) ;
00180     crires_util_extract_config.mode = crires_parameterlist_get_int(parlist,
00181             RECIPE_STRING, CRIRES_PARAM_EXTR_MODE) ;
00182     crires_util_extract_config.box_hor_size = crires_parameterlist_get_int(
00183             parlist, RECIPE_STRING, CRIRES_PARAM_HOR_SIZE) ;
00184     crires_util_extract_config.spec_hsize = crires_parameterlist_get_int(
00185             parlist, RECIPE_STRING, CRIRES_PARAM_SPEC_HSIZE) ;
00186     crires_util_extract_config.kappa = crires_parameterlist_get_double(
00187             parlist, RECIPE_STRING, CRIRES_PARAM_KAPPA) ;
00188     crires_util_extract_config.closing_hs = crires_parameterlist_get_int(
00189             parlist, RECIPE_STRING, CRIRES_PARAM_CLOSING_HSIZE) ;
00190     crires_util_extract_config.clean_rate = crires_parameterlist_get_double(
00191             parlist, RECIPE_STRING, CRIRES_PARAM_CLEAN_RATE) ;
00192     crires_util_extract_config.tot_ndit = crires_parameterlist_get_double(
00193             parlist, RECIPE_STRING, CRIRES_PARAM_TOT_NDIT) ;
00194     crires_util_extract_config.y_pos_c1=crires_parameterlist_get_string(parlist,
00195             RECIPE_STRING, CRIRES_PARAM_Y_POS_CHIP1) ;
00196     crires_util_extract_config.y_pos_c2=crires_parameterlist_get_string(parlist,
00197             RECIPE_STRING, CRIRES_PARAM_Y_POS_CHIP2) ;
00198     crires_util_extract_config.y_pos_c3=crires_parameterlist_get_string(parlist,
00199             RECIPE_STRING, CRIRES_PARAM_Y_POS_CHIP3) ;
00200     crires_util_extract_config.y_pos_c4=crires_parameterlist_get_string(parlist,
00201             RECIPE_STRING, CRIRES_PARAM_Y_POS_CHIP4) ;
00202     crires_util_extract_config.y_width= crires_parameterlist_get_int(parlist,
00203             RECIPE_STRING, CRIRES_PARAM_Y_WIDTH) ;
00204     sval = crires_parameterlist_get_string(parlist, RECIPE_STRING,
00205             CRIRES_PARAM_SPEC_ZONE) ;
00206     if (sscanf(sval, "%d,%d",
00207                     &crires_util_extract_config.extr_spec_starty,
00208                     &crires_util_extract_config.extr_spec_stopy)!=2) {
00209         return -1 ;
00210     }
00211     sval = crires_parameterlist_get_string(parlist, RECIPE_STRING,
00212             CRIRES_PARAM_REJECT) ;
00213     if (sscanf(sval, "%d,%d",
00214                     &crires_util_extract_config.rej_left,
00215                     &crires_util_extract_config.rej_right)!=2) {
00216         return -1 ;
00217     }
00218  
00219     /* Identify the RAW and CALIB frames in the input frameset */
00220     if (crires_dfs_set_groups(frameset, NULL)) {
00221         cpl_msg_error(__func__, "Cannot identify RAW and CALIB frames") ;
00222         return -1 ;
00223     }
00224   
00225     /* Get the detector illumination period */
00226     fr = cpl_frameset_get_position(frameset, 0);
00227     crires_util_extract_config.period =
00228         crires_get_detector_illum_period(cpl_frame_get_filename(fr)) ;
00229     if (crires_util_extract_config.period == CRIRES_ILLUM_UNKNOWN) {
00230         cpl_msg_error(__func__, 
00231                 "Cannot determine the detector illumination period") ;
00232         return -1 ;
00233     }
00234  
00235     /* Windowing mode ? */
00236     if ((plist=cpl_propertylist_load(cpl_frame_get_filename(fr), 0)) == NULL) 
00237         return -1 ;
00238     sval = crires_pfits_get_ncorrs(plist) ;
00239     if (!strcmp(sval, "FowlerNsampGRstWin")) {
00240         crires_util_extract_config.period = CRIRES_ILLUM_FULL_DETECTOR ;
00241         crires_util_extract_config.win_mode = 1 ;
00242     } else {
00243         crires_util_extract_config.win_mode = 0 ;
00244     }
00245     cpl_propertylist_delete(plist) ;
00246     
00247     /* Display the Detector illumination */
00248     crires_display_detector_illum(crires_util_extract_config.period) ;
00249 
00250     /* Load the first file in an image list */
00251     cpl_msg_info(__func__, "Input image loading") ;
00252     imlist = crires_load_file(cpl_frame_get_filename(fr), 
00253             crires_util_extract_config.period, CPL_TYPE_FLOAT) ;
00254   
00255     /* Load the optional contribution map */
00256     if (cpl_frameset_get_size(frameset) >= 2) {
00257         fr = cpl_frameset_get_position(frameset, 1);
00258         cpl_msg_info(__func__, "Contribution map specified: %s",
00259                 cpl_frame_get_filename(fr)) ;
00260         contrib = crires_load_file(cpl_frame_get_filename(fr), 
00261                 crires_util_extract_config.period, CPL_TYPE_INT) ;
00262     } else contrib = NULL ;
00263    
00264     if (crires_util_extract_config.mode == 1) {
00265         /* Get the total ndit */
00266         fr = cpl_frameset_get_position(frameset, 0);
00267         if (crires_util_extract_config.tot_ndit < 0) {
00268             crires_util_extract_config.tot_ndit = 
00269                 crires_get_totndit(cpl_frame_get_filename(fr)) ;
00270             if (crires_util_extract_config.tot_ndit < 0) {
00271                 cpl_msg_error(__func__, 
00272                         "Cannot get the total number of NDIT*DIT") ;
00273                 cpl_imagelist_delete(imlist) ;
00274                 if (contrib != NULL) cpl_imagelist_delete(contrib) ;
00275                 return -1 ;
00276             }
00277         }
00278         /* Get the number of exposures used for the frames combination */
00279         plist=cpl_propertylist_load(cpl_frame_get_filename(fr), 0) ;
00280         nexp = crires_pfits_get_datancom(plist) ;
00281         cpl_propertylist_delete(plist) ;
00282         if (cpl_error_get_code() != CPL_ERROR_NONE) {
00283             cpl_msg_error(__func__,"No PRO DATANCOM information in the header");
00284             cpl_imagelist_delete(imlist) ;
00285             if (contrib != NULL) cpl_imagelist_delete(contrib) ;
00286             return -1 ;
00287         }
00288         crires_util_extract_config.tot_ndit *= nexp ;
00289     }
00290     
00291     /* Extract chips */
00292     cpl_msg_info(__func__, "Spectrum extraction") ;
00293     cpl_msg_indent_more() ;
00294     for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
00295         /* Skip some detectors in windowing mode */
00296         if ((i==0 || i==CRIRES_NB_DETECTORS-1) && 
00297                 (crires_util_extract_config.win_mode == 1)) {
00298             continue ;
00299         }
00300         cpl_msg_info(__func__, "Spectrum extraction from chip number %d", i+1) ;
00301         cpl_msg_indent_more() ;
00302         if (crires_util_extract_config.mode == 1) {
00303             /* Extract spectrum */
00304             if (contrib != NULL) 
00305                 contribution_map = cpl_imagelist_get(contrib, i) ;
00306             else
00307                 contribution_map = NULL ;
00308             ext[i] = crires_extract_spectrum(cpl_imagelist_get(imlist, i),
00309                     contribution_map,
00310                     crires_util_extract_config.box_hor_size, 
00311                     crires_util_extract_config.spec_hsize, 
00312                     crires_util_extract_config.kappa,
00313                     crires_util_extract_config.closing_hs,
00314                     crires_util_extract_config.clean_rate,
00315                     crires_util_extract_config.rej_left,
00316                     crires_util_extract_config.rej_right,
00317                     crires_util_extract_config.extr_spec_starty,
00318                     crires_util_extract_config.extr_spec_stopy,
00319                     i+1,
00320                     crires_util_extract_config.tot_ndit,
00321                     crires_util_extract_config.period,
00322                     &(crires_util_extract_config.qc_specpos[i]), 
00323                     &(crires_util_extract_config.qc_specwrec[i]), 
00324                     &(crires_util_extract_config.qc_specwopt[i]), 
00325                     &(crires_util_extract_config.qc_specoptmed[i]),
00326                     &(crires_util_extract_config.qc_s2nmed[i]),
00327                     &(prof[i]),
00328                     &(bgmap[i])) ;
00329             cpl_msg_info(__func__, "Chip number %d FWHM Computation", i+1) ;
00330             if (crires_extract_qc_fwhm(cpl_imagelist_get(imlist, i),
00331                         prof[i],
00332                         &(crires_util_extract_config.qc_fwhm_comb_pix[i]),
00333                         &(crires_util_extract_config.qc_fwhm_comb_as[i]),
00334                         &(crires_util_extract_config.qc_fwhm_prof_pix[i]),
00335                         &(crires_util_extract_config.qc_fwhm_prof_as[i]),
00336                         &(crires_util_extract_config.qc_fwhm_diff[i])) == -1) {
00337                 cpl_msg_warning(__func__, "Failed for FWHM computation") ;
00338                 crires_util_extract_config.qc_fwhm_comb_pix[i] = -1.0 ;
00339                 crires_util_extract_config.qc_fwhm_comb_as[i] = -1.0 ;
00340                 crires_util_extract_config.qc_fwhm_prof_pix[i] = -1.0 ;
00341                 crires_util_extract_config.qc_fwhm_prof_as[i] = -1.0 ;
00342                 crires_util_extract_config.qc_fwhm_diff[i] = -1.0 ;
00343             }
00344         } else if (crires_util_extract_config.mode == 2) {
00345             /* Get the correction for the position */
00346             if (i+1 == 1) 
00347                 ly = crires_get_detector_ly1(crires_util_extract_config.period);
00348             if (i+1 == 2) 
00349                 ly = crires_get_detector_ly2(crires_util_extract_config.period);
00350             if (i+1 == 3) 
00351                 ly = crires_get_detector_ly3(crires_util_extract_config.period);
00352             if (i+1 == 4) 
00353                 ly = crires_get_detector_ly4(crires_util_extract_config.period);
00354             /* If ly not found, use the bottom of the image */
00355             if (ly < 0) ly = 1 ;
00356 
00357             /* Where is the Y extraction zone ? */
00358             y_pos = "" ;
00359             if (i+1 == 1) y_pos = crires_util_extract_config.y_pos_c1 ;
00360             if (i+1 == 2) y_pos = crires_util_extract_config.y_pos_c2 ;
00361             if (i+1 == 3) y_pos = crires_util_extract_config.y_pos_c3 ;
00362             if (i+1 == 4) y_pos = crires_util_extract_config.y_pos_c4 ;
00363 
00364             /* Try to parse the user specified positions */
00365             if (!strcmp(y_pos, "")) {
00366                 ypos_vec = NULL ;
00367             } else {
00368                 if ((ypos_vec = crires_parse_y_positions(y_pos)) == NULL) {
00369                     cpl_msg_warning(__func__,
00370                             "Cannot parse the y_positions value : %s", y_pos) ;
00371                     ypos_vec = NULL ;
00372                 }
00373             } 
00374             
00375             if (ypos_vec == NULL) {
00376                 cpl_msg_info(__func__, "Collapse the full image along Y") ;
00377                 starty = 1 ;
00378                 stopy = cpl_image_get_size_y(cpl_imagelist_get(imlist, i)) ;
00379             } else {
00380                 cpl_msg_info(__func__, "Collapse the area around Y=%g",
00381                         cpl_vector_get(ypos_vec, 0)) ;
00382                 /* TODO : Only the first passed value is used */
00383                 starty = (int)cpl_vector_get(ypos_vec, 0) - 
00384                     (int)(crires_util_extract_config.y_width/2.0) ;
00385                 stopy = (int)cpl_vector_get(ypos_vec, 0) +
00386                     (int)(crires_util_extract_config.y_width/2.0) ;
00387                 cpl_vector_delete(ypos_vec) ;
00388                 starty -= ly-1 ;
00389                 stopy -= ly-1 ;
00390             }
00391 
00392             /* Extract lines */
00393             ext_vec = crires_extract_lines(cpl_imagelist_get(imlist, i),
00394                     starty, stopy,
00395                     crires_util_extract_config.rej_left,
00396                     crires_util_extract_config.rej_right) ;
00397             if (ext_vec != NULL) {
00398                 ext[i] = crires_extract_gen_tab(ext_vec, NULL, NULL, NULL, 
00399                         NULL, NULL, NULL) ;     
00400                 crires_util_extract_config.qc_specpos[i] =
00401                     (starty+stopy)/2 + (ly-1) ;
00402                 crires_util_extract_config.qc_specwrec[i] = starty-stopy+1;
00403                 cpl_vector_delete(ext_vec) ;
00404             }
00405         } else {
00406             cpl_msg_warning(__func__, "Unsuported mode: %d", 
00407                     crires_util_extract_config.mode) ;
00408         }
00409 
00410         /* Plot the result if required */
00411         if ((ext[i] != NULL) && (crires_util_extract_config.display == i+1)) {
00412             ext_vec = cpl_vector_wrap(cpl_table_get_nrow(ext[i]),
00413             cpl_table_get_data_double(ext[i], CRIRES_COL_EXTRACT_INT_RECT));
00414             cpl_plot_vector(
00415 "set grid;set xlabel 'Position (pixels)';set ylabel 'Intensity RECT (ADU/sec)';",
00416             "t 'Extracted Spectrum RECT' w lines", "", ext_vec) ;
00417             cpl_vector_unwrap(ext_vec) ;
00418             ext_vec = cpl_vector_wrap(cpl_table_get_nrow(ext[i]),
00419             cpl_table_get_data_double(ext[i], CRIRES_COL_EXTRACT_INT_OPT)) ;
00420             cpl_plot_vector(
00421 "set grid;set xlabel 'Position (pixels)';set ylabel 'Intensity OPT (ADU/sec)';",
00422             "t 'Extracted Spectrum OPT' w lines", "", ext_vec) ;
00423             cpl_vector_unwrap(ext_vec) ;
00424         }
00425         cpl_msg_indent_less() ;
00426     }
00427     cpl_imagelist_delete(imlist) ;
00428     if (contrib != NULL) cpl_imagelist_delete(contrib) ;
00429     cpl_msg_indent_less() ;
00430 
00431     /* Reconstruct chips in windowing mode using detector 2 */
00432     if (crires_util_extract_config.win_mode == 1) {
00433         if (ext[1] != NULL) {
00434             ext[0] = cpl_table_duplicate(ext[1]) ;
00435             cpl_table_set_size(ext[0], 0) ;
00436             ext[CRIRES_NB_DETECTORS-1] = cpl_table_duplicate(ext[0]) ;
00437         }
00438         if (prof[1] != NULL) {
00439             prof[0] = cpl_image_duplicate(prof[1]) ;
00440             cpl_image_multiply_scalar(prof[0], 0.0) ;
00441             prof[CRIRES_NB_DETECTORS-1] = cpl_image_duplicate(prof[0]) ;
00442         }
00443         if (bgmap[1] != NULL) {
00444             bgmap[0] = cpl_image_duplicate(bgmap[1]) ;
00445             cpl_image_multiply_scalar(bgmap[0], 0.0) ;
00446             bgmap[CRIRES_NB_DETECTORS-1] = cpl_image_duplicate(bgmap[0]) ;
00447         }
00448     }
00449 
00450     /* Test that the spectrum is at the same place in all detectors */
00451     for (i=1 ; i<CRIRES_NB_DETECTORS ; i++) {
00452         /* Skip some detectors in windowing mode */
00453         if ((i==1 || i==CRIRES_NB_DETECTORS-1) && 
00454                 (crires_util_extract_config.win_mode == 1)) {
00455             continue ;
00456         }
00457         if (crires_util_extract_config.qc_specpos[i-1] > 0 && 
00458                 crires_util_extract_config.qc_specpos[i] > 0 &&
00459                 fabs(crires_util_extract_config.qc_specpos[i-1] - 
00460                     crires_util_extract_config.qc_specpos[i]) > 
00461                 CRIRES_SPEC_POS_TOLERANCE) {
00462             cpl_msg_warning(__func__, 
00463     "The spectrum positions in chip %d and chip %d are too different: %d -> %d",
00464                     i, i+1, crires_util_extract_config.qc_specpos[i-1], 
00465                     crires_util_extract_config.qc_specpos[i]) ;
00466         }
00467     }
00468  
00469     /* Create the profile */
00470     profile = cpl_imagelist_new() ;
00471     for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
00472         if (prof[i] != NULL) cpl_imagelist_set(profile, prof[i], i) ;
00473         else {
00474             cpl_imagelist_delete(profile) ;
00475             profile = NULL ;
00476             for (j=i+1 ; j<CRIRES_NB_DETECTORS ; j++) 
00477                 if (prof[j] != NULL) cpl_image_delete(prof[j]) ;
00478             break ;
00479         }
00480     }
00481    
00482     /* Create the bg maps */
00483     bgmaps = cpl_imagelist_new() ;
00484     for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
00485         if (bgmap[i] != NULL) cpl_imagelist_set(bgmaps, bgmap[i], i) ;
00486         else {
00487             cpl_imagelist_delete(bgmaps) ;
00488             bgmaps = NULL ;
00489             for (j=i+1 ; j<CRIRES_NB_DETECTORS ; j++) 
00490                 if (bgmap[j] != NULL) cpl_image_delete(bgmap[j]) ;
00491             break ;
00492         }
00493     }
00494         
00495     /* Save the result */
00496     cpl_msg_info(__func__, "Save the products") ;
00497     cpl_msg_indent_more() ;
00498     if (crires_util_extract_save((const cpl_table **)ext, profile, bgmaps, 
00499                 parlist, frameset) == -1) {
00500         cpl_msg_error(__func__, "Cannot save products") ;
00501         cpl_msg_indent_less() ;
00502         for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
00503             if (ext[i] != NULL) cpl_table_delete(ext[i]) ;
00504         }
00505         if (profile != NULL) cpl_imagelist_delete(profile) ;
00506         if (bgmaps != NULL) cpl_imagelist_delete(bgmaps) ;
00507         return -1 ;
00508     }
00509     cpl_msg_indent_less() ;
00510    
00511     /* Deallocate */
00512     for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
00513         if (ext[i] != NULL) cpl_table_delete(ext[i]) ;
00514     }
00515     if (profile != NULL) cpl_imagelist_delete(profile) ;
00516     if (bgmaps != NULL) cpl_imagelist_delete(bgmaps) ;
00517 
00518     /* Return */
00519     if (cpl_error_get_code()) return -1 ;
00520     else return 0 ;
00521 }
00522 
00523 /*----------------------------------------------------------------------------*/
00533 /*----------------------------------------------------------------------------*/
00534 static int crires_util_extract_save(
00535         const cpl_table             **  ext,
00536         const cpl_imagelist         *   profile,
00537         const cpl_imagelist         *   bgmaps,
00538         const cpl_parameterlist     *   parlist,
00539         cpl_frameset                *   set)
00540 {
00541     cpl_propertylist    **  qclists ;
00542     const cpl_frame     *   ref_frame ;
00543     cpl_propertylist    *   inputlist ;
00544     const char          *   recipe_name = "crires_util_extract" ;
00545     int                     i ;
00546 
00547     /* Get the reference frame */
00548     ref_frame = irplib_frameset_get_first_from_group(set, CPL_FRAME_GROUP_RAW) ;
00549 
00550     /* Create the QC lists */
00551     qclists = cpl_malloc(CRIRES_NB_DETECTORS * sizeof(cpl_propertylist*)) ;
00552     for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
00553         qclists[i] = cpl_propertylist_new() ;
00554         cpl_propertylist_append_int(qclists[i], "ESO QC SPECPOS",
00555                 crires_util_extract_config.qc_specpos[i]) ;
00556         cpl_propertylist_append_int(qclists[i], "ESO QC SPECWREC",
00557                 crires_util_extract_config.qc_specwrec[i]) ;
00558         cpl_propertylist_append_int(qclists[i], "ESO QC SPECWOPT",
00559                 crires_util_extract_config.qc_specwopt[i]) ;
00560         cpl_propertylist_append_double(qclists[i], "ESO QC SIGNAL MED",
00561                 crires_util_extract_config.qc_specoptmed[i]) ;
00562         cpl_propertylist_append_double(qclists[i], "ESO QC S2NMED",
00563                 crires_util_extract_config.qc_s2nmed[i]) ;
00564         cpl_propertylist_append_double(qclists[i], "ESO QC FWHMPIX COMBINED",
00565                 crires_util_extract_config.qc_fwhm_comb_pix[i]) ;
00566         cpl_propertylist_append_double(qclists[i], "ESO QC FWHMARC COMBINED",
00567                 crires_util_extract_config.qc_fwhm_comb_as[i]) ;
00568         cpl_propertylist_append_double(qclists[i], "ESO QC FWHMPIX PROFILE",
00569                 crires_util_extract_config.qc_fwhm_prof_pix[i]) ;
00570         cpl_propertylist_append_double(qclists[i], "ESO QC FWHMARC PROFILE",
00571                 crires_util_extract_config.qc_fwhm_prof_as[i]) ;
00572         cpl_propertylist_append_double(qclists[i], "ESO QC FWHM DIFF",
00573                 crires_util_extract_config.qc_fwhm_diff[i]) ;
00574 
00575         /* Propagate some keywords from input raw frame extensions */
00576         inputlist = cpl_propertylist_load_regexp(
00577                 cpl_frame_get_filename(ref_frame), i+1,
00578                 CRIRES_HEADER_EXT_FORWARD, 0) ;
00579         cpl_propertylist_copy_property_regexp(qclists[i], inputlist, 
00580                 CRIRES_HEADER_EXT_FORWARD, 0) ;
00581         cpl_propertylist_delete(inputlist) ;
00582     }
00583 
00584     if (profile != NULL) {
00585         /* Write the image */
00586         crires_image_save(set,
00587                 parlist,
00588                 set,
00589                 profile,
00590                 recipe_name,
00591                 CRIRES_OBS_EXTRACT_PROFILE_IMA,
00592                 CRIRES_PROTYPE_PROFILE,
00593                 crires_util_extract_config.period,
00594                 NULL,
00595                 (const cpl_propertylist**)qclists,
00596                 PACKAGE "/" PACKAGE_VERSION,
00597                 "crires_util_extract_profile.fits") ;
00598     }
00599 
00600     if (bgmaps!= NULL) {
00601         /* Write the image */
00602         crires_image_save(set,
00603                 parlist,
00604                 set,
00605                 bgmaps,
00606                 recipe_name,
00607                 CRIRES_OBS_EXTRACT_BGMAP_IMA,
00608                 CRIRES_PROTYPE_BGD_MAP,
00609                 crires_util_extract_config.period,
00610                 NULL,
00611                 (const cpl_propertylist**)qclists,
00612                 PACKAGE "/" PACKAGE_VERSION,
00613                 "crires_util_extract_bgmap.fits") ;
00614     }
00615 
00616     /* Write the table */
00617     crires_table_save(set,
00618             parlist,
00619             set,
00620             ext,
00621             recipe_name,
00622             CRIRES_EXTRACT_PIX_TAB,
00623             CRIRES_PROTYPE_SPEC_PIX,
00624             NULL,
00625             (const cpl_propertylist**)qclists,
00626             PACKAGE "/" PACKAGE_VERSION,
00627             "crires_util_extract_extracted.fits") ;
00628 
00629     /* Free and return */
00630     for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
00631         cpl_propertylist_delete(qclists[i]) ;
00632     }
00633     cpl_free(qclists) ;
00634     return  0;
00635 }
00636