uves_wavecal_body.c

00001 /*                                                                              *
00002  *   This file is part of the ESO UVES Pipeline                                 *
00003  *   Copyright (C) 2004,2005 European Southern Observatory                      *
00004  *                                                                              *
00005  *   This library is free software; you can redistribute it and/or modify       *
00006  *   it under the terms of the GNU General Public License as published by       *
00007  *   the Free Software Foundation; either version 2 of the License, or          *
00008  *   (at your option) any later version.                                        *
00009  *                                                                              *
00010  *   This program is distributed in the hope that it will be useful,            *
00011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of             *
00012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
00013  *   GNU General Public License for more details.                               *
00014  *                                                                              *
00015  *   You should have received a copy of the GNU General Public License          *
00016  *   along with this program; if not, write to the Free Software                *
00017  *   Foundation, 51 Franklin St, Fifth Floor, Boston, MA  02111-1307  USA       *
00018  *                                                                              */
00019  
00020 /*
00021  * $Author: amodigli $
00022  * $Date: 2011/04/14 11:25:22 $
00023  * $Revision: 1.99 $
00024  * $Name: uves-5_0_0 $
00025  *
00026  */
00027 
00028 /*-----------------------------------------------------------------------------
00029                                 Includes
00030  -----------------------------------------------------------------------------*/
00031 
00032 #ifdef HAVE_CONFIG_H
00033 #  include <config.h>
00034 #endif
00035 /*----------------------------------------------------------------------------*/
00039 /*----------------------------------------------------------------------------*/
00040 
00041 #include <uves_wavecal_body.h>
00042 
00043 /* Definitions */
00044 #include <uves.h>
00045 
00046 /* Macro steps */
00047 #include <uves_extract.h>
00048 #include <uves_flatfield.h>
00049 #include <uves_wavecal_search.h>
00050 #include <uves_wavecal_firstsolution.h>
00051 #include <uves_wavecal_identify.h>
00052 #include <uves_rebin.h>
00053 #include <uves_merge.h>
00054 
00055 /* Utility functions */
00056 #include <uves_wavecal_utils.h>
00057 #include <uves_utils.h>
00058 #include <uves_utils_wrappers.h>
00059 #include <uves_plot.h>
00060 #include <uves_parameters.h>
00061 #include <uves_dfs.h>
00062 #include <uves_pfits.h>
00063 #include <uves_qclog.h>
00064 #include <uves_recipe.h>
00065 #include <uves_error.h>
00066 #include <flames_reduce_vcorrel.h>
00067 
00068 #include <cpl.h>
00069 
00070 #include <stdbool.h>
00071 #include <float.h>
00072 #include <string.h>
00073 /*-----------------------------------------------------------------------------
00074                                 Defines
00075  -----------------------------------------------------------------------------*/
00076 /* threshold values for maximum pixel saturation */
00077 #define DRS_PTHRES_MAX 55000
00078 #define DRS_PTHRES_MIN -20
00079 #define DRS_CVEL_MIN -6.
00080 #define DRS_CVEL_MAX +6.
00081 #define N_FIBRES_MAX 9
00082 /*-----------------------------------------------------------------------------
00083                             Functions prototypes
00084  -----------------------------------------------------------------------------*/
00085 static void uves_wavecal_qclog(const cpl_table* table,
00086                                int firstabs,
00087                                int lastabs,
00088                    const cpl_image *arclamp,
00089                    const uves_propertylist* raw_header,
00090                    bool flames,
00091                    int trace_number,
00092                    int fibre_mask,
00093                    double offset,
00094                    enum uves_chip chip,
00095                    cpl_table* qclog);
00096 
00097 static void uves_wavecal_qclog_intmon(cpl_table* table,
00098                       const cpl_table *line_intmon,
00099                       const uves_propertylist* raw_header,
00100                       bool flames,
00101                       int fibre,
00102                       enum uves_chip chip,
00103                       cpl_table* qclog);
00104 
00105 /*-----------------------------------------------------------------------------
00106                             Recipe standard code
00107  -----------------------------------------------------------------------------*/
00108 
00109 const char * const uves_wavecal_desc_short = "Performs the wavelength calibration";
00110 
00111 const char * const uves_wavecal_desc =
00112 "The recipe performs a wavelength calibration for each extraction window.\n"
00113 "Conceptually, each chip contains a number of order lines, each of which\n"
00114 "contains a number of fibre traces, each of which contains a number of\n"
00115 "extraction windows. For UVES data, there is only one trace per order and\n"
00116 "three extraction windows (sky, object, sky). For FLAMES/UVES data there\n"
00117 "are multiple traces per order but only one extraction window per trace.\n"
00118 "The number of traces is defined in the order table while the geometry of\n"
00119 "the extraction windows is specified by recipe parameters (see below).\n"
00120 "\n"
00121 "Expected input for this recipe is an arc lamp frame, ARC_LAMP_xxx or\n"
00122 "ECH_ARC_LAMP_xxx (where xxx=BLUE, RED), order table(s) for each chip,\n"
00123 "ORDER_TABLE_xxxx (where xxxx=BLUE, REDL, REDU), 'guess' line table(s)\n"
00124 "for each chip, LINE_TABLE_xxxx, a wavelength catalogue table, \n"
00125 "LINE_REFER_TABLE, and optionally a wavelength table of bright lines,\n"
00126 "LINE_INTMON_TABLE, used only for computing Quality Control parameters.\n"
00127 "\n"
00128 "The output line table(s), LINE_TABLE_xxxx, contains the columns\n"
00129 "X            : Horizontal position (from Gaussian fit) of detected line\n"
00130 "dX           : Uncertainty (one sigma) of X\n"
00131 "Ynew         : Vertical position of detected line\n"
00132 "XWidth       : Width (in pixels) of detected line from Gaussian fit\n"
00133 "Peak         : Intensity of detected line\n"
00134 "Background   : Fitted background (ADU) of detected line\n"
00135 "Slope        : Linear background slope (ADU/pixel) of detected line\n"
00136 "               from Gaussian fit\n"
00137 "Intensity    : Intensity of detected line scaled to unit exposure\n"
00138 "               time. (This column only present if a LINE_INTMON_TABLE\n"
00139 "               is provided.)\n"
00140 "Order        : Absolute order number of detected line\n"
00141 "Y            : Relative order number of detected line\n"
00142 "               (it's not a very descriptive column name)\n"
00143 "WaveC        : Wavelength of this line (computed using the resulting\n"
00144 "               dispersion relation)\n"
00145 "dLambdaC     : Uncertainty (one sigma) of 'WaveC'.\n"
00146 "Pixel        : The width in w.l.u. of a pixel (computed locally).\n"
00147 "Residual     : Residual (in w.l.u.) of this line\n"
00148 "Residual_pix : Residual (in pixels) of this line\n"
00149 "Lambda_candidate : Nearest line in catalogue\n"
00150 "dLambda_cat_sq   : Squared distance to nearest catalogue line\n"
00151 "dLambda_nn_sq    : Squared distance to nearest neighbour multiplied by ALPHA\n"
00152 "Ident        : The wavelength associated with this emission line,\n"
00153 "               or invalid if this line was not identified\n"
00154 "dIdent       : Uncertainty of catalogue wavelength\n"
00155 "Select       : 1 if the line was identified, 0 otherwise\n"
00156 "NLinSol      : 1 if the line was identified and accepted for the\n"
00157 "               polynomial fit, 0 otherwise\n"
00158 "Intensity    : Intensity of detected line scaled to unit exposure\n"
00159 "               time. (This column is present only if a LINE_INTMON_TABLE\n"
00160 "               is provided.)\n"
00161 "\n"
00162 "The 2nd table extension contains the dispersion relation (a 2d polynomial).\n"
00163 "The 3rd table extension contains the map from (pixel, pixel)-space to\n"
00164 " physical order numbers (used internally by the calibration recipe; \n"
00165 "another 2d polynomial).\n"
00166 "\n"
00167 "If there is more than one extraction window, the results of each calibration\n"
00168 "is stored in subsequent table extensions of the same FITS file. For \n"
00169 "example, extensions 4, 5 and 6 would contain the resulting line table \n"
00170 "(and its two associated polynomials) for the second extraction window. \n"
00171 "The results for the calibration of the n'th extraction window is stored \n"
00172 "in extensions (3*n - 2) to 3*n.\n";
00175 /*-----------------------------------------------------------------------------
00176                             Functions code
00177  -----------------------------------------------------------------------------*/
00178 
00179 /*----------------------------------------------------------------------------*/
00187 /*----------------------------------------------------------------------------*/
00188 int
00189 uves_wavecal_define_parameters_body(cpl_parameterlist *parameters, 
00190                     const char *recipe_id, double slit)
00191 {
00192     const char *subcontext;
00193 
00194     /*****************
00195      *    General    *
00196      *****************/
00197     
00198     if (uves_define_global_parameters(parameters) != CPL_ERROR_NONE)
00199     {
00200         return -1;
00201     }
00202     
00203     /*****************
00204      *  Extraction   *
00205      *****************/
00206 
00207     subcontext = NULL;
00208 
00209     /* nwindows */
00210     uves_par_new_range("nwindows",
00211                CPL_TYPE_INT,
00212                "Number of extraction windows per trace. "
00213                "The windows will be aligned (i.e. no overlap "
00214                "and no spacing between adjacent windows). "
00215                "Unless an offset is specified, the middle "
00216                "window(s) is centered on the trace",
00217                strcmp(recipe_id, "flames_cal_wavecal") == 0 ?
00218             1 : 3,      /* FLAMES: 1; UVES: 3 */
00219             1, INT_MAX);
00220 
00221     /* length */
00222     uves_par_new_range("length",
00223                CPL_TYPE_DOUBLE,
00224                "Length (in pixels) of each extraction window. "
00225                "This parameter is also equal to the seperation of "
00226                "adjacent window centers, causing the extraction "
00227                "windows to always be aligned. The parameter is "
00228                "automatically adjusted according to the binning "
00229                "of the input raw frame. If negative, the extraction "
00230                        "window length is determined automatically "
00231                        "to cover the full slit",
00232                slit, -2.0, DBL_MAX);
00233 
00234     /* offset */
00235     uves_par_new_range("offset",
00236                CPL_TYPE_DOUBLE,
00237                "A global offset (in pixels) of all extraction windows",
00238                0.0, -25., 25.);
00239     
00240     /* method */
00241     if (uves_propagate_parameters_step(UVES_EXTRACT_ID, parameters, 
00242                        recipe_id, NULL) != 0)
00243     {
00244         return -1;
00245     }
00246     
00247     /* Override default optimal extraction profile. Assume constant profile */
00248 #if 0
00249     /* this should perhaps be enabled but doesn't work properly in the moment.
00250 
00251         ChangeLog:
00252     uves_cal_wavecal: The arc lamp spectrum is now extracted using
00253     average extraction and weighting each pixel with its inverse
00254     variance. This is equivalent to doing an optimal extraction under
00255     the assumption of a constant spatial profile, and is implemented
00256     as such. This was a necessary change in order to be robust against
00257     interorder noisy pixels caused by dividing by the flat-field.
00258 
00259        */
00260     {
00261     const char *profile = "constant";
00262         double kappa = -1;
00263     
00264     if (uves_set_parameter_default(parameters, 
00265                        recipe_id, UVES_EXTRACT_ID ".profile",
00266                        CPL_TYPE_STRING, &profile)
00267         != CPL_ERROR_NONE)
00268         {
00269         return -1;
00270         }
00271 
00272         /* Disable cosmic ray rejection, it does not work well for
00273            this particular profile and very high S/N */
00274     if (uves_set_parameter_default(parameters,
00275                        recipe_id, UVES_EXTRACT_ID ".kappa",
00276                        CPL_TYPE_DOUBLE, &kappa)
00277         != CPL_ERROR_NONE)
00278         {
00279         return -1;
00280         }
00281     }
00282 #else
00283     {
00284     const char *method = "average";
00285     
00286     if (uves_set_parameter_default(parameters, 
00287                        recipe_id, UVES_EXTRACT_ID ".method",
00288                        CPL_TYPE_STRING, &method)
00289         != CPL_ERROR_NONE)
00290         {
00291         return -1;
00292         }
00293         
00294     }
00295 #endif
00296     
00297     /*****************
00298      *    Search     *
00299      *****************/
00300 
00301     subcontext = "search";
00302 
00303     /* range */
00304     uves_par_new_range("range",
00305                CPL_TYPE_INT,
00306                "Width (pix) of search window is 2*range + 1. "
00307                "This parameter is automatically adjusted "
00308                "according to binning.",
00309                8, 1, INT_MAX);
00310 
00311     /* minlines */
00312     uves_par_new_range("minlines",
00313                CPL_TYPE_INT,
00314                "Minimum number of lines to detect. If zero, "
00315                "the default value (1100 for BLUE/REDL chips; "
00316                "1000 for REDU chip) is used.",
00317                0, 0, INT_MAX);
00318 
00319     /* maxlines */
00320     uves_par_new_range("maxlines",
00321                CPL_TYPE_INT,
00322                "Maximum number of lines to detect. If zero, "
00323                "the default value (1600 for BLUE/REDL chip; "
00324                "1400 for REDU chip) is used.",
00325                0, 0, INT_MAX);
00326     
00327     /* centeringmethod */
00328 /*  Temporally removed as 'gravity' do not work and it does not make 
00329     sense a parameter with only one option
00330 
00331     uves_par_new_enum("centeringmethod",
00332               CPL_TYPE_STRING,
00333               "Line centering method",
00334               "gaussian",             // Default 
00335               1,                      // Number of options 
00336                       "gaussian");    // List of options 
00337      
00338 */
00339          /* old setting allowed gravity "gaussian", "gravity"); */
00340 
00341     /*******************
00342      *  First solution *
00343      *******************/
00344 
00345     subcontext = "first";
00346 
00347     /* shiftmax */
00348     uves_par_new_range("shiftmax",
00349                CPL_TYPE_DOUBLE,
00350                "The maximum shift (pix) in either direction compared to "
00351                "guess solution. This parameter is automatically "
00352                "corrected for binning",
00353                10.0, 0.0, DBL_MAX);
00354 
00355     /* shiftstep */
00356     uves_par_new_range("shiftstep",
00357                CPL_TYPE_DOUBLE,
00358                "The step size (pix) used when searching "
00359                "for the optimum shift. This parameter is "
00360                "automatically corrected for binning",
00361                0.1, 0.0, DBL_MAX);
00362 
00363     /* shifttoler */
00364     uves_par_new_range("shifttoler",
00365                CPL_TYPE_DOUBLE,
00366                "Tolerance (pix) when matching shifted lines. "
00367                "This parameter is not adjusted according to binning",
00368                0.05, 0.0, DBL_MAX);
00369 
00370 
00371     /*****************
00372      *  Identify     *
00373      *****************/
00374 
00375     subcontext = "identify";
00376     
00377     /* alpha */
00378     uves_par_new_range("alpha",
00379                CPL_TYPE_DOUBLE,
00380                "The parameter that controls the distance to the "
00381                "nearest neighbours",
00382                0.1, 0.0, 1.0);
00383 
00384     /* maxerror */
00385     uves_par_new_range("maxerror",
00386                CPL_TYPE_DOUBLE,
00387                "This parameter controls the graceful exit of "
00388                "the identification loop. If the RMS of the "
00389                "global fit exceeds this value (pix) the "
00390                "iteration stops",
00391                20.0, 0.0, DBL_MAX);
00392     
00393     /* degree */
00394     uves_par_new_range("degree",
00395                CPL_TYPE_INT,
00396                "Degrees of the global 2d dispersion polynomial. If "
00397                        "a negative number is specified, the polynomial "
00398                        "degrees are automatically selected by starting from "
00399                        "(1, 1) and inreasing the degrees as long as the RMS "
00400                        "residual decreases significantly",
00401                4, -2, INT_MAX);
00402 
00403 
00404     /*****************
00405      * Calibration   *
00406      *****************/
00407 
00408     subcontext = "calibrate";
00409 
00410     /* tolerance */
00411     uves_par_new_value("tolerance",
00412                        CPL_TYPE_DOUBLE,
00413                        "Tolerance of fit. If positive, the tolerance "
00414                        "is in pixel units. If negative, abs(tolerance) "
00415                        "is in wavelength units. Lines with residuals "
00416                        "worse than the tolerance are excluded from the "
00417                        "final fit. Unlike in previous versions, this "
00418                        "parameter is not corrected for CCD binning. "
00419                        "This rejection based on the absolute residual in "
00420                        "pixel can be effectively disabled by setting the "
00421                        "tolerance to a very large number (e.g. 9999). In "
00422                        "that case outliers will be rejected using only "
00423                        "kappa sigma clipping.",
00424                        0.6); 
00425 /*               0.07); */
00426 /*                       9999.0);*/
00427 
00428     
00429     /* kappa */
00430     uves_par_new_range("kappa",
00431                CPL_TYPE_DOUBLE,
00432                "Lines with residuals more then kappa stdev "
00433                        "are rejected from the final fit",
00434                        4.0,0.,100.);
00435 
00436     /***************
00437      * Rebinning   *
00438      ***************/
00439     if (uves_propagate_parameters_step(UVES_REBIN_ID, parameters, 
00440                        recipe_id, NULL) != 0)
00441     {
00442         return -1;
00443     }
00444     
00445     return (cpl_error_get_code() != CPL_ERROR_NONE);
00446 }
00447 
00448 /*----------------------------------------------------------------------------*/
00519 /*----------------------------------------------------------------------------*/
00520 static cpl_table *
00521 uves_wavecal_process_window(const cpl_image *arclamp, 
00522                             const cpl_image *arclamp_noise,
00523                             const uves_propertylist *rotated_header,
00524                             const cpl_table *ordertable, 
00525                             const polynomial *order_locations,
00526                             bool flat_fielded,
00527                             cpl_image *weights,
00528                             /* const cpl_table *drs_table,  Not used */
00529                             const cpl_table *guess,
00530                             const cpl_table *line_refer,
00531                             bool flames,
00532                             int tab_in_out_oshift,
00533                             double tab_in_out_yshift,
00534                             enum uves_chip chip, int bin_disp,
00535                             int trace, int window, int NWINDOWS,
00536                             /* General */
00537                             bool DEBUG,
00538                             /* Extraction */
00539                             double offset,
00540                             double slitlength,
00541                             const cpl_parameterlist *parameters,
00542                             const char *recipe_id,
00543                             /* Search */
00544                             int RANGE,
00545                             int MINLINES,
00546                             int MAXLINES,
00547                             centering_method CENTERING_METHOD,
00548                             /* First solution */
00549                             double SHIFT_MAX,
00550                             double SHIFT_STEP,
00551                             double SHIFT_TOLERANCE,
00552                             /* Identify */
00553                             double ALPHA,
00554                             double MAXERROR,
00555                             int DEGREE,
00556                             /* Calibrate */
00557                             double TOLERANCE,
00558                             double kappa,
00559                             cpl_frame* corvel_frm,
00560                             cpl_table** flames_qclog,
00561                             /* Result */
00562                             polynomial **dispersion_relation,
00563                             polynomial **absolute_order,
00564                             int *first_absolute_order,
00565                             int *last_absolute_order)
00566 {
00567     cpl_table        *linetable          = NULL;  /* Result */
00568     cpl_table        *temp               = NULL;
00569     cpl_image        *spectrum           = NULL;
00570     cpl_image        *spectrum_noise     = NULL;
00571     cpl_image        *debug_image        = NULL;
00572     polynomial       *initial_dispersion = NULL;
00573     int              *relative_order     = NULL;  /* Map from physical 
00574                              order to relative order */
00575     uves_propertylist *spectrum_header    = NULL;
00576 
00577     cpl_image        *rebinned           = NULL;  /* Used for calculating 
00578                              the instrument resolution */
00579     cpl_image        *rebinned_noise     = NULL;  /* Used for calculating 
00580                              the instrument resolution */
00581     uves_propertylist *rebinned_header    = NULL;
00582     cpl_image        *merged             = NULL;
00583     cpl_image        *merged_noise       = NULL;
00584     uves_propertylist *merged_header      = NULL;
00585     cpl_table        *info_tbl           = NULL;
00586 
00587     /* Needed for optimal extraction */
00588     cpl_image *weights_opt = NULL;
00589     cpl_table *cr_table = NULL;
00590     cpl_image *cr_image = NULL;
00591     cpl_table *order_trace = NULL;
00592 
00593     merge_method m_method = flat_fielded ? MERGE_OPTIMAL : MERGE_SUM;
00594 
00595     /* Extract the spectrum */
00596     uves_free_table(&info_tbl);
00597 
00598 
00599     check( spectrum = uves_extract((cpl_image *)arclamp,/* Const-casts are okay,
00600                                                            the image (bpm) + error bars
00601                                                            is changed
00602                                                            only in optimal extraction */
00603                                    (cpl_image *)arclamp_noise,
00604                                    NULL,            /* Header (optimal only)    */
00605                                    ordertable, 
00606                                    order_locations,
00607                                    slitlength,      /* Slit length (pixels)     */
00608                                    offset,          /* Slit center offset       */
00609                                    parameters,      /* Extraction method        */
00610                                    recipe_id, 
00611                                    "",     
00612                                    true,            /* Extraction partial bins? */
00613                                    DEBUG,
00614                                    chip,
00615                                    &spectrum_header,
00616                                    &spectrum_noise,
00617                                    NULL, 
00618                                    NULL,            /* Optimal:  sky+noise      */
00619                                    &cr_table, 
00620                                    &cr_image, 
00621                                    NULL, 
00622                                    (weights != NULL) ? &weights : &weights_opt,
00623                                    &info_tbl,
00624                                    &order_trace),
00625            "Error extracting spectrum");
00626     uves_free_table(&info_tbl);
00627 
00628 
00629     check(uves_propertylist_copy_property_regexp(spectrum_header,
00630                                                  rotated_header,
00631                          "^ESO ", 0),"error copying hierarch keys");
00632 
00633     /* Set bad pixels to 0, so that the search algorithm doesn't
00634        fail because of bad pixels (but simply does not detect anything)
00635     */
00636     cpl_image_fill_rejected(spectrum, 0);
00637     cpl_image_accept_all(spectrum);
00638     cpl_image_fill_rejected(spectrum_noise, 1);
00639     cpl_image_accept_all(spectrum_noise);
00640 
00641     /* Save spectrum + noise */
00642     if (DEBUG)
00643     {
00644 
00645 
00646       check(uves_propertylist_copy_property_regexp(spectrum_header, rotated_header,
00647           "^ESO ", 0),
00648        "Error copying hieararch keys");
00649 
00650         check( uves_save_image_local("Extracted spectrum", "spectrum", 
00651                      spectrum, chip, trace, window, spectrum_header, true),
00652            "Error saving spectrum");
00653 
00654         check( uves_save_image_local("Extracted spectrum noise", "spectrum_noise",
00655                      spectrum_noise, chip, trace, window, spectrum_header, true),
00656            "Error saving spectrum");
00657     }
00658 
00659     /* Locate lines */
00660     debug_image = cpl_image_duplicate(arclamp);
00661     check( linetable = uves_wavecal_search(spectrum, 
00662                                            spectrum_noise,
00663                                            spectrum_header,
00664                                            flat_fielded,
00665                                            order_locations,
00666                                            debug_image,
00667                                            RANGE,
00668                                            MINLINES, 
00669                                            MAXLINES, 
00670                                            CENTERING_METHOD,
00671                                            bin_disp,trace,window,
00672                                            flames_qclog[0]),
00673        "Line search failed");
00674 
00675      /* Read first solution from guess line table */
00676     {
00677         int degree = 5; /* for the initial solution only. For the
00678                            final solution the degree given as recipe
00679                            parameter is used */
00680         uves_polynomial_delete(&initial_dispersion);
00681         cpl_free(relative_order);
00682         check( initial_dispersion = uves_wavecal_firstsolution(linetable,
00683                                                                guess, 
00684                                                                absolute_order,
00685                                                                ordertable,
00686                                                                order_locations,
00687                                                                flames,
00688                                                                offset,
00689                                                                &relative_order,
00690                                                                degree,
00691                                                                SHIFT_MAX, 
00692                                                                SHIFT_STEP, 
00693                                                                SHIFT_TOLERANCE, 
00694                                                                MAXERROR,
00695                                                                first_absolute_order,
00696                                                                last_absolute_order),
00697                "Could not get first solution");
00698     }
00699 
00700 
00701     if (flames)
00702     {
00703         /* !AM: To correct eventual residual shifts between Guess and Final order
00704            ! (and line) table
00705            compute/table {LINTAB} :YNEW =
00706            :YNEW - {{ORDTAB},TAB_IN_OUT_YSHIFT} - {{OLDORDTAB},FIBREPOS({i1})}
00707            compute/table {LINTAB} :Y = :Y +{{ORDTAB},TAB_IN_OUT_OSHIFT}
00708         */
00709 
00710         cpl_table_add_scalar(linetable, "Y", tab_in_out_oshift);
00711         cpl_table_add_scalar(linetable, "Ynew", - tab_in_out_yshift - offset);
00712     }
00713 
00714     /* Calibrate */
00715     check( *dispersion_relation = uves_wavecal_identify(linetable, /* Guess solution */
00716                                                         line_refer,
00717                                                         initial_dispersion,
00718                                                         DEGREE,
00719                                                         TOLERANCE, ALPHA, 
00720                                                         MAXERROR,
00721                                                         kappa,trace,window,flames_qclog[0]),
00722        "Could not calibrate orders");
00723 
00724     if (flames)
00725     {
00726         /* AM: To have correct split of fibres in line table:
00727            > compute/table {LINTAB} :YNEW = :YNEW + {{ORDTAB},TAB_IN_OUT_YSHIFT}
00728                      + {{OLDORDTAB},FIBREPOS({i1})}
00729         */
00730 
00731         cpl_table_add_scalar(linetable, "Ynew", + tab_in_out_yshift + offset);
00732     }
00733 
00734     /* UVES: make plots (resolution + etc.) for the central window,
00735      * FLAMES: all fibres
00736      */
00737     if (flames || (trace == 0 && window == 2)|| (window == 1 && NWINDOWS == 1))
00738     {
00739         /* Create x-FWHM column:   FWHM = 2.3548 sigma */
00740         check(( cpl_table_duplicate_column(linetable, "deltaX", linetable, "Xwidth"),
00741             cpl_table_multiply_scalar (linetable, "deltaX", TWOSQRT2LN2)),
00742           "Error creating FWHM column");
00743         
00744 
00745         check_nomsg( temp = uves_extract_table_rows(
00746                              linetable, "NLinSol", CPL_NOT_EQUAL_TO, 0) );
00747 
00748         check( uves_plot_table(temp, "Order", LINETAB_RESIDUAL, "Residual of fit"), 
00749            "Plotting failed");
00750         
00751         check( uves_plot_table(temp, "X", "deltaX", "line FWHM (mean = %.2f pixels)",
00752                    cpl_table_get_column_mean(linetable, "deltaX")),
00753            "Plotting failed");
00754         /*
00755           check( uves_plot_table(linetable, "Y", "deltaX", 
00756           "line FWHM (mean FWHM = %.2f pixels)",
00757           cpl_table_get_column_mean(linetable, "deltaX")), "Plotting failed");
00758         */
00759         
00760         
00761         /* Compute resolution as as lambda / deltalambda   where deltalambda
00762                is the peak FWHM in wavelength space (after resampling using 
00763            WAVESTEP = average pixelsize) 
00764         */
00765         
00766         {
00767         /* Rebin using steps of median pixelsize */
00768         double wavestep;
00769         double lambda_start = 0;
00770         int n_traces = 1;      /* We didn't do a 2d extraction; 
00771                       there's only 1 trace
00772                       per order */
00773         int i, nbins;
00774                 bool threshold_to_positive = true;
00775 
00776         cpl_table_new_column(linetable, "deltaLambda", CPL_TYPE_DOUBLE);
00777         
00778         check( rebinned_noise = uves_rebin(spectrum_noise,
00779                                            parameters, 
00780                                            recipe_id,
00781                                            linetable, 
00782                                            *dispersion_relation, 
00783                                            *first_absolute_order, 
00784                                            *last_absolute_order,
00785                                            n_traces,
00786                                            threshold_to_positive,
00787                                            true,
00788                                            &rebinned_header),
00789                "Could not rebin noise of arc lamp spectrum");
00790 
00791         threshold_to_positive = false;
00792         uves_free_propertylist(&rebinned_header);
00793         check( rebinned = uves_rebin(spectrum,
00794                                      parameters, 
00795                                      recipe_id,
00796                                      linetable, 
00797                                      *dispersion_relation, 
00798                                      *first_absolute_order, 
00799                                      *last_absolute_order,
00800                                      n_traces,
00801                                      threshold_to_positive,
00802                                      false,
00803                                      &rebinned_header),
00804                "Could not rebin arc lamp spectrum");
00805 
00806         /* Save order-by-order rebinned spectrum+noise */
00807         if (DEBUG)
00808             {
00809             check( uves_save_image_local("Rebinned spectrum",
00810                              "wxb", rebinned, chip, 
00811                              trace, window, rebinned_header, true),
00812                    "Error saving rebinned spectrum");
00813 
00814             check( uves_save_image_local("Noise of rebinned spectrum",
00815                              "errwxb", rebinned_noise, chip, 
00816                              trace, window, rebinned_header, true),
00817                    "Error saving noise of rebinned spectrum");
00818             }
00819         
00820         check( merged = uves_merge_orders(rebinned, 
00821                       rebinned_noise,
00822                       rebinned_header,
00823                       m_method,
00824                       n_traces,
00825                       &merged_header,
00826                       0,0,chip,
00827                       &merged_noise),
00828                "Could not merge arc lamp spectrum");
00829 
00830         check( uves_plot_image_rows(merged, 1, 1, 1, 
00831                         "Wavelength (arbitrary units)", 
00832                         "Flux", "Resampled arc lamp spectrum"),
00833                "Plotting failed");
00834 
00835         /* Save merged arc lamp spectrum */
00836         if (DEBUG)
00837             {
00838             check( uves_save_image_local("Rebinned, merged spectrum",
00839                              "merged", merged, chip, 
00840                              trace, window, merged_header, true),
00841                    "Error saving merged spectrum");
00842             }
00843         
00844         nbins = cpl_image_get_size_x(merged);
00845 
00846         check( wavestep = uves_pfits_get_cdelt1(merged_header),
00847                "Error reading resampling step size");
00848         
00849         check( lambda_start = uves_pfits_get_crval1(merged_header), 
00850                "Could not read start wavelength of merged spectrum");
00851 
00852 
00853     //Begin commented region
00854     
00855    if (flames && trace == 0 && corvel_frm != NULL)
00856     {
00857        //The following (flames_reduce.VCORREL) calculates 
00858        //a cross correlation and does some QC
00859 
00860 
00861 //> !To support simcal Mode
00862 //> if i1 .eq. 1 then
00863 //>    w/o "DRS_CVEL_SWITCH={DRS_CVEL_SWITCH}"
00864 //>    if "{DRS_CVEL_SWITCH}" .eq. "Y" then
00865 //>       w/o "To support simcal Mode"
00866 //>       define/local ord_min/i/1/1 0
00867 //>       define/local ord_max/i/1/1 0
00868 //>       define/local rsample/d/1/1 0
00869 //>       statistic/table {ORDTAB} :ORDER >Null
00870 //>       ord_min = outputr(1)
00871 //>       ord_max = outputr(2)
00872 //>       rsample = {{LINTAB},PIXEL(1)}
00873 //>       rsample = 2./3. * rsample
00874 //>       rebin/echelle  {ofrm} w{ofrm} {rsample} NONL {LINTAB} {SESSOUTV}
00875 //>       mercut/echelle w{ofrm} mw{ofrm} {ord_min},{ord_max} NOAPPEND
00876 //>       !corvel stuff
00877 //>       define/local OLD_CVEL_MAX/d/1/1 {DRS_CVEL_MAX}
00878 //>       define/local OLD_CVEL_MIN/d/1/1 {DRS_CVEL_MIN}
00879 //>       @p flames_reduce,VCORREL x1_rbf_ cvel1 0 {ord_max} {parCorVelTab} _0 _{chip({PATHID})} 0
00880 //>       DRS_CVEL_MAX = DRS_CVEL_MAX + {q1}
00881 //>       DRS_CVEL_MIN = DRS_CVEL_MIN + {q1}
00882 //>
00883 //>       @p flames_reduce,VCORREL x1_rbf_ cvel2 0 {ord_max} {parCorVelTab} _0 _{chip({PATHID})} 0
00884 //>       cvel_0 = {q1}
00885 //>       DRS_CVEL_MAX = OLD_CVEL_MAX
00886 //>       DRS_CVEL_MIN = OLD_CVEL_MIN
00887 //>    endif
00888 //>    write/keyword DRS_CVEL_SWITCH Y
00889 //> endif
00890 
00891 
00892 
00893 
00894        
00895 
00896 
00897       const char* drs_base_name=NULL;
00898       const char* prefid=NULL;
00899       double ccf_posmax_zero_point=0;
00900       double ccf_posmax_zero_point_iter0=0;
00901       double cvel_max=0;
00902       double cvel_sig=0;
00903       if(chip == UVES_CHIP_REDL) {
00904     prefid="l";
00905       } else {
00906     prefid="u";
00907       }
00908       const char* name=NULL;
00909       const char* file=NULL;
00910       cpl_propertylist* plist=NULL;
00911       double drs_cvel_min=0;
00912       double drs_cvel_max=0;
00913 
00914  
00915       check( uves_save_image_local("Rebinned spectrum",
00916                    "wxb", rebinned, chip, 
00917                    trace, window, rebinned_header, true),
00918          "Error saving rebinned spectrum");
00919 
00920       check( uves_save_image_local("Rebinned, merged spectrum",
00921                    "mwxb", merged, chip, 
00922                    trace, window, merged_header, true),
00923          "Error saving merged spectrum");
00924      
00925 
00926       check( file = uves_local_filename("wxb", chip, trace, window),
00927          "Error getting filename");
00928       check_nomsg(plist=cpl_propertylist_load(file,0));
00929 
00930       name=uves_sprintf("wfxb_%s%s%4.4d%s",prefid,"_raw",1,".fits");
00931       drs_base_name=uves_sprintf("fxb_%s",prefid);
00932 
00933       cpl_image_save(rebinned,name, CPL_BPP_IEEE_FLOAT,plist, 
00934              CPL_IO_DEFAULT);
00935 
00936 
00937       name=uves_sprintf("mwfxb_%s%s%4.4d%s",prefid,"_raw",1,".fits");
00938       cpl_image_save(merged,name, CPL_BPP_IEEE_FLOAT,plist, 
00939              CPL_IO_DEFAULT);
00940      
00941       cpl_propertylist_delete(plist);
00942 
00943 
00944       int ord_max=(*first_absolute_order-*last_absolute_order)+1;
00945      
00946       uves_msg("cvel max:%g %g",DRS_CVEL_MAX,DRS_CVEL_MIN);
00947       drs_cvel_max =DRS_CVEL_MAX;
00948       drs_cvel_min =DRS_CVEL_MIN;
00949 
00950       check_nomsg(flames_reduce_vcorrel(drs_base_name,
00951                     "cvel2", 
00952                     prefid,
00953                     ord_max,
00954                     corvel_frm, 
00955                     "_raw0001", 
00956                     "_raw0001", 
00957                                         DRS_CVEL_MIN,
00958                                         DRS_CVEL_MAX,
00959                     &ccf_posmax_zero_point,
00960                     &cvel_max,
00961                     &cvel_sig,
00962                     flames_qclog[0]));
00963      
00964      drs_cvel_max +=cvel_max;
00965      drs_cvel_min +=cvel_max;
00966      ccf_posmax_zero_point_iter0 =cvel_max;
00967      uves_msg("cvel max:%g %g",drs_cvel_max,drs_cvel_min);
00968 
00969      check_nomsg(flames_reduce_vcorrel(drs_base_name,
00970                     "cvel2", 
00971                     prefid,
00972                     ord_max,
00973                     corvel_frm, 
00974                     "_raw0001", 
00975                     "_raw0001", 
00976                                         drs_cvel_min,
00977                                         drs_cvel_max,
00978                     &ccf_posmax_zero_point,
00979                     &cvel_max,
00980                     &cvel_sig,
00981                     flames_qclog[1]));
00982       
00983       drs_cvel_max +=cvel_max;
00984       drs_cvel_min +=cvel_max;
00985       ccf_posmax_zero_point =ccf_posmax_zero_point_iter0;
00986       ck0_nomsg(uves_qclog_add_double(flames_qclog[1],
00987                    "QC CCF POSOFF",
00988                    ccf_posmax_zero_point,
00989                    "CCF pos avg from ThAr calibration",
00990                    "%f"));
00991 
00992 
00993       uves_msg("cvel max:%g min: %g zp: %g",
00994            drs_cvel_max,drs_cvel_min,ccf_posmax_zero_point);
00995 
00996    
00997     }
00998    //End commented region
00999 
01000 
01001         /* For all identified lines fit the line width in the
01002            merged spectrum to get the resolution  */
01003          for (i = 0; i < cpl_table_get_nrow(linetable); i++)
01004             {
01005             double lambda = cpl_table_get_double(
01006                 linetable, LINETAB_LAMBDAC, i, NULL);
01007             double width  = 
01008                 cpl_table_get_double(linetable, "Xwidth"   , i, NULL) *
01009                 fabs(cpl_table_get_double(linetable, LINETAB_PIXELSIZE, i, NULL)); 
01010             /* in wlu */
01011             
01012             /* Convert line wavelength and width to 'bin' units */
01013             int bin       = 1 + 
01014                 uves_round_double((lambda - lambda_start) / wavestep);
01015             double width_bin = width / wavestep;
01016 
01017             /* Set fitting window to +-5 sigma */
01018             int first_bin = uves_max_int(    1, uves_round_double(bin - 5*width_bin));
01019             int last_bin  = uves_min_int(nbins, uves_round_double(bin + 5*width_bin));
01020 
01021             double my, sigma, norm, background;    /* Results of fit */
01022             double lambda_fwhm;
01023             
01024             if (cpl_table_is_valid(linetable, "Ident", i) && first_bin < last_bin)
01025                 {
01026                 /* Fit a gaussian to the merged arc spectrum */
01027                 uves_fit_1d_image(merged, 
01028 #if 1
01029                                                   merged_noise, 
01030 #else /* Unweighted fit like MIDAS which gives larger sigma */
01031                                                   NULL,
01032 #endif
01033                                                   NULL,
01034                           true,     /* Horizontal?    */
01035                           false,    /* Fix background?*/
01036                           false,    /* Fit background?*/
01037                           first_bin, 
01038                                                   last_bin, 
01039                                                   1,  /* xlo, xhi, y    */
01040                           &my, 
01041                                                   &sigma, 
01042                                                   &norm, 
01043                                                   &background, NULL, /* slope */
01044                           NULL, 
01045                                                   NULL, 
01046                                                   NULL,    /* mse, red_chisq,
01047                                   covariance     */
01048                           uves_gauss, 
01049                                                   uves_gauss_derivative, 
01050                                                   4);
01051                                         
01052                 if (cpl_error_get_code() == CPL_ERROR_CONTINUE)
01053                     {
01054                     uves_error_reset();
01055                     uves_msg_debug("Gaussian fitting failed "
01056                                "at lambda = %f wlu, bins = "
01057                                "%d - %d, ignoring line",
01058                                lambda, first_bin, last_bin);
01059                     
01060                     cpl_table_set_invalid(linetable, "deltaLambda", i);
01061                     
01062                     }
01063                 else
01064                     {
01065                         assure(cpl_error_get_code() == CPL_ERROR_NONE,
01066                                cpl_error_get_code(), "Gaussian fitting failed");
01067                     
01068                     /* Convert from bins to wavelength */
01069                     lambda_fwhm = TWOSQRT2LN2 * sigma * wavestep;
01070                     
01071                     cpl_table_set_double(linetable, "deltaLambda",
01072                                  i, lambda_fwhm);
01073 
01074                     }
01075                 }
01076             else
01077                 {
01078                 cpl_table_set_invalid(linetable, "deltaLambda", i);
01079                 }
01080             }
01081         
01082         
01083         /* Create column 'Resol'(ution) = lambda / deltalambda */
01084         check(( cpl_table_duplicate_column(linetable, "Resol", 
01085                            linetable, LINETAB_LAMBDAC),
01086             cpl_table_divide_columns  (linetable, "Resol",
01087                            "deltaLambda")),
01088               "Error creating 'Resol' column");
01089         
01090         /* Filter out extreme outliers (due to bad gaussian fit) */
01091         {
01092          
01093           int ninvalid=0;
01094           int nrows=0;
01095            double resol_avg   = 0;
01096            double resol_stdev = 0;
01097            double kappar = 10.0;
01098            nrows=cpl_table_get_nrow(linetable);
01099            ninvalid=cpl_table_count_invalid(linetable,"Resol");
01100            assure(ninvalid < nrows,CPL_ERROR_ILLEGAL_INPUT, 
01101                  "No valid elements in Resol column. "
01102                  "You must decrease parameter rebin.wavestep");
01103            check_nomsg(resol_avg=cpl_table_get_column_median(linetable, "Resol"));
01104            check_nomsg(resol_stdev=cpl_table_get_column_stdev (linetable, "Resol"));
01105 
01106             for (i = 0; i < cpl_table_get_nrow(linetable); i++)
01107             {
01108                 double r = cpl_table_get_double(linetable, "Resol", i, NULL);
01109                 if (r < resol_avg - kappar*resol_stdev ||
01110                 r > resol_avg + kappar*resol_stdev)
01111                 {
01112                     cpl_table_set_invalid(linetable, "Resol", i);
01113                     cpl_table_set_invalid(linetable, "deltaLambda", i);
01114                 }
01115             }
01116         }
01117 
01118         /* check( uves_plot_table(linetable, "X", "Resol", 
01119            "(x, l / dl)"), "Plotting failed"); 
01120            check( uves_plot_table(linetable, "Y", "Resol", 
01121            "(y, l / dl)"), "Plotting failed"); 
01122         */
01123         check( uves_plot_table(linetable, LINETAB_LAMBDAC, "Resol",
01124                        "(l, l / dl)"), "Plotting failed");
01125         }
01126         
01127         /* Plot identifications */
01128             uves_free_table(&temp);
01129         check( temp = cpl_table_duplicate(linetable), 
01130            "Error copying line table");
01131         check( uves_erase_invalid_table_rows(temp, "Ident"), 
01132            "Error removing un-identified lines");
01133         check( uves_plot_table(temp, "X", "Ynew", 
01134                    "Line identifications"), 
01135            "Plotting failed");
01136         uves_free_table(&temp);
01137 
01138     } /* Plots for middle (object) window */
01139 
01140     if (DEBUG) 
01141     {
01142         /* Results of uves_wavecal_search are already 
01143            drawn on debug_image */
01144         
01145         /* Draw guess table lines using the initial solution */
01146         if (0) check( uves_draw_lines(debug_image, initial_dispersion,
01147                       order_locations, guess,
01148                       "Ident", "Order", relative_order,
01149                       -1, -1,
01150                       false,     /* true = vertical */
01151                       12), "Error drawing guess solution");
01152         
01153         /* Draw catalogue lines using the initial solution */
01154         check( uves_draw_lines(debug_image, initial_dispersion, order_locations,
01155                    line_refer, "Wave", NULL, relative_order,
01156                    uves_min_int(*first_absolute_order, *last_absolute_order),
01157                    uves_max_int(*first_absolute_order, *last_absolute_order),
01158                    true,                   /* true = vertical */
01159                    8), "Error drawing catalogue lines");
01160         
01161         /* Draw catalogue lines using the final solution */
01162         check( uves_draw_lines(debug_image, *dispersion_relation, order_locations, 
01163                    line_refer, "Wave", NULL, relative_order,
01164                    uves_min_int(*first_absolute_order, *last_absolute_order),
01165                    uves_max_int(*first_absolute_order, *last_absolute_order),
01166                    true,                     /* true = vertical */
01167                    16), "Error drawing catalogue lines");
01168         
01169         /* Draw detected lines using initial solution */
01170         if (0) check( uves_draw_lines(debug_image, initial_dispersion, 
01171                       order_locations, linetable, 
01172                       LINETAB_LAMBDAC, "Order", relative_order,
01173                       -1, -1,
01174                       false,            /* true = vertical */
01175                       -16), "Error drawing detected lines");
01176         
01177         /* Draw IDed lines */
01178             uves_free_table(&temp);
01179         check(( temp = cpl_table_duplicate(linetable),
01180             /* Delete rows with invalid 'Ident' */
01181             uves_erase_invalid_table_rows(temp, "Ident")),
01182           "Error duplicating table");
01183         
01184         check( uves_draw_lines(debug_image, *dispersion_relation, order_locations,
01185                    temp, LINETAB_LAMBDAC, "Order", relative_order,
01186                    -1, -1,
01187                    true,                  /* true = vertical */
01188                    0), "Error drawing detected lines");
01189         
01190 
01191         /* Explanation of drawing produced by code above:
01192            The output frame emission lines will look like this
01193 
01194 
01195                      #### |1
01196                          ####   |2  
01197                          #|3#
01198                          -+--
01199                          #|##
01200                          ####
01201                          ####
01202         
01203 
01204                 Legend:
01205 
01206                   ##: The emmission line
01207                   --: (horizontal line) The line was detected
01208                   |1: (vertical line)   Predicted position (final solution)
01209                   |2: (vertical line)   Predicted position (initial solution)
01210                   |3: (vertical line)   Is drawn iff the line was identified
01211 
01212 
01213           
01214         */
01215 
01216         /* Save the raw arc frame with detected emission lines marked */
01217         check( uves_save_image_local("Debug image", "rawdebug", 
01218                      debug_image, chip, trace, window,
01219                      rotated_header, true),
01220            "Error saving spectrum");
01221     }
01222 
01223     if (flames)
01224     {
01225         int start = 0;
01226         int count = cpl_table_get_nrow(linetable);
01227 
01228         check_nomsg( cpl_table_new_column(linetable, "Fibre", CPL_TYPE_INT) );
01229 
01230         cpl_table_fill_column_window(linetable, "Fibre",
01231                      start, count,
01232                      trace + 1);   /* Write value in range 1-9 */
01233     }
01234 
01235   cleanup:
01236 
01237     uves_free_table(&info_tbl);
01238     uves_free_table(&temp);
01239     uves_free_image(&weights_opt);
01240     uves_free_table(&cr_table);
01241     uves_free_image(&cr_image);
01242     uves_free_image(&spectrum);
01243     uves_free_image(&spectrum_noise);
01244     uves_free_image(&debug_image);
01245     uves_free_image(&rebinned);
01246     uves_free_image(&rebinned_noise);
01247     uves_free_image(&merged);
01248     uves_free_image(&merged_noise);
01249     uves_free_propertylist(&spectrum_header);
01250     uves_free_propertylist(&rebinned_header);
01251     uves_free_propertylist(&merged_header);
01252     cpl_free(relative_order);
01253     uves_polynomial_delete(&initial_dispersion);
01254     uves_free_table(&order_trace);
01255 
01256     return linetable;
01257 }
01258 
01259 
01260 
01261 /*----------------------------------------------------------------------------*/
01286 /*----------------------------------------------------------------------------*/
01287 void
01288 uves_wavecal_exe_body(cpl_frameset *frames,
01289               bool flames,
01290               const char *recipe_id,
01291               const cpl_parameterlist *parameters,
01292               const char *starttime)
01293 {
01294     /*
01295      * Variables containg the values of recipe parameters 
01296      */
01297 
01298     /* General */
01299     bool DEBUG;
01300 
01301     /* Extraction */
01302     int NWINDOWS;
01303     double OFFSET;
01304     double SLITLENGTH_par;  /* slitlength given by user */
01305 
01306     /* Search */
01307     int    RANGE;
01308     int    MAXLINES;
01309     int    MINLINES;
01310     centering_method CENTERING_METHOD;
01311 
01312     /* First solution */
01313     double SHIFT_MAX;
01314     double SHIFT_STEP;
01315     double SHIFT_TOLERANCE;
01316 
01317     /* Identify */
01318     double  ALPHA;
01319     double  MAXERROR;
01320     int     DEGREE;
01321     /* Calibrate */
01322     double  TOLERANCE;
01323     double  KAPPA;
01324 
01325     /* Input */
01326     cpl_image        *arclamp[2]          = {NULL, NULL};
01327     cpl_image        *arclamp_noise       = NULL;
01328     uves_propertylist *arclamp_header[2]   = {NULL, NULL};
01329     uves_propertylist *rotated_header[2]   = {NULL, NULL};
01330     
01331     /* Order table */
01332     cpl_table        *ordertable            = NULL;
01333     uves_propertylist *ordertable_header     = NULL;
01334     polynomial       *order_locations       = NULL;
01335     cpl_table        *traces                = NULL;
01336     
01337     /* Bias */
01338     cpl_image        *master_bias        = NULL;
01339     uves_propertylist *master_bias_header = NULL;
01340 
01341     /* Flat field */
01342     cpl_image        *master_flat        = NULL;
01343     cpl_image        *mflat_noise        = NULL;
01344     uves_propertylist *master_flat_header = NULL;
01345 
01346     /* Weight map */
01347     cpl_image        *weights            = NULL;
01348 
01349     /* DRS guess table is not used */
01350     /* 
01351        cpl_table        *drs_table             = NULL;
01352        uves_propertylist *drs_header            = NULL;
01353     */
01354 
01355     //FLAMES-DRS specific descriptors
01356     int* fibres_mask=NULL;
01357     double* fibres_pos=NULL;
01358 
01359     /* Guess line table */
01360     cpl_table        *guess              = NULL;
01361     polynomial       *absolute_order     = NULL;
01362     
01363     /* Velocity correction table */
01364     cpl_table        *corvel             = NULL;
01365     cpl_frame        *corvel_frm         = NULL;
01366     uves_propertylist *corvel_header      = NULL;
01367 
01368     /* Reference catalogue */
01369     cpl_table        *line_refer            = NULL;
01370     cpl_table        *line_intmon           = NULL;
01371    
01372     /* Output */
01373     lt_type          *linetable             = NULL;
01374 
01375     uves_propertylist *primary_header        = NULL;
01376     uves_propertylist *table_header          = NULL;
01377     /* QC for resolution + intmon + NULL */
01378     cpl_table        *qclog[3]              = {NULL, NULL, NULL};
01379 
01380     /* Local variables */
01381     cpl_image        *absorder_image     = NULL;
01382     const char *arclamp_filename = "";
01383     const char *line_refer_filename = "";
01384     const char *line_intmon_filename = "";
01385     char *product_filename = NULL;
01386     char *temp = NULL;
01387     bool blue  = false;
01388     bool sim_cal = false;
01389     enum uves_chip chip;
01390     int binx = 0;
01391     int biny = 0;
01392     bool drs_cvel_sw=false;
01393     const char* PROCESS_CHIP=NULL;
01394     extract_method em;
01395 
01396     /* Read recipe parameters */
01397     {
01398     const char *centering_m = "gaussian";
01399         const char *profile = "";
01400 
01401  
01402 
01403     /* General */
01404     check( uves_get_parameter(parameters, NULL, "uves", "debug", 
01405                   CPL_TYPE_BOOL, &DEBUG), "Could not read parameter");
01406     
01407     check( uves_get_parameter(parameters, NULL, "uves", "process_chip", CPL_TYPE_STRING, &PROCESS_CHIP),
01408                "Could not read parameter");
01409     uves_string_toupper((char*)PROCESS_CHIP);
01410 
01411         /* Extraction */
01412     check( uves_get_parameter(parameters, NULL, recipe_id, "nwindows",
01413                   CPL_TYPE_INT   , &NWINDOWS    ), "Could not read parameter");
01414     check( uves_get_parameter(parameters, NULL, recipe_id, "length",
01415                   CPL_TYPE_DOUBLE, &SLITLENGTH_par), "Could not read parameter");
01416     check( uves_get_parameter(parameters, NULL, recipe_id, "offset",
01417                   CPL_TYPE_DOUBLE, &OFFSET      ), "Could not read parameter");
01418     
01419     /* Don't allow optimal extraction. This requires that
01420        additional arguments (weight image, ..) are passed to uves_extract */
01421     temp = uves_sprintf("%s.%s", recipe_id, UVES_EXTRACT_ID);
01422     check( em = uves_get_extract_method(parameters, NULL, temp),
01423            "Could not read extraction method");
01424     
01425     check( uves_get_parameter(parameters, NULL, recipe_id, UVES_EXTRACT_ID ".profile",
01426                   CPL_TYPE_STRING, &profile), "Could not read parameter");
01427 
01428     assure( em == EXTRACT_LINEAR || em == EXTRACT_AVERAGE || em == EXTRACT_WEIGHTED ||
01429             (em == EXTRACT_OPTIMAL && strcmp(profile, "constant") == 0),
01430             CPL_ERROR_UNSUPPORTED_MODE, 
01431             "Only linear/average/weighted/optimal(constant profile) extraction "
01432             "methods are supported by this recipe");
01433     
01434     /* Search */
01435     check( uves_get_parameter(parameters, NULL, recipe_id, "search.range",
01436                   CPL_TYPE_INT   , &RANGE       ), "Could not read parameter");
01437     check( uves_get_parameter(parameters, NULL, recipe_id, "search.minlines",
01438                   CPL_TYPE_INT   , &MINLINES    ), "Could not read parameter");
01439     check( uves_get_parameter(parameters, NULL, recipe_id, "search.maxlines",
01440                   CPL_TYPE_INT   , &MAXLINES    ), "Could not read parameter");
01441 /*
01442     check( uves_get_parameter(parameters, NULL, recipe_id, "search.centeringmethod",
01443                   CPL_TYPE_STRING, &centering_m ), "Could not read parameter");
01444 */
01445     if      (strcmp(centering_m, "gravity" ) == 0) CENTERING_METHOD = CENTERING_GRAVITY;
01446     else if (strcmp(centering_m, "gaussian") == 0) CENTERING_METHOD = CENTERING_GAUSSIAN;
01447     else
01448         { 
01449         /* Impossible */ assure(false, CPL_ERROR_ILLEGAL_INPUT,
01450                     "Unrecognized parameter value '%s'", centering_m);
01451         }
01452     
01453     /* First solution */
01454     check( uves_get_parameter(parameters, NULL, recipe_id, "first.shiftmax",
01455                   CPL_TYPE_DOUBLE , &SHIFT_MAX      ),
01456            "Could not read parameter");
01457     check( uves_get_parameter(parameters, NULL, recipe_id, "first.shiftstep", 
01458                   CPL_TYPE_DOUBLE , &SHIFT_STEP     ), 
01459            "Could not read parameter");
01460     check( uves_get_parameter(parameters, NULL, recipe_id, "first.shifttoler",
01461                   CPL_TYPE_DOUBLE , &SHIFT_TOLERANCE), 
01462            "Could not read parameter");
01463     
01464     /* Identify */
01465     check( uves_get_parameter(parameters, NULL, recipe_id, "identify.alpha",
01466                   CPL_TYPE_DOUBLE , &ALPHA      ), "Could not read parameter");
01467     check( uves_get_parameter(parameters, NULL, recipe_id, "identify.maxerror",
01468                   CPL_TYPE_DOUBLE , &MAXERROR   ), "Could not read parameter");
01469     check( uves_get_parameter(parameters, NULL, recipe_id, "identify.degree",
01470                   CPL_TYPE_INT    , &DEGREE     ), "Could not read parameter");
01471     
01472     /* Calibrate */
01473     check( uves_get_parameter(parameters, NULL, recipe_id, "calibrate.tolerance",
01474                   CPL_TYPE_DOUBLE, &TOLERANCE   ), "Could not read parameter");
01475     check( uves_get_parameter(parameters, NULL, recipe_id, "calibrate.kappa",
01476                   CPL_TYPE_DOUBLE, &KAPPA   ), "Could not read parameter");
01477     
01478     /* Additional checks */
01479     if (CENTERING_METHOD == CENTERING_GRAVITY)
01480         {
01481         uves_msg_warning("Centering method 'gravity' might lead to inaccurate "
01482                  "results. Recommended is 'gaussian'");
01483         }
01484     }
01485 
01486     /* Load raw image and header, and identify input frame as red or blue */
01487     check( uves_load_arclamp(frames, flames, &arclamp_filename, arclamp, arclamp_header, 
01488                  rotated_header, &blue, &sim_cal), "Error loading raw frame");
01489 
01490     /* Load reference line table */
01491     check( uves_load_linerefertable(frames, &line_refer_filename, &line_refer, NULL),
01492        "Could not load line reference table");
01493     uves_msg("Using line reference table '%s'", line_refer_filename);
01494     
01495     /* Load INTensity MONitoring table if present */
01496     if (cpl_frameset_find(frames, UVES_LINE_INTMON_TABLE) != NULL)
01497     {
01498         uves_free_table(&line_intmon);
01499         check( uves_load_lineintmon(frames, &line_intmon_filename,
01500                     &line_intmon),
01501            "Error loading line reference table");
01502         
01503         uves_msg("Using bright line table '%s'", line_intmon_filename);
01504     }
01505   
01506     /*
01507      * Adjust parameters according to binning 
01508      */
01509     check (binx = uves_pfits_get_binx(arclamp_header[0]),
01510        "Could not read x binning factor from input header");
01511     check (biny = uves_pfits_get_biny(arclamp_header[0]),
01512        "Could not read y binning factor from input header");
01513     SLITLENGTH_par /= (1.0*binx);  /* Extraction slit length */
01514     RANGE /= (1.0*biny);           /* Search window */
01515     SHIFT_MAX /= (1.0*binx);       /* Max shift compared to guess solution */
01516     SHIFT_STEP /= (1.0*binx);
01517 
01518     /* After the default tolerance was lowered to 0.07, do not adjust it according to binning,
01519        which would cause too many lines to be rejected
01520        
01521        TOLERANCE /= (1.0*biny); 
01522     */
01523 
01524 
01525     /* Loop over one or two chips, over traces and
01526        over extraction windows */
01527     for (chip = uves_chip_get_first(blue); 
01528          chip != UVES_CHIP_INVALID; 
01529          chip = uves_chip_get_next(chip)) {
01530 
01531 
01532         if(strcmp(PROCESS_CHIP,"REDU") == 0) {
01533             chip = uves_chip_get_next(chip);
01534         }
01535       
01536         const char *ordertable_filename = "";
01537         const char *corvel_filename = "";
01538         const char *master_flat_filename = "";
01539         const char *master_bias_filename = "";
01540         const char *weights_filename = "";
01541         /* const char *drs_filename        = "";    not used */
01542         const char *guess_filename      = "";
01543         const char *chip_name = "";
01544         int ntraces;
01545         int tracerow;                       /* Index of table row */
01546         int raw_index = uves_chip_get_index(chip);
01547         int current_linetable_extension;
01548         int tab_in_out_oshift = -1;
01549         double tab_in_out_yshift = -1;
01550         double slitlength;
01551       
01552       uves_msg("Processing %s chip in '%s'",
01553                uves_chip_tostring_upper(chip), arclamp_filename);
01554       
01555       check_nomsg( chip_name = uves_pfits_get_chipid(arclamp_header[raw_index], chip));
01556       
01557       
01558       uves_msg_debug("binning = %dx%d", binx, biny);
01559       
01560       
01561       /* Load the order table for this chip */
01562       uves_free_table       (&ordertable);
01563       uves_free_propertylist(&ordertable_header);
01564       uves_polynomial_delete(&order_locations);
01565       uves_free_table       (&traces);
01566       
01567       
01568       check( uves_load_ordertable(frames, 
01569                                   flames,
01570                                   chip_name, 
01571                                   &ordertable_filename,
01572                                   &ordertable, 
01573                                   &ordertable_header,
01574                                   NULL,
01575                                   &order_locations, 
01576                                   &traces, 
01577                                   (flames) ? &tab_in_out_oshift : NULL,
01578                                   (flames) ? &tab_in_out_yshift : NULL,
01579                                   &fibres_mask, 
01580                                   &fibres_pos, /* fibre_pos,fibre_mask */
01581                                   chip, 
01582                                   false  /* load guess table? */),
01583              "Could not load order table");
01584       uves_msg("Using order table in '%s'", ordertable_filename);
01585       ntraces = cpl_table_get_nrow(traces);
01586       uves_free_double(&fibres_pos);
01587       uves_free_int(&fibres_mask);
01588       
01589       /* Load master bias if present */
01590       uves_free_image(&master_bias);
01591       uves_free_propertylist(&master_bias_header);
01592       if (cpl_frameset_find(frames, UVES_MASTER_BIAS(chip)) != NULL)
01593           {
01594               check( uves_load_mbias(frames, chip_name, &master_bias_filename, &master_bias, 
01595                                      &master_bias_header, chip),
01596                      "Error loading master bias");
01597               
01598               uves_msg_low("Using master bias in '%s'", master_bias_filename);
01599           }
01600       else
01601           {
01602               uves_msg_warning("Master bias not provided. Bias subtraction not done");
01603           }
01604       
01605       
01606       /* Load master flat if present */
01607       uves_free_image(&master_flat);
01608       uves_free_propertylist(&master_flat_header);
01609       if ((cpl_frameset_find(frames, UVES_MASTER_FLAT(chip)) != NULL ||
01610            cpl_frameset_find(frames, UVES_MASTER_DFLAT(chip)) != NULL ||
01611            cpl_frameset_find(frames, UVES_MASTER_IFLAT(chip)) != NULL ||
01612            cpl_frameset_find(frames, UVES_MASTER_TFLAT(chip)) != NULL))
01613           {
01614               check( uves_load_mflat(frames, chip_name, &master_flat_filename, &master_flat, 
01615                                      &master_flat_header, chip, NULL),
01616                      "Error loading master flat");
01617               
01618               uves_msg_low("Using master flat in '%s'", master_flat_filename);
01619           }
01620       else
01621           {
01622               uves_msg_warning("Master flat not provided. Flat-fielding not done");
01623           }
01624 
01625       /* Load weight map if present */
01626       if (em == EXTRACT_WEIGHTED) {
01627           uves_free_image(&weights);
01628           check( weights = uves_load_weights(frames, &weights_filename, chip),
01629                  "Error loading weight map");
01630 
01631           uves_msg_low("Using weight map %s", weights_filename);
01632       }
01633 
01634       if (flames)
01635           /* Load CORVEL table */
01636           {
01637              if ((corvel_frm=cpl_frameset_find(frames, FLAMES_CORVEL_MASK)))
01638                   {
01639                       check( uves_load_corvel(frames,
01640                                               &corvel, &corvel_header,
01641                                               &corvel_filename),
01642                              "Could not load velocity correction table");
01643                       
01644                       uves_msg("Using velocity correction table %s", corvel_filename);
01645                       drs_cvel_sw=true;
01646                       
01647                       
01648                   }
01649               else
01650                   {
01651                       uves_msg("No corvel table found. Switch off corvel");
01652                       corvel = NULL;
01653                   }
01654           }
01655 
01656       /* Allocate all line tables for this chip */
01657       uves_lt_delete(&linetable);
01658       linetable = uves_lt_new(NWINDOWS, ntraces);
01659 
01660 
01661       /* Init QC tables for this chip */
01662       uves_qclog_delete(&qclog[0]); qclog[0] = uves_qclog_init(arclamp_header[raw_index], chip);
01663       uves_qclog_delete(&qclog[1]); qclog[1] = uves_qclog_init(arclamp_header[raw_index], chip);
01664 
01665       /* Saving the rotated raw arc frame */
01666       if (DEBUG) check( uves_save_image_local("Arc lamp frame", "raw", 
01667                                               arclamp[raw_index], 
01668                                               chip, -1, -1, rotated_header[raw_index], true),
01669                         "Error saving arc lamp frame");
01670 
01671       if (master_bias != NULL)
01672           {
01673               uves_msg("Subtracting master bias");
01674                 
01675               check( uves_subtract_bias(arclamp[raw_index], master_bias),
01676                      "Error during bias subtraction");
01677           }
01678       else {
01679           /* In lack of a real master bias frame, one might subtract the bias by estimating it
01680              as the median value across the chip (which should be okay for arc lamp frames)
01681           */
01682             
01683           /* Disabled. Would need to be tested. probably doesn't make any big difference anyway
01684              double bias = cpl_image_get_median(ff);
01685              uves_msg_debug("Estimated bias level is %f ADU", bias);
01686              cpl_image_subtract_scalar(ff, bias);
01687           */
01688       }
01689 
01690 
01691       /* Define arc lamp noise */
01692       uves_free_image(&arclamp_noise);
01693       check( arclamp_noise = uves_define_noise(arclamp[raw_index], 
01694                                                arclamp_header[raw_index], 1, chip),
01695              "Could not set arc lamp noise");
01696 
01697       if (master_flat != NULL)
01698           {
01699               uves_msg("Dividing by master flat");
01700                 
01701               uves_free_image(&mflat_noise);
01702               check( mflat_noise = 
01703                      uves_define_noise(master_flat, master_flat_header, 
01704                                        uves_pfits_get_datancom(master_flat_header),
01705                                        chip),
01706                      "Could not set master flat error bars");
01707                 
01708               check( uves_flatfielding(arclamp[raw_index], arclamp_noise,
01709                                        master_flat, mflat_noise),
01710                      "Error while dividing by flat field");
01711           }
01712 
01713       if (DEBUG) check( uves_save_image_local("Pre-processed arc lamp frame",
01714                                               "preproc", 
01715                                               arclamp[raw_index], chip, -1, -1,
01716                                               rotated_header[raw_index], true),
01717                         "Error saving arc lamp frame");
01718 
01719       /* Set appropriate slitlength if user did not */
01720       if (SLITLENGTH_par < 0) {
01721             
01722           double header_full_slit;
01723             
01724           check( header_full_slit = 
01725                  uves_pfits_get_slitlength_pixels(arclamp_header[raw_index], chip),
01726                  "Could not read slit length");
01727             
01728           /* Avoid pixels at the edge of the slit
01729            *  which are likely to be noisy 
01730            */
01731           slitlength = uves_max_double(1.0, (header_full_slit - 2)/NWINDOWS);
01732 
01733           uves_msg("Full slit = %.2f pixels", header_full_slit);
01734       }
01735       else {
01736           slitlength = SLITLENGTH_par;
01737       }
01738                 
01739    
01740       /* Loop over traces */
01741       for(tracerow = 0; tracerow < ntraces; tracerow++) {
01742         double trace_offset;
01743         int trace_number;
01744         int trace_enabled;
01745         
01746         trace_offset  = cpl_table_get_double(traces, "Offset"   , tracerow, NULL);
01747         trace_number  = cpl_table_get_int   (traces, "TraceID"  , tracerow, NULL);
01748         trace_enabled = cpl_table_get_int   (traces, "Tracemask", tracerow, NULL);
01749 
01750             if (ntraces > 1) {
01751                 uves_msg("Processing trace %d", trace_number);
01752             }
01753 
01754         if (flames && sim_cal) 
01755         {
01756             /* Only calibrate SIMCAL fibre in SIMCAL mode */
01757             trace_enabled = (trace_number == 1) ? 1 : 0;
01758         }
01759 
01760         uves_msg_low("Trace offset = %.2f pixels ; enabled = %d",
01761              trace_offset, trace_enabled);
01762         
01763         assure( flames || trace_number == 0, CPL_ERROR_ILLEGAL_INPUT,
01764             "%s: UVES trace number must be 0, it is %d", 
01765             ordertable_filename, trace_number );
01766         
01767         
01768         if (trace_enabled != 0) {
01769         int window;          /* window number */
01770 
01771         /* Load guess line table for this trace, any window */
01772         uves_free_table       (&guess);
01773         uves_polynomial_delete(&absolute_order);
01774 
01775         check( uves_load_linetable(
01776                frames, flames, chip_name, order_locations,
01777                cpl_table_get_column_min(ordertable, "Order"),
01778                cpl_table_get_column_max(ordertable, "Order"),
01779                &guess_filename, &guess, 
01780                NULL, NULL,
01781                &absolute_order, chip, trace_number, -1),
01782                "Could not load guess line table for trace number %d", 
01783                trace_number);
01784         uves_msg("Using guess line table '%s'", guess_filename);
01785  
01786         if (DEBUG)
01787             {
01788             /* Create an image showing the polynomial   m = f(x,y)
01789                where m is the absolute order number
01790             */
01791             int x, y;
01792 
01793             absorder_image = cpl_image_new(cpl_image_get_size_x(arclamp[raw_index]),
01794                                cpl_image_get_size_y(arclamp[raw_index]),
01795                                CPL_TYPE_FLOAT);
01796             assure_mem(absorder_image);
01797             
01798             for (y = 1; y <= cpl_image_get_size_y(arclamp[raw_index]); y++)
01799                 {
01800                 for (x = 1; x <= cpl_image_get_size_x(arclamp[raw_index]); x++)
01801                     {
01802                     double absorder = 
01803                         uves_polynomial_evaluate_2d(absolute_order, x, y);
01804                     
01805                     cpl_image_set(absorder_image, x, y, absorder);
01806                     }
01807                 }
01808             
01809             check( uves_save_image_local("Absolute order image", "absord",
01810                              absorder_image, chip, trace_number,
01811                              1, rotated_header[raw_index], true),
01812                    "Error saving absolute order image");
01813             
01814             uves_free_image(&absorder_image);
01815             }
01816 
01817         /* Loop over sky windows */
01818         for (window = 1; window <= NWINDOWS; window ++) {
01819             /*      
01820                 | -trace_offs- | 
01821                 |              |  -win_offs-  |
01822                 |              |              |
01823                 |              | | -glb_offs- | 
01824                         order_loc.=0       |
01825                 |
01826                 window_loc.
01827             */
01828                 
01829             /* Adjacent windows are separated by slitlength,
01830                and offset is zero when window_number = (NWINDOWS+1)/2,
01831                so the formula is */
01832             double window_offset =
01833             slitlength * (window - (NWINDOWS+1) / 2.0);
01834 
01835             /* Total offset (see sketch) */
01836             double offset = trace_offset + window_offset + OFFSET;
01837 
01838             /* Number of lines to detect. Use defaults if 
01839                parameter values are negative */
01840 #if 0
01841             int lines_min = (MINLINES >= 1) ? MINLINES : 
01842             (chip == UVES_CHIP_REDU) ? 1000 : 2000;
01843             int lines_max = (MAXLINES >= 1) ? MAXLINES : 
01844             (chip == UVES_CHIP_REDU) ? 1400 : 2400;
01845 #else
01846 /* like MIDAS (fewer lines): */
01847             int lines_min = (MINLINES >= 1) ? MINLINES : 
01848             (chip == UVES_CHIP_REDU) ? 1000 : 1100;
01849             int lines_max = (MAXLINES >= 1) ? MAXLINES : 
01850             (chip == UVES_CHIP_REDU) ? 1400 : 1600;
01851 #endif
01852 
01853             assure( lines_min <= lines_max , CPL_ERROR_ILLEGAL_INPUT, 
01854                 "Minimum and maximum number of requested line "
01855                 "detections don't make sense (min = %d; max = %d)",
01856                 lines_min, lines_max);
01857 
01858             if (NWINDOWS > 1) {
01859                 uves_msg("Processing window %d of %d", window, NWINDOWS);
01860             }
01861                     
01862             passure( *(uves_lt_get_disprel(linetable, window, trace_number))
01863                  == NULL, "%d %d", window, trace_number);
01864             passure( *(uves_lt_get_absord (linetable, window, trace_number))
01865                  == NULL, "%d %d", window, trace_number);
01866 
01867 
01868             if (weights != NULL) {
01869                 /* Object weighted extraction, use offset = 0 three times */
01870                 offset = 0;
01871             }
01872                     
01873             /* Set absord guess solution */
01874             *uves_lt_get_absord(linetable, window, trace_number) = 
01875             uves_polynomial_duplicate(absolute_order);
01876 
01877             /* Execute macrosteps */
01878             check( *uves_lt_get_table(linetable, window, trace_number) =
01879                    uves_wavecal_process_window(
01880                        /* Raw */
01881                        arclamp[raw_index], 
01882                        arclamp_noise,
01883                        rotated_header[raw_index],
01884                        /* Calibration */
01885                        ordertable, order_locations,
01886                        master_flat != NULL,
01887                        weights,
01888                        /* drs_table,  not used */
01889                        guess,
01890                        line_refer,
01891                        flames,
01892                        tab_in_out_oshift,
01893                        tab_in_out_yshift,
01894                    /* Which window? */
01895                        chip, biny, trace_number, window,NWINDOWS,
01896                    /* Parameters    */
01897                    DEBUG,
01898                    /* Extract       */
01899                    offset, slitlength, parameters, recipe_id,
01900                    /* Search        */
01901                    RANGE, lines_min, lines_max, CENTERING_METHOD,
01902                    /* First solution */
01903                    SHIFT_MAX, SHIFT_STEP, SHIFT_TOLERANCE,
01904                    /* Identify      */
01905                    ALPHA, MAXERROR, DEGREE,
01906                    /* Calibrate     */
01907                TOLERANCE, KAPPA,
01908                        corvel_frm,qclog,
01909                    /* Returned */
01910                    uves_lt_get_disprel(linetable, window, trace_number),
01911                    uves_lt_get_absord (linetable, window, trace_number),
01912                    uves_lt_get_firstabs(linetable, window, trace_number),
01913                    uves_lt_get_lastabs(linetable, window, trace_number)),
01914                "Wavelength calibration failed");
01915 
01916 
01917             //If CORVEL map is provided we perform the 
01918                     //corresponding analysis
01919             if(drs_cvel_sw) {
01920               /*
01921               define/local ord_min/i/1/1 0
01922               define/local ord_max/i/1/1 0
01923               define/local rsample/d/1/1 0
01924               statistic/table {ORDTAB} :ORDER >Null
01925               ord_min = outputr(1)
01926               ord_max = outputr(2)
01927               rsample = {{LINTAB},PIXEL(1)}
01928               rsample = 2./3. * rsample
01929               rebin/echelle  {ofrm} w{ofrm} {rsample} NONL {LINTAB} {SESSOUTV}
01930               mercut/echelle w{ofrm} mw{ofrm} {ord_min},{ord_max} NOAPPEND 
01931               !corvel stuff
01932               define/local OLD_CVEL_MAX/d/1/1 {DRS_CVEL_MAX}
01933               define/local OLD_CVEL_MIN/d/1/1 {DRS_CVEL_MIN}
01934               @p flames_reduce,VCORREL x1_rbf_ cvel1 0 {ord_max} {parCorVelTab} _0 _{chip({PATHID})} 0
01935               DRS_CVEL_MAX = DRS_CVEL_MAX + {q1}
01936               DRS_CVEL_MIN = DRS_CVEL_MIN + {q1}
01937 
01938               @p flames_reduce,VCORREL x1_rbf_ cvel2 0 {ord_max} {parCorVelTab} _0 _{chip({PATHID})} 0
01939               cvel_0 = {q1}
01940               DRS_CVEL_MAX = OLD_CVEL_MAX
01941               DRS_CVEL_MIN = OLD_CVEL_MIN
01942               */
01943 
01944 
01945             }
01946 
01947 
01948 
01949             if (flames ||                             /* FLAMES: all fibres */
01950             (window == 2 && trace_number == 0)|| /* UVES: central window */
01951             (window == 1 && NWINDOWS == 1)) { /* UVES: special user setting */
01952 
01953             check( uves_wavecal_qclog(
01954                    *uves_lt_get_table(
01955                        linetable,
01956                        window,
01957                        trace_number),
01958                                    *uves_lt_get_firstabs(linetable, window, trace_number),
01959                                    *uves_lt_get_lastabs(linetable, window, trace_number),
01960                    arclamp[raw_index], 
01961                    arclamp_header[raw_index],
01962                    flames, 
01963                    trace_number, trace_enabled, trace_offset,
01964                    chip,
01965                                    qclog[0]),
01966                    "Could not calculate resolution QC parameters");
01967 
01968             if (line_intmon != NULL) {
01969                 check( uves_wavecal_qclog_intmon(
01970                        *uves_lt_get_table(
01971                        linetable,
01972                        window,
01973                        trace_number), 
01974                        line_intmon,
01975                        arclamp_header[raw_index],
01976                        flames, trace_number,
01977                        chip,
01978                        qclog[1]),
01979                    "Could not calculate int.mon. QC parameters");
01980             }
01981             else
01982                 {
01983                 /* Kill initialization and set pointer to NULL */
01984                 uves_qclog_delete(&qclog[1]);
01985                 }
01986             }
01987                     
01988             /* Finished processing. Save later (because
01989                all QC parameters must be available
01990                when the product file is first created). */
01991 
01992         }/* for each window... */
01993             
01994         }/* if trace enabled? */
01995         else
01996         {
01997             uves_msg("Skipping trace number %d", trace_number);
01998         }
01999     }/* for each trace... */
02000 
02001     /* Finished calculating all line tables for current chip. Now save. */
02002 
02003     /* Prepare product filename 
02004        (which need not be calculated for each trace and window) */
02005     cpl_free(product_filename);
02006     check( product_filename = uves_line_table_filename(chip), "Error getting filename");
02007     current_linetable_extension = 1;
02008         
02009     /* Loop over traces */
02010     for(tracerow = 0; tracerow < cpl_table_get_nrow(traces); tracerow++)
02011         {
02012         int trace_number;
02013         double trace_offset;
02014         int trace_enabled;
02015             
02016         trace_offset  = cpl_table_get_double(traces, "Offset"    , tracerow, NULL);
02017         trace_number  = cpl_table_get_int   (traces, "TraceID"   , tracerow, NULL);
02018         trace_enabled = cpl_table_get_int   (traces, "Tracemask" , tracerow, NULL);
02019             
02020         if (trace_enabled != 0)
02021                     {
02022             int window;
02023                 
02024             /* Loop over sky windows */
02025             for (window = 1; window <= NWINDOWS; window ++)
02026                 {
02027                 double window_offset =
02028                     slitlength * (window - (NWINDOWS+1) / 2.0);
02029             
02030                 double offset = trace_offset + window_offset + OFFSET;
02031         
02032                 /* Table header */
02033                 uves_free_propertylist(&table_header);
02034                 table_header   = uves_propertylist_new();
02035                 check( uves_pfits_set_traceid     ( table_header, trace_number),
02036                        "Error writing trace ID to product header");
02037                 check( uves_pfits_set_offset      ( table_header, offset),
02038                        "Error writing trace offset to product header");
02039                 check( uves_pfits_set_windownumber( table_header, window),
02040                        "Error writing window number to product header");
02041                 check( uves_pfits_set_firstabsorder( table_header, 
02042                                      *uves_lt_get_firstabs(
02043                                      linetable, 
02044                                      window,
02045                                      trace_number)),
02046                        "Error writing order number to product header");
02047                 check( uves_pfits_set_lastabsorder( table_header,
02048                                     *uves_lt_get_lastabs(
02049                                     linetable, 
02050                                     window,
02051                                     trace_number)),
02052                        "Error writing order number to product header");
02053 
02054                 /* Save line table + 2 polynomials (in 3 extensions) */
02055 
02056                 if (current_linetable_extension == 1) {
02057                     uves_free_propertylist(&primary_header);
02058                     primary_header = uves_propertylist_new();
02059                     
02060                     if (flames)
02061               {
02062             char values[80];
02063             /* The MIDAS pipeline writes this QC to the
02064                header (always zero), but not as part of
02065                the QC logging */
02066             check_nomsg( uves_flames_pfits_set_ccfposmax(
02067                                      primary_header, 0.0) );
02068             //Add descriptors needed for science reduction
02069             /* FIBREMASK */
02070 
02071             uves_propertylist_append_string(primary_header, 
02072                             "HISTORY", 
02073                             "'FIBREMASK','I*4'");
02074 
02075             {
02076               int i;
02077               for (i = 0; i < N_FIBRES_MAX; i++) {
02078                 snprintf(values, 80, "%1.1d ",
02079                      cpl_table_get_int(traces,"Tracemask",
02080                                i,NULL));
02081                 uves_propertylist_append_string(primary_header,
02082                                 "HISTORY", values);
02083                 uves_msg_debug("value=%d",
02084                          cpl_table_get_int(traces,
02085                                    "Tracemask",
02086                                    i,NULL));
02087               }
02088             }
02089             uves_propertylist_append_string(primary_header,
02090                             "HISTORY", " ");
02091 
02092 
02093             /* PIXEL */        
02094                         double pixelsize;
02095                         double wavestep;
02096 
02097             check( pixelsize = 
02098                    cpl_table_get_column_mean(
02099                              *uves_lt_get_table(
02100                                         linetable,
02101                                         window,
02102                                         trace_number),
02103                              LINETAB_PIXELSIZE),
02104                    "Error reading mean pixelsize");
02105             uves_msg_warning("Average pixelsize = %f w.l.u.", 
02106                        pixelsize);
02107 
02108             wavestep = pixelsize*2.0/3;
02109 
02110             uves_propertylist_append_string(primary_header, 
02111                             "HISTORY", 
02112                             "'PIXEL','R*4'");
02113             snprintf(values,80,"%14.7g %14.7g",pixelsize,pixelsize);
02114             uves_propertylist_append_string(primary_header,
02115                             "HISTORY", values);
02116             uves_propertylist_append_string(primary_header,
02117                             "HISTORY", " ");
02118                       
02119 
02120 
02121               }
02122                     
02123                     uves_msg("Creating line table '%s'", product_filename);
02124                     check( uves_frameset_insert(
02125                            frames,
02126                            *uves_lt_get_table(
02127                                linetable,
02128                                window,
02129                                trace_number),
02130                            CPL_FRAME_GROUP_PRODUCT,
02131                            CPL_FRAME_TYPE_TABLE,
02132                            CPL_FRAME_LEVEL_INTERMEDIATE,
02133                            product_filename,
02134                            UVES_LINE_TABLE(flames, chip),
02135                            arclamp_header[raw_index],     
02136                            primary_header,
02137                            table_header,
02138                            parameters,
02139                            recipe_id,
02140                            PACKAGE "/" PACKAGE_VERSION,
02141                            qclog, starttime, true, 0),
02142                            "Could not add line table '%s' (%s) to frameset",
02143                            product_filename, UVES_LINE_TABLE(flames, chip));
02144                         
02145                     uves_msg("Line table '%s' (%s) added to frameset",
02146                          product_filename, UVES_LINE_TABLE(flames, chip));
02147                     }
02148                 else   /* If this is not the first line table, 
02149                       append to the existing file */
02150                     {
02151                     check( uves_table_save(
02152                            *uves_lt_get_table(linetable,
02153                                       window,
02154                                       trace_number),
02155                            NULL,            /* Primary header,
02156                                        ignored when mode
02157                                        is IO_EXTEND */
02158                            table_header,    /* Extension header */
02159                            product_filename,/* This file 
02160                                        already exists */
02161                            CPL_IO_EXTEND),   /* Append to
02162                                     existing file */
02163                            "Error appending table to file '%s'", 
02164                            product_filename);
02165                     }
02166                 current_linetable_extension += 1;
02167                 
02168                 /* Save in next extension */
02169                 check( uves_save_polynomial(*uves_lt_get_disprel(
02170                                 linetable, 
02171                                 window,
02172                                 trace_number),
02173                                 product_filename,
02174                                 table_header), 
02175                        "Could not write polynomial to file '%s'", 
02176                        product_filename);
02177                 current_linetable_extension += 1;
02178 
02179                 /* Save in next extension */
02180                 check( uves_save_polynomial(*uves_lt_get_absord(
02181                                 linetable, 
02182                                 window,
02183                                 trace_number), 
02184                                 product_filename,
02185                                 table_header), 
02186                        "Could not write polynomial to file '%s'", 
02187                        product_filename);
02188                 current_linetable_extension += 1;
02189 
02190                 uves_msg("Line table for trace %d, window #%d "
02191                      "saved to extensions %d-%d of '%s'",
02192                      trace_number, window, 
02193                      current_linetable_extension - 3,
02194                      current_linetable_extension - 1, 
02195                      product_filename);
02196 
02197                 } /* for each window */
02198             } /* if trace enabled */
02199         } /* for each trace */
02200 
02201       if(strcmp(PROCESS_CHIP,"REDL") == 0) {
02202     chip = uves_chip_get_next(chip);
02203       }
02204 
02205 
02206     }/* For each chip */
02207 
02208   cleanup:
02209 
02210     /* Input */
02211     uves_free_image(&arclamp[0]);
02212     uves_free_image(&arclamp[1]);
02213     uves_free_image(&arclamp_noise);
02214     uves_free_image(&absorder_image);
02215     uves_free_propertylist(&arclamp_header[0]);
02216     uves_free_propertylist(&arclamp_header[1]);
02217     uves_free_propertylist(&rotated_header[0]);
02218     uves_free_propertylist(&rotated_header[1]);
02219 
02220 
02221     uves_free_table(&ordertable);
02222     uves_free_propertylist(&ordertable_header);
02223     uves_free_table(&corvel);
02224     uves_free_propertylist(&corvel_header);
02225     uves_polynomial_delete(&order_locations);
02226     uves_polynomial_delete(&absolute_order);
02227     uves_free_table(&traces);
02228 
02229     
02230     uves_free_image(&master_bias);
02231     uves_free_propertylist(&master_bias_header);
02232     uves_free_image(&master_flat);
02233     uves_free_image(&mflat_noise);
02234     uves_free_propertylist(&master_flat_header);
02235     uves_free_image(&weights);
02236 
02237     
02238     /* DRS not used
02239        uves_free_table(&drs_table);
02240        uves_free_propertylist(&drs_header);
02241     */
02242     
02243     uves_free_table(&guess);
02244 
02245     uves_free_table(&line_refer);
02246     uves_free_table(&line_intmon);
02247 
02248 
02249     /* Output */
02250     uves_lt_delete(&linetable);
02251     uves_free_propertylist(&primary_header);
02252     uves_free_propertylist(&table_header);
02253     uves_qclog_delete(&qclog[0]);
02254     uves_qclog_delete(&qclog[1]);
02255 
02256     cpl_free(product_filename);
02257     cpl_free(temp);
02258      
02259     return;
02260 }
02261 
02262 
02275 static void uves_wavecal_qclog(const cpl_table* linetable,
02276                                int firstabs,
02277                                int lastabs,
02278                    const cpl_image *arclamp,
02279                    const uves_propertylist* raw_header,
02280                    bool flames,
02281                    int trace_number,
02282                    int fibre_mask,
02283                    double offset,
02284                    enum uves_chip chip,
02285                    cpl_table* qclog)
02286 {
02287 
02288     const char *qc_fib_drsno_name= uves_qclog_get_qc_name("DRSNO", flames, trace_number);
02289     const char *qc_fib_seq_name  = uves_qclog_get_qc_name("SEQ", flames, trace_number);
02290     const char *qc_fib_pos_name  = uves_qclog_get_qc_name("POS", flames, trace_number);
02291     const char *qc_fib_msk_name  = uves_qclog_get_qc_name("MSK", flames, trace_number);
02292     const char *qc_fwhmavg_name  = uves_qclog_get_qc_name("FWHMAVG", flames, trace_number);
02293     const char *qc_fwhmrms_name  = uves_qclog_get_qc_name("FWHMRMS", flames, trace_number);
02294     const char *qc_fwhmmed_name  = uves_qclog_get_qc_name("FWHMMED", flames, trace_number);
02295     const char *qc_resolavg_name = uves_qclog_get_qc_name("RESOLAVG", flames, trace_number);
02296     const char *qc_resolrms_name = uves_qclog_get_qc_name("RESOLRMS", flames, trace_number);
02297     const char *qc_resolmed_name = uves_qclog_get_qc_name("RESOLMED", flames, trace_number);
02298     const char *qc_wlenmin_name  = uves_qclog_get_qc_name("WLENMIN", flames, trace_number);
02299     const char *qc_wlenmax_name  = uves_qclog_get_qc_name("WLENMAX", flames, trace_number);
02300     const char *qc_ordmin_name   = uves_qclog_get_qc_name("ORDMIN", flames, trace_number);
02301     const char *qc_ordmax_name   = uves_qclog_get_qc_name("ORDMAX", flames, trace_number);
02302     const char *qc_detected_ordmin_name   = uves_qclog_get_qc_name("ORDMIN DETECTED", flames, trace_number);
02303     const char *qc_detected_ordmax_name   = uves_qclog_get_qc_name("ORDMAX DETECTED", flames, trace_number);
02304     const char *qc_nlintot_name  = uves_qclog_get_qc_name("NLINTOT", flames, trace_number);
02305     const char *qc_nlinsel_name  = uves_qclog_get_qc_name("NLINSEL", flames, trace_number);
02306     const char *qc_nlinsol_name  = uves_qclog_get_qc_name("NLINSOL", flames, trace_number);
02307     const char *qc_line_werr_name  = uves_qclog_get_qc_name("LINE WAVEERR", flames, trace_number);
02308     const char *qc_line_wsys_name  = uves_qclog_get_qc_name("LINE SYSERR", flames, trace_number);
02309     const char *qc_nlinres1_name = uves_qclog_get_qc_name("NLINRES1", flames, trace_number);
02310     const char *qc_lineresidavg_name = 
02311     uves_qclog_get_qc_name("LINE RESIDAVG", flames, trace_number);
02312     const char *qc_lineresidrms_name = 
02313     uves_qclog_get_qc_name("LINE RESIDRMS", flames, trace_number);
02314     char comment[80];
02315     cpl_table *selected = NULL;
02316     double wmin=0;
02317     double wmax=0;
02318     double wcen=0;
02319     int nfinal=0;
02320 
02321     char test_id[80];
02322     sprintf(test_id,"%sResolution-Test-Results",flames ? "Fibre-" : "");
02323 
02324     check_nomsg(uves_qclog_add_string(qclog,
02325                       "QC TEST1 ID",
02326                       test_id,
02327                       "Name of QC test",
02328                       "%s"));
02329 
02330     check_nomsg( uves_qclog_add_common_wave(raw_header, chip, qclog) );
02331 
02332     if (flames)
02333     {
02334         /* Fibre ID */
02335         check_nomsg(uves_qclog_add_int(qclog,
02336                        qc_fib_drsno_name,
02337                        trace_number + 1,
02338                        "DRS det. fibre seq. pos.",
02339                        "%d"));
02340         
02341         /* Index */
02342         check_nomsg(uves_qclog_add_int(qclog,
02343                        qc_fib_seq_name,
02344                        trace_number + 1,
02345                        "det. fibre seq. no.",
02346                        "%d"));
02347 
02348         check_nomsg(uves_qclog_add_double(qclog,
02349                           qc_fib_pos_name,
02350                           offset,
02351                           "det. fibre seq. rel. pos.",
02352                           "%.4f"));
02353 
02354         check_nomsg(uves_qclog_add_int(qclog,
02355                        qc_fib_msk_name,
02356                        fibre_mask,
02357                        "DRS det. fibre mask value",
02358                        "%d"));
02359 
02360         {
02361 
02362         double exptime;
02363       
02364         check( exptime = uves_flames_pfits_get_dit(raw_header),
02365                "Error reading exposure time");
02366       
02367         check_nomsg(uves_qclog_add_double(qclog,
02368                           "QC FIB ABSTRANS",
02369                           cpl_image_get_flux(arclamp) / exptime,
02370                           "abs. trans. countrate",
02371                           "%.4f"));
02372         }
02373         {
02374         int n_hpix;
02375         int x, y;
02376       
02377         n_hpix = 0;
02378         for (y = 1; y <= cpl_image_get_size_y(arclamp); y++)
02379             for (x = 1; x <= cpl_image_get_size_x(arclamp); x++)
02380             {
02381                 int pis_rejected;
02382                 int value = cpl_image_get(arclamp, x, y, &pis_rejected);
02383           
02384                 if (!pis_rejected &&
02385                 (value < DRS_PTHRES_MIN || value > DRS_PTHRES_MAX))
02386                 {
02387                     n_hpix += 1;
02388                 }
02389             }
02390 
02391         check_nomsg(uves_qclog_add_int(qclog,
02392                            "QC NHOTPIX",
02393                            n_hpix,
02394                            "no. of hot pixels",
02395                            "%d"));
02396       
02397         }
02398   
02399         {
02400         int plate_id;
02401         check( plate_id = uves_flames_pfits_get_plateid(raw_header),
02402                "Error reading plate ID");
02403         check_nomsg(uves_qclog_add_int(qclog,
02404                            "QC PLATENO",
02405                            plate_id,
02406                            "Plate Id.",
02407                            "%d"));
02408         }
02409 
02410     } /* if flames */
02411 
02412     /* FLAMES + UVES common QC params */
02413     selected = uves_extract_table_rows(linetable, "NLinSol", CPL_NOT_EQUAL_TO, 0);
02414     /* FWHM in pixels */
02415     sprintf(comment,"average FWHM in X of sel lines on TRACE%d WIN2 [pix]",trace_number);
02416     check_nomsg(uves_qclog_add_double(qclog,
02417                       qc_fwhmavg_name,
02418                       cpl_table_get_column_mean(selected,"Xwidth")*TWOSQRT2LN2,
02419                       comment,
02420                       "%.2f"));
02421 
02422     sprintf(comment,"stdev FWHM in X of sel lines on TRACE%d WIN2 [pix]",trace_number);
02423     check_nomsg(uves_qclog_add_double(qclog,
02424                       qc_fwhmrms_name,
02425                       cpl_table_get_column_stdev(selected,"Xwidth")*TWOSQRT2LN2,
02426                       comment,
02427                       "%.4f"));
02428 
02429     sprintf(comment,"median FWHM in X of sel lines on TRACE%d WIN2 [pix]",trace_number);
02430     check_nomsg(uves_qclog_add_double(qclog,
02431                       qc_fwhmmed_name,
02432                       cpl_table_get_column_median(selected,"Xwidth")*TWOSQRT2LN2,
02433                       comment,
02434                       "%.4f"));
02435    
02436     sprintf(comment,"mean R of sel lines on TRACE%d WIN2",trace_number);
02437     check_nomsg(uves_qclog_add_double(qclog,
02438                       qc_resolavg_name,
02439                       cpl_table_get_column_mean(selected,"Resol"),
02440                       comment,
02441                       "%.4f"));
02442 
02443     sprintf(comment,"stdev R of sel lines on TRACE%d WIN2",trace_number);
02444     check_nomsg(uves_qclog_add_double(qclog,
02445                       qc_resolrms_name,
02446                       cpl_table_get_column_stdev(selected,"Resol"),
02447                       comment,
02448                       "%.4f"));
02449 
02450     sprintf(comment,"median R of sel lines on TRACE%d WIN2",trace_number);
02451     check_nomsg(uves_qclog_add_double(qclog,
02452                       qc_resolmed_name,
02453                       cpl_table_get_column_median(selected,"Resol"),
02454                       comment,
02455                       "%.4f"));
02456 
02457     /* Convert A -> picometers */
02458     sprintf(comment,"mean line pos resid on TRACE%d WIN2 [pm]",trace_number);
02459     check_nomsg(uves_qclog_add_double(qclog,
02460                       qc_lineresidavg_name,
02461                       cpl_table_get_column_mean(selected, LINETAB_RESIDUAL)*100,
02462                       comment,
02463                       "%.4f"));
02464 
02465     sprintf(comment,"sigma line pos resid on TRACE%d WIN2 [pm]",trace_number);
02466     check_nomsg(uves_qclog_add_double(qclog,
02467                       qc_lineresidrms_name,
02468                       cpl_table_get_column_stdev(selected, LINETAB_RESIDUAL)*100,
02469                       comment,
02470                       "%.4f"));
02471 
02472     /* Convert A -> nm */
02473     wmin=cpl_table_get_column_min(linetable,LINETAB_LAMBDAC)/10.0;
02474     sprintf(comment,"minimum wavelength on TRACE%d WIN2 [nm]",trace_number);
02475     check_nomsg(uves_qclog_add_double(qclog,
02476                       qc_wlenmin_name,
02477                       wmin,
02478                       comment,
02479                       "%.4f"));
02480 
02481     wmax=cpl_table_get_column_max(linetable,LINETAB_LAMBDAC)/10.0;
02482     sprintf(comment,"maximum wavelength on TRACE%d WIN2 [nm]",trace_number);
02483     check_nomsg(uves_qclog_add_double(qclog,
02484                       qc_wlenmax_name,
02485                       wmax,
02486                       comment,
02487                       "%.4f"));
02488 
02489     sprintf(comment,"minimum order number expected on TRACE%d WIN2",trace_number);
02490     check_nomsg(uves_qclog_add_int(qclog,
02491                    qc_ordmin_name,
02492                    uves_min_int(firstabs, lastabs),
02493                    comment,
02494                    "%d"));
02495 
02496     sprintf(comment,"maximum order number expected on TRACE%d WIN2",trace_number);
02497     check_nomsg(uves_qclog_add_int(qclog,
02498                    qc_ordmax_name,
02499                    uves_max_int(firstabs, lastabs),
02500                    comment,
02501                    "%d"));
02502 
02503 
02504     sprintf(comment,"minimum order number detected on TRACE%d WIN2",trace_number);
02505     check_nomsg(uves_qclog_add_int(qclog,
02506                    qc_detected_ordmin_name,
02507                    cpl_table_get_column_min(linetable,"Order"),
02508                    comment,
02509                    "%d"));
02510 
02511     sprintf(comment,"maximum order number detected on TRACE%d WIN2",trace_number);
02512     check_nomsg(uves_qclog_add_int(qclog,
02513                    qc_detected_ordmax_name,
02514                    cpl_table_get_column_max(linetable,"Order"),
02515                    comment,
02516                    "%d"));
02517 
02518     sprintf(comment,"No. of lines found on TRACE%d WIN2",trace_number);
02519     check_nomsg(uves_qclog_add_int(qclog,
02520                    qc_nlintot_name,
02521                    cpl_table_get_nrow(linetable),
02522                    comment,
02523                    "%d"));
02524 
02525     sprintf(comment,"No. of lines selected on TRACE%d WIN2",trace_number);
02526     check_nomsg(uves_qclog_add_int(qclog,
02527                    qc_nlinsel_name,
02528                    cpl_table_get_nrow(linetable) -
02529                                    cpl_table_count_invalid(linetable, "Ident"),
02530                    comment,
02531                    "%d"));
02532 
02533     nfinal=cpl_table_get_nrow(selected);
02534     sprintf(comment,"Final No. of lines used on TRACE%d WIN2",trace_number);
02535     check_nomsg(uves_qclog_add_int(qclog,
02536                    qc_nlinsol_name,
02537                    nfinal,
02538                    comment,
02539                    "%d"));
02540 
02541     cpl_table* extracted=NULL;
02542     double rms_wlu=0;
02543     const char* rms_wlu_alpha=NULL;
02544     double lines_sqrt=0;
02545     double lines_werr=0;
02546     int next=0;
02547     wcen=0.5*(wmin+wmax);
02548     check_nomsg(next=cpl_table_and_selected_string(qclog,"key_name",
02549                                                    CPL_EQUAL_TO,
02550                                                    "QC LINE RESIDRMS WLU"));
02551     check_nomsg(extracted=cpl_table_extract_selected(qclog));
02552   
02553     check_nomsg(rms_wlu_alpha=cpl_table_get_string(extracted,"key_value",0));
02554     rms_wlu=atof(rms_wlu_alpha);
02555     lines_sqrt=sqrt(nfinal);
02556     lines_werr=rms_wlu/lines_sqrt;
02557     sprintf(comment,"Wavelength error on TRACE%d [Ang]",trace_number);
02558     check_nomsg(uves_qclog_add_double(qclog,
02559                                    qc_line_werr_name,
02560                                    lines_werr,
02561                                    comment,
02562                                    "%.3g"));
02563 
02564     uves_free_table(&extracted);
02565     uves_free_table(&selected);
02566     selected = cpl_table_duplicate(linetable);
02567     assure_mem( selected );
02568 
02569 
02570     sprintf(comment,"Wavelength systematic error on TRACE%d [Ang]",trace_number);
02571     check_nomsg(uves_qclog_add_double(qclog,
02572                                    qc_line_wsys_name,
02573                                    wcen*100./SPEED_OF_LIGHT,
02574                                    comment,
02575                                    "%f"));
02576 
02577 
02578     /* Remove unidentified lines and
02579        lines with residual > 1 A      */
02580     check_nomsg( uves_erase_invalid_table_rows(selected, "Ident") );
02581     check_nomsg( uves_erase_table_rows(selected, LINETAB_RESIDUAL, 
02582                        CPL_NOT_LESS_THAN,
02583                        1.0) );
02584   
02585     sprintf(comment,"No. of lines with residuals < 0.1 nm on TRACE%d",trace_number);
02586     check_nomsg(uves_qclog_add_int(qclog,
02587                    qc_nlinres1_name,
02588                    cpl_table_get_nrow(selected),
02589                    comment,
02590                    "%d"));
02591 
02592 
02593   cleanup:
02594 
02595     uves_free_string_const(&qc_fib_drsno_name);
02596     uves_free_string_const(&qc_fib_seq_name);
02597     uves_free_string_const(&qc_fib_pos_name);
02598     uves_free_string_const(&qc_fib_msk_name);
02599     uves_free_string_const(&qc_fwhmavg_name);
02600     uves_free_string_const(&qc_fwhmrms_name);
02601     uves_free_string_const(&qc_fwhmmed_name);
02602 
02603     uves_free_string_const(&qc_resolavg_name);
02604     uves_free_string_const(&qc_resolrms_name);
02605     uves_free_string_const(&qc_resolmed_name);
02606     uves_free_string_const(&qc_wlenmin_name);
02607     uves_free_string_const(&qc_wlenmax_name);
02608     uves_free_string_const(&qc_ordmin_name);
02609     uves_free_string_const(&qc_ordmax_name);
02610     uves_free_string_const(&qc_nlintot_name);
02611     uves_free_string_const(&qc_nlinsel_name);
02612     uves_free_string_const(&qc_line_werr_name);
02613     uves_free_string_const(&qc_line_wsys_name);
02614     uves_free_string_const(&qc_nlinsol_name);
02615     uves_free_string_const(&qc_nlinres1_name);
02616     uves_free_string_const(&qc_lineresidavg_name);
02617     uves_free_string_const(&qc_lineresidrms_name);
02618 
02619     uves_free_table(&selected);
02620 
02621     return;
02622  
02623 }
02624 
02633 static void uves_wavecal_qclog_intmon(cpl_table* table,
02634                       const cpl_table *line_intmon,
02635                       const uves_propertylist* raw_header,
02636                       bool flames,
02637                       int fibre,
02638                       enum uves_chip chip,
02639                       cpl_table* qclog)
02640 {
02641     const char *qc_intavg_name = NULL;
02642     const char *qc_nlinint_name = NULL;
02643 
02644     cpl_table *temp = NULL;
02645         
02646     check_nomsg(uves_qclog_add_string(qclog,
02647                                       "QC TEST2 ID",
02648                                       flames ? "Fibre-Line-Intensity-Test-Results"
02649                                       : "Line-Intensity-Test-Results",
02650                                       "Name of QC test",
02651                                       "%s"));
02652 
02653     check_nomsg( uves_qclog_add_common_wave(raw_header,
02654                                             chip, qclog) );
02655 
02656     {
02657     double tolerance = 0.001; /* (A) 
02658                      The lines in the line table
02659                      and intmon table are considered
02660                      identical if the difference
02661                      is less than this number.
02662                   */
02663                       
02664     double exptime;
02665 
02666     int N_bright = cpl_table_get_nrow(line_intmon);
02667     int i;
02668 
02669     check( exptime = uves_pfits_get_exptime(raw_header),
02670            "Could not get exposure time");
02671     
02672     cpl_table_new_column(table, "Intensity", CPL_TYPE_DOUBLE); 
02673     for (i = 0; i < cpl_table_get_nrow(table); i++)
02674     {
02675         int is_null;
02676         double ident = cpl_table_get_double(table, "Ident", i, &is_null);
02677 
02678         if (!is_null)
02679         {
02680             int bright_index = uves_wavecal_find_nearest(
02681             line_intmon, ident, 0, N_bright-1);
02682 
02683             double bright = cpl_table_get_double(
02684             line_intmon, "Wave", bright_index, NULL);
02685 
02686             if (fabs(bright - ident) < tolerance)
02687             {
02688                 double peak = cpl_table_get_double(table, "Peak", i, NULL);
02689                 double pixelsize = 
02690                 fabs(cpl_table_get_double(table, LINETAB_PIXELSIZE, i, NULL));
02691 
02692                 double lambda_fwhm = cpl_table_get_double(table, "Xwidth", i, NULL)
02693                 * TWOSQRT2LN2 * pixelsize;
02694                 /* Line FWHM in wlu */
02695 
02696                 double intensity = peak * lambda_fwhm / exptime;
02697                 /* Same formula as in MIDAS */
02698 
02699                 cpl_table_set_double(table, "Intensity", i, intensity);
02700             }
02701             else
02702             {
02703                 cpl_table_set_invalid(table, "Intensity", i);
02704             }
02705         }
02706         else
02707         {
02708             cpl_table_set_invalid(table, "Intensity", i);
02709         }
02710     }
02711     }
02712 
02713     uves_free_table(&temp);
02714     temp = cpl_table_duplicate(table);
02715     uves_erase_invalid_table_rows(temp, "Intensity");
02716 
02717     {
02718     double mean;
02719     if (cpl_table_get_nrow(temp) == 0)
02720         {
02721         uves_msg_warning("No bright lines found!");
02722         mean = 0;
02723         }
02724     else
02725         {
02726         mean = cpl_table_get_column_mean(temp, "Intensity");
02727         }
02728 
02729     if (flames)
02730         {
02731         qc_intavg_name  = uves_sprintf("QC FIB%d INTAVG", fibre+1); /* Count 1-9 */
02732         qc_nlinint_name = uves_sprintf("QC FIB%d NLININT", fibre+1);
02733         }
02734     else
02735         {
02736         qc_intavg_name  = uves_sprintf("QC INTAVG");
02737         qc_nlinint_name = uves_sprintf("QC NLININT");
02738         }
02739         
02740     check_nomsg(uves_qclog_add_double(qclog,
02741                       qc_intavg_name,
02742                       mean,
02743                       "average intensity of line list on TRACE0 WIN2",
02744                       "%.4f"));
02745     
02746     check_nomsg(uves_qclog_add_int(qclog,
02747                        qc_nlinint_name,
02748                        cpl_table_get_nrow(temp),
02749                        "No. of lines to measure INTAVG on TRACE0 WIN2",
02750                        "%d"));
02751     }
02752 
02753  cleanup:
02754     uves_free_string_const(&qc_intavg_name);
02755     uves_free_string_const(&qc_nlinint_name);
02756   uves_free_table(&temp);
02757   return;
02758 }
02759 
02760 

Generated on 9 Mar 2012 for UVES Pipeline Reference Manual by  doxygen 1.6.1