CRIRES Pipeline Reference Manual  2.3.3
crires_util_extract.c
00001 /* 
00002  * This file is part of the crires Pipeline
00003  * Copyright (C) 2002,2003 European Southern Observatory
00004  *
00005  * This program is free software; you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License as published by
00007  * the Free Software Foundation; either version 2 of the License, or
00008  * (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program; if not, write to the Free Software
00017  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018  */
00019 
00020 #ifdef HAVE_CONFIG_H
00021 #include <config.h>
00022 #endif
00023 
00024 /*-----------------------------------------------------------------------------
00025                                 Includes
00026  -----------------------------------------------------------------------------*/
00027 
00028 #include "crires_recipe.h"
00029 
00030 #include "crires_extract.h"
00031 
00032 /*-----------------------------------------------------------------------------
00033                                 Define
00034  -----------------------------------------------------------------------------*/
00035 
00036 #define RECIPE_STRING "crires_util_extract"
00037 
00038 /*-----------------------------------------------------------------------------
00039                             Functions prototypes
00040  -----------------------------------------------------------------------------*/
00041 
00042 static int crires_util_extract_save(const cpl_table **, const cpl_imagelist *, 
00043         const cpl_imagelist *, const cpl_parameterlist *, cpl_frameset *) ;
00044 
00045 static char crires_util_extract_description[] = 
00046 "This recipe accepts 1 parameter (optionally a 2nd one):\n"
00047 "First parameter:   the combined image.\n" 
00048 "                   (PRO TYPE = "CRIRES_PROTYPE_COMBINED")\n"
00049 "Second parameter (optional):   the contribution map.\n" 
00050 "                   (PRO TYPE = "CRIRES_PROTYPE_CONTRIB")\n"
00051 "\n"
00052 "This recipe produces 3 files:\n"
00053 "First product:     the image of the profile of the spectrum\n"
00054 "                   (PRO TYPE = "CRIRES_PROTYPE_PROFILE")\n"
00055 "Second product:    the table of the extracted spectrum in pixels\n"
00056 "                   (PRO TYPE = "CRIRES_PROTYPE_SPEC_PIX")\n"
00057 "Third product:     the maps of the background\n"
00058 "                   (PRO TYPE = "CRIRES_PROTYPE_BGD_MAP")\n" ;
00059 
00060 CRIRES_RECIPE_DEFINE(crires_util_extract,
00061         CRIRES_PARAM_DISPLAY            |
00062         CRIRES_PARAM_EXTR_MODE          |
00063         CRIRES_PARAM_HOR_SIZE           |
00064         CRIRES_PARAM_SPEC_HSIZE         |
00065         CRIRES_PARAM_KAPPA              |
00066         CRIRES_PARAM_CLOSING_HSIZE      |
00067         CRIRES_PARAM_CLEAN_RATE         |
00068         CRIRES_PARAM_TOT_NDIT           |
00069         CRIRES_PARAM_Y_POS_CHIP1        |
00070         CRIRES_PARAM_Y_POS_CHIP2        |
00071         CRIRES_PARAM_Y_POS_CHIP3        |
00072         CRIRES_PARAM_Y_POS_CHIP4        |
00073         CRIRES_PARAM_Y_WIDTH            |
00074         CRIRES_PARAM_Y_SPEC_ZONE_CHIP1  |
00075         CRIRES_PARAM_Y_SPEC_ZONE_CHIP2  |
00076         CRIRES_PARAM_Y_SPEC_ZONE_CHIP3  |
00077         CRIRES_PARAM_Y_SPEC_ZONE_CHIP4  |
00078         CRIRES_PARAM_REJECT,
00079         "Spectrum extraction routine",
00080         crires_util_extract_description) ;
00081 
00082 /*-----------------------------------------------------------------------------
00083                             Static variables
00084  -----------------------------------------------------------------------------*/
00085 
00086 static struct {
00087     /* Inputs */
00088     /* mode : 1=spec ; 2=lines */
00089     int                 mode ;
00090     double              kappa ;         /* mode = 1 */
00091     int                 closing_hs ;    /* mode = 1 */
00092     double              clean_rate ;    /* mode = 1 */
00093     double              tot_ndit ;      /* mode = 1 */
00094     int                 box_hor_size ;  /* mode = 1 */
00095     int                 spec_hsize ;    /* mode = 1 */
00096     const char      *   y_spec_zone_c1 ;/* mode = 1 */
00097     const char      *   y_spec_zone_c2 ;/* mode = 1 */
00098     const char      *   y_spec_zone_c3 ;/* mode = 1 */
00099     const char      *   y_spec_zone_c4 ;/* mode = 1 */
00100     const char      *   y_pos_c1 ;      /* mode = 2 */
00101     const char      *   y_pos_c2 ;      /* mode = 2 */
00102     const char      *   y_pos_c3 ;      /* mode = 2 */
00103     const char      *   y_pos_c4 ;      /* mode = 2 */
00104     int                 y_width ;       /* mode = 2 */
00105     int                 rej_right ;     /* All modes */
00106     int                 rej_left ;      /* All modes */
00107     int                 display ;       /* All modes */
00108     /* Outputs */
00109     int                 win_mode ;
00110     crires_illum_period period ;
00111     int                 qc_specpos[CRIRES_NB_DETECTORS] ;
00112     int                 qc_specwrec[CRIRES_NB_DETECTORS] ;
00113     int                 qc_specwopt[CRIRES_NB_DETECTORS] ;
00114     double              qc_specoptmed[CRIRES_NB_DETECTORS] ;
00115     double              qc_s2nmed[CRIRES_NB_DETECTORS] ;
00116     double              qc_fwhm_comb_pix[CRIRES_NB_DETECTORS] ;
00117     double              qc_fwhm_comb_as[CRIRES_NB_DETECTORS] ;
00118     double              qc_fwhm_prof_pix[CRIRES_NB_DETECTORS] ;
00119     double              qc_fwhm_prof_as[CRIRES_NB_DETECTORS] ;
00120     double              qc_fwhm_diff[CRIRES_NB_DETECTORS] ;
00121 } crires_util_extract_config ;
00122 
00123 /*-----------------------------------------------------------------------------
00124                                 Functions code
00125  -----------------------------------------------------------------------------*/
00126 
00127 /*----------------------------------------------------------------------------*/
00134 /*----------------------------------------------------------------------------*/
00135 static int crires_util_extract(
00136         cpl_frameset            *   frameset,
00137         const cpl_parameterlist *   parlist) 
00138 {
00139     const char          *   sval ;
00140     const char          *   y_pos ;
00141     cpl_imagelist       *   imlist ;
00142     cpl_propertylist    *   plist ;
00143     cpl_imagelist       *   contrib ;
00144     cpl_image           *   contribution_map ;
00145     cpl_frame           *   fr ;
00146     cpl_imagelist       *   profile ;
00147     cpl_image           *   prof[CRIRES_NB_DETECTORS] ;
00148     cpl_imagelist       *   bgmaps ;
00149     cpl_image           *   bgmap[CRIRES_NB_DETECTORS] ;
00150     cpl_table           *   ext[CRIRES_NB_DETECTORS] ;
00151     cpl_vector          *   ext_vec ;
00152     cpl_vector          *   ypos_vec ;
00153     int                     ly, nexp, starty, stopy, extr_spec_starty,
00154                             extr_spec_stopy ;
00155     int                     i, j ;
00156     
00157     /* Initialise */
00158     for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
00159         crires_util_extract_config.qc_specpos[i] = -1 ;
00160         crires_util_extract_config.qc_specwrec[i] = -1 ;
00161         crires_util_extract_config.qc_specwopt[i] = -1 ;
00162         crires_util_extract_config.qc_specoptmed[i] = -1.0 ;
00163         crires_util_extract_config.qc_s2nmed[i] = -1.0 ;
00164         crires_util_extract_config.qc_fwhm_comb_pix[i] = -1.0 ;
00165         crires_util_extract_config.qc_fwhm_comb_as[i] = -1.0 ;
00166         crires_util_extract_config.qc_fwhm_prof_pix[i] = -1.0 ;
00167         crires_util_extract_config.qc_fwhm_prof_as[i] = -1.0 ;
00168         crires_util_extract_config.qc_fwhm_diff[i] = -1.0 ;
00169         ext[i] = NULL ;
00170         prof[i] = NULL ;
00171         bgmap[i] = NULL ;
00172     }
00173     ly = -1 ;
00174     
00175     /* Retrieve input parameters */
00176     crires_util_extract_config.display = crires_parameterlist_get_int(parlist,
00177             RECIPE_STRING, CRIRES_PARAM_DISPLAY) ;
00178     crires_util_extract_config.mode = crires_parameterlist_get_int(parlist,
00179             RECIPE_STRING, CRIRES_PARAM_EXTR_MODE) ;
00180     crires_util_extract_config.box_hor_size = crires_parameterlist_get_int(
00181             parlist, RECIPE_STRING, CRIRES_PARAM_HOR_SIZE) ;
00182     crires_util_extract_config.spec_hsize = crires_parameterlist_get_int(
00183             parlist, RECIPE_STRING, CRIRES_PARAM_SPEC_HSIZE) ;
00184     crires_util_extract_config.kappa = crires_parameterlist_get_double(
00185             parlist, RECIPE_STRING, CRIRES_PARAM_KAPPA) ;
00186     crires_util_extract_config.closing_hs = crires_parameterlist_get_int(
00187             parlist, RECIPE_STRING, CRIRES_PARAM_CLOSING_HSIZE) ;
00188     crires_util_extract_config.clean_rate = crires_parameterlist_get_double(
00189             parlist, RECIPE_STRING, CRIRES_PARAM_CLEAN_RATE) ;
00190     crires_util_extract_config.tot_ndit = crires_parameterlist_get_double(
00191             parlist, RECIPE_STRING, CRIRES_PARAM_TOT_NDIT) ;
00192     crires_util_extract_config.y_pos_c1=crires_parameterlist_get_string(parlist,
00193             RECIPE_STRING, CRIRES_PARAM_Y_POS_CHIP1) ;
00194     crires_util_extract_config.y_pos_c2=crires_parameterlist_get_string(parlist,
00195             RECIPE_STRING, CRIRES_PARAM_Y_POS_CHIP2) ;
00196     crires_util_extract_config.y_pos_c3=crires_parameterlist_get_string(parlist,
00197             RECIPE_STRING, CRIRES_PARAM_Y_POS_CHIP3) ;
00198     crires_util_extract_config.y_pos_c4=crires_parameterlist_get_string(parlist,
00199             RECIPE_STRING, CRIRES_PARAM_Y_POS_CHIP4) ;
00200     crires_util_extract_config.y_width= crires_parameterlist_get_int(parlist,
00201             RECIPE_STRING, CRIRES_PARAM_Y_WIDTH) ;
00202     crires_util_extract_config.y_spec_zone_c1=crires_parameterlist_get_string(
00203             parlist, RECIPE_STRING, CRIRES_PARAM_Y_SPEC_ZONE_CHIP1) ;
00204     crires_util_extract_config.y_spec_zone_c2=crires_parameterlist_get_string(
00205             parlist, RECIPE_STRING, CRIRES_PARAM_Y_SPEC_ZONE_CHIP2) ;
00206     crires_util_extract_config.y_spec_zone_c3=crires_parameterlist_get_string(
00207             parlist, RECIPE_STRING, CRIRES_PARAM_Y_SPEC_ZONE_CHIP3) ;
00208     crires_util_extract_config.y_spec_zone_c4=crires_parameterlist_get_string(
00209             parlist, RECIPE_STRING, CRIRES_PARAM_Y_SPEC_ZONE_CHIP4) ;
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             /* Where is the spectrum extraction zone ? */
00304             y_pos = "" ;
00305             if (i+1 == 1) y_pos = crires_util_extract_config.y_spec_zone_c1 ;
00306             if (i+1 == 2) y_pos = crires_util_extract_config.y_spec_zone_c1 ;
00307             if (i+1 == 3) y_pos = crires_util_extract_config.y_spec_zone_c3 ;
00308             if (i+1 == 4) y_pos = crires_util_extract_config.y_spec_zone_c4 ;
00309             if (sscanf(y_pos,"%d,%d", &extr_spec_starty, &extr_spec_stopy)!=2) {
00310                 cpl_msg_warning(__func__, "Wrong Spectral Zone specified: %s",
00311                         y_pos) ;
00312                 extr_spec_starty = extr_spec_stopy = -1 ;
00313             }
00314 
00315             /* Extract spectrum */
00316             if (contrib != NULL) 
00317                 contribution_map = cpl_imagelist_get(contrib, i) ;
00318             else
00319                 contribution_map = NULL ;
00320             ext[i] = crires_extract_spectrum(cpl_imagelist_get(imlist, i),
00321                     contribution_map,
00322                     crires_util_extract_config.box_hor_size, 
00323                     crires_util_extract_config.spec_hsize, 
00324                     crires_util_extract_config.kappa,
00325                     crires_util_extract_config.closing_hs,
00326                     crires_util_extract_config.clean_rate,
00327                     crires_util_extract_config.rej_left,
00328                     crires_util_extract_config.rej_right,
00329                     extr_spec_starty, extr_spec_stopy,
00330                     i+1,
00331                     crires_util_extract_config.tot_ndit,
00332                     crires_util_extract_config.period,
00333                     &(crires_util_extract_config.qc_specpos[i]), 
00334                     &(crires_util_extract_config.qc_specwrec[i]), 
00335                     &(crires_util_extract_config.qc_specwopt[i]), 
00336                     &(crires_util_extract_config.qc_specoptmed[i]),
00337                     &(crires_util_extract_config.qc_s2nmed[i]),
00338                     &(prof[i]),
00339                     &(bgmap[i])) ;
00340             cpl_msg_info(__func__, "Chip number %d FWHM Computation", i+1) ;
00341             if (crires_extract_qc_fwhm(cpl_imagelist_get(imlist, i),
00342                         prof[i],
00343                         &(crires_util_extract_config.qc_fwhm_comb_pix[i]),
00344                         &(crires_util_extract_config.qc_fwhm_comb_as[i]),
00345                         &(crires_util_extract_config.qc_fwhm_prof_pix[i]),
00346                         &(crires_util_extract_config.qc_fwhm_prof_as[i]),
00347                         &(crires_util_extract_config.qc_fwhm_diff[i])) == -1) {
00348                 cpl_msg_warning(__func__, "Failed for FWHM computation") ;
00349                 crires_util_extract_config.qc_fwhm_comb_pix[i] = -1.0 ;
00350                 crires_util_extract_config.qc_fwhm_comb_as[i] = -1.0 ;
00351                 crires_util_extract_config.qc_fwhm_prof_pix[i] = -1.0 ;
00352                 crires_util_extract_config.qc_fwhm_prof_as[i] = -1.0 ;
00353                 crires_util_extract_config.qc_fwhm_diff[i] = -1.0 ;
00354             }
00355         } else if (crires_util_extract_config.mode == 2) {
00356             /* Get the correction for the position */
00357             if (i+1 == 1) 
00358                 ly = crires_get_detector_ly1(crires_util_extract_config.period);
00359             if (i+1 == 2) 
00360                 ly = crires_get_detector_ly2(crires_util_extract_config.period);
00361             if (i+1 == 3) 
00362                 ly = crires_get_detector_ly3(crires_util_extract_config.period);
00363             if (i+1 == 4) 
00364                 ly = crires_get_detector_ly4(crires_util_extract_config.period);
00365             /* If ly not found, use the bottom of the image */
00366             if (ly < 0) ly = 1 ;
00367 
00368             /* Where is the Y extraction zone ? */
00369             y_pos = "" ;
00370             if (i+1 == 1) y_pos = crires_util_extract_config.y_pos_c1 ;
00371             if (i+1 == 2) y_pos = crires_util_extract_config.y_pos_c2 ;
00372             if (i+1 == 3) y_pos = crires_util_extract_config.y_pos_c3 ;
00373             if (i+1 == 4) y_pos = crires_util_extract_config.y_pos_c4 ;
00374 
00375             /* Try to parse the user specified positions */
00376             if (!strcmp(y_pos, "")) {
00377                 ypos_vec = NULL ;
00378             } else {
00379                 if ((ypos_vec = crires_parse_y_positions(y_pos)) == NULL) {
00380                     cpl_msg_warning(__func__,
00381                             "Cannot parse the y_positions value : %s", y_pos) ;
00382                     ypos_vec = NULL ;
00383                 }
00384             } 
00385             
00386             if (ypos_vec == NULL) {
00387                 cpl_msg_info(__func__, "Collapse the full image along Y") ;
00388                 starty = 1 ;
00389                 stopy = cpl_image_get_size_y(cpl_imagelist_get(imlist, i)) ;
00390             } else {
00391                 cpl_msg_info(__func__, "Collapse the area around Y=%g",
00392                         cpl_vector_get(ypos_vec, 0)) ;
00393                 /* TODO : Only the first passed value is used */
00394                 starty = (int)cpl_vector_get(ypos_vec, 0) - 
00395                     (int)(crires_util_extract_config.y_width/2.0) ;
00396                 stopy = (int)cpl_vector_get(ypos_vec, 0) +
00397                     (int)(crires_util_extract_config.y_width/2.0) ;
00398                 cpl_vector_delete(ypos_vec) ;
00399                 starty -= ly-1 ;
00400                 stopy -= ly-1 ;
00401             }
00402 
00403             /* Extract lines */
00404             ext_vec = crires_extract_lines(cpl_imagelist_get(imlist, i),
00405                     starty, stopy,
00406                     crires_util_extract_config.rej_left,
00407                     crires_util_extract_config.rej_right) ;
00408             if (ext_vec != NULL) {
00409                 ext[i] = crires_extract_gen_tab(ext_vec, NULL, NULL, NULL, 
00410                         NULL, NULL, NULL) ;     
00411                 crires_util_extract_config.qc_specpos[i] =
00412                     (starty+stopy)/2 + (ly-1) ;
00413                 crires_util_extract_config.qc_specwrec[i] = starty-stopy+1;
00414                 cpl_vector_delete(ext_vec) ;
00415             }
00416         } else {
00417             cpl_msg_warning(__func__, "Unsuported mode: %d", 
00418                     crires_util_extract_config.mode) ;
00419         }
00420 
00421         /* Plot the result if required */
00422         if ((ext[i] != NULL) && (crires_util_extract_config.display == i+1)) {
00423             ext_vec = cpl_vector_wrap(cpl_table_get_nrow(ext[i]),
00424             cpl_table_get_data_double(ext[i], CRIRES_COL_EXTRACT_INT_RECT));
00425             cpl_plot_vector(
00426 "set grid;set xlabel 'Position (pixels)';set ylabel 'Intensity RECT (ADU/sec)';",
00427             "t 'Extracted Spectrum RECT' w lines", "", ext_vec) ;
00428             cpl_vector_unwrap(ext_vec) ;
00429             ext_vec = cpl_vector_wrap(cpl_table_get_nrow(ext[i]),
00430             cpl_table_get_data_double(ext[i], CRIRES_COL_EXTRACT_INT_OPT)) ;
00431             cpl_plot_vector(
00432 "set grid;set xlabel 'Position (pixels)';set ylabel 'Intensity OPT (ADU/sec)';",
00433             "t 'Extracted Spectrum OPT' w lines", "", ext_vec) ;
00434             cpl_vector_unwrap(ext_vec) ;
00435         }
00436         cpl_msg_indent_less() ;
00437     }
00438     cpl_imagelist_delete(imlist) ;
00439     if (contrib != NULL) cpl_imagelist_delete(contrib) ;
00440     cpl_msg_indent_less() ;
00441 
00442     /* Reconstruct chips in windowing mode using detector 2 */
00443     if (crires_util_extract_config.win_mode == 1) {
00444         if (ext[1] != NULL) {
00445             ext[0] = cpl_table_duplicate(ext[1]) ;
00446             cpl_table_set_size(ext[0], 0) ;
00447             ext[CRIRES_NB_DETECTORS-1] = cpl_table_duplicate(ext[0]) ;
00448         }
00449         if (prof[1] != NULL) {
00450             prof[0] = cpl_image_duplicate(prof[1]) ;
00451             cpl_image_multiply_scalar(prof[0], 0.0) ;
00452             prof[CRIRES_NB_DETECTORS-1] = cpl_image_duplicate(prof[0]) ;
00453         }
00454         if (bgmap[1] != NULL) {
00455             bgmap[0] = cpl_image_duplicate(bgmap[1]) ;
00456             cpl_image_multiply_scalar(bgmap[0], 0.0) ;
00457             bgmap[CRIRES_NB_DETECTORS-1] = cpl_image_duplicate(bgmap[0]) ;
00458         }
00459     }
00460 
00461     /* Test that the spectrum is at the same place in all detectors */
00462     for (i=1 ; i<CRIRES_NB_DETECTORS ; i++) {
00463         /* Skip some detectors in windowing mode */
00464         if ((i==1 || i==CRIRES_NB_DETECTORS-1) && 
00465                 (crires_util_extract_config.win_mode == 1)) {
00466             continue ;
00467         }
00468         if (crires_util_extract_config.qc_specpos[i-1] > 0 && 
00469                 crires_util_extract_config.qc_specpos[i] > 0 &&
00470                 fabs(crires_util_extract_config.qc_specpos[i-1] - 
00471                     crires_util_extract_config.qc_specpos[i]) > 
00472                 CRIRES_SPEC_POS_TOLERANCE) {
00473             cpl_msg_warning(__func__, 
00474     "The spectrum positions in chip %d and chip %d are too different: %d -> %d",
00475                     i, i+1, crires_util_extract_config.qc_specpos[i-1], 
00476                     crires_util_extract_config.qc_specpos[i]) ;
00477         }
00478     }
00479  
00480     /* Create the profile */
00481     profile = cpl_imagelist_new() ;
00482     for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
00483         if (prof[i] != NULL) cpl_imagelist_set(profile, prof[i], i) ;
00484         else {
00485             cpl_imagelist_delete(profile) ;
00486             profile = NULL ;
00487             for (j=i+1 ; j<CRIRES_NB_DETECTORS ; j++) 
00488                 if (prof[j] != NULL) cpl_image_delete(prof[j]) ;
00489             break ;
00490         }
00491     }
00492    
00493     /* Create the bg maps */
00494     bgmaps = cpl_imagelist_new() ;
00495     for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
00496         if (bgmap[i] != NULL) cpl_imagelist_set(bgmaps, bgmap[i], i) ;
00497         else {
00498             cpl_imagelist_delete(bgmaps) ;
00499             bgmaps = NULL ;
00500             for (j=i+1 ; j<CRIRES_NB_DETECTORS ; j++) 
00501                 if (bgmap[j] != NULL) cpl_image_delete(bgmap[j]) ;
00502             break ;
00503         }
00504     }
00505         
00506     /* Save the result */
00507     cpl_msg_info(__func__, "Save the products") ;
00508     cpl_msg_indent_more() ;
00509     if (crires_util_extract_save((const cpl_table **)ext, profile, bgmaps, 
00510                 parlist, frameset) == -1) {
00511         cpl_msg_error(__func__, "Cannot save products") ;
00512         cpl_msg_indent_less() ;
00513         for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
00514             if (ext[i] != NULL) cpl_table_delete(ext[i]) ;
00515         }
00516         if (profile != NULL) cpl_imagelist_delete(profile) ;
00517         if (bgmaps != NULL) cpl_imagelist_delete(bgmaps) ;
00518         return -1 ;
00519     }
00520     cpl_msg_indent_less() ;
00521    
00522     /* Deallocate */
00523     for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
00524         if (ext[i] != NULL) cpl_table_delete(ext[i]) ;
00525     }
00526     if (profile != NULL) cpl_imagelist_delete(profile) ;
00527     if (bgmaps != NULL) cpl_imagelist_delete(bgmaps) ;
00528 
00529     /* Return */
00530     if (cpl_error_get_code()) return -1 ;
00531     else return 0 ;
00532 }
00533 
00534 /*----------------------------------------------------------------------------*/
00544 /*----------------------------------------------------------------------------*/
00545 static int crires_util_extract_save(
00546         const cpl_table             **  ext,
00547         const cpl_imagelist         *   profile,
00548         const cpl_imagelist         *   bgmaps,
00549         const cpl_parameterlist     *   parlist,
00550         cpl_frameset                *   set)
00551 {
00552     cpl_propertylist    **  qclists ;
00553     const cpl_frame     *   ref_frame ;
00554     cpl_propertylist    *   inputlist ;
00555     const char          *   recipe_name = "crires_util_extract" ;
00556     int                     i ;
00557 
00558     /* Get the reference frame */
00559     ref_frame = irplib_frameset_get_first_from_group(set, CPL_FRAME_GROUP_RAW) ;
00560 
00561     /* Create the QC lists */
00562     qclists = cpl_malloc(CRIRES_NB_DETECTORS * sizeof(cpl_propertylist*)) ;
00563     for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
00564         qclists[i] = cpl_propertylist_new() ;
00565         cpl_propertylist_append_int(qclists[i], "ESO QC SPECPOS",
00566                 crires_util_extract_config.qc_specpos[i]) ;
00567         cpl_propertylist_append_int(qclists[i], "ESO QC SPECWREC",
00568                 crires_util_extract_config.qc_specwrec[i]) ;
00569         cpl_propertylist_append_int(qclists[i], "ESO QC SPECWOPT",
00570                 crires_util_extract_config.qc_specwopt[i]) ;
00571         cpl_propertylist_append_double(qclists[i], "ESO QC SIGNAL MED",
00572                 crires_util_extract_config.qc_specoptmed[i]) ;
00573         cpl_propertylist_append_double(qclists[i], "ESO QC S2NMED",
00574                 crires_util_extract_config.qc_s2nmed[i]) ;
00575         cpl_propertylist_append_double(qclists[i], "ESO QC FWHMPIX COMBINED",
00576                 crires_util_extract_config.qc_fwhm_comb_pix[i]) ;
00577         cpl_propertylist_append_double(qclists[i], "ESO QC FWHMARC COMBINED",
00578                 crires_util_extract_config.qc_fwhm_comb_as[i]) ;
00579         cpl_propertylist_append_double(qclists[i], "ESO QC FWHMPIX PROFILE",
00580                 crires_util_extract_config.qc_fwhm_prof_pix[i]) ;
00581         cpl_propertylist_append_double(qclists[i], "ESO QC FWHMARC PROFILE",
00582                 crires_util_extract_config.qc_fwhm_prof_as[i]) ;
00583         cpl_propertylist_append_double(qclists[i], "ESO QC FWHM DIFF",
00584                 crires_util_extract_config.qc_fwhm_diff[i]) ;
00585 
00586         /* Propagate some keywords from input raw frame extensions */
00587         inputlist = cpl_propertylist_load_regexp(
00588                 cpl_frame_get_filename(ref_frame), i+1,
00589                 CRIRES_HEADER_EXT_FORWARD, 0) ;
00590         cpl_propertylist_copy_property_regexp(qclists[i], inputlist, 
00591                 CRIRES_HEADER_EXT_FORWARD, 0) ;
00592         cpl_propertylist_delete(inputlist) ;
00593     }
00594 
00595     if (profile != NULL) {
00596         /* Write the image */
00597         crires_image_save(set,
00598                 parlist,
00599                 set,
00600                 profile,
00601                 recipe_name,
00602                 CRIRES_OBS_EXTRACT_PROFILE_IMA,
00603                 CRIRES_PROTYPE_PROFILE,
00604                 crires_util_extract_config.period,
00605                 NULL,
00606                 (const cpl_propertylist**)qclists,
00607                 PACKAGE "/" PACKAGE_VERSION,
00608                 "crires_util_extract_profile.fits") ;
00609     }
00610 
00611     if (bgmaps!= NULL) {
00612         /* Write the image */
00613         crires_image_save(set,
00614                 parlist,
00615                 set,
00616                 bgmaps,
00617                 recipe_name,
00618                 CRIRES_OBS_EXTRACT_BGMAP_IMA,
00619                 CRIRES_PROTYPE_BGD_MAP,
00620                 crires_util_extract_config.period,
00621                 NULL,
00622                 (const cpl_propertylist**)qclists,
00623                 PACKAGE "/" PACKAGE_VERSION,
00624                 "crires_util_extract_bgmap.fits") ;
00625     }
00626 
00627     /* Write the table */
00628     crires_table_save(set,
00629             parlist,
00630             set,
00631             ext,
00632             recipe_name,
00633             CRIRES_EXTRACT_PIX_TAB,
00634             CRIRES_PROTYPE_SPEC_PIX,
00635             NULL,
00636             (const cpl_propertylist**)qclists,
00637             PACKAGE "/" PACKAGE_VERSION,
00638             "crires_util_extract_extracted.fits") ;
00639 
00640     /* Free and return */
00641     for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
00642         cpl_propertylist_delete(qclists[i]) ;
00643     }
00644     cpl_free(qclists) ;
00645     return  0;
00646 }
00647