isaac_spc_arc.c

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