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

Generated on Tue Jun 19 14:39:20 2007 for UVES Pipeline Reference Manual by  doxygen 1.4.6