sofi_spc_arc.c

00001 /* $Id: sofi_spc_arc.c,v 1.51 2013-03-12 08:04:53 llundin Exp $
00002  *
00003  * This file is part of the SOFI 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:04:53 $
00024  * $Revision: 1.51 $
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 #include "irplib_wlxcorr.h"
00045 
00046 #include "sofi_utils.h"
00047 #include "sofi_wavelength.h"
00048 #include "sofi_pfits.h"
00049 #include "sofi_dfs.h"
00050 
00051 /*-----------------------------------------------------------------------------
00052                             Defines
00053  -----------------------------------------------------------------------------*/
00054 
00055 #define RECIPE_STRING "sofi_spc_arc"
00056 
00057 #define SOFI_ARC_SATURATION    20000
00058 
00059 /*-----------------------------------------------------------------------------
00060                             Functions prototypes
00061  -----------------------------------------------------------------------------*/
00062 
00063 static cpl_error_code sofi_spc_arc_reduce(cpl_frameset *,
00064                                           const cpl_parameterlist *, 
00065                                           const char *, const char *,
00066                                           const cpl_frameset *,
00067                                           cpl_errorstate);
00068 static cpl_table * sofi_spc_arc_compute(const cpl_image *, const char *,
00069         const char *, const char *, const char *, cpl_table **, cpl_image **);
00070 static cpl_error_code sofi_spc_arc_save(cpl_frameset *, const cpl_table *,
00071                                         const cpl_table *,
00072                                         const cpl_image *, const char *,
00073                                         const cpl_frameset *,
00074                                         const cpl_parameterlist *);
00075 static int sofi_spc_arc_compare(const cpl_frame *, const cpl_frame *);
00076 static int * sofi_spc_arc_find_lamps(const cpl_frameset *);
00077 static int sofi_is_xenon_lamp_active(const cpl_propertylist *);
00078 static int sofi_is_neon_lamp_active(const cpl_propertylist *);
00079  
00080 cpl_recipe_define(sofi_spc_arc, SOFI_BINARY_VERSION,
00081                   "Lars Lundin", PACKAGE_BUGREPORT, "2002,2003,2009", 
00082                   "SOFI Spectro arc recipe",
00083                   RECIPE_STRING " -- SOFI Spectro arc recipe.\n"
00084                   "The files listed in the Set Of Frames (sof-file) " 
00085                   "must be tagged:\n"
00086                   "raw-file.fits "SOFI_SPC_ARC_RAW" or\n"
00087                   "xe-cat.fits "SOFI_CALPRO_XE_CAT" or\n"
00088                   "ne-cat.fits "SOFI_CALPRO_NE_CAT"\n");
00089 
00090 /*-----------------------------------------------------------------------------
00091                             Static variables
00092  -----------------------------------------------------------------------------*/
00093 
00094 static struct {
00095     /* Inputs */
00096     int             display;
00097     int             rej_left;
00098     int             rej_right;
00099     int             subdark;
00100     int             arc_max_w;
00101     int             out_corr;
00102     cpl_size        degree;
00103     double          wl_err;
00104     int             wl_nsamples;
00105     int             ppm;
00106     const char  *   lines;
00107     /* Outputs */
00108     int             set_nb;
00109     int             frame_nb;
00110     int             nb_saturated;
00111     double          disprel_cc;
00112     double          fwhm_med;
00113     int             fwhm_good;
00114 } sofi_spc_arc_config;
00115 
00116 /*-----------------------------------------------------------------------------
00117                                 Functions code
00118  -----------------------------------------------------------------------------*/
00119 
00120 /*----------------------------------------------------------------------------*/
00128 /*----------------------------------------------------------------------------*/
00129 static
00130 cpl_error_code sofi_spc_arc_fill_parameterlist(cpl_parameterlist * self)
00131 {
00132     const char * context = PACKAGE "." RECIPE_STRING;
00133     cpl_error_code err;
00134 
00135     cpl_ensure_code(self, CPL_ERROR_NULL_INPUT);
00136 
00137     /* Fill the parameters list */
00138 
00139     /* --rejected */
00140     err = irplib_parameterlist_set_string(self, PACKAGE, RECIPE_STRING,
00141                                           "rejected", "100,100", "rej", context,
00142                                           "Left, right rejections [pixel]");
00143     cpl_ensure_code(!err, err);
00144 
00145     /* --subdark */
00146     err = irplib_parameterlist_set_bool(self, PACKAGE, RECIPE_STRING, "subdark",
00147                                         CPL_FALSE, NULL, context,
00148                                         "Enable dark subtraction");
00149     cpl_ensure_code(!err, err);
00150 
00151     /* --arc_max_w */
00152     err = irplib_parameterlist_set_int(self, PACKAGE, RECIPE_STRING, "arc_max_w",
00153                                        33, NULL, context, "Maximum supported "
00154                                        "arc width [pixel]");
00155     cpl_ensure_code(!err, err);
00156 
00157     /* --out_corr */
00158     err = irplib_parameterlist_set_bool(self, PACKAGE, RECIPE_STRING, "out_corr",
00159                                         CPL_FALSE, NULL, context,
00160                                         "Enable correction of output images");
00161     cpl_ensure_code(!err, err);
00162 
00163     /* --display */ 
00164     err = irplib_parameterlist_set_bool(self, PACKAGE, RECIPE_STRING, "display",
00165                                         CPL_FALSE, NULL, context,
00166                                         "Enable plotting");
00167     cpl_ensure_code(!err, err);
00168 
00169     /* --degree */
00170     err = irplib_parameterlist_set_int(self, PACKAGE, RECIPE_STRING, "degree",
00171                                        2, NULL, context, "Degree of the "
00172                                        "wavelength dispersion polynomial");
00173     cpl_ensure_code(!err, err);
00174 
00175     /* --wl_nsamples */
00176     err = irplib_parameterlist_set_int(self, PACKAGE, RECIPE_STRING,
00177                                        "wl_nsamples", 100, NULL, context,
00178                                        "Number of samples for the wavelength "
00179                                        "calibration");
00180     cpl_ensure_code(!err, err);
00181 
00182     /* --wl_err */
00183     err = irplib_parameterlist_set_double(self, PACKAGE, RECIPE_STRING,
00184                                           "wl_err", 1000.0, NULL, context,
00185                                           "The wavelength error [Angstrom]");
00186     cpl_ensure_code(!err, err);
00187 
00188     /* --lines */
00189     err = irplib_parameterlist_set_string(self, PACKAGE, RECIPE_STRING,
00190                                           "lines", NULL, NULL, context,
00191                                           "Lines ASCII-file");
00192     cpl_ensure_code(!err, err);
00193 
00194     /* --ppm */
00195     err = irplib_parameterlist_set_bool(self, PACKAGE, RECIPE_STRING, "ppm",
00196                                         CPL_FALSE, NULL, context,
00197                                         "Enable Point Pattern Matching");
00198     cpl_ensure_code(!err, err);
00199 
00200     return CPL_ERROR_NONE;
00201 }
00202 
00203 
00204 /*----------------------------------------------------------------------------*/
00211 /*----------------------------------------------------------------------------*/
00212 static int sofi_spc_arc(cpl_frameset            * framelist,
00213                         const cpl_parameterlist * parlist)
00214 {
00215     cpl_errorstate          prestate = cpl_errorstate_get();
00216     const char          *   sval;
00217     cpl_size            *   labels = NULL;
00218     cpl_size                nlabels;
00219     const int               nframes = cpl_frameset_get_size(framelist);
00220     int                     narcs;
00221     const char          *   xe;
00222     const char          *   ne;
00223     cpl_frameset        *   arcframes = NULL;
00224     cpl_frameset        *   arc_one = NULL;
00225     int                     i;
00226     
00227     /* Initialise */
00228     sofi_spc_arc_config.lines = NULL;
00229 
00230     /* Retrieve input parameters */
00231 
00232     /* Rejection parameters */
00233     sval = irplib_parameterlist_get_string(parlist, PACKAGE, RECIPE_STRING,
00234                                            "rejected");
00235     bug_if(sval == NULL);
00236 
00237     skip_if (sscanf(sval, "%d,%d",
00238                     &sofi_spc_arc_config.rej_left,
00239                     &sofi_spc_arc_config.rej_right) != 2);
00240 
00241     /* Output corrected images */
00242     sofi_spc_arc_config.out_corr
00243         = irplib_parameterlist_get_bool(parlist, PACKAGE, RECIPE_STRING,
00244                                         "out_corr");
00245     /* Dark subtraction */
00246     sofi_spc_arc_config.subdark
00247         = irplib_parameterlist_get_bool(parlist, PACKAGE, RECIPE_STRING,
00248                                         "subdark");
00249     /* ppm */
00250     sofi_spc_arc_config.ppm
00251         = irplib_parameterlist_get_bool(parlist, PACKAGE, RECIPE_STRING,
00252                                         "ppm");
00253     /* Polynomial degree */
00254     sofi_spc_arc_config.degree
00255         = irplib_parameterlist_get_int(parlist, PACKAGE, RECIPE_STRING,
00256                                        "degree");
00257 
00258     /* Number of samples */
00259     sofi_spc_arc_config.wl_nsamples
00260         = irplib_parameterlist_get_int(parlist, PACKAGE, RECIPE_STRING,
00261                                        "wl_nsamples");
00262 
00263     /* Wavelength error factor */
00264     sofi_spc_arc_config.wl_err
00265         = irplib_parameterlist_get_double(parlist, PACKAGE, RECIPE_STRING,
00266                                           "wl_err");
00267 
00268     /* Arc max width in pixels */
00269     sofi_spc_arc_config.arc_max_w
00270         = irplib_parameterlist_get_int(parlist, PACKAGE, RECIPE_STRING,
00271                                        "arc_max_w");
00272 
00273     /* Display */
00274     sofi_spc_arc_config.display
00275         = irplib_parameterlist_get_bool(parlist, PACKAGE, RECIPE_STRING,
00276                                         "display");
00277 
00278     /* Lines */
00279     sofi_spc_arc_config.lines
00280         = irplib_parameterlist_get_string(parlist, PACKAGE, RECIPE_STRING,
00281                                           "lines");
00282 
00283     /* Identify the RAW and CALIB frames in the input frameset */
00284     skip_if (sofi_dfs_set_groups(framelist));
00285 
00286     /* Retrieve raw frames */
00287     arcframes = sofi_extract_frameset(framelist, SOFI_SPC_ARC_RAW);
00288     error_if (arcframes == NULL, CPL_ERROR_DATA_NOT_FOUND,
00289               "Cannot find arc frames in the input frame set");
00290 
00291     narcs = cpl_frameset_get_size(arcframes);
00292 
00293     /* Retrieve calibration data */
00294     xe = sofi_extract_filename(framelist, SOFI_CALPRO_XE_CAT);
00295     ne = sofi_extract_filename(framelist, SOFI_CALPRO_NE_CAT);
00296 
00297     /* Labelise all input frames */
00298     labels = cpl_frameset_labelise(arcframes, sofi_spc_arc_compare, &nlabels);
00299     error_if (labels == NULL, CPL_ERROR_ILLEGAL_INPUT,
00300               "Cannot labelise the input frames");
00301    
00302     /* Extract settings and reduce each of them */
00303     for (i=0; i < nlabels; i++) {
00304 
00305         /* Reduce data set nb i */
00306         cpl_msg_info(cpl_func, "Reducing set %d/%d", i+1, (int)nlabels);
00307 
00308         sofi_spc_arc_config.set_nb = i+1;
00309 
00310         cpl_frameset_delete(arc_one);
00311         arc_one = cpl_frameset_extract(arcframes, labels, i);
00312 
00313         /* Reduce the set */
00314         if (sofi_spc_arc_reduce(framelist, parlist, xe, ne, arc_one, prestate))
00315             (void)cpl_error_set_message(cpl_func, cpl_error_get_code(), "Could "
00316                                         "not reduce set %d of %d with %d arc "
00317                                         "frame(s)", i+1, (int)nlabels,
00318                                         (int)cpl_frameset_get_size(arc_one));
00319     }
00320 
00321     error_if (cpl_frameset_get_size(framelist) == nframes,
00322               CPL_ERROR_ILLEGAL_INPUT, "No products produced from %d arc "
00323               "frames grouped into %d set(s)", narcs, (int)nlabels);
00324 
00325     end_skip;
00326     
00327     cpl_frameset_delete(arcframes);
00328     cpl_frameset_delete(arc_one);
00329     cpl_free(labels);
00330 
00331     return cpl_error_get_code();
00332 }
00333 
00334 /*----------------------------------------------------------------------------*/
00346 /*----------------------------------------------------------------------------*/
00347 static cpl_error_code sofi_spc_arc_reduce(cpl_frameset            * set_tot,
00348                                           const cpl_parameterlist * parlist,
00349                                           const char              * xe,
00350                                           const char              * ne,
00351                                           const cpl_frameset      * arcframes,
00352                                           cpl_errorstate            prestate)
00353 {
00354     /* Look for each file which lamp is activated */
00355     /* lamps[i]==0   --->   frame i : lamps off */
00356     /* lamps[i]==1   --->   frame i : Xenon lamp on */
00357     /* lamps[i]==2   --->   frame i : Neon lamp on */
00358     /* lamps[i]==3   --->   frame i : Ne and Xe lamps on  */
00359     int                 *   lamps = sofi_spc_arc_find_lamps(arcframes);
00360     const int               nframes = cpl_frameset_get_size(arcframes);
00361     char                    lines_table[16];
00362     const cpl_frame     *   cur_frame;
00363     const char          *   cur_fname;
00364     cpl_image           *   xenon = NULL;
00365     cpl_image           *   neon  = NULL;
00366     cpl_image           *   xe_ne = NULL;
00367     cpl_image           *   dark  = NULL;
00368     cpl_image           *   to_compute;
00369     cpl_table           *   arcs_fwhm;
00370     cpl_image           *   out_corr;
00371     cpl_table           *   out_table;
00372     int                     i;
00373 
00374     /* Initialise */
00375     sofi_spc_arc_config.frame_nb = 0;
00376     
00377     if (lamps == NULL) return cpl_error_set_where(cpl_func);
00378 
00379     /* Get the images */
00380     for (i=0; i<nframes; i++) {
00381         cur_frame = cpl_frameset_get_frame_const(arcframes, i);
00382         cur_fname = cpl_frame_get_filename(cur_frame);
00383         if ((lamps[i] == 0) && (dark == NULL)) {
00384             cpl_msg_info(cpl_func, "Dark image: [%s]", cur_fname);
00385             dark = cpl_image_load(cur_fname, CPL_TYPE_FLOAT, 0, 0);
00386         } else if ((lamps[i] == 1) && (xenon == NULL)) {
00387             cpl_msg_info(cpl_func, "Xenon lamp: [%s]", cur_fname);
00388             xenon = cpl_image_load(cur_fname, CPL_TYPE_FLOAT, 0, 0);
00389         } else if ((lamps[i] == 2) && (neon == NULL)) {
00390             cpl_msg_info(cpl_func, "Neon lamp: [%s]", cur_fname);
00391             neon = cpl_image_load(cur_fname, CPL_TYPE_FLOAT, 0, 0);
00392         } else if ((lamps[i] == 3) && (xe_ne == NULL)) {
00393             cpl_msg_info(cpl_func, "Xenon+Neon lamp: [%s]", cur_fname);
00394             xe_ne = cpl_image_load(cur_fname, CPL_TYPE_FLOAT, 0, 0);
00395         }
00396     }
00397     cpl_free(lamps);
00398    
00399     /* All lamps are switched off */
00400     if (!xenon && !neon && !xe_ne) {
00401         cpl_image_delete(dark);
00402         return cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
00403                                      "Neither xenon nor neon lamp activated");
00404     }
00405    
00406     /* Get the first file name */
00407     cur_frame = cpl_frameset_get_frame_const(arcframes, 0);
00408     cur_fname = cpl_frame_get_filename(cur_frame);
00409     
00410     /* Xenon lines */
00411     if (xenon) {
00412         if (!cpl_errorstate_is_equal(prestate)) {
00413             cpl_msg_warning(cpl_func, "Resetting CPL error before reducing "
00414                             "Xenon data:");
00415             cpl_errorstate_dump(prestate, CPL_FALSE, NULL);
00416             cpl_errorstate_set(prestate);
00417         }
00418         if (dark) to_compute = cpl_image_subtract_create(xenon, dark);
00419         else to_compute = cpl_image_duplicate(xenon);
00420         cpl_image_delete(xenon);
00421         strcpy(lines_table, "Xe");
00422 
00423         /* Apply the reduction */
00424         cpl_msg_info(cpl_func, "Apply the reduction");
00425         sofi_spc_arc_config.frame_nb ++;
00426         cpl_msg_indent_more();
00427         if ((out_table = sofi_spc_arc_compute(to_compute, cur_fname, 
00428                         lines_table, xe, ne, &arcs_fwhm, &out_corr)) == NULL) {
00429             cpl_msg_error(cpl_func, "arc reduction computation failed");
00430             cpl_image_delete(to_compute);
00431         } else {
00432             /* Save the products */
00433             cpl_image_delete(to_compute);
00434             cpl_msg_info(cpl_func, "Save the products");
00435             sofi_spc_arc_save(set_tot, out_table, arcs_fwhm, out_corr,
00436                               lines_table, arcframes, parlist);
00437             cpl_table_delete(out_table);
00438             if (arcs_fwhm) cpl_table_delete(arcs_fwhm);
00439             if (out_corr) cpl_image_delete(out_corr);
00440         }
00441         cpl_msg_indent_less();
00442     }
00443 
00444     /* Neon lines */
00445     if (neon) {
00446         if (!cpl_errorstate_is_equal(prestate)) {
00447             cpl_msg_warning(cpl_func, "Resetting CPL error before reducing "
00448                             "Neon data:");
00449             cpl_errorstate_dump(prestate, CPL_FALSE, NULL);
00450             cpl_errorstate_set(prestate);
00451         }
00452         if (dark) to_compute = cpl_image_subtract_create(neon, dark);
00453         else to_compute = cpl_image_duplicate(neon);
00454         cpl_image_delete(neon);
00455         strcpy(lines_table, "Ne");
00456 
00457         /* Apply the reduction */
00458         cpl_msg_info(cpl_func, "Apply the reduction");
00459         sofi_spc_arc_config.frame_nb ++;
00460         cpl_msg_indent_more();
00461         if ((out_table = sofi_spc_arc_compute(to_compute, cur_fname, 
00462                         lines_table, xe, ne, &arcs_fwhm, &out_corr)) == NULL) {
00463             cpl_msg_error(cpl_func, "arc reduction computation failed");
00464             cpl_image_delete(to_compute);
00465         } else {
00466             /* Save the products */
00467             cpl_image_delete(to_compute);
00468             cpl_msg_info(cpl_func, "Save the products");
00469             sofi_spc_arc_save(set_tot, out_table, arcs_fwhm, out_corr,
00470                               lines_table, arcframes, parlist);
00471             cpl_table_delete(out_table);
00472             if (arcs_fwhm) cpl_table_delete(arcs_fwhm);
00473             if (out_corr) cpl_image_delete(out_corr);
00474         }
00475         cpl_msg_indent_less();
00476     }
00477 
00478 
00479     /* Xenon+Neon lines */
00480     if (xe_ne) {
00481         if (!cpl_errorstate_is_equal(prestate)) {
00482             cpl_msg_warning(cpl_func, "Resetting CPL error before reducing "
00483                             "Xenon+Neon data:");
00484             cpl_errorstate_dump(prestate, CPL_FALSE, NULL);
00485             cpl_errorstate_set(prestate);
00486         }
00487         if (dark) to_compute = cpl_image_subtract_create(xe_ne, dark);
00488         else to_compute = cpl_image_duplicate(xe_ne);
00489         cpl_image_delete(xe_ne);
00490         strcpy(lines_table, "Xe+Ne");
00491 
00492         /* Apply the reduction */
00493         cpl_msg_info(cpl_func, "Apply the reduction");
00494         sofi_spc_arc_config.frame_nb ++;
00495         cpl_msg_indent_more();
00496         if ((out_table = sofi_spc_arc_compute(to_compute, cur_fname, 
00497                         lines_table, xe, ne, &arcs_fwhm, &out_corr)) == NULL) {
00498             cpl_msg_error(cpl_func, "arc reduction computation failed");
00499             cpl_image_delete(to_compute);
00500         } else {
00501             /* Save the products */
00502             cpl_image_delete(to_compute);
00503             cpl_msg_info(cpl_func, "Save the products");
00504             sofi_spc_arc_save(set_tot, out_table, arcs_fwhm, out_corr,
00505                               lines_table, arcframes, parlist);
00506             cpl_table_delete(out_table);
00507             if (arcs_fwhm) cpl_table_delete(arcs_fwhm);
00508             if (out_corr) cpl_image_delete(out_corr);
00509         }
00510         cpl_msg_indent_less();
00511     }
00512     cpl_image_delete(dark);
00513     
00514     return cpl_error_get_code();
00515 }
00516 
00517 /*----------------------------------------------------------------------------*/
00530 /*----------------------------------------------------------------------------*/
00531 static cpl_table * sofi_spc_arc_compute(
00532         const cpl_image     *   in,
00533         const char          *   in_name,
00534         const char          *   lines_table,
00535         const char          *   xe,
00536         const char          *   ne,
00537         cpl_table           **  arcs_fwhm,
00538         cpl_image           **  out_corr)
00539 {
00540     cpl_image           *   flipped;
00541     cpl_table           *   out_tab;
00542     int                     xmin, ymin, xmax, ymax;
00543     int                     nx, ny;
00544     cpl_mask            *   saturation_map;
00545     double                  slit_width;
00546     cpl_polynomial      *   distor_poly_flipped;
00547     cpl_polynomial      *   distor_poly;
00548     cpl_polynomial      *   poly2d_id;
00549     cpl_vector          *   profile;
00550     cpl_image           *   in_corr;
00551     cpl_apertures       *   arcs;
00552     cpl_polynomial      *   phdisprel;
00553     cpl_polynomial      *   disprel;
00554     cpl_size                power[5];
00555     int                     degree;
00556     double                  a, b, c, d, e, xc;
00557     cpl_size                power_flipped[2];
00558     double                  fwhm_x, fwhm_y;
00559     cpl_vector          *   fwhm_valid;
00560     int                     i;
00561 
00562     /* Initialise */
00563     nx = cpl_image_get_size_x(in);
00564     ny = cpl_image_get_size_y(in);
00565     *arcs_fwhm = NULL;
00566     *out_corr = NULL;
00567 
00568     /* Define zone */
00569     xmin = sofi_spc_arc_config.rej_left + 1;
00570     xmax = nx - sofi_spc_arc_config.rej_right;
00571     ymin = 1;
00572     ymax = ny;
00573 
00574     /* Compute the number of saturated pixels */
00575     saturation_map = cpl_mask_threshold_image_create(in,
00576             SOFI_ARC_SATURATION, DBL_MAX);
00577     if (saturation_map != NULL) {
00578         sofi_spc_arc_config.nb_saturated = cpl_mask_count(saturation_map);
00579         cpl_mask_delete(saturation_map);
00580     } else {
00581         sofi_spc_arc_config.nb_saturated = 0;
00582     }
00583 
00584     /* Distortion estimation */
00585     cpl_msg_info(cpl_func, "Estimate the distortion");
00586     cpl_msg_indent_more();
00587     /* Flip the image */
00588     flipped = cpl_image_duplicate(in);
00589     cpl_image_flip(flipped, 1);
00590     if ((distor_poly_flipped = irplib_distortion_estimate(flipped, 
00591                     ymin, xmin, ymax, xmax, 
00592                     sofi_spc_arc_config.subdark, SOFI_ARC_SATURATION,
00593                     sofi_spc_arc_config.arc_max_w, 0.33,2,&arcs)) == NULL) {
00594         cpl_msg_error(cpl_func, "cannot estimage distortion");
00595         cpl_image_delete(flipped);
00596         cpl_msg_indent_less();
00597         return NULL;
00598     }
00599     cpl_image_delete(flipped);
00600     cpl_msg_indent_less();
00601     
00602     /* Flip the polynomial back */
00603     distor_poly = cpl_polynomial_duplicate(distor_poly_flipped);
00604     power[0] = 1; power[1] = 0; power_flipped[0] = 0; power_flipped[1] = 1;
00605     cpl_polynomial_set_coeff(distor_poly, power, 
00606             cpl_polynomial_get_coeff(distor_poly_flipped, power_flipped));
00607     
00608     power[0] = 2; power[1] = 0; power_flipped[0] = 0; power_flipped[1] = 2;
00609     cpl_polynomial_set_coeff(distor_poly, power, 
00610             cpl_polynomial_get_coeff(distor_poly_flipped, power_flipped));
00611 
00612     power[0] = 0; power[1] = 1; power_flipped[0] = 1; power_flipped[1] = 0;
00613     cpl_polynomial_set_coeff(distor_poly, power, 
00614             cpl_polynomial_get_coeff(distor_poly_flipped, power_flipped));
00615 
00616     power[0] = 0; power[1] = 2; power_flipped[0] = 2; power_flipped[1] = 0;
00617     cpl_polynomial_set_coeff(distor_poly, power, 
00618             cpl_polynomial_get_coeff(distor_poly_flipped, power_flipped));
00619     cpl_polynomial_delete(distor_poly_flipped);
00620 
00621     /* Distortion correction */
00622     cpl_msg_info(cpl_func, "Correct the distortion");
00623     cpl_msg_indent_more();
00624     in_corr = cpl_image_duplicate(in);
00625 
00626     /* Create the identity polynomial */
00627     poly2d_id = cpl_polynomial_new(2);
00628     power[0] = 1; power[1] = 0;
00629     cpl_polynomial_set_coeff(poly2d_id, power, 1.0);
00630     
00631     /* Create the kernel */
00632     profile = cpl_vector_new(CPL_KERNEL_DEF_SAMPLES);
00633     cpl_vector_fill_kernel_profile(profile, CPL_KERNEL_DEFAULT,
00634             CPL_KERNEL_DEF_WIDTH);
00635 
00636     /* Apply the distortion */
00637     if (cpl_image_warp_polynomial(in_corr, in, poly2d_id, distor_poly,
00638             profile, CPL_KERNEL_DEF_WIDTH, profile,
00639             CPL_KERNEL_DEF_WIDTH) != CPL_ERROR_NONE) {
00640         cpl_msg_error(cpl_func, "cannot correct the distortion");
00641         cpl_image_delete(in_corr);
00642         cpl_polynomial_delete(poly2d_id);
00643         cpl_polynomial_delete(distor_poly);
00644         cpl_vector_delete(profile);
00645         cpl_msg_indent_less();
00646         return NULL;
00647     }
00648     cpl_polynomial_delete(poly2d_id);
00649     cpl_vector_delete(profile);
00650     cpl_msg_indent_less();
00651 
00652     /* Compute the FWHM of the detected arcs */
00653     cpl_msg_info(cpl_func, "Compute the FWHM of the detected arcs");
00654     /* Create the fwhms table */
00655     *arcs_fwhm = cpl_table_new(cpl_apertures_get_size(arcs));
00656     cpl_table_new_column(*arcs_fwhm, "POS", CPL_TYPE_DOUBLE);
00657     cpl_table_new_column(*arcs_fwhm, "FWHM", CPL_TYPE_DOUBLE);
00658     cpl_table_new_column(*arcs_fwhm, "FLUX", CPL_TYPE_DOUBLE);
00659     /* Compute the fwhms */
00660     sofi_spc_arc_config.fwhm_good = 0;
00661     for (i=0; i<cpl_apertures_get_size(arcs); i++) {
00662         cpl_table_set_double(*arcs_fwhm, "POS", i,
00663                 cpl_apertures_get_centroid_x(arcs, i+1));
00664         cpl_table_set_double(*arcs_fwhm, "FLUX", i,
00665                 cpl_apertures_get_flux(arcs, i+1));
00666         if (cpl_image_get_fwhm(in_corr, cpl_apertures_get_centroid_x(arcs, i+1),
00667                 512, &fwhm_x, &fwhm_y) != CPL_ERROR_NONE) {
00668             cpl_msg_warning(cpl_func, "Cannot get the FWHM");
00669             cpl_error_reset();
00670         }
00671         cpl_table_set_double(*arcs_fwhm, "FWHM", i, fwhm_x);
00672         if (fwhm_x > 0) sofi_spc_arc_config.fwhm_good ++;
00673     }
00674     cpl_apertures_delete(arcs);
00675     
00676     /* Compute the median of the good fwhms */
00677     if (sofi_spc_arc_config.fwhm_good > 0) {
00678         fwhm_valid = cpl_vector_new(sofi_spc_arc_config.fwhm_good);
00679         sofi_spc_arc_config.fwhm_good = 0;
00680         for (i=0; i<cpl_table_get_nrow(*arcs_fwhm); i++) {
00681             fwhm_x = cpl_table_get_double(*arcs_fwhm, "FWHM", i, NULL);
00682             if (fwhm_x > 0) {
00683                 cpl_vector_set(fwhm_valid, sofi_spc_arc_config.fwhm_good, 
00684                         fwhm_x);
00685                 sofi_spc_arc_config.fwhm_good ++;
00686             }
00687         }
00688         sofi_spc_arc_config.fwhm_med = cpl_vector_get_median_const(fwhm_valid);
00689         cpl_vector_delete(fwhm_valid);
00690     } else sofi_spc_arc_config.fwhm_med = 0.0;
00691     
00692     /* Wavelength calibration */
00693 
00694     /* Compute the slit_width */
00695     if ((slit_width = sofi_get_slitwidth(in_name)) == -1) {
00696         cpl_msg_error(cpl_func, "cannot get the slit width");
00697         cpl_polynomial_delete(distor_poly);
00698         cpl_image_delete(in_corr);
00699         cpl_table_delete(*arcs_fwhm);
00700         *arcs_fwhm = NULL;
00701         return NULL;
00702     }
00703 
00704     /* First estimation */
00705     cpl_msg_info(cpl_func, "Get the dispersion estimation");
00706     cpl_msg_indent_more();
00707     if ((phdisprel = sofi_get_disprel_estimate(in_name, 1)) == NULL) {
00708         cpl_msg_error(cpl_func, "cannot estimate the dispersion relation");
00709         cpl_polynomial_delete(distor_poly);
00710         cpl_image_delete(in_corr);
00711         cpl_table_delete(*arcs_fwhm);
00712         *arcs_fwhm = NULL;
00713         cpl_msg_indent_less();
00714         return NULL;
00715     }
00716     power[0] = 0; power[1] = 1;
00717     a = cpl_polynomial_get_coeff(phdisprel, power);
00718     b = cpl_polynomial_get_coeff(phdisprel, power + 1);
00719     cpl_msg_info(cpl_func, "f(x)=%g + %g*x", a, b);
00720     cpl_msg_indent_less();
00721 
00722     /* Compute the dispersion relation */
00723     cpl_msg_info(cpl_func, "Compute the dispersion relation");
00724     cpl_msg_indent_more();
00725     if ((disprel = sofi_wavelength_engine(in_corr, lines_table, NULL, xe, ne, 
00726                     phdisprel, slit_width, sofi_spc_arc_config.degree, 
00727                     sofi_spc_arc_config.wl_err, 
00728                     sofi_spc_arc_config.wl_nsamples, 
00729                     sofi_spc_arc_config.ppm, sofi_spc_arc_config.display, 
00730                     &xc)) == NULL) {
00731         cpl_msg_error(cpl_func, "cannot compute the dispersion relation");
00732         cpl_polynomial_delete(distor_poly);
00733         cpl_image_delete(in_corr);
00734         cpl_polynomial_delete(phdisprel);
00735         cpl_table_delete(*arcs_fwhm);
00736         *arcs_fwhm = NULL;
00737         cpl_msg_indent_less();
00738         return NULL;
00739     }
00740     if (sofi_spc_arc_config.out_corr) {
00741         *out_corr = in_corr;
00742         in_corr = NULL;
00743     } else {
00744         cpl_image_delete(in_corr);
00745     }
00746 
00747     /* Plot if requested */
00748     if (sofi_spc_arc_config.display && sofi_spc_arc_config.lines != NULL &&
00749         sofi_spc_arc_config.lines[0] != (char)0) {
00750 
00751         cpl_bivector * lines_biv
00752             = cpl_bivector_read(sofi_spc_arc_config.lines);
00753         const int nlines = cpl_bivector_get_size(lines_biv);
00754 
00755         if (nlines > sofi_spc_arc_config.degree) {
00756 
00757             /* Compute the solution from the passed associated lines */
00758             cpl_matrix * xpos
00759                 = cpl_matrix_wrap(1, nlines, cpl_bivector_get_x_data(lines_biv));
00760             cpl_polynomial * poly_sol = cpl_polynomial_new(1);
00761 
00762             if (!cpl_polynomial_fit(poly_sol, xpos, NULL,
00763                                     cpl_bivector_get_y(lines_biv), NULL,
00764                                     CPL_FALSE, NULL,
00765                                     &(sofi_spc_arc_config.degree))) {
00766                 irplib_wlxcorr_plot_solution(phdisprel, disprel, poly_sol, 1,
00767                                              1024);
00768             }
00769             (void)cpl_matrix_unwrap(xpos);
00770             cpl_polynomial_delete(poly_sol);
00771         }
00772         cpl_bivector_delete(lines_biv);
00773     }
00774     cpl_polynomial_delete(phdisprel);
00775     cpl_msg_info(cpl_func, "Cross correlation factor: %g", xc);
00776     power[0] = 0; power[1] = 1; power[2] = 2; power[3] = 3; power[4] = 4;
00777     a = b = c = d = e = 0.0;
00778     degree = cpl_polynomial_get_degree(disprel);
00779     a = cpl_polynomial_get_coeff(disprel, power);
00780     if (degree > 0) b = cpl_polynomial_get_coeff(disprel, power + 1);
00781     if (degree > 1) c = cpl_polynomial_get_coeff(disprel, power + 2);
00782     if (degree > 2) d = cpl_polynomial_get_coeff(disprel, power + 3);
00783     if (degree > 3) e = cpl_polynomial_get_coeff(disprel, power + 4);
00784     cpl_polynomial_delete(disprel);
00785     if (degree == 0)
00786         cpl_msg_info(cpl_func, "f(x)=%g", a);
00787     if (degree == 1)
00788         cpl_msg_info(cpl_func, "f(x)=%g + %g*x", a, b);
00789     if (degree == 2)
00790         cpl_msg_info(cpl_func, "f(x)=%g + %g*x + %g*x^2", a, b, c);
00791     if (degree == 3)
00792         cpl_msg_info(cpl_func, "f(x)=%g + %g*x + %g*x^2 + %g*x^3", a, b, c, d);
00793     if (degree == 4)
00794         cpl_msg_info(cpl_func, "f(x)=%g + %g*x + %g*x^2 + %g*x^3 + %g*x^4", 
00795                 a, b, c, d, e);
00796     cpl_msg_indent_less();
00797     
00798     /* Create the output table and store the relevant information */
00799     out_tab = cpl_table_new(6);
00800     
00801     /* Fill distortion polynomial */
00802     cpl_table_new_column(out_tab, "Degree_of_x", CPL_TYPE_INT);
00803     cpl_table_new_column(out_tab, "Degree_of_y", CPL_TYPE_INT);
00804     cpl_table_new_column(out_tab, "poly2d_coef", CPL_TYPE_DOUBLE);
00805     power[0] = 0; power[1] = 0;
00806     cpl_table_set_int(out_tab, "Degree_of_x", 0, power[0]);
00807     cpl_table_set_int(out_tab, "Degree_of_y", 0, power[1]);
00808     cpl_table_set_double(out_tab, "poly2d_coef", 0,
00809             cpl_polynomial_get_coeff(distor_poly, power));
00810     power[0] = 1; power[1] = 0;
00811     cpl_table_set_int(out_tab, "Degree_of_x", 1, power[0]);
00812     cpl_table_set_int(out_tab, "Degree_of_y", 1, power[1]);
00813     cpl_table_set_double(out_tab, "poly2d_coef", 1,
00814             cpl_polynomial_get_coeff(distor_poly, power));
00815     power[0] = 0; power[1] = 1;
00816     cpl_table_set_int(out_tab, "Degree_of_x", 2, power[0]);
00817     cpl_table_set_int(out_tab, "Degree_of_y", 2, power[1]);
00818     cpl_table_set_double(out_tab, "poly2d_coef", 2,
00819             cpl_polynomial_get_coeff(distor_poly, power));
00820     power[0] = 1; power[1] = 1;
00821     cpl_table_set_int(out_tab, "Degree_of_x", 3, power[0]);
00822     cpl_table_set_int(out_tab, "Degree_of_y", 3, power[1]);
00823     cpl_table_set_double(out_tab, "poly2d_coef", 3,
00824             cpl_polynomial_get_coeff(distor_poly, power));
00825     power[0] = 2; power[1] = 0;
00826     cpl_table_set_int(out_tab, "Degree_of_x", 4, power[0]);
00827     cpl_table_set_int(out_tab, "Degree_of_y", 4, power[1]);
00828     cpl_table_set_double(out_tab, "poly2d_coef", 4,
00829             cpl_polynomial_get_coeff(distor_poly, power));
00830     power[0] = 0; power[1] = 2;
00831     cpl_table_set_int(out_tab, "Degree_of_x", 5, power[0]);
00832     cpl_table_set_int(out_tab, "Degree_of_y", 5, power[1]);
00833     cpl_table_set_double(out_tab, "poly2d_coef", 5,
00834             cpl_polynomial_get_coeff(distor_poly, power));
00835 
00836     /* Fill dispersion relation */
00837     cpl_table_new_column(out_tab, "WL_coefficients", CPL_TYPE_DOUBLE);
00838     cpl_table_set_double(out_tab, "WL_coefficients", 0, a);
00839     cpl_table_set_double(out_tab, "WL_coefficients", 1, b);
00840     cpl_table_set_double(out_tab, "WL_coefficients", 2, c);
00841     cpl_table_set_double(out_tab, "WL_coefficients", 3, d);
00842     cpl_table_set_double(out_tab, "WL_coefficients", 4, e);
00843     cpl_table_set_double(out_tab, "WL_coefficients", 5, 0.0);
00844     sofi_spc_arc_config.disprel_cc     = xc;
00845 
00846     /* Free and return */
00847     cpl_polynomial_delete(distor_poly);
00848     return out_tab;
00849 }
00850 
00851 /*----------------------------------------------------------------------------*/
00863 /*----------------------------------------------------------------------------*/
00864 static cpl_error_code sofi_spc_arc_save(cpl_frameset            * set_tot,
00865                                         const cpl_table         * tab,
00866                                         const cpl_table         * fwhms,
00867                                         const cpl_image         * corr,
00868                                         const char              * lines_table,
00869                                         const cpl_frameset      * set,
00870                                         const cpl_parameterlist * parlist)
00871 {
00872     cpl_propertylist    *   plist;
00873     cpl_propertylist    *   qclist;
00874     cpl_propertylist    *   paflist;
00875     const cpl_frame     *   ref_frame;
00876     const char          *   sval;
00877     char                    qc_str[128];
00878     char                *   filename;
00879     int                     i;
00880     
00881     /* Get the QC params in qclist */
00882     qclist = cpl_propertylist_new();
00883     
00884     /* Get the reference frame */
00885     ref_frame = irplib_frameset_get_first_from_group(set, CPL_FRAME_GROUP_RAW);
00886     if ((plist=cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
00887                     0)) == NULL) {
00888         cpl_msg_error(cpl_func, "getting header from reference frame");
00889         cpl_propertylist_delete(qclist);
00890         return cpl_error_set_where(cpl_func);
00891     }
00892     /* Test the status */
00893     if (cpl_error_get_code()) {
00894         cpl_propertylist_delete(qclist);
00895         cpl_propertylist_delete(plist);
00896         return cpl_error_set_where(cpl_func);
00897     }
00898     sval = sofi_pfits_get_filter(plist);
00899     if (cpl_error_get_code()) cpl_error_reset();
00900     else cpl_propertylist_append_string(qclist, "ESO QC FILTER OBS", sval);
00901     cpl_propertylist_delete(plist);
00902     cpl_propertylist_append_string(qclist, "ESO QC LAMP", lines_table);
00903     cpl_propertylist_append_double(qclist, "ESO QC DISP XCORR",
00904             sofi_spc_arc_config.disprel_cc);
00905     cpl_propertylist_append_double(qclist, "ESO QC DISPCO1",
00906             cpl_table_get_double(tab, "WL_coefficients", 0, NULL));
00907     cpl_propertylist_append_double(qclist, "ESO QC DISPCO2",
00908             cpl_table_get_double(tab, "WL_coefficients", 1, NULL));
00909     cpl_propertylist_append_double(qclist, "ESO QC DISPCO3",
00910             cpl_table_get_double(tab, "WL_coefficients", 2, NULL));
00911     cpl_propertylist_append_double(qclist, "ESO QC DISPCO4",
00912             cpl_table_get_double(tab, "WL_coefficients", 3, NULL));
00913     cpl_propertylist_append_double(qclist, "ESO QC DISPCO5",
00914             cpl_table_get_double(tab, "WL_coefficients", 4, NULL));
00915     cpl_propertylist_append_double(qclist, "ESO QC DIST1",
00916             cpl_table_get_double(tab, "poly2d_coef", 0, NULL));
00917     cpl_propertylist_append_double(qclist, "ESO QC DISTX",
00918             cpl_table_get_double(tab, "poly2d_coef", 1, NULL));
00919     cpl_propertylist_append_double(qclist, "ESO QC DISTY",
00920             cpl_table_get_double(tab, "poly2d_coef", 2, NULL));
00921     cpl_propertylist_append_double(qclist, "ESO QC DISTXY",
00922             cpl_table_get_double(tab, "poly2d_coef", 3, NULL));
00923     cpl_propertylist_append_double(qclist, "ESO QC DISTXX",
00924             cpl_table_get_double(tab, "poly2d_coef", 4, NULL));
00925     cpl_propertylist_append_double(qclist, "ESO QC DISTYY",
00926             cpl_table_get_double(tab, "poly2d_coef", 5, NULL));
00927     cpl_propertylist_append_int(qclist, "ESO QC SATUR NBPIX",
00928             sofi_spc_arc_config.nb_saturated);
00929     cpl_propertylist_append_double(qclist, "ESO QC WLEN",
00930         (double)(cpl_table_get_double(tab, "WL_coefficients", 0, NULL) +
00931              512.0*cpl_table_get_double(tab, "WL_coefficients", 1, NULL) +
00932          512.0*512.0*cpl_table_get_double(tab, "WL_coefficients", 2, NULL) +
00933      512.0*512.0*512.0*cpl_table_get_double(tab, "WL_coefficients", 3, NULL) +
00934 512.0*512.0*512.0*512.0*cpl_table_get_double(tab, "WL_coefficients", 4, NULL)));
00935 
00936     if (fwhms) {
00937         cpl_propertylist_append_int(qclist, "ESO QC ARCS NUM",
00938                 cpl_table_get_nrow(fwhms));
00939         for(i=0; i<cpl_table_get_nrow(fwhms); i++) {
00940             sprintf(qc_str, "ESO QC ARCS%d XPOS", i+1);
00941             cpl_propertylist_append_double(qclist, qc_str,
00942                     cpl_table_get_double(fwhms, "POS", i, NULL));
00943             sprintf(qc_str, "ESO QC ARCS%d FWHM", i+1);
00944             cpl_propertylist_append_double(qclist, qc_str,
00945                     cpl_table_get_double(fwhms, "FWHM", i, NULL));
00946             sprintf(qc_str, "ESO QC ARCS%d FLUX", i+1);
00947             cpl_propertylist_append_double(qclist, qc_str,
00948                     cpl_table_get_double(fwhms, "FLUX", i, NULL));
00949         }
00950         cpl_propertylist_append_int(qclist, "ESO QC ARCS NUMGOOD",
00951                 sofi_spc_arc_config.fwhm_good);
00952         cpl_propertylist_append_double(qclist, "ESO QC FWHM MED",
00953                 sofi_spc_arc_config.fwhm_med);
00954     }
00955 
00956     /* Write the arc table  */
00957     filename = cpl_sprintf("sofi_spc_arc_set%d_frame%d.fits",
00958             sofi_spc_arc_config.set_nb, sofi_spc_arc_config.frame_nb);
00959     irplib_dfs_save_table(set_tot,
00960                 parlist,
00961                 set,
00962                 tab,
00963                 NULL,
00964                 "sofi_spc_arc",
00965                 SOFI_SPC_ARC_RES,
00966                 qclist,
00967                 NULL,
00968                 PACKAGE "/" PACKAGE_VERSION,
00969                 filename);
00970     cpl_free(filename);
00971 
00972     /* Write the corrected image  */
00973     if (corr) {
00974         filename = cpl_sprintf("sofi_spc_arc_set%d_frame%d_corr.fits",
00975                 sofi_spc_arc_config.set_nb, sofi_spc_arc_config.frame_nb);
00976         irplib_dfs_save_image(set_tot,
00977                 parlist,
00978                 set,
00979                 corr,
00980                 CPL_BPP_IEEE_FLOAT,
00981                 "sofi_spc_arc",
00982                 SOFI_SPC_ARC_CORR,
00983                 qclist,
00984                 NULL,
00985                 PACKAGE "/" PACKAGE_VERSION,
00986                 filename);
00987         cpl_free(filename);
00988     }
00989 
00990     /* Get the reference frame */
00991     ref_frame = irplib_frameset_get_first_from_group(set, CPL_FRAME_GROUP_RAW);
00992 
00993     /* Get FITS header from reference file */
00994     if ((plist=cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
00995                     0)) == NULL) {
00996         cpl_msg_error(cpl_func, "getting header from reference frame");
00997         cpl_propertylist_delete(qclist);
00998         return cpl_error_set_where(cpl_func);
00999     }
01000 
01001     /* Get the keywords for the paf file */
01002     paflist = cpl_propertylist_new();
01003     cpl_propertylist_copy_property_regexp(paflist, plist,
01004         "^(ARCFILE|MJD-OBS|INSTRUME|ESO TPL ID|ESO TPL NEXP|ESO DPR CATG|"
01005         "ESO DPR TECH|ESO DPR TYPE|DATE-OBS|ESO INS GRAT NAME|"
01006         "ESO INS GRAT WLEN|ESO INS GRAT ORDER|ESO INS MODE|"
01007         "ESO INS OPTI1 ID)$", 0);
01008     cpl_propertylist_delete(plist);
01009 
01010     /* Copy the QC in paflist */
01011     cpl_propertylist_copy_property_regexp(paflist, qclist, "", 0);
01012     cpl_propertylist_delete(qclist);
01013 
01014     /* Save the PAF file */
01015     filename = cpl_sprintf("sofi_spc_arc_set%d_frame%d.paf",
01016             sofi_spc_arc_config.set_nb, sofi_spc_arc_config.frame_nb);
01017     cpl_dfs_save_paf("SOFI",
01018             "sofi_spc_arc",
01019             paflist,
01020             filename);
01021     cpl_free(filename);
01022     cpl_propertylist_delete(paflist);
01023 
01024     return cpl_error_get_code();
01025 }
01026 
01027 /*----------------------------------------------------------------------------*/
01034 /*----------------------------------------------------------------------------*/
01035 static int sofi_spc_arc_compare(
01036         const cpl_frame *   frame1, 
01037         const cpl_frame *   frame2) 
01038 {
01039     int                     comparison;
01040     cpl_propertylist    *   plist1;
01041     cpl_propertylist    *   plist2;
01042     const char          *   sval1,
01043                         *   sval2;
01044 
01045     /* Test entries */
01046     if (frame1==NULL || frame2==NULL) return -1;
01047 
01048     /* Get property lists */
01049     if ((plist1=cpl_propertylist_load(cpl_frame_get_filename(frame1),
01050                     0)) == NULL) {
01051         cpl_msg_error(cpl_func, "getting header from reference frame");
01052         return -1;
01053     }
01054     if ((plist2=cpl_propertylist_load(cpl_frame_get_filename(frame2),
01055                     0)) == NULL) {
01056         cpl_msg_error(cpl_func, "getting header from reference frame");
01057         cpl_propertylist_delete(plist1);
01058         return -1;
01059     }
01060 
01061     /* Test status */
01062     if (cpl_error_get_code()) {
01063         cpl_propertylist_delete(plist1);
01064         cpl_propertylist_delete(plist2);
01065         return -1;
01066     }
01067 
01068     comparison = 1;
01069 
01070     /* Compare the slit used */
01071     sval1 = sofi_pfits_get_opti1_id(plist1);
01072     sval2 = sofi_pfits_get_opti1_id(plist2);
01073     if (cpl_error_get_code()) {
01074         cpl_msg_error(cpl_func, "cannot get the slit used");
01075         cpl_propertylist_delete(plist1);
01076         cpl_propertylist_delete(plist2);
01077         return -1;
01078     }
01079     if (strcmp(sval1, sval2)) comparison = 0;
01080 
01081     /* Compare the mode */
01082     sval1 = sofi_pfits_get_mode(plist1);
01083     sval2 = sofi_pfits_get_mode(plist2);
01084     if (cpl_error_get_code()) {
01085         cpl_msg_error(cpl_func, "cannot get the mode");
01086         cpl_propertylist_delete(plist1);
01087         cpl_propertylist_delete(plist2);
01088         return -1;
01089     }
01090     if (strcmp(sval1, sval2)) comparison = 0;
01091 
01092     cpl_propertylist_delete(plist1);
01093     cpl_propertylist_delete(plist2);
01094     return comparison;
01095 }
01096 
01097 /*----------------------------------------------------------------------------*/
01104 /*----------------------------------------------------------------------------*/
01105 static int * sofi_spc_arc_find_lamps(const cpl_frameset * fset)
01106 {
01107     const int   nframes = cpl_frameset_get_size(fset);
01108     int       * lamps;
01109     int         i;
01110 
01111     cpl_ensure(nframes > 0, CPL_ERROR_UNSPECIFIED, NULL); /* A bug */
01112   
01113     /* Allocate the output array */
01114     lamps = (int*)cpl_malloc(nframes * sizeof(int));
01115 
01116     for (i=0; i<nframes; i++) {
01117         const cpl_frame  * cur_frame = cpl_frameset_get_frame_const(fset, i);
01118         cpl_propertylist * plist
01119             = cpl_propertylist_load(cpl_frame_get_filename(cur_frame), 0);
01120         const int xenon = sofi_is_xenon_lamp_active(plist);
01121         const int neon  = sofi_is_neon_lamp_active(plist);
01122 
01123         cpl_propertylist_delete(plist);
01124         if ((neon != 0 && neon != 1) || (xenon != 0 && xenon != 1)) {
01125             cpl_free(lamps);
01126             (void)cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
01127                                         "Cannot check which lamp is on for "
01128                                         "frame %d", i+1);
01129             return NULL;
01130         }
01131         if (xenon == 1) {
01132             if (neon == 1)         lamps[i] = 3;
01133             else if (neon == 0)    lamps[i] = 1;
01134         } else if (xenon == 0 ) {
01135             if (neon == 1)         lamps[i] = 2;
01136             else if (neon == 0)    lamps[i] = 0;
01137         }
01138     }
01139 
01140     return lamps;
01141 }
01142 
01143 /*----------------------------------------------------------------------------*/
01149 /*----------------------------------------------------------------------------*/
01150 static int sofi_is_neon_lamp_active(const cpl_propertylist * plist)
01151 {
01152     int             status;
01153     const char  *   lamp;
01154 
01155     /* Test error */
01156     if (cpl_error_get_code()) return -1;
01157 
01158     if ((lamp=sofi_pfits_get_lamp2_name(plist)) == NULL) {
01159         cpl_error_reset();
01160         return 0;
01161     }
01162     if (!strcmp(lamp, "Neon")) {
01163         status = sofi_pfits_get_lamp2_status(plist);
01164         if (cpl_error_get_code()) {
01165             cpl_error_reset();
01166             return 0;
01167         }
01168         if (status == 1) return 1;
01169     }
01170     return 0;
01171 }
01172 
01173 /*----------------------------------------------------------------------------*/
01179 /*----------------------------------------------------------------------------*/
01180 static int sofi_is_xenon_lamp_active(const cpl_propertylist * plist)
01181 {
01182     int             status;
01183     const char  *   lamp;
01184 
01185     /* Test error */
01186     if (cpl_error_get_code()) return -1;
01187 
01188     if ((lamp=sofi_pfits_get_lamp1_name(plist)) == NULL) {
01189         cpl_error_reset();
01190         return 0;
01191     }
01192     if (!strcmp(lamp, "Xenon")) {
01193         status = sofi_pfits_get_lamp1_status(plist);
01194         if (cpl_error_get_code()) {
01195             cpl_error_reset();
01196             return 0;
01197         }
01198         if (status == 1) return 1;
01199     }
01200     return 0;
01201 }
Generated on Mon Feb 17 15:20:50 2014 for SOFI Pipeline Reference Manual by  doxygen 1.6.3