isaac_spc_arc.c

00001 /* $Id: isaac_spc_arc.c,v 1.54 2010/03/02 13:26:12 llundin Exp $
00002  *
00003  * This file is part of the ISAAC 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: llundin $
00023  * $Date: 2010/03/02 13:26:12 $
00024  * $Revision: 1.54 $
00025  * $Name: HEAD $
00026  */
00027 
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031 
00032 /*-----------------------------------------------------------------------------
00033                                 Includes
00034  -----------------------------------------------------------------------------*/
00035 
00036 #include <string.h>
00037 #include <math.h>
00038 #include <float.h>
00039 #include <cpl.h>
00040 
00041 #include "irplib_plugin.h"
00042 #include "irplib_utils.h"
00043 #include "irplib_distortion.h"
00044 
00045 #include "isaac_utils.h"
00046 #include "isaac_wavelength.h"
00047 #include "isaac_physicalmodel.h"
00048 #include "isaac_pfits.h"
00049 #include "isaac_dfs.h"
00050 
00051 /*-----------------------------------------------------------------------------
00052                             Define
00053  -----------------------------------------------------------------------------*/
00054 
00055 #define RECIPE_STRING "isaac_spc_arc"
00056 
00057 #define ISAAC_ARC_SATURATION    20000
00058 
00059 /*-----------------------------------------------------------------------------
00060                             Functions prototypes
00061  -----------------------------------------------------------------------------*/
00062 
00063 static int isaac_spc_arc_reduce_sw(cpl_frameset *, const cpl_parameterlist *, 
00064         const char *, const char *, cpl_frameset *);
00065 static int isaac_spc_arc_reduce_lw(cpl_frameset *, const cpl_parameterlist *, 
00066         const char *, const char *, cpl_frameset *);
00067 static cpl_table * isaac_spc_arc_compute(const cpl_image *, const char *,
00068         const char *, const char *, const char *, cpl_table **, cpl_image **);
00069 static int isaac_spc_arc_save(const cpl_table *, const cpl_table *,
00070         const cpl_image *, const char *, cpl_frameset *,
00071         const cpl_parameterlist *,  cpl_frameset *);
00072 static int isaac_spc_arc_compare(const cpl_frame *, const cpl_frame *); 
00073 static int * isaac_spc_arc_find_lamps(cpl_frameset *);
00074 static int isaac_is_xenon_lamp_active(const cpl_propertylist *);
00075 static int isaac_is_argon_lamp_active(const cpl_propertylist *);
00076 
00077 static
00078 cpl_error_code isaac_spc_arc_fill_parameterlist(cpl_parameterlist *);
00079 
00080 CPL_RECIPE_DEFINE(isaac_spc_arc, ISAAC_BINARY_VERSION,
00081                   isaac_spc_arc_fill_parameterlist(recipe->parameters),
00082                   "Lars Lundin", PACKAGE_BUGREPORT, "2002, 2003, 2008", 
00083                   "ISAAC Spectro arc recipe",
00084                   RECIPE_STRING " -- ISAAC Spectro arc recipe\n"
00085                   "The files listed in the Set Of Frames (sof-file) " 
00086                   "must be tagged:\n"
00087                   "raw-file.fits "ISAAC_SPC_ARC_RAW" or\n"
00088                   "xe-cat.fits   "ISAAC_CALPRO_XE_CAT" or\n"
00089                   "ar-cat.fits   "ISAAC_CALPRO_AR_CAT"\n");
00090 
00091  
00092 /*-----------------------------------------------------------------------------
00093                             Static variables
00094  -----------------------------------------------------------------------------*/
00095 
00096 static struct {
00097     /* Inputs */
00098     int         rej_left;
00099     int         rej_right;
00100     int         rej_bottom;
00101     int         rej_top;
00102     int         sub_dark;
00103     int         arc_max_width;
00104     int         max_offset;
00105     double      arc_kappa;
00106     int         out_corr;
00107     /* Outputs */
00108     int         set_nb;
00109     int         pair_nb;
00110     int         nb_saturated;
00111     int         arm;
00112     char        resol;
00113     double      disprel_cc;
00114     int         disprel_clines;
00115     int         disprel_dlines;
00116     double      disprel_rms;
00117     double      disprel_offset;
00118     double      fwhm_med;
00119     int         fwhm_good;
00120 } isaac_spc_arc_config;
00121 
00122 /*-----------------------------------------------------------------------------
00123                                 Functions code
00124  -----------------------------------------------------------------------------*/
00125 
00126 /*----------------------------------------------------------------------------*/
00134 /*----------------------------------------------------------------------------*/
00135 static
00136 cpl_error_code isaac_spc_arc_fill_parameterlist(cpl_parameterlist * self)
00137 {
00138     const char * context = PACKAGE "." RECIPE_STRING;
00139     cpl_error_code err;
00140 
00141     cpl_ensure_code(self, CPL_ERROR_NULL_INPUT);
00142 
00143     /* Fill the parameters list */
00144 
00145     /* --rejected */
00146     err = irplib_parameterlist_set_string(self, PACKAGE, RECIPE_STRING,
00147                                           "rejected", "-1,-1,100,100", "rej",
00148                                           context,
00149                                           "left right bottom top rejections");
00150     cpl_ensure_code(!err, err);
00151 
00152     /* --subdark */
00153     err = irplib_parameterlist_set_bool(self, PACKAGE, RECIPE_STRING,
00154                                         "subdark", CPL_FALSE, NULL, context,
00155                                         "Flag to subtract the dark");
00156     cpl_ensure_code(!err, err);
00157 
00158     /* --arc_max_w */
00159     err = irplib_parameterlist_set_int(self, PACKAGE, RECIPE_STRING,
00160                                        "arc_max_w", 33, NULL, context,
00161                                        "Maximum arc width allowed in pixels");
00162     cpl_ensure_code(!err, err);
00163 
00164     /* --max_offset */
00165     err = irplib_parameterlist_set_int(self, PACKAGE, RECIPE_STRING,
00166                                        "max_offset", 50, NULL, context,
00167                                        "Maximum offset from the physical "
00168                                        "model allowed in pixels");
00169     cpl_ensure_code(!err, err);
00170 
00171     /* --arc_kappa */
00172     err = irplib_parameterlist_set_double(self, PACKAGE, RECIPE_STRING,
00173                                        "arc_kappa", 0.33, NULL, context,
00174                                        "kappa for the threshold used for "
00175                                        "arcs detection");
00176     cpl_ensure_code(!err, err);
00177 
00178     /* --out_corr */
00179     err = irplib_parameterlist_set_bool(self, PACKAGE, RECIPE_STRING,
00180                                         "out_corr", CPL_FALSE, NULL, context,
00181                                         "Flag to output corrected images");
00182     cpl_ensure_code(!err, err);
00183 
00184     return CPL_ERROR_NONE;
00185 }
00186 
00187 /*----------------------------------------------------------------------------*/
00194 /*----------------------------------------------------------------------------*/
00195 static int isaac_spc_arc(cpl_frameset            * framelist,
00196                          const cpl_parameterlist * parlist)
00197 {
00198     const char          *   sval;
00199     int                 *   labels = NULL;
00200     int                     nlabels = 0;
00201     const char          *   xe;
00202     const char          *   ar;
00203     cpl_propertylist    *   plist = NULL;
00204     cpl_frameset        *   arcframes = NULL;
00205     cpl_frameset        *   arc_one = NULL;
00206     int                     i;
00207     
00208     /* Retrieve input parameters */
00209     /* Rejection parameters */
00210     sval = irplib_parameterlist_get_string(parlist, PACKAGE, RECIPE_STRING,
00211                                            "rejected");
00212     skip_if(sval == NULL);
00213     error_if (sscanf(sval, "%d,%d,%d,%d",
00214                      &isaac_spc_arc_config.rej_left,
00215                      &isaac_spc_arc_config.rej_right,
00216                      &isaac_spc_arc_config.rej_bottom,
00217                      &isaac_spc_arc_config.rej_top) != 4,
00218               CPL_ERROR_DATA_NOT_FOUND, "Parameter not in format %s: %s",
00219               "%d,%d,%d,%d", sval);
00220 
00221     /* Output corrected images */
00222     isaac_spc_arc_config.out_corr
00223         = irplib_parameterlist_get_bool(parlist, PACKAGE, RECIPE_STRING,
00224                                         "out_corr");
00225     /* Dark subtraction */
00226     isaac_spc_arc_config.sub_dark
00227         = irplib_parameterlist_get_bool(parlist, PACKAGE, RECIPE_STRING,
00228                                         "subdark");
00229 
00230     /* Arc max width in pixels */
00231     isaac_spc_arc_config.arc_max_width
00232         = irplib_parameterlist_get_int(parlist, PACKAGE, RECIPE_STRING,
00233                                        "arc_max_w");
00234 
00235     /* Max offset in pixels */
00236     isaac_spc_arc_config.max_offset
00237         = irplib_parameterlist_get_int(parlist, PACKAGE, RECIPE_STRING,
00238                                        "max_offset");
00239     /* Arc detection kappa */
00240     isaac_spc_arc_config.arc_kappa
00241         = irplib_parameterlist_get_double(parlist, PACKAGE, RECIPE_STRING,
00242                                           "arc_kappa");
00243 
00244     /* Identify the RAW and CALIB frames in the input frameset */
00245     skip_if (isaac_dfs_set_groups(framelist));
00246 
00247     /* Retrieve raw frames */
00248     arcframes = isaac_extract_frameset(framelist, ISAAC_SPC_ARC_RAW);
00249     error_if (arcframes == NULL, CPL_ERROR_DATA_NOT_FOUND,
00250               "No frames are tagged %s", ISAAC_SPC_ARC_RAW);
00251         
00252     /* Retrieve calibration data */
00253     xe = isaac_extract_filename(framelist, ISAAC_CALPRO_XE_CAT);
00254     error_if (xe == NULL, CPL_ERROR_DATA_NOT_FOUND,
00255               "Xe catalogue not found");
00256 
00257     ar = isaac_extract_filename(framelist, ISAAC_CALPRO_AR_CAT);
00258     error_if (ar == NULL, CPL_ERROR_DATA_NOT_FOUND,
00259               "Ar catalogue not found");
00260 
00261     /* Labelise all input frames */
00262     labels = cpl_frameset_labelise(arcframes, isaac_spc_arc_compare, &nlabels);
00263     any_if ("Could not labelise input frames (nlabels=%d)", nlabels);
00264    
00265     /* Extract settings and reduce each of them */
00266     for (i=0; i < nlabels; i++) {
00267         const cpl_frame * cur_frame;
00268         const char      * filename;
00269         int error;
00270 
00271         /* Reduce data set nb i */
00272         cpl_msg_info(cpl_func, "Reducing data set %d of %d", i+1, nlabels);
00273         isaac_spc_arc_config.set_nb = i+1;
00274         cpl_frameset_delete(arc_one);
00275         arc_one = cpl_frameset_extract(arcframes, labels, i);
00276 
00277         /* Get the arm used (SW or LW) */
00278         cur_frame = cpl_frameset_get_frame(arc_one, 0);
00279         filename = cpl_frame_get_filename(cur_frame);
00280         cpl_propertylist_delete(plist);
00281         plist = cpl_propertylist_load(filename, 0);
00282         sval = isaac_pfits_get_arm(plist);
00283         any_if ("Could not get the arm from %s in set %d of %d", filename,
00284                 i+1, nlabels);
00285 
00286         if (sval[0] == 'S') {
00287             isaac_spc_arc_config.arm = 1;
00288         } else if (sval[0] == 'L') {
00289             isaac_spc_arc_config.arm = 2;
00290         } else {
00291             isaac_spc_arc_config.arm = 0;
00292             error_if(1, CPL_ERROR_UNSUPPORTED_MODE,
00293                      "Unsupported arm in %s in set %d of %d: %s", filename,
00294                      i+1, nlabels, sval);
00295         }
00296 
00297         /* Get the resolution */
00298         sval = isaac_pfits_get_resolution(plist);
00299         any_if ("Could not get the resolution from %s in set %d of %d",
00300                 filename, i+1, nlabels);
00301 
00302         if (sval[0]=='L') isaac_spc_arc_config.resol = 'L';
00303         else if (sval[0]=='M') isaac_spc_arc_config.resol = 'M';
00304         else isaac_spc_arc_config.resol = 'U';
00305         cpl_propertylist_empty(plist);
00306 
00307         error = isaac_spc_arc_config.arm == 1 ?
00308             /* SW mode */
00309             isaac_spc_arc_reduce_sw(arc_one, parlist, ar, xe, framelist) :
00310             /* LW mode */
00311             isaac_spc_arc_reduce_lw(arc_one, parlist, ar, xe, framelist);
00312 
00313         error_if(error, cpl_error_get_code(), 
00314                  "Could not reduce set %d of %d", i+1, nlabels);
00315     }
00316     
00317     end_skip;
00318 
00319     cpl_frameset_delete(arc_one);
00320     cpl_frameset_delete(arcframes);
00321     cpl_free(labels);
00322     cpl_propertylist_delete(plist);
00323 
00324     return cpl_error_get_code();
00325 }
00326 
00327 /*----------------------------------------------------------------------------*/
00337 /*----------------------------------------------------------------------------*/
00338 static int isaac_spc_arc_reduce_sw(
00339         cpl_frameset        *   arcframes,
00340         const cpl_parameterlist * parlist,
00341         const char          *   ar,
00342         const char          *   xe,
00343         cpl_frameset        *   set_tot)
00344 {
00345     int                 *   lamps;
00346     int                     nframes;
00347     char                    lines_table[16];
00348     cpl_frame           *   cur_frame;
00349     const char          *   cur_fname;
00350     cpl_image           *   xenon;
00351     cpl_image           *   argon;
00352     cpl_image           *   xe_ar;
00353     cpl_image           *   dark;
00354     cpl_image           *   to_compute;
00355     cpl_table           *   arcs_fwhm;
00356     cpl_image           *   out_corr;
00357     cpl_table           *   out_table;
00358     int                     i;
00359 
00360     /* Initialise */
00361     nframes = cpl_frameset_get_size(arcframes);
00362     isaac_spc_arc_config.pair_nb = 0;
00363     to_compute = NULL;
00364     
00365     /* Look for each file which lamp is activated */
00366     /* lamps[i]==0   --->   frame i : lamps off */
00367     /* lamps[i]==1   --->   frame i : Xenon lamp on */
00368     /* lamps[i]==2   --->   frame i : Argon lamp on */
00369     /* lamps[i]==3   --->   frame i : Arg and Xe lamps on  */
00370     if ((lamps=isaac_spc_arc_find_lamps(arcframes)) == NULL) {
00371         cpl_msg_error(cpl_func, "in finding the activated lamps");
00372         return -1;
00373     }
00374 
00375     /* Get the images */
00376     xenon = argon = xe_ar = dark = NULL;
00377     for (i=0; i<nframes; i++) {
00378         cur_frame = cpl_frameset_get_frame(arcframes, i);
00379         cur_fname = cpl_frame_get_filename(cur_frame);
00380         if ((lamps[i] == 0) && (dark == NULL)) {
00381             cpl_msg_info(cpl_func, "Dark image: [%s]", cur_fname);
00382             dark = cpl_image_load(cur_fname, CPL_TYPE_FLOAT, 0, 0);
00383         } else if ((lamps[i] == 1) && (xenon == NULL)) {
00384             cpl_msg_info(cpl_func, "Xenon lamp: [%s]", cur_fname);
00385             xenon = cpl_image_load(cur_fname, CPL_TYPE_FLOAT, 0, 0);
00386         } else if ((lamps[i] == 2) && (argon == NULL)) {
00387             cpl_msg_info(cpl_func, "Argon lamp: [%s]", cur_fname);
00388             argon = cpl_image_load(cur_fname, CPL_TYPE_FLOAT, 0, 0);
00389         } else if ((lamps[i] == 3) && (xe_ar == NULL)) {
00390             cpl_msg_info(cpl_func, "Xenon+Argon lamp: [%s]", cur_fname);
00391             xe_ar = cpl_image_load(cur_fname, CPL_TYPE_FLOAT, 0, 0);
00392         }
00393     }
00394     cpl_free(lamps);
00395    
00396     /* All lamps are switched off */
00397     if (!xenon && !argon && !xe_ar) {
00398         cpl_msg_error(cpl_func, "neither xenon nor argon lamp activated");
00399         if (dark) cpl_image_delete(dark);
00400         return -1;
00401     }
00402    
00403     /* Get the first file name */
00404     cur_frame = cpl_frameset_get_frame(arcframes, 0);
00405     cur_fname = cpl_frame_get_filename(cur_frame);
00406     
00407     /* Reduction in LR  */
00408     if (isaac_spc_arc_config.resol == 'L') {
00409         cpl_msg_info(cpl_func, "Low resolution");
00410          
00411         /* Xenon lines */
00412         if (xenon) {
00413             if (dark) to_compute = cpl_image_subtract_create(xenon, dark);
00414             else to_compute = cpl_image_duplicate(xenon);
00415             cpl_image_delete(xenon);
00416             strcpy(lines_table, "Xe");
00417 
00418             /* Apply the reduction */
00419             cpl_msg_info(cpl_func, "Apply the reduction");
00420             isaac_spc_arc_config.pair_nb ++;
00421             cpl_msg_indent_more();
00422             if ((out_table = isaac_spc_arc_compute(to_compute, cur_fname, 
00423                             lines_table, ar, xe, &arcs_fwhm, 
00424                             &out_corr)) == NULL) {
00425                 cpl_msg_error(cpl_func, "arc reduction computation failed");
00426                 cpl_image_delete(to_compute);
00427             } else {
00428                 /* Save the products */
00429                 cpl_image_delete(to_compute);
00430                 cpl_msg_info(cpl_func, "Save the products");
00431                 isaac_spc_arc_save(out_table, arcs_fwhm, out_corr, lines_table, 
00432                         arcframes, parlist, set_tot);
00433                 cpl_table_delete(out_table);
00434                 if (arcs_fwhm) cpl_table_delete(arcs_fwhm);
00435                 if (out_corr) cpl_image_delete(out_corr);
00436             }
00437             cpl_msg_indent_less();
00438         }
00439 
00440         /* Argon lines */
00441         if (argon) {
00442             if (dark) to_compute = cpl_image_subtract_create(argon, dark);
00443             else to_compute = cpl_image_duplicate(argon);
00444             cpl_image_delete(argon);
00445             strcpy(lines_table, "Ar");
00446 
00447             /* Apply the reduction */
00448             cpl_msg_info(cpl_func, "Apply the reduction");
00449             isaac_spc_arc_config.pair_nb ++;
00450             cpl_msg_indent_more();
00451             if ((out_table = isaac_spc_arc_compute(to_compute, cur_fname, 
00452                             lines_table, ar, xe, &arcs_fwhm, 
00453                             &out_corr)) == NULL) {
00454                 cpl_msg_error(cpl_func, "arc reduction computation failed");
00455                 cpl_image_delete(to_compute);
00456             } else {
00457                 /* Save the products */
00458                 cpl_image_delete(to_compute);
00459                 cpl_msg_info(cpl_func, "Save the products");
00460                 isaac_spc_arc_save(out_table, arcs_fwhm, out_corr, lines_table, 
00461                         arcframes, parlist, set_tot);
00462                 cpl_table_delete(out_table);
00463                 if (arcs_fwhm) cpl_table_delete(arcs_fwhm);
00464                 if (out_corr) cpl_image_delete(out_corr);
00465             }
00466             cpl_msg_indent_less();
00467         }
00468 
00469         /* Xenon+Argon lines */
00470         if (xe_ar) {
00471             if (dark) to_compute = cpl_image_subtract_create(xe_ar, dark);
00472             else to_compute = cpl_image_duplicate(xe_ar);
00473             cpl_image_delete(xe_ar);
00474             strcpy(lines_table, "Xe+Ar");
00475 
00476             /* Apply the reduction */
00477             cpl_msg_info(cpl_func, "Apply the reduction");
00478             isaac_spc_arc_config.pair_nb ++;
00479             cpl_msg_indent_more();
00480             if ((out_table = isaac_spc_arc_compute(to_compute, cur_fname, 
00481                             lines_table, ar, xe, &arcs_fwhm, 
00482                             &out_corr)) == NULL) {
00483                 cpl_msg_error(cpl_func, "arc reduction computation failed");
00484                 cpl_image_delete(to_compute);
00485             } else {
00486                 /* Save the products */
00487                 cpl_image_delete(to_compute);
00488                 cpl_msg_info(cpl_func, "Save the products");
00489                 isaac_spc_arc_save(out_table, arcs_fwhm, out_corr, lines_table, 
00490                         arcframes, parlist, set_tot);
00491                 cpl_table_delete(out_table);
00492                 if (arcs_fwhm) cpl_table_delete(arcs_fwhm);
00493                 if (out_corr) cpl_image_delete(out_corr);
00494             }
00495             cpl_msg_indent_less();
00496         }
00497         
00498     } else if (isaac_spc_arc_config.resol == 'M') {
00499         cpl_msg_info(cpl_func, "Medium resolution");
00500         /* Get the input image */
00501         if (xenon && argon) {
00502             if (dark) {
00503                 cpl_image_subtract(xenon, dark);
00504                 cpl_image_subtract(argon, dark);
00505                 to_compute = cpl_image_add_create(xenon, argon);
00506             } else to_compute = cpl_image_add_create(xenon, argon);
00507             cpl_image_delete(xenon);
00508             cpl_image_delete(argon);
00509             strcpy(lines_table, "Xe+Ar");
00510         } else if (xenon) {
00511             if (dark) to_compute = cpl_image_subtract_create(xenon, dark);
00512             else to_compute = cpl_image_duplicate(xenon);
00513             cpl_image_delete(xenon);
00514             strcpy(lines_table, "Xe");
00515         } else if (argon) {
00516             if (dark) to_compute = cpl_image_subtract_create(argon, dark);
00517             else to_compute = cpl_image_duplicate(argon);
00518             cpl_image_delete(argon);
00519             strcpy(lines_table, "Ar");
00520         } else if (xe_ar) {
00521             if (dark) to_compute = cpl_image_subtract_create(xe_ar, dark);
00522             else to_compute = cpl_image_duplicate(xe_ar);
00523             cpl_image_delete(xe_ar);
00524             strcpy(lines_table, "Xe+Ar");
00525         }
00526 
00527         /* Apply the reduction */
00528         cpl_msg_info(cpl_func, "Apply the reduction");
00529         isaac_spc_arc_config.pair_nb ++;
00530         cpl_msg_indent_more();
00531         if ((out_table = isaac_spc_arc_compute(to_compute, cur_fname, 
00532                         lines_table, ar, xe, &arcs_fwhm, 
00533                         &out_corr)) == NULL) {
00534             cpl_msg_error(cpl_func, "arc reduction computation failed");
00535             cpl_image_delete(to_compute);
00536         } else {
00537             /* Save the products */
00538             cpl_image_delete(to_compute);
00539             cpl_msg_info(cpl_func, "Save the products");
00540             isaac_spc_arc_save(out_table, arcs_fwhm, out_corr, lines_table, 
00541                     arcframes, parlist, set_tot);
00542             cpl_table_delete(out_table);
00543             if (arcs_fwhm) cpl_table_delete(arcs_fwhm);
00544             if (out_corr) cpl_image_delete(out_corr);
00545         }
00546         cpl_msg_indent_less();
00547     }
00548 
00549     if (dark) cpl_image_delete(dark);
00550     
00551     return 0;
00552 }
00553 
00554 /*----------------------------------------------------------------------------*/
00564 /*----------------------------------------------------------------------------*/
00565 static int isaac_spc_arc_reduce_lw(
00566         cpl_frameset        *   arcframes,
00567         const cpl_parameterlist * parlist,
00568         const char          *   ar,
00569         const char          *   xe,
00570         cpl_frameset        *   set_tot)
00571 {
00572     int                 *   lamps;
00573     int                     nframes;
00574     char                    lines_table[16];
00575     cpl_frame           *   cur_frame;
00576     const char          *   cur_fname;
00577     cpl_image           *   to_compute;
00578     cpl_image           *   dark;
00579     cpl_table           *   arcs_fwhm;
00580     cpl_image           *   out_corr;
00581     cpl_table           *   out_table;
00582     cpl_boolean             did_reduce = CPL_FALSE;
00583     int                     i;
00584 
00585     /* Initialise */
00586     nframes = cpl_frameset_get_size(arcframes);
00587     
00588      /* The number of frames must be even */
00589     if (nframes % 2) {
00590         cpl_msg_error(cpl_func, "An even nb of frames expected in input %d", 
00591                 nframes);
00592         return -1;
00593     }
00594 
00595     /* Look for each file which lamp is activated */
00596     /* lamps[i]==0   --->   frame i : lamps off */
00597     /* lamps[i]==1   --->   frame i : Xenon lamp on */
00598     /* lamps[i]==2   --->   frame i : Argon lamp on */
00599     /* lamps[i]==3   --->   frame i : Arg and Xe lamps on  */
00600     if ((lamps=isaac_spc_arc_find_lamps(arcframes)) == NULL) {
00601         cpl_msg_error(cpl_func, "in finding the activated lamps");
00602         return -1;
00603     }
00604 
00605     /* Loop on the pairs */
00606     for (i=0; i<nframes/2; i++) {
00607         isaac_spc_arc_config.pair_nb = i+1;
00608         /* Load the image */
00609         cur_frame = cpl_frameset_get_frame(arcframes, 2*i);
00610         cur_fname = cpl_frame_get_filename(cur_frame);
00611         if ((to_compute = cpl_image_load(cur_fname,CPL_TYPE_FLOAT,0,0))==NULL){
00612             cpl_msg_error(cpl_func, "Could not load frame %s", cur_fname);
00613             cpl_free(lamps);
00614         }
00615         cpl_msg_info(cpl_func, "Pair %d: Lamp and dark identification", i+1);
00616         switch (lamps[2*i]) {
00617             /* Xenon lamp */
00618             case 1:
00619                 strcpy(lines_table, "Xe");
00620                 cpl_msg_info(cpl_func, "Xenon lamp: [%s]", cur_fname);
00621                 break;
00622             /* Argon lamp */
00623             case 2:
00624                 strcpy(lines_table, "Ar");
00625                 cpl_msg_info(cpl_func, "Argon lamp: [%s]", cur_fname);
00626                 break;
00627             /* Xenon+Argon lamp */
00628             case 3:
00629                 strcpy(lines_table, "Xe+Ar");
00630                 cpl_msg_info(cpl_func, "Xenon+Argon lamp: [%s]", cur_fname);
00631                 break;
00632             default:
00633                 cpl_image_delete(to_compute);
00634                 cpl_msg_info(cpl_func, "Lamps are off. Next pair...");
00635                 continue;
00636         }
00637         
00638         /* Get the dark if present */
00639         if (lamps[2*i+1] == 0) {
00640             cur_frame = cpl_frameset_get_frame(arcframes, 2*i+1);
00641             cur_fname = cpl_frame_get_filename(cur_frame);
00642             dark = cpl_image_load(cur_fname, CPL_TYPE_FLOAT, 0, 0);
00643             cpl_image_subtract(to_compute, dark);
00644             cpl_image_delete(dark);
00645             cpl_msg_info(cpl_func, "Dark frame : [%s]", cur_fname);
00646         } else {
00647             cpl_msg_info(cpl_func, "No dark frame");
00648         }
00649 
00650         /* Get the file name */
00651         cur_frame = cpl_frameset_get_frame(arcframes, 2*i);
00652         cur_fname = cpl_frame_get_filename(cur_frame);
00653         
00654         /* Apply the reduction */
00655         cpl_msg_info(cpl_func, "Apply the reduction");
00656         cpl_msg_indent_more();
00657         if ((out_table = isaac_spc_arc_compute(to_compute, cur_fname, 
00658                         lines_table, ar, xe, &arcs_fwhm, 
00659                         &out_corr)) == NULL) {
00660             cpl_msg_error(cpl_func, "arc reduction computation failed");
00661             cpl_image_delete(to_compute);
00662         } else {
00663             /* Save the products */
00664             cpl_image_delete(to_compute);
00665             cpl_msg_info(cpl_func, "Save the products");
00666             isaac_spc_arc_save(out_table, arcs_fwhm, out_corr, lines_table, 
00667                     arcframes, parlist, set_tot);
00668             cpl_table_delete(out_table);
00669             if (arcs_fwhm) cpl_table_delete(arcs_fwhm);
00670             if (out_corr) cpl_image_delete(out_corr);
00671             if (!cpl_error_get_code()) did_reduce = CPL_TRUE;
00672         }
00673         cpl_msg_indent_less();
00674     }
00675 
00676     /* Free and return */
00677     cpl_free(lamps);
00678     cpl_ensure_code(did_reduce, CPL_ERROR_ILLEGAL_INPUT);
00679 
00680     return cpl_error_set_where(cpl_func); /* Propagate error, if any */
00681 }
00682 
00683 /*----------------------------------------------------------------------------*/
00696 /*----------------------------------------------------------------------------*/
00697 static cpl_table * isaac_spc_arc_compute(
00698         const cpl_image     *   in,
00699         const char          *   in_name,
00700         const char          *   lines_table,
00701         const char          *   ar,
00702         const char          *   xe,
00703         cpl_table           **  arcs_fwhm,
00704         cpl_image           **  out_corr)
00705 {
00706     cpl_table           *   out_tab;
00707     int                     xmin, ymin, xmax, ymax;
00708     int                     nx, ny;
00709     cpl_mask            *   saturation_map;
00710     double                  slit_width;
00711     int                     order;
00712     cpl_polynomial      *   distor_poly;
00713     cpl_polynomial      *   poly2d_id;
00714     cpl_vector          *   profile;
00715     cpl_image           *   in_corr;
00716     cpl_apertures       *   arcs;
00717     double              *   phdisprel;
00718     computed_disprel    *   disprel;
00719     int                     power[2];
00720     double                  fwhm_x, fwhm_y;
00721     cpl_vector          *   fwhm_valid;
00722     int                     i;
00723 
00724     /* Initialise */
00725     nx = cpl_image_get_size_x(in);
00726     ny = cpl_image_get_size_y(in);
00727     *arcs_fwhm = NULL;
00728     *out_corr = NULL;
00729 
00730     /* Define zone */
00731     xmin = 1;
00732     xmax = nx;
00733     ymin = isaac_spc_arc_config.rej_bottom + 1;
00734     ymax = ny - isaac_spc_arc_config.rej_top;
00735 
00736     /* Compute the number of saturated pixels */
00737     saturation_map = cpl_mask_threshold_image_create(in, ISAAC_ARC_SATURATION, 
00738             DBL_MAX);
00739     if (saturation_map != NULL) {
00740         isaac_spc_arc_config.nb_saturated = cpl_mask_count(saturation_map);
00741         cpl_mask_delete(saturation_map);
00742     } else {
00743         isaac_spc_arc_config.nb_saturated = 0;
00744     }
00745 
00746     /* Distortion estimation */
00747     cpl_msg_info(cpl_func, "Estimate the distortion");
00748     cpl_msg_indent_more();
00749     if ((distor_poly = irplib_distortion_estimate(in, xmin, ymin, xmax, ymax, 
00750                     isaac_spc_arc_config.sub_dark, ISAAC_ARC_SATURATION,
00751                     isaac_spc_arc_config.arc_max_width, 
00752                     isaac_spc_arc_config.arc_kappa, 2, &arcs)) == NULL) {
00753         cpl_msg_error(cpl_func, "Could not estimage distortion");
00754         cpl_msg_indent_less();
00755         return NULL;
00756     }
00757     cpl_msg_indent_less();
00758                     
00759     /* Distortion correction */
00760     cpl_msg_info(cpl_func, "Correct the distortion");
00761     cpl_msg_indent_more();
00762     in_corr = cpl_image_duplicate(in);
00763 
00764     /* Create the identity polynomial */
00765     poly2d_id = cpl_polynomial_new(2);
00766     power[0] = 0; power[1] = 1;
00767     cpl_polynomial_set_coeff(poly2d_id, power, 1.0);
00768     
00769     /* Create the kernel */
00770     profile = cpl_vector_new(CPL_KERNEL_DEF_SAMPLES);
00771     cpl_vector_fill_kernel_profile(profile, CPL_KERNEL_DEFAULT,
00772             CPL_KERNEL_DEF_WIDTH);
00773 
00774     /* Apply the distortion */
00775     if (cpl_image_warp_polynomial(in_corr, in, distor_poly,
00776             poly2d_id, profile, CPL_KERNEL_DEF_WIDTH, profile,
00777             CPL_KERNEL_DEF_WIDTH) != CPL_ERROR_NONE) {
00778         cpl_msg_error(cpl_func, "Could not correct the distortion");
00779         cpl_image_delete(in_corr);
00780         cpl_polynomial_delete(poly2d_id);
00781         cpl_polynomial_delete(distor_poly);
00782         cpl_vector_delete(profile);
00783         cpl_msg_indent_less();
00784         return NULL;
00785     }
00786     cpl_polynomial_delete(poly2d_id);
00787     cpl_vector_delete(profile);
00788     cpl_msg_indent_less();
00789 
00790     /* Compute the FWHM of the detected arcs */
00791     cpl_msg_info(cpl_func, "Compute the FWHM of the detected arcs");
00792     /* Create the fwhms table */
00793     *arcs_fwhm = cpl_table_new(cpl_apertures_get_size(arcs));
00794     cpl_table_new_column(*arcs_fwhm, "XPOS", CPL_TYPE_DOUBLE);
00795     cpl_table_new_column(*arcs_fwhm, "FWHM", CPL_TYPE_DOUBLE);
00796     cpl_table_new_column(*arcs_fwhm, "FLUX", CPL_TYPE_DOUBLE);
00797     /* Compute the fwhms */
00798     isaac_spc_arc_config.fwhm_good = 0;
00799     for (i=0; i<cpl_apertures_get_size(arcs); i++) {
00800         cpl_table_set_double(*arcs_fwhm, "XPOS", i,
00801                 cpl_apertures_get_centroid_x(arcs, i+1));
00802         cpl_table_set_double(*arcs_fwhm, "FLUX", i,
00803                 cpl_apertures_get_flux(arcs, i+1));
00804         if (cpl_image_get_fwhm(in_corr, cpl_apertures_get_centroid_x(arcs, i+1),
00805                 512, &fwhm_x, &fwhm_y) != CPL_ERROR_NONE) {
00806             cpl_msg_warning(cpl_func, "Could not get the FWHM");
00807             cpl_error_reset();
00808         }
00809         cpl_table_set_double(*arcs_fwhm, "FWHM", i, fwhm_x);
00810         if (fwhm_x > 0) isaac_spc_arc_config.fwhm_good ++;
00811     }
00812     cpl_apertures_delete(arcs);
00813     
00814     /* Compute the median of the good fwhms */
00815     if (isaac_spc_arc_config.fwhm_good > 0) {
00816         fwhm_valid = cpl_vector_new(isaac_spc_arc_config.fwhm_good);
00817         isaac_spc_arc_config.fwhm_good = 0;
00818         for (i=0; i<cpl_table_get_nrow(*arcs_fwhm); i++) {
00819             fwhm_x = cpl_table_get_double(*arcs_fwhm, "FWHM", i, NULL);
00820             if (fwhm_x > 0) {
00821                 cpl_vector_set(fwhm_valid, isaac_spc_arc_config.fwhm_good, 
00822                         fwhm_x);
00823                 isaac_spc_arc_config.fwhm_good ++;
00824             }
00825         }
00826         isaac_spc_arc_config.fwhm_med = cpl_vector_get_median_const(fwhm_valid);
00827         cpl_vector_delete(fwhm_valid);
00828     } else isaac_spc_arc_config.fwhm_med = 0.0;
00829     
00830     /* Wavelength calibration */
00831  
00832     /* Compute the slit_width */
00833     if ((slit_width = isaac_get_slitwidth(in_name)) == -1) {
00834         cpl_msg_error(cpl_func, "Could not get the slit width");
00835         cpl_polynomial_delete(distor_poly);
00836         cpl_image_delete(in_corr);
00837         cpl_table_delete(*arcs_fwhm);
00838         *arcs_fwhm = NULL;
00839         return NULL;
00840     }
00841 
00842     /* Get the order */
00843     if ((order = isaac_find_order(in_name)) == -1) {
00844         cpl_msg_error(cpl_func, "Could not get the order");
00845         cpl_polynomial_delete(distor_poly);
00846         cpl_image_delete(in_corr);
00847         cpl_table_delete(*arcs_fwhm);
00848         *arcs_fwhm = NULL;
00849         return NULL;
00850     }
00851 
00852     /* First estimation using a physical model */
00853     cpl_msg_info(cpl_func, "Compute the physical model");
00854     cpl_msg_indent_more();
00855     if ((phdisprel = isaac_get_disprel_estimate(in_name, 3)) == NULL) {
00856         cpl_msg_error(cpl_func, "Could not estimate the dispersion relation");
00857         cpl_polynomial_delete(distor_poly);
00858         cpl_image_delete(in_corr);
00859         cpl_table_delete(*arcs_fwhm);
00860         *arcs_fwhm = NULL;
00861         cpl_msg_indent_less();
00862         return NULL;
00863     }
00864     cpl_msg_info(cpl_func, "f(x)=%g + %g*x + %g*x^2 + %g*x^3",
00865             phdisprel[0], phdisprel[1], phdisprel[2], phdisprel[3]);
00866     cpl_msg_indent_less();
00867 
00868     /* Compute the dispersion relation */
00869     cpl_msg_info(cpl_func, "Compute the dispersion relation");
00870     cpl_msg_indent_more();
00871     if ((disprel = spectro_compute_disprel(in_corr, 
00872                     isaac_spc_arc_config.rej_bottom,
00873                     isaac_spc_arc_config.rej_top,
00874                     isaac_spc_arc_config.rej_left,
00875                     isaac_spc_arc_config.rej_right,
00876                     isaac_spc_arc_config.max_offset,
00877                     isaac_has_thermal(in_name) > 0,
00878                     lines_table, NULL, ar, xe, slit_width, order, 
00879                     (int)(cpl_msg_get_level() == CPL_MSG_DEBUG), 
00880                     phdisprel)) == NULL) {
00881         cpl_msg_error(cpl_func, "Could not compute the dispersion relation");
00882         cpl_polynomial_delete(distor_poly);
00883         cpl_image_delete(in_corr);
00884         cpl_free(phdisprel);
00885         cpl_table_delete(*arcs_fwhm);
00886         *arcs_fwhm = NULL;
00887         cpl_msg_indent_less();
00888         return NULL;
00889     }
00890     if (isaac_spc_arc_config.out_corr) {
00891         *out_corr = in_corr;
00892         in_corr = NULL;
00893     } else {
00894         cpl_image_delete(in_corr);
00895     }
00896     cpl_free(phdisprel);
00897     cpl_msg_info(cpl_func, "Cross correlation factor: %g", disprel->cc);
00898     cpl_msg_info(cpl_func, "f(x)=%g + %g*x + %g*x^2 + %g*x^3",
00899             disprel->poly[0], disprel->poly[1], disprel->poly[2],
00900             disprel->poly[3]);
00901     cpl_msg_indent_less();
00902     
00903     /* Create the output table and store the relevant information */
00904     out_tab = cpl_table_new(6);
00905     
00906     /* Fill distortion polynomial */
00907     cpl_table_new_column(out_tab, "Degree_of_x", CPL_TYPE_INT);
00908     cpl_table_new_column(out_tab, "Degree_of_y", CPL_TYPE_INT);
00909     cpl_table_new_column(out_tab, "poly2d_coef", CPL_TYPE_DOUBLE);
00910     power[0] = 0; power[1] = 0;
00911     cpl_table_set_int(out_tab, "Degree_of_x", 0, power[0]);
00912     cpl_table_set_int(out_tab, "Degree_of_y", 0, power[1]);
00913     cpl_table_set_double(out_tab, "poly2d_coef", 0,
00914             cpl_polynomial_get_coeff(distor_poly, power));
00915     power[0] = 1; power[1] = 0;
00916     cpl_table_set_int(out_tab, "Degree_of_x", 1, power[0]);
00917     cpl_table_set_int(out_tab, "Degree_of_y", 1, power[1]);
00918     cpl_table_set_double(out_tab, "poly2d_coef", 1,
00919             cpl_polynomial_get_coeff(distor_poly, power));
00920     power[0] = 0; power[1] = 1;
00921     cpl_table_set_int(out_tab, "Degree_of_x", 2, power[0]);
00922     cpl_table_set_int(out_tab, "Degree_of_y", 2, power[1]);
00923     cpl_table_set_double(out_tab, "poly2d_coef", 2,
00924             cpl_polynomial_get_coeff(distor_poly, power));
00925     power[0] = 1; power[1] = 1;
00926     cpl_table_set_int(out_tab, "Degree_of_x", 3, power[0]);
00927     cpl_table_set_int(out_tab, "Degree_of_y", 3, power[1]);
00928     cpl_table_set_double(out_tab, "poly2d_coef", 3,
00929             cpl_polynomial_get_coeff(distor_poly, power));
00930     power[0] = 2; power[1] = 0;
00931     cpl_table_set_int(out_tab, "Degree_of_x", 4, power[0]);
00932     cpl_table_set_int(out_tab, "Degree_of_y", 4, power[1]);
00933     cpl_table_set_double(out_tab, "poly2d_coef", 4,
00934             cpl_polynomial_get_coeff(distor_poly, power));
00935     power[0] = 0; power[1] = 2;
00936     cpl_table_set_int(out_tab, "Degree_of_x", 5, power[0]);
00937     cpl_table_set_int(out_tab, "Degree_of_y", 5, power[1]);
00938     cpl_table_set_double(out_tab, "poly2d_coef", 5,
00939             cpl_polynomial_get_coeff(distor_poly, power));
00940 
00941     /* Fill dispersion relation */
00942     cpl_table_new_column(out_tab, "WL_coefficients", CPL_TYPE_DOUBLE);
00943     cpl_table_set_double(out_tab, "WL_coefficients", 0, disprel->poly[0]);
00944     cpl_table_set_double(out_tab, "WL_coefficients", 1, disprel->poly[1]);
00945     cpl_table_set_double(out_tab, "WL_coefficients", 2, disprel->poly[2]);
00946     cpl_table_set_double(out_tab, "WL_coefficients", 3, disprel->poly[3]);
00947     cpl_table_set_double(out_tab, "WL_coefficients", 4, 0.0);
00948     cpl_table_set_double(out_tab, "WL_coefficients", 5, 0.0);
00949     isaac_spc_arc_config.disprel_cc     = disprel->cc;
00950     isaac_spc_arc_config.disprel_clines = disprel->clines;
00951     isaac_spc_arc_config.disprel_dlines = disprel->dlines;
00952     isaac_spc_arc_config.disprel_rms    = disprel->rms;
00953     isaac_spc_arc_config.disprel_offset = disprel->offset;
00954 
00955     /* Free and return */
00956     cpl_polynomial_delete(distor_poly);
00957     if (disprel->poly != NULL) cpl_free(disprel->poly);
00958     cpl_free(disprel);
00959     return out_tab;
00960 }
00961 
00962 /*----------------------------------------------------------------------------*/
00974 /*----------------------------------------------------------------------------*/
00975 static int isaac_spc_arc_save(
00976         const cpl_table     *   tab,
00977         const cpl_table     *   fwhms,
00978         const cpl_image     *   corr,
00979         const char          *   lines_table,
00980         cpl_frameset        *   set,
00981         const cpl_parameterlist * parlist,
00982         cpl_frameset        *   set_tot)
00983 {
00984     cpl_propertylist    *   plist;
00985     cpl_propertylist    *   qclist;
00986     cpl_propertylist    *   paflist;
00987     const cpl_frame           *   ref_frame;
00988     const char          *   sval;
00989     char                    qc_str[128];
00990     const char          *   procat = isaac_spc_arc_config.arm == 1
00991         ? ISAAC_SPC_ARC_SW_RES : ISAAC_SPC_ARC_LW_RES;
00992     char                *   filename;
00993     int                     i;
00994 
00995 
00996     /* Get the QC params in qclist */
00997     qclist = cpl_propertylist_new();
00998 
00999     /* Get the reference frame */
01000     ref_frame = irplib_frameset_get_first_from_group(set, CPL_FRAME_GROUP_RAW);
01001     if ((plist=cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
01002                     0)) == NULL) {
01003         cpl_msg_error(cpl_func, "getting header from reference frame");
01004         cpl_propertylist_delete(qclist);
01005         return -1;
01006     }
01007     /* Test the status */
01008     if (cpl_error_get_code()) {
01009         cpl_propertylist_delete(qclist);
01010         cpl_propertylist_delete(plist);
01011         return -1;
01012     }
01013     sval = isaac_pfits_get_filter(plist);
01014     if (cpl_error_get_code()) cpl_error_reset();
01015     else cpl_propertylist_append_string(qclist, "ESO QC FILTER OBS", sval);
01016     cpl_propertylist_delete(plist);
01017     cpl_propertylist_append_string(qclist, "ESO QC LAMP", lines_table);
01018     cpl_propertylist_append_double(qclist, "ESO QC DISP XCORR", 
01019             isaac_spc_arc_config.disprel_cc);
01020     cpl_propertylist_append_int(qclist, "ESO QC DISP NUMCAT", 
01021             isaac_spc_arc_config.disprel_clines);
01022     cpl_propertylist_append_int(qclist, "ESO QC DISP NUMMATCH", 
01023             isaac_spc_arc_config.disprel_dlines);
01024     cpl_propertylist_append_double(qclist, "ESO QC DISP STDEV", 
01025             isaac_spc_arc_config.disprel_rms);
01026     cpl_propertylist_append_double(qclist, "ESO QC DISP OFFSET", 
01027             isaac_spc_arc_config.disprel_offset);
01028     cpl_propertylist_append_double(qclist, "ESO QC DISPCO1", 
01029             cpl_table_get_double(tab, "WL_coefficients", 0, NULL));
01030     cpl_propertylist_append_double(qclist, "ESO QC DISPCO2", 
01031             cpl_table_get_double(tab, "WL_coefficients", 1, NULL));
01032     cpl_propertylist_append_double(qclist, "ESO QC DISPCO3", 
01033             cpl_table_get_double(tab, "WL_coefficients", 2, NULL));
01034     cpl_propertylist_append_double(qclist, "ESO QC DISPCO4", 
01035             cpl_table_get_double(tab, "WL_coefficients", 3, NULL));
01036     cpl_propertylist_append_double(qclist, "ESO QC DIST1", 
01037             cpl_table_get_double(tab, "poly2d_coef", 0, NULL));
01038     cpl_propertylist_append_double(qclist, "ESO QC DISTX", 
01039             cpl_table_get_double(tab, "poly2d_coef", 1, NULL));
01040     cpl_propertylist_append_double(qclist, "ESO QC DISTY", 
01041             cpl_table_get_double(tab, "poly2d_coef", 2, NULL));
01042     cpl_propertylist_append_double(qclist, "ESO QC DISTXY", 
01043             cpl_table_get_double(tab, "poly2d_coef", 3, NULL));
01044     cpl_propertylist_append_double(qclist, "ESO QC DISTXX", 
01045             cpl_table_get_double(tab, "poly2d_coef", 4, NULL));
01046     cpl_propertylist_append_double(qclist, "ESO QC DISTYY", 
01047             cpl_table_get_double(tab, "poly2d_coef", 5, NULL));
01048     cpl_propertylist_append_int(qclist, "ESO QC SATUR NBPIX", 
01049             isaac_spc_arc_config.nb_saturated);
01050     cpl_propertylist_append_double(qclist, "ESO QC WLEN",
01051         (double)(cpl_table_get_double(tab, "WL_coefficients", 0, NULL) +
01052              512*cpl_table_get_double(tab, "WL_coefficients", 1, NULL) +
01053          512*512*cpl_table_get_double(tab, "WL_coefficients", 2, NULL) +
01054      512*512*512*cpl_table_get_double(tab, "WL_coefficients", 3, NULL)));
01055    
01056     if (fwhms) {
01057         cpl_propertylist_append_int(qclist, "ESO QC ARCS NUM", 
01058                 cpl_table_get_nrow(fwhms));
01059         for(i=0; i<cpl_table_get_nrow(fwhms); i++) {
01060             sprintf(qc_str, "ESO QC ARCS%d XPOS", i+1);
01061             cpl_propertylist_append_double(qclist, qc_str, 
01062                     cpl_table_get_double(fwhms, "XPOS", i, NULL));
01063             sprintf(qc_str, "ESO QC ARCS%d FWHM", i+1);
01064             cpl_propertylist_append_double(qclist, qc_str, 
01065                     cpl_table_get_double(fwhms, "FWHM", i, NULL));
01066             sprintf(qc_str, "ESO QC ARCS%d FLUX", i+1);
01067             cpl_propertylist_append_double(qclist, qc_str, 
01068                     cpl_table_get_double(fwhms, "FLUX", i, NULL));
01069         }
01070         cpl_propertylist_append_int(qclist, "ESO QC ARCS NUMGOOD", 
01071                 isaac_spc_arc_config.fwhm_good);
01072         cpl_propertylist_append_double(qclist, "ESO QC FWHM MED", 
01073                 isaac_spc_arc_config.fwhm_med);
01074     }
01075    
01076   
01077     /* Write the arc table  */
01078     filename = cpl_sprintf("isaac_spc_arc_set%d_pair%d.fits",
01079             isaac_spc_arc_config.set_nb, isaac_spc_arc_config.pair_nb);
01080     irplib_dfs_save_table(set_tot,
01081                 parlist,
01082                 set,
01083                 tab,
01084                 NULL,
01085                 "isaac_spc_arc",
01086                 procat,
01087                 qclist,
01088                 NULL,
01089                 PACKAGE "/" PACKAGE_VERSION,
01090                 filename);
01091     cpl_free(filename);
01092 
01093     /* Write the corrected image  */
01094     if (corr) {
01095         const char * procatc = isaac_spc_arc_config.arm == 1
01096             ? ISAAC_SPC_ARC_SW_CORR : ISAAC_SPC_ARC_LW_CORR;
01097         filename = cpl_sprintf("isaac_spc_arc_set%d_pair%d_corr.fits",
01098                 isaac_spc_arc_config.set_nb, isaac_spc_arc_config.pair_nb);
01099         irplib_dfs_save_image(set_tot,
01100                 parlist,
01101                 set,
01102                 corr,
01103                 CPL_BPP_IEEE_FLOAT,
01104                 "isaac_spc_arc",
01105                 procatc,
01106                 qclist,
01107                 NULL,
01108                 PACKAGE "/" PACKAGE_VERSION,
01109                 filename);
01110         cpl_free(filename);
01111     }
01112 
01113     /* Get the reference frame */
01114     ref_frame = irplib_frameset_get_first_from_group(set, CPL_FRAME_GROUP_RAW);
01115 
01116     /* Get FITS header from reference file */
01117     if ((plist=cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
01118                     0)) == NULL) {
01119         cpl_msg_error(cpl_func, "getting header from reference frame");
01120         cpl_propertylist_delete(qclist);
01121         return -1;
01122     }
01123     
01124     /* Get the keywords for the paf file */
01125     paflist = cpl_propertylist_new();
01126     cpl_propertylist_copy_property_regexp(paflist, plist, 
01127         "^(ARCFILE|MJD-OBS|INSTRUME|ESO TPL ID|ESO TPL NEXP|ESO DPR CATG|"
01128         "ESO DPR TECH|ESO DPR TYPE|DATE-OBS|ESO INS GRAT NAME|"
01129         "ESO INS GRAT WLEN|ESO INS GRAT ORDER|ESO INS MODE|"
01130         "ESO INS OPTI1 ID)$", 0);
01131     cpl_propertylist_delete(plist);
01132 
01133     /* Copy the QC in paflist */
01134     cpl_propertylist_copy_property_regexp(paflist, qclist, "", 0);
01135     cpl_propertylist_delete(qclist);
01136 
01137     /* PRO.CATG */
01138     cpl_propertylist_update_string(paflist, CPL_DFS_PRO_CATG, procat);
01139 
01140     /* Save the PAF file */
01141     filename = cpl_sprintf("isaac_spc_arc_set%d_pair%d.paf",
01142             isaac_spc_arc_config.set_nb, isaac_spc_arc_config.pair_nb);
01143     cpl_dfs_save_paf("ISAAC",
01144             "isaac_spc_arc",
01145             paflist,
01146             filename);
01147     cpl_free(filename);
01148     cpl_propertylist_delete(paflist);
01149     return  0;
01150 }
01151 
01152 /*----------------------------------------------------------------------------*/
01159 /*----------------------------------------------------------------------------*/
01160 static int isaac_spc_arc_compare(const cpl_frame * frame1, 
01161                                  const cpl_frame * frame2) 
01162 {
01163     int                comparison = 1;
01164     const char       * file1 = cpl_frame_get_filename(frame1);
01165     const char       * file2 = cpl_frame_get_filename(frame2);
01166     cpl_propertylist * plist1 = NULL;
01167     cpl_propertylist * plist2 = NULL;
01168     const char       * sval1,
01169                      * sval2;
01170     double             dval1, dval2;
01171 
01172     bug_if(frame1 == NULL);
01173     bug_if(frame2 == NULL);
01174 
01175     /* Get property lists */
01176     plist1 = cpl_propertylist_load(file1, 0);
01177     any_if("Could not load header from 1st frame %s", file1);
01178 
01179     plist2 = cpl_propertylist_load(file2, 0);
01180     any_if("Could not load header from 2nd frame %s", file2);
01181 
01182     /* Compare the slit used */
01183     sval1 = isaac_pfits_get_opti1_id(plist1);
01184     any_if("Could not get slit from 1st frame %s", file1);
01185 
01186     sval2 = isaac_pfits_get_opti1_id(plist2);
01187     any_if("Could not get slit from 2nd frame %s", file2);
01188 
01189     if (strcmp(sval1, sval2)) comparison = 0;
01190 
01191     /* Compare the resolution */
01192     sval1 = isaac_pfits_get_resolution(plist1);
01193     any_if("Could not get resolution from 1st frame %s", file1);
01194 
01195     sval2 = isaac_pfits_get_resolution(plist2);
01196     any_if("Could not get resolution from 2nd frame %s", file2);
01197 
01198     if (strcmp(sval1, sval2)) comparison = 0;
01199 
01200     /* Compare the central wavelength */
01201     dval1 = isaac_pfits_get_wlen(plist1);
01202     any_if("Could not get wavelength from 1st frame %s", file1);
01203 
01204     dval2 = isaac_pfits_get_wlen(plist2);
01205     any_if("Could not get wavelength from 2nd frame %s", file2);
01206 
01207     if (fabs(dval1-dval2) > 1e-4) comparison = 0;
01208 
01209     end_skip;
01210 
01211     cpl_propertylist_delete(plist1);
01212     cpl_propertylist_delete(plist2);
01213 
01214     return cpl_error_get_code() ? -1 : comparison;
01215 }
01216 
01217 /*----------------------------------------------------------------------------*/
01224 /*----------------------------------------------------------------------------*/
01225 static int * isaac_spc_arc_find_lamps(cpl_frameset * fset)
01226 {
01227     int                 *   lamps;
01228     int                     nframes;
01229     cpl_frame           *   cur_frame;
01230     cpl_propertylist    *   plist;
01231     int                     xenon, argon;
01232     int                     i;
01233 
01234     /* Check entries */
01235     if (fset == NULL) return NULL;
01236     
01237     /* Initialise */
01238     nframes = cpl_frameset_get_size(fset);
01239     xenon = argon = 0;
01240     
01241     /* Allocate the output array */
01242     lamps = cpl_malloc(nframes * sizeof(int));
01243 
01244     for (i=0; i<nframes; i++) {
01245         cur_frame = cpl_frameset_get_frame(fset, i);
01246         plist=cpl_propertylist_load(cpl_frame_get_filename(cur_frame), 0);
01247         xenon = isaac_is_xenon_lamp_active(plist);
01248         argon = isaac_is_argon_lamp_active(plist);
01249         cpl_propertylist_delete(plist);
01250         if ((argon != 0 && argon != 1) || (xenon != 0 && xenon != 1)) {
01251             cpl_msg_error(cpl_func, "Could not check which lamp is on");
01252             cpl_free(lamps);
01253             return NULL;
01254         }
01255         if (xenon == 1) {
01256             if (argon == 1)         lamps[i] = 3;
01257             else if (argon == 0)    lamps[i] = 1;
01258         } else if (xenon == 0 ) {
01259             if (argon == 1)         lamps[i] = 2;
01260             else if (argon == 0)    lamps[i] = 0;
01261         }
01262     }
01263 
01264     /* Free and return */
01265     return lamps;
01266 }
01267 
01268 /*----------------------------------------------------------------------------*/
01274 /*----------------------------------------------------------------------------*/
01275 static int isaac_is_argon_lamp_active(const cpl_propertylist * plist)
01276 {
01277     int             status1, status2;
01278 
01279     /* Test error */
01280     if (cpl_error_get_code()) return -1;
01281     status1 = isaac_pfits_get_lamp1_status(plist);
01282     if (cpl_error_get_code()) return -1;
01283     if (status1 == 1) {
01284         /* Still has to verify that shutter is open */
01285         status2 = isaac_pfits_get_calshut_status(plist);
01286         if (cpl_error_get_code()) {
01287             cpl_error_reset();
01288             return 1;
01289         }
01290         if (status2 == 1) return 1;
01291     }
01292     return 0;
01293 }
01294 
01295 /*----------------------------------------------------------------------------*/
01301 /*----------------------------------------------------------------------------*/
01302 static int isaac_is_xenon_lamp_active(const cpl_propertylist * plist)
01303 {
01304     int             status1, status2;
01305 
01306     /* Test error */
01307     if (cpl_error_get_code()) return -1;
01308     status1 = isaac_pfits_get_lamp2_status(plist);
01309     if (cpl_error_get_code()) return -1;
01310     if (status1 == 1) {
01311         /* Still has to verify that shutter is open */
01312         status2 = isaac_pfits_get_calshut_status(plist);
01313         if (cpl_error_get_code()) {
01314             cpl_error_reset();
01315             return 1;
01316         }
01317         if (status2 == 1) return 1;
01318     }
01319     return 0;
01320 }
01321 
01322 

Generated on Wed Mar 9 15:43:10 2011 for ISAAC Pipeline Reference Manual by  doxygen 1.5.8