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/02/17 08:27:26 $
00023  * $Revision: 1.88 $
00024  * $Name: uves-4_9_1 $
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),
00672        "Line search failed");
00673 
00674      /* Read first solution from guess line table */
00675     {
00676         int degree = 5; /* for the initial solution only. For the
00677                            final solution the degree given as recipe
00678                            parameter is used */
00679         uves_polynomial_delete(&initial_dispersion);
00680         cpl_free(relative_order);
00681         check( initial_dispersion = uves_wavecal_firstsolution(linetable,
00682                                                                guess, 
00683                                                                absolute_order,
00684                                                                ordertable,
00685                                                                order_locations,
00686                                                                flames,
00687                                                                offset,
00688                                                                &relative_order,
00689                                                                degree,
00690                                                                SHIFT_MAX, 
00691                                                                SHIFT_STEP, 
00692                                                                SHIFT_TOLERANCE, 
00693                                                                MAXERROR,
00694                                                                first_absolute_order,
00695                                                                last_absolute_order),
00696                "Could not get first solution");
00697     }
00698 
00699 
00700     if (flames)
00701     {
00702         /* !AM: To correct eventual residual shifts between Guess and Final order
00703            ! (and line) table
00704            compute/table {LINTAB} :YNEW =
00705            :YNEW - {{ORDTAB},TAB_IN_OUT_YSHIFT} - {{OLDORDTAB},FIBREPOS({i1})}
00706            compute/table {LINTAB} :Y = :Y +{{ORDTAB},TAB_IN_OUT_OSHIFT}
00707         */
00708 
00709         cpl_table_add_scalar(linetable, "Y", tab_in_out_oshift);
00710         cpl_table_add_scalar(linetable, "Ynew", - tab_in_out_yshift - offset);
00711     }
00712 
00713     /* Calibrate */
00714     check( *dispersion_relation = uves_wavecal_identify(linetable, /* Guess solution */
00715                             line_refer,
00716                             initial_dispersion, 
00717                                                         DEGREE,
00718                             TOLERANCE, ALPHA, MAXERROR,
00719                                                         kappa),
00720        "Could not calibrate orders");
00721 
00722     if (flames)
00723     {
00724         /* AM: To have correct split of fibres in line table:
00725            > compute/table {LINTAB} :YNEW = :YNEW + {{ORDTAB},TAB_IN_OUT_YSHIFT}
00726                      + {{OLDORDTAB},FIBREPOS({i1})}
00727         */
00728 
00729         cpl_table_add_scalar(linetable, "Ynew", + tab_in_out_yshift + offset);
00730     }
00731 
00732     /* UVES: make plots (resolution + etc.) for the central window,
00733      * FLAMES: all fibres
00734      */
00735     if (flames || (trace == 0 && window == 2)|| (window == 1 && NWINDOWS == 1))
00736     {
00737         /* Create x-FWHM column:   FWHM = 2.3548 sigma */
00738         check(( cpl_table_duplicate_column(linetable, "deltaX", linetable, "Xwidth"),
00739             cpl_table_multiply_scalar (linetable, "deltaX", TWOSQRT2LN2)),
00740           "Error creating FWHM column");
00741         
00742 
00743         check_nomsg( temp = uves_extract_table_rows(
00744                              linetable, "NLinSol", CPL_NOT_EQUAL_TO, 0) );
00745 
00746         check( uves_plot_table(temp, "Order", LINETAB_RESIDUAL, "Residual of fit"), 
00747            "Plotting failed");
00748         
00749         check( uves_plot_table(temp, "X", "deltaX", "line FWHM (mean = %.2f pixels)",
00750                    cpl_table_get_column_mean(linetable, "deltaX")),
00751            "Plotting failed");
00752         /*
00753           check( uves_plot_table(linetable, "Y", "deltaX", 
00754           "line FWHM (mean FWHM = %.2f pixels)",
00755           cpl_table_get_column_mean(linetable, "deltaX")), "Plotting failed");
00756         */
00757         
00758         
00759         /* Compute resolution as as lambda / deltalambda   where deltalambda
00760                is the peak FWHM in wavelength space (after resampling using 
00761            WAVESTEP = average pixelsize) 
00762         */
00763         
00764         {
00765         /* Rebin using steps of median pixelsize */
00766         double wavestep;
00767         double lambda_start = 0;
00768         int n_traces = 1;      /* We didn't do a 2d extraction; 
00769                       there's only 1 trace
00770                       per order */
00771         int i, nbins;
00772                 bool threshold_to_positive = true;
00773 
00774         cpl_table_new_column(linetable, "deltaLambda", CPL_TYPE_DOUBLE);
00775         
00776         check( rebinned_noise = uves_rebin(spectrum_noise,
00777                                            parameters, 
00778                                            recipe_id,
00779                                            linetable, 
00780                                            *dispersion_relation, 
00781                                            *first_absolute_order, 
00782                                            *last_absolute_order,
00783                                            n_traces,
00784                                            threshold_to_positive,
00785                                            true,
00786                                            &rebinned_header),
00787                "Could not rebin noise of arc lamp spectrum");
00788 
00789         threshold_to_positive = false;
00790         uves_free_propertylist(&rebinned_header);
00791         check( rebinned = uves_rebin(spectrum,
00792                                      parameters, 
00793                                      recipe_id,
00794                                      linetable, 
00795                                      *dispersion_relation, 
00796                                      *first_absolute_order, 
00797                                      *last_absolute_order,
00798                                      n_traces,
00799                                      threshold_to_positive,
00800                                      false,
00801                                      &rebinned_header),
00802                "Could not rebin arc lamp spectrum");
00803 
00804         /* Save order-by-order rebinned spectrum+noise */
00805         if (DEBUG)
00806             {
00807             check( uves_save_image_local("Rebinned spectrum",
00808                              "wxb", rebinned, chip, 
00809                              trace, window, rebinned_header, true),
00810                    "Error saving rebinned spectrum");
00811 
00812             check( uves_save_image_local("Noise of rebinned spectrum",
00813                              "errwxb", rebinned_noise, chip, 
00814                              trace, window, rebinned_header, true),
00815                    "Error saving noise of rebinned spectrum");
00816             }
00817         
00818         check( merged = uves_merge_orders(rebinned, 
00819                       rebinned_noise,
00820                       rebinned_header,
00821                       m_method,
00822                       n_traces,
00823                       &merged_header,
00824                       0,0,chip,
00825                       &merged_noise),
00826                "Could not merge arc lamp spectrum");
00827 
00828         check( uves_plot_image_rows(merged, 1, 1, 1, 
00829                         "Wavelength (arbitrary units)", 
00830                         "Flux", "Resampled arc lamp spectrum"),
00831                "Plotting failed");
00832 
00833         /* Save merged arc lamp spectrum */
00834         if (DEBUG)
00835             {
00836             check( uves_save_image_local("Rebinned, merged spectrum",
00837                              "merged", merged, chip, 
00838                              trace, window, merged_header, true),
00839                    "Error saving merged spectrum");
00840             }
00841         
00842         nbins = cpl_image_get_size_x(merged);
00843 
00844         check( wavestep = uves_pfits_get_cdelt1(merged_header),
00845                "Error reading resampling step size");
00846         
00847         check( lambda_start = uves_pfits_get_crval1(merged_header), 
00848                "Could not read start wavelength of merged spectrum");
00849 
00850 
00851     //Begin commented region
00852     
00853    if (flames && trace == 0 && corvel_frm != NULL)
00854     {
00855        //The following (flames_reduce.VCORREL) calculates 
00856        //a cross correlation and does some QC
00857 
00858 
00859 //> !To support simcal Mode
00860 //> if i1 .eq. 1 then
00861 //>    w/o "DRS_CVEL_SWITCH={DRS_CVEL_SWITCH}"
00862 //>    if "{DRS_CVEL_SWITCH}" .eq. "Y" then
00863 //>       w/o "To support simcal Mode"
00864 //>       define/local ord_min/i/1/1 0
00865 //>       define/local ord_max/i/1/1 0
00866 //>       define/local rsample/d/1/1 0
00867 //>       statistic/table {ORDTAB} :ORDER >Null
00868 //>       ord_min = outputr(1)
00869 //>       ord_max = outputr(2)
00870 //>       rsample = {{LINTAB},PIXEL(1)}
00871 //>       rsample = 2./3. * rsample
00872 //>       rebin/echelle  {ofrm} w{ofrm} {rsample} NONL {LINTAB} {SESSOUTV}
00873 //>       mercut/echelle w{ofrm} mw{ofrm} {ord_min},{ord_max} NOAPPEND
00874 //>       !corvel stuff
00875 //>       define/local OLD_CVEL_MAX/d/1/1 {DRS_CVEL_MAX}
00876 //>       define/local OLD_CVEL_MIN/d/1/1 {DRS_CVEL_MIN}
00877 //>       @p flames_reduce,VCORREL x1_rbf_ cvel1 0 {ord_max} {parCorVelTab} _0 _{chip({PATHID})} 0
00878 //>       DRS_CVEL_MAX = DRS_CVEL_MAX + {q1}
00879 //>       DRS_CVEL_MIN = DRS_CVEL_MIN + {q1}
00880 //>
00881 //>       @p flames_reduce,VCORREL x1_rbf_ cvel2 0 {ord_max} {parCorVelTab} _0 _{chip({PATHID})} 0
00882 //>       cvel_0 = {q1}
00883 //>       DRS_CVEL_MAX = OLD_CVEL_MAX
00884 //>       DRS_CVEL_MIN = OLD_CVEL_MIN
00885 //>    endif
00886 //>    write/keyword DRS_CVEL_SWITCH Y
00887 //> endif
00888 
00889 
00890 
00891 
00892        
00893 
00894 
00895       const char* drs_base_name=NULL;
00896       const char* prefid=NULL;
00897       double ccf_posmax_zero_point=0;
00898       double ccf_posmax_zero_point_iter0=0;
00899       double cvel_max=0;
00900       double cvel_sig=0;
00901       if(chip == UVES_CHIP_REDL) {
00902     prefid="l";
00903       } else {
00904     prefid="u";
00905       }
00906       const char* name=NULL;
00907       const char* file=NULL;
00908       cpl_propertylist* plist=NULL;
00909       double drs_cvel_min=0;
00910       double drs_cvel_max=0;
00911 
00912  
00913       check( uves_save_image_local("Rebinned spectrum",
00914                    "wxb", rebinned, chip, 
00915                    trace, window, rebinned_header, true),
00916          "Error saving rebinned spectrum");
00917 
00918       check( uves_save_image_local("Rebinned, merged spectrum",
00919                    "mwxb", merged, chip, 
00920                    trace, window, merged_header, true),
00921          "Error saving merged spectrum");
00922      
00923 
00924       check( file = uves_local_filename("wxb", chip, trace, window),
00925          "Error getting filename");
00926       check_nomsg(plist=cpl_propertylist_load(file,0));
00927 
00928       name=uves_sprintf("wfxb_%s%s%4.4d%s",prefid,"_raw",1,".fits");
00929       drs_base_name=uves_sprintf("fxb_%s",prefid);
00930 
00931       cpl_image_save(rebinned,name, CPL_BPP_IEEE_FLOAT,plist, 
00932              CPL_IO_DEFAULT);
00933 
00934 
00935       name=uves_sprintf("mwfxb_%s%s%4.4d%s",prefid,"_raw",1,".fits");
00936       cpl_image_save(merged,name, CPL_BPP_IEEE_FLOAT,plist, 
00937              CPL_IO_DEFAULT);
00938      
00939       cpl_propertylist_delete(plist);
00940 
00941 
00942       int ord_max=(*first_absolute_order-*last_absolute_order)+1;
00943      
00944       uves_msg("cvel max:%g %g",DRS_CVEL_MAX,DRS_CVEL_MIN);
00945       drs_cvel_max =DRS_CVEL_MAX;
00946       drs_cvel_min =DRS_CVEL_MIN;
00947 
00948       check_nomsg(flames_reduce_vcorrel(drs_base_name,
00949                     "cvel2", 
00950                     prefid,
00951                     ord_max,
00952                     corvel_frm, 
00953                     "_raw0001", 
00954                     "_raw0001", 
00955                                         DRS_CVEL_MIN,
00956                                         DRS_CVEL_MAX,
00957                     &ccf_posmax_zero_point,
00958                     &cvel_max,
00959                     &cvel_sig,
00960                     flames_qclog[0]));
00961      
00962      drs_cvel_max +=cvel_max;
00963      drs_cvel_min +=cvel_max;
00964      ccf_posmax_zero_point_iter0 =cvel_max;
00965      uves_msg("cvel max:%g %g",drs_cvel_max,drs_cvel_min);
00966 
00967      check_nomsg(flames_reduce_vcorrel(drs_base_name,
00968                     "cvel2", 
00969                     prefid,
00970                     ord_max,
00971                     corvel_frm, 
00972                     "_raw0001", 
00973                     "_raw0001", 
00974                                         drs_cvel_min,
00975                                         drs_cvel_max,
00976                     &ccf_posmax_zero_point,
00977                     &cvel_max,
00978                     &cvel_sig,
00979                     flames_qclog[1]));
00980       
00981       drs_cvel_max +=cvel_max;
00982       drs_cvel_min +=cvel_max;
00983       ccf_posmax_zero_point =ccf_posmax_zero_point_iter0;
00984       ck0_nomsg(uves_qclog_add_double(flames_qclog[1],
00985                    "QC CCF POSOFF",
00986                    ccf_posmax_zero_point,
00987                    "CCF pos avg from ThAr calibration",
00988                    "%f"));
00989 
00990 
00991       uves_msg("cvel max:%g min: %g zp: %g",
00992            drs_cvel_max,drs_cvel_min,ccf_posmax_zero_point);
00993 
00994    
00995     }
00996    //End commented region
00997 
00998 
00999         /* For all identified lines fit the line width in the
01000            merged spectrum to get the resolution  */
01001          for (i = 0; i < cpl_table_get_nrow(linetable); i++)
01002             {
01003             double lambda = cpl_table_get_double(
01004                 linetable, LINETAB_LAMBDAC, i, NULL);
01005             double width  = 
01006                 cpl_table_get_double(linetable, "Xwidth"   , i, NULL) *
01007                 fabs(cpl_table_get_double(linetable, LINETAB_PIXELSIZE, i, NULL)); 
01008             /* in wlu */
01009             
01010             /* Convert line wavelength and width to 'bin' units */
01011             int bin       = 1 + 
01012                 uves_round_double((lambda - lambda_start) / wavestep);
01013             double width_bin = width / wavestep;
01014 
01015             /* Set fitting window to +-5 sigma */
01016             int first_bin = uves_max_int(    1, uves_round_double(bin - 5*width_bin));
01017             int last_bin  = uves_min_int(nbins, uves_round_double(bin + 5*width_bin));
01018 
01019             double my, sigma, norm, background;    /* Results of fit */
01020             double lambda_fwhm;
01021             
01022             if (cpl_table_is_valid(linetable, "Ident", i) && first_bin < last_bin)
01023                 {
01024                 /* Fit a gaussian to the merged arc spectrum */
01025                 uves_fit_1d_image(merged, 
01026 #if 1
01027                                                   merged_noise, 
01028 #else /* Unweighted fit like MIDAS which gives larger sigma */
01029                                                   NULL,
01030 #endif
01031                                                   NULL,
01032                           true,     /* Horizontal?    */
01033                           false,    /* Fix background?*/
01034                           false,    /* Fit background?*/
01035                           first_bin, 
01036                                                   last_bin, 
01037                                                   1,  /* xlo, xhi, y    */
01038                           &my, 
01039                                                   &sigma, 
01040                                                   &norm, 
01041                                                   &background, NULL, /* slope */
01042                           NULL, 
01043                                                   NULL, 
01044                                                   NULL,    /* mse, red_chisq,
01045                                   covariance     */
01046                           uves_gauss, 
01047                                                   uves_gauss_derivative, 
01048                                                   4);
01049                                         
01050                 if (cpl_error_get_code() == CPL_ERROR_CONTINUE)
01051                     {
01052                     uves_error_reset();
01053                     uves_msg_debug("Gaussian fitting failed "
01054                                "at lambda = %f wlu, bins = "
01055                                "%d - %d, ignoring line",
01056                                lambda, first_bin, last_bin);
01057                     
01058                     cpl_table_set_invalid(linetable, "deltaLambda", i);
01059                     
01060                     }
01061                 else
01062                     {
01063                         assure(cpl_error_get_code() == CPL_ERROR_NONE,
01064                                cpl_error_get_code(), "Gaussian fitting failed");
01065                     
01066                     /* Convert from bins to wavelength */
01067                     lambda_fwhm = TWOSQRT2LN2 * sigma * wavestep;
01068                     
01069                     cpl_table_set_double(linetable, "deltaLambda",
01070                                  i, lambda_fwhm);
01071 
01072                     }
01073                 }
01074             else
01075                 {
01076                 cpl_table_set_invalid(linetable, "deltaLambda", i);
01077                 }
01078             }
01079         
01080         
01081         /* Create column 'Resol'(ution) = lambda / deltalambda */
01082         check(( cpl_table_duplicate_column(linetable, "Resol", 
01083                            linetable, LINETAB_LAMBDAC),
01084             cpl_table_divide_columns  (linetable, "Resol",
01085                            "deltaLambda")),
01086               "Error creating 'Resol' column");
01087         
01088         /* Filter out extreme outliers (due to bad gaussian fit) */
01089         {
01090          
01091           int ninvalid=0;
01092           int nrows=0;
01093            double resol_avg   = 0;
01094            double resol_stdev = 0;
01095            double kappar = 10.0;
01096            nrows=cpl_table_get_nrow(linetable);
01097            ninvalid=cpl_table_count_invalid(linetable,"Resol");
01098            assure(ninvalid < nrows,CPL_ERROR_ILLEGAL_INPUT, 
01099                  "No valid elements in Resol column. "
01100                  "You must decrease parameter rebin.wavestep");
01101            check_nomsg(resol_avg=cpl_table_get_column_median(linetable, "Resol"));
01102            check_nomsg(resol_stdev=cpl_table_get_column_stdev (linetable, "Resol"));
01103 
01104             for (i = 0; i < cpl_table_get_nrow(linetable); i++)
01105             {
01106                 double r = cpl_table_get_double(linetable, "Resol", i, NULL);
01107                 if (r < resol_avg - kappar*resol_stdev ||
01108                 r > resol_avg + kappar*resol_stdev)
01109                 {
01110                     cpl_table_set_invalid(linetable, "Resol", i);
01111                     cpl_table_set_invalid(linetable, "deltaLambda", i);
01112                 }
01113             }
01114         }
01115 
01116         /* check( uves_plot_table(linetable, "X", "Resol", 
01117            "(x, l / dl)"), "Plotting failed"); 
01118            check( uves_plot_table(linetable, "Y", "Resol", 
01119            "(y, l / dl)"), "Plotting failed"); 
01120         */
01121         check( uves_plot_table(linetable, LINETAB_LAMBDAC, "Resol",
01122                        "(l, l / dl)"), "Plotting failed");
01123         }
01124         
01125         /* Plot identifications */
01126             uves_free_table(&temp);
01127         check( temp = cpl_table_duplicate(linetable), 
01128            "Error copying line table");
01129         check( uves_erase_invalid_table_rows(temp, "Ident"), 
01130            "Error removing un-identified lines");
01131         check( uves_plot_table(temp, "X", "Ynew", 
01132                    "Line identifications"), 
01133            "Plotting failed");
01134         uves_free_table(&temp);
01135 
01136     } /* Plots for middle (object) window */
01137 
01138     if (DEBUG) 
01139     {
01140         /* Results of uves_wavecal_search are already 
01141            drawn on debug_image */
01142         
01143         /* Draw guess table lines using the initial solution */
01144         if (0) check( uves_draw_lines(debug_image, initial_dispersion,
01145                       order_locations, guess,
01146                       "Ident", "Order", relative_order,
01147                       -1, -1,
01148                       false,     /* true = vertical */
01149                       12), "Error drawing guess solution");
01150         
01151         /* Draw catalogue lines using the initial solution */
01152         check( uves_draw_lines(debug_image, initial_dispersion, order_locations,
01153                    line_refer, "Wave", NULL, relative_order,
01154                    uves_min_int(*first_absolute_order, *last_absolute_order),
01155                    uves_max_int(*first_absolute_order, *last_absolute_order),
01156                    true,                   /* true = vertical */
01157                    8), "Error drawing catalogue lines");
01158         
01159         /* Draw catalogue lines using the final solution */
01160         check( uves_draw_lines(debug_image, *dispersion_relation, order_locations, 
01161                    line_refer, "Wave", NULL, relative_order,
01162                    uves_min_int(*first_absolute_order, *last_absolute_order),
01163                    uves_max_int(*first_absolute_order, *last_absolute_order),
01164                    true,                     /* true = vertical */
01165                    16), "Error drawing catalogue lines");
01166         
01167         /* Draw detected lines using initial solution */
01168         if (0) check( uves_draw_lines(debug_image, initial_dispersion, 
01169                       order_locations, linetable, 
01170                       LINETAB_LAMBDAC, "Order", relative_order,
01171                       -1, -1,
01172                       false,            /* true = vertical */
01173                       -16), "Error drawing detected lines");
01174         
01175         /* Draw IDed lines */
01176             uves_free_table(&temp);
01177         check(( temp = cpl_table_duplicate(linetable),
01178             /* Delete rows with invalid 'Ident' */
01179             uves_erase_invalid_table_rows(temp, "Ident")),
01180           "Error duplicating table");
01181         
01182         check( uves_draw_lines(debug_image, *dispersion_relation, order_locations,
01183                    temp, LINETAB_LAMBDAC, "Order", relative_order,
01184                    -1, -1,
01185                    true,                  /* true = vertical */
01186                    0), "Error drawing detected lines");
01187         
01188 
01189         /* Explanation of drawing produced by code above:
01190            The output frame emission lines will look like this
01191 
01192 
01193                      #### |1
01194                          ####   |2  
01195                          #|3#
01196                          -+--
01197                          #|##
01198                          ####
01199                          ####
01200         
01201 
01202                 Legend:
01203 
01204                   ##: The emmission line
01205                   --: (horizontal line) The line was detected
01206                   |1: (vertical line)   Predicted position (final solution)
01207                   |2: (vertical line)   Predicted position (initial solution)
01208                   |3: (vertical line)   Is drawn iff the line was identified
01209 
01210 
01211           
01212         */
01213 
01214         /* Save the raw arc frame with detected emission lines marked */
01215         check( uves_save_image_local("Debug image", "rawdebug", 
01216                      debug_image, chip, trace, window,
01217                      rotated_header, true),
01218            "Error saving spectrum");
01219     }
01220 
01221     if (flames)
01222     {
01223         int start = 0;
01224         int count = cpl_table_get_nrow(linetable);
01225 
01226         check_nomsg( cpl_table_new_column(linetable, "Fibre", CPL_TYPE_INT) );
01227 
01228         cpl_table_fill_column_window(linetable, "Fibre",
01229                      start, count,
01230                      trace + 1);   /* Write value in range 1-9 */
01231     }
01232 
01233   cleanup:
01234 
01235     uves_free_table(&info_tbl);
01236     uves_free_table(&temp);
01237     uves_free_image(&weights_opt);
01238     uves_free_table(&cr_table);
01239     uves_free_image(&cr_image);
01240     uves_free_image(&spectrum);
01241     uves_free_image(&spectrum_noise);
01242     uves_free_image(&debug_image);
01243     uves_free_image(&rebinned);
01244     uves_free_image(&rebinned_noise);
01245     uves_free_image(&merged);
01246     uves_free_image(&merged_noise);
01247     uves_free_propertylist(&spectrum_header);
01248     uves_free_propertylist(&rebinned_header);
01249     uves_free_propertylist(&merged_header);
01250     cpl_free(relative_order);
01251     uves_polynomial_delete(&initial_dispersion);
01252     uves_free_table(&order_trace);
01253 
01254     return linetable;
01255 }
01256 
01257 
01258 
01259 /*----------------------------------------------------------------------------*/
01284 /*----------------------------------------------------------------------------*/
01285 void
01286 uves_wavecal_exe_body(cpl_frameset *frames,
01287               bool flames,
01288               const char *recipe_id,
01289               const cpl_parameterlist *parameters,
01290               const char *starttime)
01291 {
01292     /*
01293      * Variables containg the values of recipe parameters 
01294      */
01295 
01296     /* General */
01297     bool DEBUG;
01298 
01299     /* Extraction */
01300     int NWINDOWS;
01301     double OFFSET;
01302     double SLITLENGTH_par;  /* slitlength given by user */
01303 
01304     /* Search */
01305     int    RANGE;
01306     int    MAXLINES;
01307     int    MINLINES;
01308     centering_method CENTERING_METHOD;
01309 
01310     /* First solution */
01311     double SHIFT_MAX;
01312     double SHIFT_STEP;
01313     double SHIFT_TOLERANCE;
01314 
01315     /* Identify */
01316     double  ALPHA;
01317     double  MAXERROR;
01318     int     DEGREE;
01319     /* Calibrate */
01320     double  TOLERANCE;
01321     double  KAPPA;
01322 
01323     /* Input */
01324     cpl_image        *arclamp[2]          = {NULL, NULL};
01325     cpl_image        *arclamp_noise       = NULL;
01326     uves_propertylist *arclamp_header[2]   = {NULL, NULL};
01327     uves_propertylist *rotated_header[2]   = {NULL, NULL};
01328     
01329     /* Order table */
01330     cpl_table        *ordertable            = NULL;
01331     uves_propertylist *ordertable_header     = NULL;
01332     polynomial       *order_locations       = NULL;
01333     cpl_table        *traces                = NULL;
01334     
01335     /* Bias */
01336     cpl_image        *master_bias        = NULL;
01337     uves_propertylist *master_bias_header = NULL;
01338 
01339     /* Flat field */
01340     cpl_image        *master_flat        = NULL;
01341     cpl_image        *mflat_noise        = NULL;
01342     uves_propertylist *master_flat_header = NULL;
01343 
01344     /* Weight map */
01345     cpl_image        *weights            = NULL;
01346 
01347     /* DRS guess table is not used */
01348     /* 
01349        cpl_table        *drs_table             = NULL;
01350        uves_propertylist *drs_header            = NULL;
01351     */
01352 
01353     //FLAMES-DRS specific descriptors
01354     int* fibres_mask=NULL;
01355     double* fibres_pos=NULL;
01356 
01357     /* Guess line table */
01358     cpl_table        *guess              = NULL;
01359     polynomial       *absolute_order     = NULL;
01360     
01361     /* Velocity correction table */
01362     cpl_table        *corvel             = NULL;
01363     cpl_frame        *corvel_frm         = NULL;
01364     uves_propertylist *corvel_header      = NULL;
01365 
01366     /* Reference catalogue */
01367     cpl_table        *line_refer            = NULL;
01368     cpl_table        *line_intmon           = NULL;
01369    
01370     /* Output */
01371     lt_type          *linetable             = NULL;
01372 
01373     uves_propertylist *primary_header        = NULL;
01374     uves_propertylist *table_header          = NULL;
01375     /* QC for resolution + intmon + NULL */
01376     cpl_table        *qclog[3]              = {NULL, NULL, NULL};
01377 
01378     /* Local variables */
01379     cpl_image        *absorder_image     = NULL;
01380     const char *arclamp_filename = "";
01381     const char *line_refer_filename = "";
01382     const char *line_intmon_filename = "";
01383     char *product_filename = NULL;
01384     char *temp = NULL;
01385     bool blue  = false;
01386     bool sim_cal = false;
01387     enum uves_chip chip;
01388     int binx = 0;
01389     int biny = 0;
01390     bool drs_cvel_sw=false;
01391     const char* PROCESS_CHIP=NULL;
01392     extract_method em;
01393 
01394     /* Read recipe parameters */
01395     {
01396     const char *centering_m = "gaussian";
01397         const char *profile = "";
01398 
01399  
01400 
01401     /* General */
01402     check( uves_get_parameter(parameters, NULL, "uves", "debug", 
01403                   CPL_TYPE_BOOL, &DEBUG), "Could not read parameter");
01404     
01405     check( uves_get_parameter(parameters, NULL, "uves", "process_chip", CPL_TYPE_STRING, &PROCESS_CHIP),
01406                "Could not read parameter");
01407     uves_string_toupper((char*)PROCESS_CHIP);
01408 
01409         /* Extraction */
01410     check( uves_get_parameter(parameters, NULL, recipe_id, "nwindows",
01411                   CPL_TYPE_INT   , &NWINDOWS    ), "Could not read parameter");
01412     check( uves_get_parameter(parameters, NULL, recipe_id, "length",
01413                   CPL_TYPE_DOUBLE, &SLITLENGTH_par), "Could not read parameter");
01414     check( uves_get_parameter(parameters, NULL, recipe_id, "offset",
01415                   CPL_TYPE_DOUBLE, &OFFSET      ), "Could not read parameter");
01416     
01417     /* Don't allow optimal extraction. This requires that
01418        additional arguments (weight image, ..) are passed to uves_extract */
01419     temp = uves_sprintf("%s.%s", recipe_id, UVES_EXTRACT_ID);
01420     check( em = uves_get_extract_method(parameters, NULL, temp),
01421            "Could not read extraction method");
01422     
01423     check( uves_get_parameter(parameters, NULL, recipe_id, UVES_EXTRACT_ID ".profile",
01424                   CPL_TYPE_STRING, &profile), "Could not read parameter");
01425 
01426     assure( em == EXTRACT_LINEAR || em == EXTRACT_AVERAGE || em == EXTRACT_WEIGHTED ||
01427             (em == EXTRACT_OPTIMAL && strcmp(profile, "constant") == 0),
01428             CPL_ERROR_UNSUPPORTED_MODE, 
01429             "Only linear/average/weighted/optimal(constant profile) extraction "
01430             "methods are supported by this recipe");
01431     
01432     /* Search */
01433     check( uves_get_parameter(parameters, NULL, recipe_id, "search.range",
01434                   CPL_TYPE_INT   , &RANGE       ), "Could not read parameter");
01435     check( uves_get_parameter(parameters, NULL, recipe_id, "search.minlines",
01436                   CPL_TYPE_INT   , &MINLINES    ), "Could not read parameter");
01437     check( uves_get_parameter(parameters, NULL, recipe_id, "search.maxlines",
01438                   CPL_TYPE_INT   , &MAXLINES    ), "Could not read parameter");
01439 /*
01440     check( uves_get_parameter(parameters, NULL, recipe_id, "search.centeringmethod",
01441                   CPL_TYPE_STRING, &centering_m ), "Could not read parameter");
01442 */
01443     if      (strcmp(centering_m, "gravity" ) == 0) CENTERING_METHOD = CENTERING_GRAVITY;
01444     else if (strcmp(centering_m, "gaussian") == 0) CENTERING_METHOD = CENTERING_GAUSSIAN;
01445     else
01446         { 
01447         /* Impossible */ assure(false, CPL_ERROR_ILLEGAL_INPUT,
01448                     "Unrecognized parameter value '%s'", centering_m);
01449         }
01450     
01451     /* First solution */
01452     check( uves_get_parameter(parameters, NULL, recipe_id, "first.shiftmax",
01453                   CPL_TYPE_DOUBLE , &SHIFT_MAX      ),
01454            "Could not read parameter");
01455     check( uves_get_parameter(parameters, NULL, recipe_id, "first.shiftstep", 
01456                   CPL_TYPE_DOUBLE , &SHIFT_STEP     ), 
01457            "Could not read parameter");
01458     check( uves_get_parameter(parameters, NULL, recipe_id, "first.shifttoler",
01459                   CPL_TYPE_DOUBLE , &SHIFT_TOLERANCE), 
01460            "Could not read parameter");
01461     
01462     /* Identify */
01463     check( uves_get_parameter(parameters, NULL, recipe_id, "identify.alpha",
01464                   CPL_TYPE_DOUBLE , &ALPHA      ), "Could not read parameter");
01465     check( uves_get_parameter(parameters, NULL, recipe_id, "identify.maxerror",
01466                   CPL_TYPE_DOUBLE , &MAXERROR   ), "Could not read parameter");
01467     check( uves_get_parameter(parameters, NULL, recipe_id, "identify.degree",
01468                   CPL_TYPE_INT    , &DEGREE     ), "Could not read parameter");
01469     
01470     /* Calibrate */
01471     check( uves_get_parameter(parameters, NULL, recipe_id, "calibrate.tolerance",
01472                   CPL_TYPE_DOUBLE, &TOLERANCE   ), "Could not read parameter");
01473     check( uves_get_parameter(parameters, NULL, recipe_id, "calibrate.kappa",
01474                   CPL_TYPE_DOUBLE, &KAPPA   ), "Could not read parameter");
01475     
01476     /* Additional checks */
01477     if (CENTERING_METHOD == CENTERING_GRAVITY)
01478         {
01479         uves_msg_warning("Centering method 'gravity' might lead to inaccurate "
01480                  "results. Recommended is 'gaussian'");
01481         }
01482     }
01483 
01484     /* Load raw image and header, and identify input frame as red or blue */
01485     check( uves_load_arclamp(frames, flames, &arclamp_filename, arclamp, arclamp_header, 
01486                  rotated_header, &blue, &sim_cal), "Error loading raw frame");
01487 
01488     /* Load reference line table */
01489     check( uves_load_linerefertable(frames, &line_refer_filename, &line_refer, NULL),
01490        "Could not load line reference table");
01491     uves_msg("Using line reference table '%s'", line_refer_filename);
01492     
01493     /* Load INTensity MONitoring table if present */
01494     if (cpl_frameset_find(frames, UVES_LINE_INTMON_TABLE) != NULL)
01495     {
01496         uves_free_table(&line_intmon);
01497         check( uves_load_lineintmon(frames, &line_intmon_filename,
01498                     &line_intmon),
01499            "Error loading line reference table");
01500         
01501         uves_msg("Using bright line table '%s'", line_intmon_filename);
01502     }
01503   
01504     /*
01505      * Adjust parameters according to binning 
01506      */
01507     check (binx = uves_pfits_get_binx(arclamp_header[0]),
01508        "Could not read x binning factor from input header");
01509     check (biny = uves_pfits_get_biny(arclamp_header[0]),
01510        "Could not read y binning factor from input header");
01511     SLITLENGTH_par /= (1.0*binx);  /* Extraction slit length */
01512     RANGE /= (1.0*biny);           /* Search window */
01513     SHIFT_MAX /= (1.0*binx);       /* Max shift compared to guess solution */
01514     SHIFT_STEP /= (1.0*binx);
01515 
01516     /* After the default tolerance was lowered to 0.07, do not adjust it according to binning,
01517        which would cause too many lines to be rejected
01518        
01519        TOLERANCE /= (1.0*biny); 
01520     */
01521 
01522 
01523     /* Loop over one or two chips, over traces and
01524        over extraction windows */
01525     for (chip = uves_chip_get_first(blue); 
01526          chip != UVES_CHIP_INVALID; 
01527          chip = uves_chip_get_next(chip)) {
01528 
01529 
01530         if(strcmp(PROCESS_CHIP,"REDU") == 0) {
01531             chip = uves_chip_get_next(chip);
01532         }
01533       
01534         const char *ordertable_filename = "";
01535         const char *corvel_filename = "";
01536         const char *master_flat_filename = "";
01537         const char *master_bias_filename = "";
01538         const char *weights_filename = "";
01539         /* const char *drs_filename        = "";    not used */
01540         const char *guess_filename      = "";
01541         const char *chip_name = "";
01542         int ntraces;
01543         int tracerow;                       /* Index of table row */
01544         int raw_index = uves_chip_get_index(chip);
01545         int current_linetable_extension;
01546         int tab_in_out_oshift = -1;
01547         double tab_in_out_yshift = -1;
01548         double slitlength;
01549       
01550       uves_msg("Processing %s chip in '%s'",
01551                uves_chip_tostring_upper(chip), arclamp_filename);
01552       
01553       check_nomsg( chip_name = uves_pfits_get_chipid(arclamp_header[raw_index], chip));
01554       
01555       
01556       uves_msg_debug("binning = %dx%d", binx, biny);
01557       
01558       
01559       /* Load the order table for this chip */
01560       uves_free_table       (&ordertable);
01561       uves_free_propertylist(&ordertable_header);
01562       uves_polynomial_delete(&order_locations);
01563       uves_free_table       (&traces);
01564       
01565       
01566       check( uves_load_ordertable(frames, 
01567                                   flames,
01568                                   chip_name, 
01569                                   &ordertable_filename,
01570                                   &ordertable, 
01571                                   &ordertable_header,
01572                                   NULL,
01573                                   &order_locations, 
01574                                   &traces, 
01575                                   (flames) ? &tab_in_out_oshift : NULL,
01576                                   (flames) ? &tab_in_out_yshift : NULL,
01577                                   &fibres_mask, 
01578                                   &fibres_pos, /* fibre_pos,fibre_mask */
01579                                   chip, 
01580                                   false  /* load guess table? */),
01581              "Could not load order table");
01582       uves_msg("Using order table in '%s'", ordertable_filename);
01583       ntraces = cpl_table_get_nrow(traces);
01584       uves_free_double(&fibres_pos);
01585       uves_free_int(&fibres_mask);
01586       
01587       /* Load master bias if present */
01588       uves_free_image(&master_bias);
01589       uves_free_propertylist(&master_bias_header);
01590       if (cpl_frameset_find(frames, UVES_MASTER_BIAS(chip)) != NULL)
01591           {
01592               check( uves_load_mbias(frames, chip_name, &master_bias_filename, &master_bias, 
01593                                      &master_bias_header, chip),
01594                      "Error loading master bias");
01595               
01596               uves_msg_low("Using master bias in '%s'", master_bias_filename);
01597           }
01598       else
01599           {
01600               uves_msg_warning("Master bias not provided. Bias subtraction not done");
01601           }
01602       
01603       
01604       /* Load master flat if present */
01605       uves_free_image(&master_flat);
01606       uves_free_propertylist(&master_flat_header);
01607       if ((cpl_frameset_find(frames, UVES_MASTER_FLAT(chip)) != NULL ||
01608            cpl_frameset_find(frames, UVES_MASTER_DFLAT(chip)) != NULL ||
01609            cpl_frameset_find(frames, UVES_MASTER_IFLAT(chip)) != NULL ||
01610            cpl_frameset_find(frames, UVES_MASTER_TFLAT(chip)) != NULL))
01611           {
01612               check( uves_load_mflat(frames, chip_name, &master_flat_filename, &master_flat, 
01613                                      &master_flat_header, chip, NULL),
01614                      "Error loading master flat");
01615               
01616               uves_msg_low("Using master flat in '%s'", master_flat_filename);
01617           }
01618       else
01619           {
01620               uves_msg_warning("Master flat not provided. Flat-fielding not done");
01621           }
01622 
01623       /* Load weight map if present */
01624       if (em == EXTRACT_WEIGHTED) {
01625           uves_free_image(&weights);
01626           check( weights = uves_load_weights(frames, &weights_filename, chip),
01627                  "Error loading weight map");
01628 
01629           uves_msg_low("Using weight map %s", weights_filename);
01630       }
01631 
01632       if (flames)
01633           /* Load CORVEL table */
01634           {
01635              if ((corvel_frm=cpl_frameset_find(frames, FLAMES_CORVEL_MASK)))
01636                   {
01637                       check( uves_load_corvel(frames,
01638                                               &corvel, &corvel_header,
01639                                               &corvel_filename),
01640                              "Could not load velocity correction table");
01641                       
01642                       uves_msg("Using velocity correction table %s", corvel_filename);
01643                       drs_cvel_sw=true;
01644                       
01645                       
01646                   }
01647               else
01648                   {
01649                       uves_msg("No corvel table found. Switch off corvel");
01650                       corvel = NULL;
01651                   }
01652           }
01653 
01654       /* Allocate all line tables for this chip */
01655       uves_lt_delete(&linetable);
01656       linetable = uves_lt_new(NWINDOWS, ntraces);
01657 
01658 
01659       /* Init QC tables for this chip */
01660       uves_qclog_delete(&qclog[0]); qclog[0] = uves_qclog_init(arclamp_header[raw_index], chip);
01661       uves_qclog_delete(&qclog[1]); qclog[1] = uves_qclog_init(arclamp_header[raw_index], chip);
01662 
01663       /* Saving the rotated raw arc frame */
01664       if (DEBUG) check( uves_save_image_local("Arc lamp frame", "raw", 
01665                                               arclamp[raw_index], 
01666                                               chip, -1, -1, rotated_header[raw_index], true),
01667                         "Error saving arc lamp frame");
01668 
01669       if (master_bias != NULL)
01670           {
01671               uves_msg("Subtracting master bias");
01672                 
01673               check( uves_subtract_bias(arclamp[raw_index], master_bias),
01674                      "Error during bias subtraction");
01675           }
01676       else {
01677           /* In lack of a real master bias frame, one might subtract the bias by estimating it
01678              as the median value across the chip (which should be okay for arc lamp frames)
01679           */
01680             
01681           /* Disabled. Would need to be tested. probably doesn't make any big difference anyway
01682              double bias = cpl_image_get_median(ff);
01683              uves_msg_debug("Estimated bias level is %f ADU", bias);
01684              cpl_image_subtract_scalar(ff, bias);
01685           */
01686       }
01687 
01688 
01689       /* Define arc lamp noise */
01690       uves_free_image(&arclamp_noise);
01691       check( arclamp_noise = uves_define_noise(arclamp[raw_index], 
01692                                                arclamp_header[raw_index], 1, chip),
01693              "Could not set arc lamp noise");
01694 
01695       if (master_flat != NULL)
01696           {
01697               uves_msg("Dividing by master flat");
01698                 
01699               uves_free_image(&mflat_noise);
01700               check( mflat_noise = 
01701                      uves_define_noise(master_flat, master_flat_header, 
01702                                        uves_pfits_get_datancom(master_flat_header),
01703                                        chip),
01704                      "Could not set master flat error bars");
01705                 
01706               check( uves_flatfielding(arclamp[raw_index], arclamp_noise,
01707                                        master_flat, mflat_noise),
01708                      "Error while dividing by flat field");
01709           }
01710 
01711       if (DEBUG) check( uves_save_image_local("Pre-processed arc lamp frame",
01712                                               "preproc", 
01713                                               arclamp[raw_index], chip, -1, -1,
01714                                               rotated_header[raw_index], true),
01715                         "Error saving arc lamp frame");
01716 
01717       /* Set appropriate slitlength if user did not */
01718       if (SLITLENGTH_par < 0) {
01719             
01720           double header_full_slit;
01721             
01722           check( header_full_slit = 
01723                  uves_pfits_get_slitlength_pixels(arclamp_header[raw_index], chip),
01724                  "Could not read slit length");
01725             
01726           /* Avoid pixels at the edge of the slit
01727            *  which are likely to be noisy 
01728            */
01729           slitlength = uves_max_double(1.0, (header_full_slit - 2)/NWINDOWS);
01730 
01731           uves_msg("Full slit = %.2f pixels", header_full_slit);
01732       }
01733       else {
01734           slitlength = SLITLENGTH_par;
01735       }
01736                 
01737    
01738       /* Loop over traces */
01739       for(tracerow = 0; tracerow < ntraces; tracerow++) {
01740         double trace_offset;
01741         int trace_number;
01742         int trace_enabled;
01743         
01744         trace_offset  = cpl_table_get_double(traces, "Offset"   , tracerow, NULL);
01745         trace_number  = cpl_table_get_int   (traces, "TraceID"  , tracerow, NULL);
01746         trace_enabled = cpl_table_get_int   (traces, "Tracemask", tracerow, NULL);
01747 
01748             if (ntraces > 1) {
01749                 uves_msg("Processing trace %d", trace_number);
01750             }
01751 
01752         if (flames && sim_cal) 
01753         {
01754             /* Only calibrate SIMCAL fibre in SIMCAL mode */
01755             trace_enabled = (trace_number == 1) ? 1 : 0;
01756         }
01757 
01758         uves_msg_low("Trace offset = %.2f pixels ; enabled = %d",
01759              trace_offset, trace_enabled);
01760         
01761         assure( flames || trace_number == 0, CPL_ERROR_ILLEGAL_INPUT,
01762             "%s: UVES trace number must be 0, it is %d", 
01763             ordertable_filename, trace_number );
01764         
01765         
01766         if (trace_enabled != 0) {
01767         int window;          /* window number */
01768 
01769         /* Load guess line table for this trace, any window */
01770         uves_free_table       (&guess);
01771         uves_polynomial_delete(&absolute_order);
01772 
01773         check( uves_load_linetable(
01774                frames, flames, chip_name, order_locations,
01775                cpl_table_get_column_min(ordertable, "Order"),
01776                cpl_table_get_column_max(ordertable, "Order"),
01777                &guess_filename, &guess, 
01778                NULL, NULL,
01779                &absolute_order, chip, trace_number, -1),
01780                "Could not load guess line table for trace number %d", 
01781                trace_number);
01782         uves_msg("Using guess line table '%s'", guess_filename);
01783  
01784         if (DEBUG)
01785             {
01786             /* Create an image showing the polynomial   m = f(x,y)
01787                where m is the absolute order number
01788             */
01789             int x, y;
01790 
01791             absorder_image = cpl_image_new(cpl_image_get_size_x(arclamp[raw_index]),
01792                                cpl_image_get_size_y(arclamp[raw_index]),
01793                                CPL_TYPE_FLOAT);
01794             assure_mem(absorder_image);
01795             
01796             for (y = 1; y <= cpl_image_get_size_y(arclamp[raw_index]); y++)
01797                 {
01798                 for (x = 1; x <= cpl_image_get_size_x(arclamp[raw_index]); x++)
01799                     {
01800                     double absorder = 
01801                         uves_polynomial_evaluate_2d(absolute_order, x, y);
01802                     
01803                     cpl_image_set(absorder_image, x, y, absorder);
01804                     }
01805                 }
01806             
01807             check( uves_save_image_local("Absolute order image", "absord",
01808                              absorder_image, chip, trace_number,
01809                              1, rotated_header[raw_index], true),
01810                    "Error saving absolute order image");
01811             
01812             uves_free_image(&absorder_image);
01813             }
01814 
01815         /* Loop over sky windows */
01816         for (window = 1; window <= NWINDOWS; window ++) {
01817             /*      
01818                 | -trace_offs- | 
01819                 |              |  -win_offs-  |
01820                 |              |              |
01821                 |              | | -glb_offs- | 
01822                         order_loc.=0       |
01823                 |
01824                 window_loc.
01825             */
01826                 
01827             /* Adjacent windows are separated by slitlength,
01828                and offset is zero when window_number = (NWINDOWS+1)/2,
01829                so the formula is */
01830             double window_offset =
01831             slitlength * (window - (NWINDOWS+1) / 2.0);
01832 
01833             /* Total offset (see sketch) */
01834             double offset = trace_offset + window_offset + OFFSET;
01835 
01836             /* Number of lines to detect. Use defaults if 
01837                parameter values are negative */
01838 #if 0
01839             int lines_min = (MINLINES >= 1) ? MINLINES : 
01840             (chip == UVES_CHIP_REDU) ? 1000 : 2000;
01841             int lines_max = (MAXLINES >= 1) ? MAXLINES : 
01842             (chip == UVES_CHIP_REDU) ? 1400 : 2400;
01843 #else
01844 /* like MIDAS (fewer lines): */
01845             int lines_min = (MINLINES >= 1) ? MINLINES : 
01846             (chip == UVES_CHIP_REDU) ? 1000 : 1100;
01847             int lines_max = (MAXLINES >= 1) ? MAXLINES : 
01848             (chip == UVES_CHIP_REDU) ? 1400 : 1600;
01849 #endif
01850 
01851             assure( lines_min <= lines_max , CPL_ERROR_ILLEGAL_INPUT, 
01852                 "Minimum and maximum number of requested line "
01853                 "detections don't make sense (min = %d; max = %d)",
01854                 lines_min, lines_max);
01855 
01856             if (NWINDOWS > 1) {
01857                 uves_msg("Processing window %d of %d", window, NWINDOWS);
01858             }
01859                     
01860             passure( *(uves_lt_get_disprel(linetable, window, trace_number))
01861                  == NULL, "%d %d", window, trace_number);
01862             passure( *(uves_lt_get_absord (linetable, window, trace_number))
01863                  == NULL, "%d %d", window, trace_number);
01864 
01865 
01866             if (weights != NULL) {
01867                 /* Object weighted extraction, use offset = 0 three times */
01868                 offset = 0;
01869             }
01870                     
01871             /* Set absord guess solution */
01872             *uves_lt_get_absord(linetable, window, trace_number) = 
01873             uves_polynomial_duplicate(absolute_order);
01874 
01875             /* Execute macrosteps */
01876             check( *uves_lt_get_table(linetable, window, trace_number) =
01877                    uves_wavecal_process_window(
01878                        /* Raw */
01879                        arclamp[raw_index], 
01880                        arclamp_noise,
01881                        rotated_header[raw_index],
01882                        /* Calibration */
01883                        ordertable, order_locations,
01884                        master_flat != NULL,
01885                        weights,
01886                        /* drs_table,  not used */
01887                        guess,
01888                        line_refer,
01889                        flames,
01890                        tab_in_out_oshift,
01891                        tab_in_out_yshift,
01892                    /* Which window? */
01893                        chip, biny, trace_number, window,NWINDOWS,
01894                    /* Parameters    */
01895                    DEBUG,
01896                    /* Extract       */
01897                    offset, slitlength, parameters, recipe_id,
01898                    /* Search        */
01899                    RANGE, lines_min, lines_max, CENTERING_METHOD,
01900                    /* First solution */
01901                    SHIFT_MAX, SHIFT_STEP, SHIFT_TOLERANCE,
01902                    /* Identify      */
01903                    ALPHA, MAXERROR, DEGREE,
01904                    /* Calibrate     */
01905                TOLERANCE, KAPPA,
01906                        corvel_frm,qclog,
01907                    /* Returned */
01908                    uves_lt_get_disprel(linetable, window, trace_number),
01909                    uves_lt_get_absord (linetable, window, trace_number),
01910                    uves_lt_get_firstabs(linetable, window, trace_number),
01911                    uves_lt_get_lastabs(linetable, window, trace_number)),
01912                "Wavelength calibration failed");
01913 
01914 
01915             //If CORVEL map is provided we perform the 
01916                     //corresponding analysis
01917             if(drs_cvel_sw) {
01918               /*
01919               define/local ord_min/i/1/1 0
01920               define/local ord_max/i/1/1 0
01921               define/local rsample/d/1/1 0
01922               statistic/table {ORDTAB} :ORDER >Null
01923               ord_min = outputr(1)
01924               ord_max = outputr(2)
01925               rsample = {{LINTAB},PIXEL(1)}
01926               rsample = 2./3. * rsample
01927               rebin/echelle  {ofrm} w{ofrm} {rsample} NONL {LINTAB} {SESSOUTV}
01928               mercut/echelle w{ofrm} mw{ofrm} {ord_min},{ord_max} NOAPPEND 
01929               !corvel stuff
01930               define/local OLD_CVEL_MAX/d/1/1 {DRS_CVEL_MAX}
01931               define/local OLD_CVEL_MIN/d/1/1 {DRS_CVEL_MIN}
01932               @p flames_reduce,VCORREL x1_rbf_ cvel1 0 {ord_max} {parCorVelTab} _0 _{chip({PATHID})} 0
01933               DRS_CVEL_MAX = DRS_CVEL_MAX + {q1}
01934               DRS_CVEL_MIN = DRS_CVEL_MIN + {q1}
01935 
01936               @p flames_reduce,VCORREL x1_rbf_ cvel2 0 {ord_max} {parCorVelTab} _0 _{chip({PATHID})} 0
01937               cvel_0 = {q1}
01938               DRS_CVEL_MAX = OLD_CVEL_MAX
01939               DRS_CVEL_MIN = OLD_CVEL_MIN
01940               */
01941 
01942 
01943             }
01944 
01945 
01946 
01947             if (flames ||                             /* FLAMES: all fibres */
01948             (window == 2 && trace_number == 0)|| /* UVES: central window */
01949             (window == 1 && NWINDOWS == 1)) { /* UVES: special user setting */
01950 
01951             check( uves_wavecal_qclog(
01952                    *uves_lt_get_table(
01953                        linetable,
01954                        window,
01955                        trace_number),
01956                                    *uves_lt_get_firstabs(linetable, window, trace_number),
01957                                    *uves_lt_get_lastabs(linetable, window, trace_number),
01958                    arclamp[raw_index], 
01959                    arclamp_header[raw_index],
01960                    flames, 
01961                    trace_number, trace_enabled, trace_offset,
01962                    chip,
01963                                    qclog[0]),
01964                    "Could not calculate resolution QC parameters");
01965 
01966             if (line_intmon != NULL) {
01967                 check( uves_wavecal_qclog_intmon(
01968                        *uves_lt_get_table(
01969                        linetable,
01970                        window,
01971                        trace_number), 
01972                        line_intmon,
01973                        arclamp_header[raw_index],
01974                        flames, trace_number,
01975                        chip,
01976                        qclog[1]),
01977                    "Could not calculate int.mon. QC parameters");
01978             }
01979             else
01980                 {
01981                 /* Kill initialization and set pointer to NULL */
01982                 uves_qclog_delete(&qclog[1]);
01983                 }
01984             }
01985                     
01986             /* Finished processing. Save later (because
01987                all QC parameters must be available
01988                when the product file is first created). */
01989 
01990         }/* for each window... */
01991             
01992         }/* if trace enabled? */
01993         else
01994         {
01995             uves_msg("Skipping trace number %d", trace_number);
01996         }
01997     }/* for each trace... */
01998 
01999     /* Finished calculating all line tables for current chip. Now save. */
02000 
02001     /* Prepare product filename 
02002        (which need not be calculated for each trace and window) */
02003     cpl_free(product_filename);
02004     check( product_filename = uves_line_table_filename(chip), "Error getting filename");
02005     current_linetable_extension = 1;
02006         
02007     /* Loop over traces */
02008     for(tracerow = 0; tracerow < cpl_table_get_nrow(traces); tracerow++)
02009         {
02010         int trace_number;
02011         double trace_offset;
02012         int trace_enabled;
02013             
02014         trace_offset  = cpl_table_get_double(traces, "Offset"    , tracerow, NULL);
02015         trace_number  = cpl_table_get_int   (traces, "TraceID"   , tracerow, NULL);
02016         trace_enabled = cpl_table_get_int   (traces, "Tracemask" , tracerow, NULL);
02017             
02018         if (trace_enabled != 0)
02019                     {
02020             int window;
02021                 
02022             /* Loop over sky windows */
02023             for (window = 1; window <= NWINDOWS; window ++)
02024                 {
02025                 double window_offset =
02026                     slitlength * (window - (NWINDOWS+1) / 2.0);
02027             
02028                 double offset = trace_offset + window_offset + OFFSET;
02029         
02030                 /* Table header */
02031                 uves_free_propertylist(&table_header);
02032                 table_header   = uves_propertylist_new();
02033                 check( uves_pfits_set_traceid     ( table_header, trace_number),
02034                        "Error writing trace ID to product header");
02035                 check( uves_pfits_set_offset      ( table_header, offset),
02036                        "Error writing trace offset to product header");
02037                 check( uves_pfits_set_windownumber( table_header, window),
02038                        "Error writing window number to product header");
02039                 check( uves_pfits_set_firstabsorder( table_header, 
02040                                      *uves_lt_get_firstabs(
02041                                      linetable, 
02042                                      window,
02043                                      trace_number)),
02044                        "Error writing order number to product header");
02045                 check( uves_pfits_set_lastabsorder( table_header,
02046                                     *uves_lt_get_lastabs(
02047                                     linetable, 
02048                                     window,
02049                                     trace_number)),
02050                        "Error writing order number to product header");
02051 
02052                 /* Save line table + 2 polynomials (in 3 extensions) */
02053 
02054                 if (current_linetable_extension == 1) {
02055                     uves_free_propertylist(&primary_header);
02056                     primary_header = uves_propertylist_new();
02057                     
02058                     if (flames)
02059               {
02060             char values[80];
02061             /* The MIDAS pipeline writes this QC to the
02062                header (always zero), but not as part of
02063                the QC logging */
02064             check_nomsg( uves_flames_pfits_set_ccfposmax(
02065                                      primary_header, 0.0) );
02066             //Add descriptors needed for science reduction
02067             /* FIBREMASK */
02068 
02069             uves_propertylist_append_string(primary_header, 
02070                             "HISTORY", 
02071                             "'FIBREMASK','I*4'");
02072 
02073             {
02074               int i;
02075               for (i = 0; i < N_FIBRES_MAX; i++) {
02076                 snprintf(values, 80, "%1.1d ",
02077                      cpl_table_get_int(traces,"Tracemask",
02078                                i,NULL));
02079                 uves_propertylist_append_string(primary_header,
02080                                 "HISTORY", values);
02081                 uves_msg_debug("value=%d",
02082                          cpl_table_get_int(traces,
02083                                    "Tracemask",
02084                                    i,NULL));
02085               }
02086             }
02087             uves_propertylist_append_string(primary_header,
02088                             "HISTORY", " ");
02089 
02090 
02091             /* PIXEL */        
02092                         double pixelsize;
02093                         double wavestep;
02094 
02095             check( pixelsize = 
02096                    cpl_table_get_column_mean(
02097                              *uves_lt_get_table(
02098                                         linetable,
02099                                         window,
02100                                         trace_number),
02101                              LINETAB_PIXELSIZE),
02102                    "Error reading mean pixelsize");
02103             uves_msg_warning("Average pixelsize = %f w.l.u.", 
02104                        pixelsize);
02105 
02106             wavestep = pixelsize*2.0/3;
02107 
02108             uves_propertylist_append_string(primary_header, 
02109                             "HISTORY", 
02110                             "'PIXEL','R*4'");
02111             snprintf(values,80,"%14.7g %14.7g",pixelsize,pixelsize);
02112             uves_propertylist_append_string(primary_header,
02113                             "HISTORY", values);
02114             uves_propertylist_append_string(primary_header,
02115                             "HISTORY", " ");
02116                       
02117 
02118 
02119               }
02120                     
02121                     uves_msg("Creating line table '%s'", product_filename);
02122                     check( uves_frameset_insert(
02123                            frames,
02124                            *uves_lt_get_table(
02125                                linetable,
02126                                window,
02127                                trace_number),
02128                            CPL_FRAME_GROUP_PRODUCT,
02129                            CPL_FRAME_TYPE_TABLE,
02130                            CPL_FRAME_LEVEL_INTERMEDIATE,
02131                            product_filename,
02132                            UVES_LINE_TABLE(flames, chip),
02133                            arclamp_header[raw_index],     
02134                            primary_header,
02135                            table_header,
02136                            parameters,
02137                            recipe_id,
02138                            PACKAGE "/" PACKAGE_VERSION,
02139                            qclog, starttime, true, 0),
02140                            "Could not add line table '%s' (%s) to frameset",
02141                            product_filename, UVES_LINE_TABLE(flames, chip));
02142                         
02143                     uves_msg("Line table '%s' (%s) added to frameset",
02144                          product_filename, UVES_LINE_TABLE(flames, chip));
02145                     }
02146                 else   /* If this is not the first line table, 
02147                       append to the existing file */
02148                     {
02149                     check( uves_table_save(
02150                            *uves_lt_get_table(linetable,
02151                                       window,
02152                                       trace_number),
02153                            NULL,            /* Primary header,
02154                                        ignored when mode
02155                                        is IO_EXTEND */
02156                            table_header,    /* Extension header */
02157                            product_filename,/* This file 
02158                                        already exists */
02159                            CPL_IO_EXTEND),   /* Append to
02160                                     existing file */
02161                            "Error appending table to file '%s'", 
02162                            product_filename);
02163                     }
02164                 current_linetable_extension += 1;
02165                 
02166                 /* Save in next extension */
02167                 check( uves_save_polynomial(*uves_lt_get_disprel(
02168                                 linetable, 
02169                                 window,
02170                                 trace_number),
02171                                 product_filename,
02172                                 table_header), 
02173                        "Could not write polynomial to file '%s'", 
02174                        product_filename);
02175                 current_linetable_extension += 1;
02176 
02177                 /* Save in next extension */
02178                 check( uves_save_polynomial(*uves_lt_get_absord(
02179                                 linetable, 
02180                                 window,
02181                                 trace_number), 
02182                                 product_filename,
02183                                 table_header), 
02184                        "Could not write polynomial to file '%s'", 
02185                        product_filename);
02186                 current_linetable_extension += 1;
02187 
02188                 uves_msg("Line table for trace %d, window #%d "
02189                      "saved to extensions %d-%d of '%s'",
02190                      trace_number, window, 
02191                      current_linetable_extension - 3,
02192                      current_linetable_extension - 1, 
02193                      product_filename);
02194 
02195                 } /* for each window */
02196             } /* if trace enabled */
02197         } /* for each trace */
02198 
02199       if(strcmp(PROCESS_CHIP,"REDL") == 0) {
02200     chip = uves_chip_get_next(chip);
02201       }
02202 
02203 
02204     }/* For each chip */
02205 
02206   cleanup:
02207 
02208     /* Input */
02209     uves_free_image(&arclamp[0]);
02210     uves_free_image(&arclamp[1]);
02211     uves_free_image(&arclamp_noise);
02212     uves_free_image(&absorder_image);
02213     uves_free_propertylist(&arclamp_header[0]);
02214     uves_free_propertylist(&arclamp_header[1]);
02215     uves_free_propertylist(&rotated_header[0]);
02216     uves_free_propertylist(&rotated_header[1]);
02217 
02218 
02219     uves_free_table(&ordertable);
02220     uves_free_propertylist(&ordertable_header);
02221     uves_free_table(&corvel);
02222     uves_free_propertylist(&corvel_header);
02223     uves_polynomial_delete(&order_locations);
02224     uves_polynomial_delete(&absolute_order);
02225     uves_free_table(&traces);
02226 
02227     
02228     uves_free_image(&master_bias);
02229     uves_free_propertylist(&master_bias_header);
02230     uves_free_image(&master_flat);
02231     uves_free_image(&mflat_noise);
02232     uves_free_propertylist(&master_flat_header);
02233     uves_free_image(&weights);
02234 
02235     
02236     /* DRS not used
02237        uves_free_table(&drs_table);
02238        uves_free_propertylist(&drs_header);
02239     */
02240     
02241     uves_free_table(&guess);
02242 
02243     uves_free_table(&line_refer);
02244     uves_free_table(&line_intmon);
02245 
02246 
02247     /* Output */
02248     uves_lt_delete(&linetable);
02249     uves_free_propertylist(&primary_header);
02250     uves_free_propertylist(&table_header);
02251     uves_qclog_delete(&qclog[0]);
02252     uves_qclog_delete(&qclog[1]);
02253 
02254     cpl_free(product_filename);
02255     cpl_free(temp);
02256      
02257     return;
02258 }
02259 
02260 
02273 static void uves_wavecal_qclog(const cpl_table* linetable,
02274                                int firstabs,
02275                                int lastabs,
02276                    const cpl_image *arclamp,
02277                    const uves_propertylist* raw_header,
02278                    bool flames,
02279                    int trace_number,
02280                    int fibre_mask,
02281                    double offset,
02282                    enum uves_chip chip,
02283                    cpl_table* qclog)
02284 {
02285 
02286     const char *qc_fib_drsno_name= uves_qclog_get_qc_name("DRSNO", flames, trace_number);
02287     const char *qc_fib_seq_name  = uves_qclog_get_qc_name("SEQ", flames, trace_number);
02288     const char *qc_fib_pos_name  = uves_qclog_get_qc_name("POS", flames, trace_number);
02289     const char *qc_fib_msk_name  = uves_qclog_get_qc_name("MSK", flames, trace_number);
02290     const char *qc_fwhmavg_name  = uves_qclog_get_qc_name("FWHMAVG", flames, trace_number);
02291     const char *qc_fwhmrms_name  = uves_qclog_get_qc_name("FWHMRMS", flames, trace_number);
02292     const char *qc_fwhmmed_name  = uves_qclog_get_qc_name("FWHMMED", flames, trace_number);
02293     const char *qc_resolavg_name = uves_qclog_get_qc_name("RESOLAVG", flames, trace_number);
02294     const char *qc_resolrms_name = uves_qclog_get_qc_name("RESOLRMS", flames, trace_number);
02295     const char *qc_resolmed_name = uves_qclog_get_qc_name("RESOLMED", flames, trace_number);
02296     const char *qc_wlenmin_name  = uves_qclog_get_qc_name("WLENMIN", flames, trace_number);
02297     const char *qc_wlenmax_name  = uves_qclog_get_qc_name("WLENMAX", flames, trace_number);
02298     const char *qc_ordmin_name   = uves_qclog_get_qc_name("ORDMIN", flames, trace_number);
02299     const char *qc_ordmax_name   = uves_qclog_get_qc_name("ORDMAX", flames, trace_number);
02300     const char *qc_nlintot_name  = uves_qclog_get_qc_name("NLINTOT", flames, trace_number);
02301     const char *qc_nlinsel_name  = uves_qclog_get_qc_name("NLINSEL", flames, trace_number);
02302     const char *qc_nlinsol_name  = uves_qclog_get_qc_name("NLINSOL", flames, trace_number);
02303     const char *qc_nlinres1_name = uves_qclog_get_qc_name("NLINRES1", flames, trace_number);
02304     const char *qc_lineresidavg_name = 
02305     uves_qclog_get_qc_name("LINE RESIDAVG", flames, trace_number);
02306     const char *qc_lineresidrms_name = 
02307     uves_qclog_get_qc_name("LINE RESIDRMS", flames, trace_number);
02308     char comment[80];
02309     cpl_table *selected = NULL;
02310 
02311     char test_id[80];
02312     sprintf(test_id,"%sResolution-Test-Results",flames ? "Fibre-" : "");
02313 
02314     check_nomsg(uves_qclog_add_string(qclog,
02315                       "QC TEST1 ID",
02316                       test_id,
02317                       "Name of QC test",
02318                       "%s"));
02319 
02320     check_nomsg( uves_qclog_add_common_wave(raw_header, chip, qclog) );
02321 
02322     if (flames)
02323     {
02324         /* Fibre ID */
02325         check_nomsg(uves_qclog_add_int(qclog,
02326                        qc_fib_drsno_name,
02327                        trace_number + 1,
02328                        "DRS det. fibre seq. pos.",
02329                        "%d"));
02330         
02331         /* Index */
02332         check_nomsg(uves_qclog_add_int(qclog,
02333                        qc_fib_seq_name,
02334                        trace_number + 1,
02335                        "det. fibre seq. no.",
02336                        "%d"));
02337 
02338         check_nomsg(uves_qclog_add_double(qclog,
02339                           qc_fib_pos_name,
02340                           offset,
02341                           "det. fibre seq. rel. pos.",
02342                           "%.4f"));
02343 
02344         check_nomsg(uves_qclog_add_int(qclog,
02345                        qc_fib_msk_name,
02346                        fibre_mask,
02347                        "DRS det. fibre mask value",
02348                        "%d"));
02349 
02350         {
02351 
02352         double exptime;
02353       
02354         check( exptime = uves_flames_pfits_get_dit(raw_header),
02355                "Error reading exposure time");
02356       
02357         check_nomsg(uves_qclog_add_double(qclog,
02358                           "QC FIB ABSTRANS",
02359                           cpl_image_get_flux(arclamp) / exptime,
02360                           "abs. trans. countrate",
02361                           "%.4f"));
02362         }
02363         {
02364         int n_hpix;
02365         int x, y;
02366       
02367         n_hpix = 0;
02368         for (y = 1; y <= cpl_image_get_size_y(arclamp); y++)
02369             for (x = 1; x <= cpl_image_get_size_x(arclamp); x++)
02370             {
02371                 int pis_rejected;
02372                 int value = cpl_image_get(arclamp, x, y, &pis_rejected);
02373           
02374                 if (!pis_rejected &&
02375                 (value < DRS_PTHRES_MIN || value > DRS_PTHRES_MAX))
02376                 {
02377                     n_hpix += 1;
02378                 }
02379             }
02380 
02381         check_nomsg(uves_qclog_add_int(qclog,
02382                            "QC NHOTPIX",
02383                            n_hpix,
02384                            "no. of hot pixels",
02385                            "%d"));
02386       
02387         }
02388   
02389         {
02390         int plate_id;
02391         check( plate_id = uves_flames_pfits_get_plateid(raw_header),
02392                "Error reading plate ID");
02393         check_nomsg(uves_qclog_add_int(qclog,
02394                            "QC PLATENO",
02395                            plate_id,
02396                            "Plate Id.",
02397                            "%d"));
02398         }
02399 
02400     } /* if flames */
02401 
02402     /* FLAMES + UVES common QC params */
02403     selected = uves_extract_table_rows(linetable, "NLinSol", CPL_NOT_EQUAL_TO, 0);
02404     /* FWHM in pixels */
02405     sprintf(comment,"average FWHM in X of lines selected on trace %d",trace_number+1);
02406     check_nomsg(uves_qclog_add_double(qclog,
02407                       qc_fwhmavg_name,
02408                       cpl_table_get_column_mean(selected,"Xwidth")*TWOSQRT2LN2,
02409                       comment,
02410                       "%.2f"));
02411 
02412     sprintf(comment,"stdev FWHM in X of lines selected on trace %d",trace_number+1);
02413     check_nomsg(uves_qclog_add_double(qclog,
02414                       qc_fwhmrms_name,
02415                       cpl_table_get_column_stdev(selected,"Xwidth")*TWOSQRT2LN2,
02416                       comment,
02417                       "%.4f"));
02418 
02419     sprintf(comment,"median FWHM in X of lines selected on trace %d",trace_number+1);
02420     check_nomsg(uves_qclog_add_double(qclog,
02421                       qc_fwhmmed_name,
02422                       cpl_table_get_column_median(selected,"Xwidth")*TWOSQRT2LN2,
02423                       comment,
02424                       "%.4f"));
02425    
02426     sprintf(comment,"mean resol power of lines selected on trace %d",trace_number+1);
02427     check_nomsg(uves_qclog_add_double(qclog,
02428                       qc_resolavg_name,
02429                       cpl_table_get_column_mean(selected,"Resol"),
02430                       comment,
02431                       "%.4f"));
02432 
02433     sprintf(comment,"stdev resol power of lines selected on trace %d",trace_number+1);
02434     check_nomsg(uves_qclog_add_double(qclog,
02435                       qc_resolrms_name,
02436                       cpl_table_get_column_stdev(selected,"Resol"),
02437                       comment,
02438                       "%.4f"));
02439 
02440     sprintf(comment,"median resol power of lines selected on trace %d",trace_number+1);
02441     check_nomsg(uves_qclog_add_double(qclog,
02442                       qc_resolmed_name,
02443                       cpl_table_get_column_median(selected,"Resol"),
02444                       comment,
02445                       "%.4f"));
02446 
02447     /* Convert A -> picometers */
02448     sprintf(comment,"mean resid of line pos to fit on trace %d",trace_number+1);
02449     check_nomsg(uves_qclog_add_double(qclog,
02450                       qc_lineresidavg_name,
02451                       cpl_table_get_column_mean(selected, LINETAB_RESIDUAL)*100,
02452                       comment,
02453                       "%.4f"));
02454 
02455     sprintf(comment,"sigma resid of line pos to fit on trace %d",trace_number+1);
02456     check_nomsg(uves_qclog_add_double(qclog,
02457                       qc_lineresidrms_name,
02458                       cpl_table_get_column_stdev(selected, LINETAB_RESIDUAL)*100,
02459                       comment,
02460                       "%.4f"));
02461 
02462     /* Convert A -> nm */
02463     sprintf(comment,"minimum wavelength on trace %d",trace_number+1);
02464     check_nomsg(uves_qclog_add_double(qclog,
02465                       qc_wlenmin_name,
02466                       cpl_table_get_column_min(linetable,LINETAB_LAMBDAC)/10.0,
02467                       comment,
02468                       "%.4f"));
02469 
02470     sprintf(comment,"maximum wavelength on trace %d",trace_number+1);
02471     check_nomsg(uves_qclog_add_double(qclog,
02472                       qc_wlenmax_name,
02473                       cpl_table_get_column_max(linetable,LINETAB_LAMBDAC)/10.0,
02474                       comment,
02475                       "%.4f"));
02476     sprintf(comment,"minimum order number detected on trace %d",trace_number+1);
02477     check_nomsg(uves_qclog_add_int(qclog,
02478                    qc_ordmin_name,
02479                    uves_min_int(firstabs, lastabs),
02480                    comment,
02481                    "%d"));
02482 
02483     sprintf(comment,"maximum order number detected on trace %d",trace_number+1);
02484     check_nomsg(uves_qclog_add_int(qclog,
02485                    qc_ordmax_name,
02486                    uves_max_int(firstabs, lastabs),
02487                    comment,
02488                    "%d"));
02489 
02490     sprintf(comment,"No of lines found on trace %d",trace_number+1);
02491     check_nomsg(uves_qclog_add_int(qclog,
02492                    qc_nlintot_name,
02493                    cpl_table_get_nrow(linetable),
02494                    comment,
02495                    "%d"));
02496 
02497     sprintf(comment,"No of lines selected on trace %d",trace_number+1);
02498     check_nomsg(uves_qclog_add_int(qclog,
02499                    qc_nlinsel_name,
02500                    cpl_table_get_nrow(linetable) -
02501                                    cpl_table_count_invalid(linetable, "Ident"),
02502                    comment,
02503                    "%d"));
02504 
02505     sprintf(comment,"No of lines used on trace %d",trace_number+1);
02506     check_nomsg(uves_qclog_add_int(qclog,
02507                    qc_nlinsol_name,
02508                    cpl_table_get_nrow(selected),
02509                    comment,
02510                    "%d"));
02511 
02512     uves_free_table(&selected);
02513     selected = cpl_table_duplicate(linetable);
02514     assure_mem( selected );
02515 
02516     /* Remove unidentified lines and
02517        lines with residual > 1 A      */
02518     check_nomsg( uves_erase_invalid_table_rows(selected, "Ident") );
02519     check_nomsg( uves_erase_table_rows(selected, LINETAB_RESIDUAL, 
02520                        CPL_NOT_LESS_THAN,
02521                        1.0) );
02522   
02523     sprintf(comment,"No of lines with residuals < 0.1 nm on trace %d",trace_number+1);
02524     check_nomsg(uves_qclog_add_int(qclog,
02525                    qc_nlinres1_name,
02526                    cpl_table_get_nrow(selected),
02527                    comment,
02528                    "%d"));
02529 
02530 
02531   cleanup:
02532 
02533     uves_free_string_const(&qc_fib_drsno_name);
02534     uves_free_string_const(&qc_fib_seq_name);
02535     uves_free_string_const(&qc_fib_pos_name);
02536     uves_free_string_const(&qc_fib_msk_name);
02537     uves_free_string_const(&qc_fwhmavg_name);
02538     uves_free_string_const(&qc_fwhmrms_name);
02539     uves_free_string_const(&qc_fwhmmed_name);
02540 
02541     uves_free_string_const(&qc_resolavg_name);
02542     uves_free_string_const(&qc_resolrms_name);
02543     uves_free_string_const(&qc_resolmed_name);
02544     uves_free_string_const(&qc_wlenmin_name);
02545     uves_free_string_const(&qc_wlenmax_name);
02546     uves_free_string_const(&qc_ordmin_name);
02547     uves_free_string_const(&qc_ordmax_name);
02548     uves_free_string_const(&qc_nlintot_name);
02549     uves_free_string_const(&qc_nlinsel_name);
02550     uves_free_string_const(&qc_nlinsol_name);
02551     uves_free_string_const(&qc_nlinres1_name);
02552     uves_free_string_const(&qc_lineresidavg_name);
02553     uves_free_string_const(&qc_lineresidrms_name);
02554 
02555     uves_free_table(&selected);
02556 
02557     return;
02558  
02559 }
02560 
02569 static void uves_wavecal_qclog_intmon(cpl_table* table,
02570                       const cpl_table *line_intmon,
02571                       const uves_propertylist* raw_header,
02572                       bool flames,
02573                       int fibre,
02574                       enum uves_chip chip,
02575                       cpl_table* qclog)
02576 {
02577     const char *qc_intavg_name = NULL;
02578     const char *qc_nlinint_name = NULL;
02579 
02580     cpl_table *temp = NULL;
02581         
02582     check_nomsg(uves_qclog_add_string(qclog,
02583                                       "QC TEST2 ID",
02584                                       flames ? "Fibre-Line-Intensity-Test-Results"
02585                                       : "Line-Intensity-Test-Results",
02586                                       "Name of QC test",
02587                                       "%s"));
02588 
02589     check_nomsg( uves_qclog_add_common_wave(raw_header,
02590                                             chip, qclog) );
02591 
02592     {
02593     double tolerance = 0.001; /* (A) 
02594                      The lines in the line table
02595                      and intmon table are considered
02596                      identical if the difference
02597                      is less than this number.
02598                   */
02599                       
02600     double exptime;
02601 
02602     int N_bright = cpl_table_get_nrow(line_intmon);
02603     int i;
02604 
02605     check( exptime = uves_pfits_get_exptime(raw_header),
02606            "Could not get exposure time");
02607     
02608     cpl_table_new_column(table, "Intensity", CPL_TYPE_DOUBLE); 
02609     for (i = 0; i < cpl_table_get_nrow(table); i++)
02610     {
02611         int is_null;
02612         double ident = cpl_table_get_double(table, "Ident", i, &is_null);
02613 
02614         if (!is_null)
02615         {
02616             int bright_index = uves_wavecal_find_nearest(
02617             line_intmon, ident, 0, N_bright-1);
02618 
02619             double bright = cpl_table_get_double(
02620             line_intmon, "Wave", bright_index, NULL);
02621 
02622             if (fabs(bright - ident) < tolerance)
02623             {
02624                 double peak = cpl_table_get_double(table, "Peak", i, NULL);
02625                 double pixelsize = 
02626                 fabs(cpl_table_get_double(table, LINETAB_PIXELSIZE, i, NULL));
02627 
02628                 double lambda_fwhm = cpl_table_get_double(table, "Xwidth", i, NULL)
02629                 * TWOSQRT2LN2 * pixelsize;
02630                 /* Line FWHM in wlu */
02631 
02632                 double intensity = peak * lambda_fwhm / exptime;
02633                 /* Same formula as in MIDAS */
02634 
02635                 cpl_table_set_double(table, "Intensity", i, intensity);
02636             }
02637             else
02638             {
02639                 cpl_table_set_invalid(table, "Intensity", i);
02640             }
02641         }
02642         else
02643         {
02644             cpl_table_set_invalid(table, "Intensity", i);
02645         }
02646     }
02647     }
02648 
02649     uves_free_table(&temp);
02650     temp = cpl_table_duplicate(table);
02651     uves_erase_invalid_table_rows(temp, "Intensity");
02652 
02653     {
02654     double mean;
02655     if (cpl_table_get_nrow(temp) == 0)
02656         {
02657         uves_msg_warning("No bright lines found!");
02658         mean = 0;
02659         }
02660     else
02661         {
02662         mean = cpl_table_get_column_mean(temp, "Intensity");
02663         }
02664 
02665     if (flames)
02666         {
02667         qc_intavg_name  = uves_sprintf("QC FIB%d INTAVG", fibre+1); /* Count 1-9 */
02668         qc_nlinint_name = uves_sprintf("QC FIB%d NLININT", fibre+1);
02669         }
02670     else
02671         {
02672         qc_intavg_name  = uves_sprintf("QC INTAVG");
02673         qc_nlinint_name = uves_sprintf("QC NLININT");
02674         }
02675         
02676     check_nomsg(uves_qclog_add_double(qclog,
02677                       qc_intavg_name,
02678                       mean,
02679                       "average intensity of line list",
02680                       "%.4f"));
02681     
02682     check_nomsg(uves_qclog_add_int(qclog,
02683                        qc_nlinint_name,
02684                        cpl_table_get_nrow(temp),
02685                        "No of lines to measure INTAVG",
02686                        "%d"));
02687     }
02688 
02689  cleanup:
02690     uves_free_string_const(&qc_intavg_name);
02691     uves_free_string_const(&qc_nlinint_name);
02692   uves_free_table(&temp);
02693   return;
02694 }
02695 
02696 

Generated on 8 Mar 2011 for UVES Pipeline Reference Manual by  doxygen 1.6.1