uves_orderpos_body.c

00001 /*                                                                              *
00002  *   This file is part of the ESO UVES Pipeline                                 *
00003  *   Copyright (C) 2004,2005 European Southern Observatory                      *
00004  *                                                                              *
00005  *   This library is free software; you can redistribute it and/or modify       *
00006  *   it under the terms of the GNU General Public License as published by       *
00007  *   the Free Software Foundation; either version 2 of the License, or          *
00008  *   (at your option) any later version.                                        *
00009  *                                                                              *
00010  *   This program is distributed in the hope that it will be useful,            *
00011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of             *
00012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
00013  *   GNU General Public License for more details.                               *
00014  *                                                                              *
00015  *   You should have received a copy of the GNU General Public License          *
00016  *   along with this program; if not, write to the Free Software                *
00017  *   Foundation, 51 Franklin St, Fifth Floor, Boston, MA  02111-1307  USA       *
00018  *                                                                              */
00019  
00020 /*
00021  * $Author: amodigli $
00022  * $Date: 2007/06/06 08:17:33 $
00023  * $Revision: 1.24 $
00024  * $Name: uves-3_3_1 $
00025  * $Log: uves_orderpos_body.c,v $
00026  * Revision 1.24  2007/06/06 08:17:33  amodigli
00027  * replace tab with 4 spaces
00028  *
00029  * Revision 1.23  2007/05/22 14:34:32  jmlarsen
00030  * Removed unnecessary includes
00031  *
00032  * Revision 1.22  2007/04/24 16:45:17  amodigli
00033  * changed interface of calls to uves_load_ordertable to match new interface
00034  *
00035  * Revision 1.21  2007/04/24 12:50:29  jmlarsen
00036  * Replaced cpl_propertylist -> uves_propertylist which is much faster
00037  *
00038  * Revision 1.20  2007/04/17 09:34:38  jmlarsen
00039  * Parametrize the assumption about consecutive orders (for FLAMES support)
00040  *
00041  * Revision 1.19  2007/04/12 12:01:44  jmlarsen
00042  * Skip Hough transform if guess table is provided
00043  *
00044  * Revision 1.18  2007/04/03 06:29:21  amodigli
00045  * changed interface to uves_load_ordertable
00046  *
00047  * Revision 1.17  2007/03/28 14:02:18  jmlarsen
00048  * Removed unused parameter
00049  *
00050  * Revision 1.16  2007/03/28 11:38:55  jmlarsen
00051  * Killed MIDAS flag, removed dead code
00052  *
00053  * Revision 1.15  2006/12/11 12:34:58  jmlarsen
00054  * Fixed QC bugs
00055  *
00056  * Revision 1.14  2006/12/11 11:06:44  jmlarsen
00057  * Read QC chip name from input header
00058  *
00059  * Revision 1.13  2006/12/07 08:24:21  jmlarsen
00060  * Factored some common QC parameters
00061  *
00062  * Revision 1.12  2006/12/01 12:26:51  jmlarsen
00063  * Factored out FLAMES plate-id code
00064  *
00065  * Revision 1.11  2006/11/16 14:12:21  jmlarsen
00066  * Changed undefined trace number from 0 to -1, to support zero as an actual trace number
00067  *
00068  * Revision 1.10  2006/11/16 09:49:25  jmlarsen
00069  * Fixed doxygen bug
00070  *
00071  * Revision 1.9  2006/11/15 15:02:14  jmlarsen
00072  * Implemented const safe workarounds for CPL functions
00073  *
00074  * Revision 1.7  2006/11/15 14:04:08  jmlarsen
00075  * Removed non-const version of parameterlist_get_first/last/next which is 
00076  * already in CPL, added const-safe wrapper, unwrapper and deallocator functions
00077  *
00078  * Revision 1.6  2006/11/13 12:46:26  jmlarsen
00079  * Added doc.
00080  *
00081  * Revision 1.5  2006/11/06 15:19:41  jmlarsen
00082  * Removed unused include directives
00083  *
00084  * Revision 1.4  2006/10/26 14:03:33  jmlarsen
00085  * Fixed position of const modifier
00086  *
00087  * Revision 1.3  2006/10/25 07:22:59  jmlarsen
00088  * Fixed wrong parameter context: hough -> trace
00089  *
00090  * Revision 1.2  2006/10/24 14:42:26  jmlarsen
00091  * Added plate number logging
00092  *
00093  * Revision 1.34  2006/10/17 12:33:02  jmlarsen
00094  * Added semicolon at UVES_RECIPE_DEFINE invocation
00095  *
00096  * Revision 1.33  2006/10/09 13:01:13  jmlarsen
00097  * Use macro to define recipe interface functions
00098  *
00099  * Revision 1.32  2006/09/20 12:53:57  jmlarsen
00100  * Replaced stringcat functions with uves_sprintf()
00101  *
00102  * Revision 1.31  2006/09/19 14:31:10  jmlarsen
00103  * uves_insert_frame(): use bitmap to specify which image statistics keywords must be computed
00104  *
00105  * Revision 1.30  2006/09/19 06:55:11  jmlarsen
00106  * Changed interface of uves_frameset to optionally write image statistics kewwords
00107  *
00108  * Revision 1.29  2006/08/24 11:36:37  jmlarsen
00109  * Write recipe start/stop time to header
00110  *
00111  * Revision 1.28  2006/08/18 13:35:42  jmlarsen
00112  * Fixed/changed QC parameter formats
00113  *
00114  * Revision 1.27  2006/08/11 14:56:05  amodigli
00115  * removed Doxygen warnings
00116  *
00117  * Revision 1.26  2006/08/07 11:35:35  jmlarsen
00118  * Disabled parameter environment variable mode
00119  *
00120  * Revision 1.25  2006/07/14 12:19:28  jmlarsen
00121  * Support multiple QC tests per product
00122  *
00123  * Revision 1.24  2006/07/03 14:20:39  jmlarsen
00124  * Exclude bad pixels from order tracing
00125  *
00126  * Revision 1.23  2006/07/03 13:09:24  amodigli
00127  * adjusted description display layout
00128  *
00129  * Revision 1.22  2006/07/03 12:46:34  amodigli
00130  * updated description
00131  *
00132  * Revision 1.21  2006/06/22 12:13:10  amodigli
00133  * removed ESO prefix
00134  *
00135  * Revision 1.20  2006/06/22 06:44:06  amodigli
00136  * added some QC param
00137  *
00138  * Revision 1.19  2006/06/16 08:25:34  jmlarsen
00139  * Do the order tracing on non-median filtered frame
00140  *
00141  * Revision 1.18  2006/06/13 11:57:02  jmlarsen
00142  * Check that calibration frames are from the same chip ID
00143  *
00144  * Revision 1.17  2006/06/08 11:40:50  amodigli
00145  * added check to have output order table as input guess, if provided
00146  *
00147  * Revision 1.16  2006/06/08 08:42:53  jmlarsen
00148  * Added support for computing Hough transform on image subwindow
00149  *
00150  * Revision 1.15  2006/06/07 13:06:28  jmlarsen
00151  * Changed doxygen tag addtogroup -> defgroup
00152  *
00153  * Revision 1.14  2006/06/07 09:01:28  amodigli
00154  * added some doc
00155  *
00156  * Revision 1.13  2006/06/06 08:40:10  jmlarsen
00157  * Shortened max line length
00158  *
00159  * Revision 1.12  2006/05/09 15:42:00  amodigli
00160  * added QC log
00161  *
00162  * Revision 1.11  2006/05/08 15:41:32  amodigli
00163  * added order table chopping (commented out)
00164  *
00165  * Revision 1.10  2006/05/05 13:55:17  jmlarsen
00166  * Minor doc update
00167  *
00168  * Revision 1.9  2006/04/20 10:47:39  amodigli
00169  * added qclog
00170  *
00171  * Revision 1.8  2006/04/06 09:48:15  amodigli
00172  * changed uves_frameset_insert interface to have QC log
00173  *
00174  * Revision 1.7  2006/04/06 08:46:40  jmlarsen
00175  * Changed default polynomial degrees to auto
00176  *
00177  * Revision 1.6  2006/03/24 14:04:14  jmlarsen
00178  * Changed background subtraction sample density default parameter value
00179  *
00180  * Revision 1.5  2006/03/09 10:53:41  jmlarsen
00181  * Changed default bivariate degrees to MIDAS values
00182  *
00183  * Revision 1.4  2006/03/03 13:54:11  jmlarsen
00184  * Changed syntax of check macro
00185  *
00186  * Revision 1.3  2006/02/28 09:15:22  jmlarsen
00187  * Minor update
00188  *
00189  * Revision 1.2  2006/02/21 14:26:54  jmlarsen
00190  * Minor changes
00191  *
00192  * Revision 1.1  2006/02/03 07:46:30  jmlarsen
00193  * Moved recipe implementations to ./uves directory
00194  *
00195  * Revision 1.63  2006/01/19 08:47:24  jmlarsen
00196  * Inserted missing doxygen end tag
00197  *
00198  * Revision 1.62  2006/01/05 14:31:31  jmlarsen
00199  * Checking for guess DRS table before guess order table
00200  *
00201  * Revision 1.61  2005/12/20 16:10:32  jmlarsen
00202  * Added some documentation
00203  *
00204  * Revision 1.60  2005/12/19 16:17:55  jmlarsen
00205  * Replaced bool -> int
00206  *
00207  */
00208 #ifdef HAVE_CONFIG_H
00209 #  include <config.h>
00210 #endif
00211 
00212 /*----------------------------------------------------------------------------*/
00216 /*----------------------------------------------------------------------------*/
00217 
00218 /*-----------------------------------------------------------------------------
00219                                 Includes
00220  -----------------------------------------------------------------------------*/
00221 
00222 #include <uves_orderpos_body.h>
00223 
00224 #include <uves_orderpos_hough.h>
00225 #include <uves_orderpos_follow.h>
00226 
00227 #include <uves_physmod_chop_otab.h>
00228 #include <uves_corrbadpix.h>
00229 #include <uves_utils.h>
00230 #include <uves_recipe.h>
00231 #include <uves_parameters.h>
00232 #include <uves_backsub.h>
00233 #include <uves_pfits.h>
00234 #include <uves_dfs.h>
00235 #include <uves_qclog.h>
00236 #include <uves_utils_wrappers.h>
00237 #include <uves_utils_cpl.h>
00238 #include <uves_error.h>
00239 #include <uves_msg.h>
00240 
00241 #include <irplib_access.h>
00242 #include <cpl.h>
00243 
00244 #include <float.h>
00245 
00246 /*-----------------------------------------------------------------------------
00247                             Functions prototypes
00248  -----------------------------------------------------------------------------*/
00249 /* compute qclog */
00250 static void uves_orderpos_qclog(cpl_table* table,
00251                 bool flames,
00252                 int pord, 
00253                 int dord,
00254                 int samples_per_order,
00255                 uves_propertylist* rhead, 
00256                 enum uves_chip chip,
00257                 cpl_table* qclog);
00258 
00261 /*-----------------------------------------------------------------------------
00262                             Exported variables
00263  -----------------------------------------------------------------------------*/
00264 
00265 const char * const uves_orderpos_desc_short = "Defines echelle order positions";
00266 const char * const uves_orderpos_desc =
00267 "The recipe defines the order positions in an echelle image. The orders are\n"
00268 "initially detected by means of a Hough transformation, the orders are then \n"
00269 "traced, and the positions are finally fitted with a global polynomial.\n"
00270 "\n"
00271 "Expected input frames are narrow flat fields, ORDER_FLAT_xxx, or standard \n"
00272 "stars, STANDARD_xxx, where xxx is 'BLUE' or 'RED', and optionally for each \n"
00273 "chip a DRS setup table (DRS_TABLE_BLUE, DRS_TABLE_REDL, DRS_TABLE_REDU) or \n"
00274 "guess order table (ORDER_GUESS_TAB_BLUE, ORDER_GUESS_TAB_REDL, \n"
00275 "ORDER_GUESS_TAB_REDU, \n"
00276 "or, for backward compatibility, ORDER_TABLE_BLUE, ORDER_TABLE_REDL, \n"
00277 "ORDER_TABLE_REDU). The recipe processes only the first raw frame found.\n"
00278 "\n"
00279 "Output is one (or two if input is a red frame) order table(s) \n"
00280 "(UVES: ORDER_TABLE_(BLUE|REDL|REDU); FLAMES: FIB_ORDEF_(REDL|REDU) contaning\n"
00281 "the columns:\n"
00282 "X                : Position along x\n"
00283 "Order            : Relative order number\n"
00284 "Y                : Order line centroid location\n"
00285 "Yfit             : The fitted order location\n"
00286 "dY               : Uncertainty of Y\n"
00287 "dYfit_Square     : Variance of Yfit\n"
00288 "Residual         : Y - Yfit\n"
00289 "Residual_Square  : Residual^2\n"
00290 "OrderRMS         : Root mean squared residual of initial\n"
00291 "                   one-dimensional linear fit of order\n"
00292 "\n"
00293 "The bivariate fit polynomial itself is stored in table extension no. 2.\n"
00294 "The 3rd table extension contains a table that defines the active fibre traces\n"
00295 "and their positions (for support of FLAMES/UVES)\n";
00296 
00297 
00298 /*-----------------------------------------------------------------------------
00299                               Functions code
00300  -----------------------------------------------------------------------------*/
00301 /*----------------------------------------------------------------------------*/
00308 /*----------------------------------------------------------------------------*/
00309 int
00310 uves_orderpos_define_parameters_body(cpl_parameterlist *parameters,
00311                      const char *recipe_id)
00312 {
00313     const char *subcontext;
00314 
00315     /*****************
00316      *    General    *
00317      *****************/
00318     
00319     if (uves_define_global_parameters(parameters) != CPL_ERROR_NONE)
00320     {
00321         return -1;
00322     }
00323     
00324     /*****************
00325      * Preprocessing *
00326      *****************/
00327 
00328     subcontext = "preproc";
00329     
00330     /* Radx, Rady */
00331     uves_par_new_range("radx", 
00332                CPL_TYPE_INT,
00333                "X-radius of median filtering window",
00334                2, 0, INT_MAX);
00335     
00336     uves_par_new_range("rady",
00337                CPL_TYPE_INT,
00338                "Y-radius of median filtering window",
00339                1, 0, INT_MAX);
00340 
00341     /* Mmethod */
00342     uves_par_new_enum("mmethod",
00343               CPL_TYPE_STRING,
00344               "Background subtraction method. If equal "
00345               "to 'median' the background is sampled using "
00346               "the median of a sub-window. If 'minimum', "
00347               "the minimum sub-window value is used. If "
00348               "'no', no background subtraction is done.",
00349               "median",                        /* Default */
00350               3,                               /* Number of options */
00351               "median", "minimum", "no");      /* List of options */
00352   
00353     /* Backsubgrid */
00354     uves_par_new_range("backsubgrid",
00355                CPL_TYPE_INT,
00356                "Number of grid points (in x- and y-direction) "
00357                "used to estimate "
00358                "the background (mode=poly).",
00359                50, 1, INT_MAX);
00360     
00361     /* Backsubradiusy */
00362     uves_par_new_range("backsubradiusy",
00363                CPL_TYPE_INT,
00364                "The height (in pixels) of the background "
00365                "sampling window is (2*radiusy + 1). "
00366                "This parameter is not corrected for binning.",
00367                2, 0, INT_MAX);
00368     
00369     /* Backsubkappa */
00370     uves_par_new_range("backsubkappa",
00371                CPL_TYPE_DOUBLE,
00372                "The value of kappa in the one-sided kappa-sigma "
00373                "clipping used to "
00374                "estimate the background (mode=poly).",
00375                4.0, 0.0, DBL_MAX);
00376     
00377     /* Backsubdegx, backsubdegy */
00378     uves_par_new_range("backsubdegx",
00379                CPL_TYPE_INT,
00380                "Degree (in x) of polynomial used "
00381                "to estimate the background (mode=poly).",
00382                2, 1, INT_MAX);
00383     
00384     uves_par_new_range("backsubdegy",
00385                CPL_TYPE_INT,
00386                "Degree (in y) of polynomial used "
00387                "to estimate the background (mode=poly).",
00388                2, 1, INT_MAX);
00389     
00390     /*******************
00391      * Hough detection *
00392      *******************/
00393     subcontext = "hough";  
00394 
00395     /* Samplewidth */
00396     uves_par_new_range("samplewidth",
00397                CPL_TYPE_INT,
00398                "Separation of sample traces "
00399                "(used by Hough transform) in input image",
00400                50, 1, INT_MAX);
00401     
00402     /* Minslope, Maxslope */
00403     uves_par_new_range("minslope",
00404                CPL_TYPE_DOUBLE,
00405                "Minimum possible line slope. This should "
00406                "be the 'physical' slope on the chip, "
00407                "i.e. not taking binning factors into "
00408                "account, which is handled by the recipe",
00409                0.0, 0.0, DBL_MAX);
00410     
00411     uves_par_new_range("maxslope",
00412                CPL_TYPE_DOUBLE,
00413                "Maximum possible line slope",
00414                0.2, 0.0, DBL_MAX);
00415     
00416     /* Sloperes */
00417     uves_par_new_range("sloperes",
00418                CPL_TYPE_INT,
00419                "Resolution (width in pixels) of Hough space",
00420                120, 1, INT_MAX);
00421     
00422     /* Norders */
00423     uves_par_new_range("norders",
00424                CPL_TYPE_INT,
00425                "Number of echelle orders to detect. If "
00426                "set to 0 the predicted number of orders will "
00427                "be read from the guess order table. If no "
00428                "guess order table is given, the recipe will "
00429                "try to autodetect the number of orders. If "
00430                "the raw frame is a red chip and this parameter "
00431                "is specified, the given value will be used "
00432                "for both red chips",
00433                0, 0, INT_MAX);
00434     
00435     /* Pthres */
00436     uves_par_new_range("pthres",
00437                CPL_TYPE_DOUBLE,
00438                "In automatic mode, or if the number of orders "
00439                "to detect is read from a guess table, the detection "
00440                "of new lines stops when the intensity of a candidate "
00441                "line drops to less than 'pthres' times the intensity "
00442                "of the previous detection. Otherwise - i.e. if the "
00443                "number of orders to detect was specified by setting "
00444                "the 'norders' parameters - this parameter is "
00445                "ignored.",
00446                0.2, 0.0, 1.0);
00447     
00448     /*******************
00449      * Order tracing   *
00450      *******************/
00451     subcontext = "trace";
00452 
00453     /* Tracestep */
00454     uves_par_new_range("tracestep",
00455                CPL_TYPE_INT,
00456                "The step size used when tracing the orders",
00457                10, 1, INT_MAX);
00458     
00459     /* Minthres */
00460     uves_par_new_range("minthresh",
00461                        CPL_TYPE_DOUBLE,
00462                        "The minimum threshold value is (min + "
00463                        "minthres*(max - min)). Here 'min' "
00464                "and 'max' are the lowest and highest pixel "
00465                "values in the central bin of the order",
00466                        0.2, 0.0, 1.0);
00467     
00468     /* Maxgap */
00469     uves_par_new_range("maxgap",
00470                        CPL_TYPE_DOUBLE,
00471                        "If the order line drops below detection "
00472                        "threshold, the order tracing algorithm "
00473                        "will try to jump a gap of maximum size 'maxgap' "
00474                        "multiplied by the image width",
00475                        .2, 0.0, 1.0);
00476 
00477     /***************
00478      *  Rejection  *
00479      ***************/
00480 
00481     subcontext = "reject";
00482 
00483     /* Maxrms */   /* In uves/midas default is 3.5 */
00484     uves_par_new_range("maxrms",
00485                  CPL_TYPE_DOUBLE,
00486                  "When fitting the orders with straight lines, "
00487                  "this is the maximum allowed RMS relative to "
00488                  "the median RMS of all orders",
00489                  100.0, 0.0, DBL_MAX);
00490 
00491     /* In MIDAS,  defpol=2,3 is used which is not optimal
00492        but faster than (-1,-1)               */
00493     /* Defpol1 */
00494     uves_par_new_range("defpol1",
00495                  CPL_TYPE_INT,
00496                  "The degree of the bivarite fit (cross "
00497                  "dispersion direction). If negative, "
00498                  "the degree is optimized to give the best fit",
00499                  -1,
00500                  -1, INT_MAX);
00501     
00502     /* Defpol2 */
00503     uves_par_new_range("defpol2",
00504                  CPL_TYPE_INT,
00505                  "The degree of the bivarite fit (order number). "
00506                  "If negative, "
00507                  "the degree is optimized to give the best fit",
00508                  -1,
00509                  -1, INT_MAX);
00510     
00511     /* Kappa */
00512     uves_par_new_range("kappa",
00513                  CPL_TYPE_DOUBLE,
00514                  "Used for kappa-sigma clipping of the final "
00515                  "polynomial fit. If negative, no clipping is done",
00516                  6.0, -2.0, DBL_MAX);
00517 
00518     return (cpl_error_get_code() != CPL_ERROR_NONE);
00519 }
00520 
00521 /*----------------------------------------------------------------------------*/
00569 /*----------------------------------------------------------------------------*/
00570 static cpl_table *
00571 uves_orderpos_process_chip(const cpl_image *raw_image, uves_propertylist *raw_header,
00572                const uves_propertylist *rotated_header, 
00573                enum uves_chip chip, int binx, int biny,
00574                /* General */
00575                bool      DEBUG,
00576                /* Preprocessing */
00577                int      RADX,
00578                int      RADY,
00579                background_measure_method BM_METHOD,
00580                int      BACKSUBGRID,
00581                int      BACKSUBRADIUSY,
00582                double   BACKSUBKAPPA,
00583                int      BACKSUBDEGX,
00584                int      BACKSUBDEGY,
00585                /* Hough transform */
00586                int      SAMPLEWIDTH,
00587                double   MINSLOPE,
00588                double   MAXSLOPE,
00589                int      SLOPERES,
00590                int      NORDERS,
00591                bool      norders_is_guess,
00592                double   PTHRES,
00593                /* Order following */
00594                int      TRACESTEP,
00595                double   MINTHRESH,
00596                double   MAXGAP,
00597                /* Rejection */
00598                double   MAXRMS,
00599                int      DEFPOL1,
00600                int      DEFPOL2,
00601                double   KAPPA,
00602                /* Output */
00603                polynomial **bivariate_fit,
00604                int *norders,
00605                            cpl_table* guess_table)
00606 {
00607     /* Result */
00608     cpl_table   *tracetable     = NULL;
00609 
00610     cpl_image   *noise          = NULL;    /* Image defining the noise
00611                            of the current image */
00612     cpl_image   *back_subbed    = NULL;
00613     cpl_image   *hough_trans    = NULL;
00614     polynomial  *guess_locations = NULL;
00615     
00616     /* Debug objects */
00617     cpl_image   *inputlines     = NULL; /* Hough solution drawn
00618                         on top of input image */
00619     cpl_table   *ordertable     = NULL; /* A preliminary order table
00620                         containing one row per order */
00621     cpl_image   *hough_original = NULL;
00622     int abs_ord_min=0;
00623     int abs_ord_max=0;
00624     int badpixels_marked = 0;
00625 
00626     check( back_subbed = cpl_image_duplicate(raw_image), "Error duplicating image");
00627 
00628     /* Calculate the basic order table */
00629     if(guess_table != NULL) 
00630     {
00631             /* Create a table with order lines in the same format as the
00632                Hough transform would do it, i.e. intersept + slope for each order.
00633             */
00634             int minorder = uves_round_double(
00635                 cpl_table_get_column_min(guess_table, "Order"));
00636             int maxorder = uves_round_double(
00637                 cpl_table_get_column_max(guess_table, "Order"));
00638             int nx = cpl_image_get_size_x(back_subbed);
00639             int order;
00640 
00641             {
00642                 double kappa = 4;
00643                 int max_degree = 6;
00644                 double min_rms = 0.1; /* pixels */
00645                 double mse;
00646                 check( guess_locations = uves_polynomial_regression_2d_autodegree(
00647                            guess_table,
00648                            "X", "Order", "Yfit", NULL,
00649                            NULL, NULL, NULL,
00650                            &mse, NULL, NULL,
00651                            kappa,
00652                            max_degree, max_degree, min_rms, -1,
00653                            false,
00654                            NULL, NULL, -1, NULL),
00655                    "Could not fit polynomial to provided table");
00656 
00657             uves_msg("Provided table contains orders %d - %d. RMS = %.3f pixels",
00658                      minorder, maxorder, sqrt(mse));
00659             }
00660 
00661 
00662             
00663             ordertable = cpl_table_new(maxorder - minorder + 1);
00664             cpl_table_new_column(ordertable, "Order", CPL_TYPE_INT);
00665             cpl_table_new_column(ordertable, "Intersept", CPL_TYPE_DOUBLE);
00666             cpl_table_new_column(ordertable, "Slope", CPL_TYPE_DOUBLE);
00667             cpl_table_new_column(ordertable, "Spacing", CPL_TYPE_INT);
00668 
00669             for (order = minorder; order <= maxorder; order++)
00670                 {
00671                     int row = order - minorder;
00672                     double slope = 
00673                         uves_polynomial_derivative_2d(guess_locations, nx/2, order, 1);
00674                     double intersept = uves_polynomial_evaluate_2d(guess_locations, nx/2, order)
00675                         - slope*(nx/2);
00676                     int spacing = 
00677                         uves_round_double(uves_polynomial_derivative_2d(
00678                                               guess_locations, nx/2, order, 2));
00679                     
00680                     cpl_table_set_int   (ordertable, "Order", row, order);
00681                     cpl_table_set_double(ordertable, "Slope", row, slope);
00682                     cpl_table_set_int   (ordertable, "Spacing", row, spacing);
00683                     cpl_table_set_double(ordertable, "Intersept", row, intersept);
00684                 }
00685     }
00686     else
00687         {
00688             /* Detect orders from scratch */
00689             int ymin = 1;
00690             int ymax = cpl_image_get_size_y(back_subbed);
00691 
00692             /* Remove bad/hot pixels with a median filter.
00693              * This is needed for the Hough transform, but
00694              * we trace the orders on the raw image (gives better fit).
00695              */
00696             {
00697                 bool extrapolate_border = true;     /* This is needed to avoid a sudden
00698                                                        intensity increase near the image
00699                                                        borders (which will confuse the Hough
00700                                                        transform) */
00701                 
00702                 uves_msg("Applying %dx%d median filter", RADX*2+1, RADY*2+1);
00703                 check( uves_filter_image_median(&back_subbed, RADX, RADY, extrapolate_border), 
00704                        "Could not filter image");
00705             }
00706 
00707             /* Subtract background */
00708             uves_msg("Subtracting background (grid sampling)");
00709             
00710             check( uves_backsub_poly(back_subbed,
00711                                      NULL, NULL,            /* Order locations are unknown */
00712                                      BM_METHOD,
00713                                      BACKSUBGRID,
00714                                      BACKSUBRADIUSY,
00715                                      BACKSUBDEGX,
00716                                      BACKSUBDEGY,
00717                                      BACKSUBKAPPA),
00718                    "Could not subtract background");
00719 
00720             check( ordertable = uves_hough(back_subbed,
00721                                            ymin, ymax,
00722                                            NORDERS, norders_is_guess,
00723                                            SAMPLEWIDTH,
00724                                            PTHRES,
00725                                            MINSLOPE,
00726                                            MAXSLOPE,
00727                                            SLOPERES,
00728                                            true,  /* Consecutive orders? */
00729                                            &hough_trans,
00730                                            &hough_original), 
00731                    "Could not locate echelle orders");
00732             
00733             if (DEBUG)
00734                 {
00735                     check( uves_save_image_local("Hough transform", "hough", 
00736                                                  hough_original, chip, -1, -1, NULL),
00737                            "Error saving hough image");
00738                     
00739                     check( uves_save_image_local("Hough transform (peaks deleted)", 
00740                                                  "hough_delete", hough_trans, chip, -1, -1, NULL),
00741                            "Error saving hough image");
00742                     
00743                     /* For debugging, draw Hough detected orders
00744                        (straight lines) on top of the input image */
00745                     check( inputlines = cpl_image_duplicate(raw_image), 
00746                            "Could not duplicate image");
00747                     check( uves_draw_orders(ordertable, inputlines), 
00748                            "Could not draw hough orders on image");
00749                     
00750                     check( uves_save_image_local("Lines detected by Hough transform",
00751                                                  "inputlines", inputlines, chip, -1, -1, rotated_header),
00752                            "Error saving hough image");
00753                     
00754                     uves_free_image(&inputlines);
00755                 }
00756 
00757             /* Clean up */
00758             uves_free_image(&hough_trans);
00759             uves_free_image(&hough_original);
00760         }
00761     /* Initial order detection done */
00762 
00763     /* Subtract background, but this time sample the interorder space */
00764     check(( uves_free_image(&back_subbed),
00765             back_subbed = cpl_image_duplicate(raw_image)),
00766           "Error duplicating image");
00767     
00768     uves_msg("Subtracting background (inter-order sampling)");
00769     check( uves_backsub_poly(back_subbed,
00770                              ordertable, NULL,
00771                              BM_METHOD,
00772                              BACKSUBGRID,
00773                              BACKSUBRADIUSY,
00774                              BACKSUBDEGX,
00775                              BACKSUBDEGY,
00776                              BACKSUBKAPPA),
00777            "Could not subtract background");
00778     
00779     /* Create noise image (readout + photonic noise) 
00780      * We need to do this *after* background subtraction,
00781      * because we cannot distinguish bias from scattered light
00782      * (if master bias was explicitly subtracted, we should
00783      *  define the noise model before background subtraction)
00784      */
00785     check( noise = uves_define_noise(back_subbed, raw_header, 1, chip),
00786        "Error creating noise image");
00787     
00788     if (DEBUG)
00789     {
00790         /* Save pre-processed (cropped, rotated, median filtered, 
00791            backgr. subtracted) input image  */
00792         check( uves_save_image_local("Pre-processed raw frame", "preproc", 
00793                      back_subbed, chip, -1, -1, rotated_header), 
00794            "Error saving image");
00795         
00796         /* Save noise of pre-processed input image */
00797         check( uves_save_image_local("Noise of pre-processed image", 
00798                      "preproc_noise", 
00799                      noise, chip, -1, -1, rotated_header),
00800            "Error saving image");
00801     }
00802     
00803     /* Mark bad pixels */
00804     check( badpixels_marked = 
00805        uves_correct_badpix_all(back_subbed,   /* MIDAS uses raw_image here */
00806                    raw_header, 
00807                    chip, 
00808                    binx, biny, 
00809                    true           /* Mark, don't interpolate bad pixels */
00810            ),
00811        "Error marking bad pixels");
00812     
00813     uves_msg("%d pixels marked as bad", badpixels_marked);
00814 
00815     /* Trace the orders
00816        (using the background subtracted image or not if MIDAS) */
00817     check( tracetable = uves_locate_orders(back_subbed,    /* MIDAS uses raw_image here */
00818                        noise,
00819                        ordertable,
00820                        TRACESTEP,
00821                        MINTHRESH,
00822                        MAXGAP,
00823                        MAXRMS,
00824                        DEFPOL1, DEFPOL2,
00825                        KAPPA,
00826                        bivariate_fit,
00827                        norders), "Could not trace orders");
00828     
00829 
00830 
00831     if (false)
00832         /* This is a workaround for a broken wavecal recipe in the MIDAS
00833            pipeline. There is no reason to do this in the CPL pipeline,
00834            where the wavecal recipe is able to deal with partial orders */
00835         {
00836             check(uves_physmod_chop_otab(raw_header,chip,&tracetable,"Order",
00837                                          &abs_ord_min,&abs_ord_max),
00838                   "Could not run uves_physmod_chop_otab on trace order table");
00839         }
00840 
00841 
00842     /* add QC log */
00843 
00844 
00845     /* Save basic info about orders */
00846     if (DEBUG) check( uves_save_table_local("Basic order table", "basic",
00847                         ordertable, chip, -1, -1, NULL, NULL),
00848               "Error saving table");
00849     
00850   cleanup:
00851     uves_free_image(&back_subbed);
00852     uves_free_image(&noise);
00853     uves_free_image(&hough_trans);
00854     uves_polynomial_delete(&guess_locations);
00855 
00856     /* Debug objects */
00857     uves_free_image(&hough_original);
00858     uves_free_image(&inputlines);
00859     uves_free_table(&ordertable);
00860     
00861     return tracetable;
00862 }
00863 
00864 /*----------------------------------------------------------------------------*/
00879 /*----------------------------------------------------------------------------*/
00880 void
00881 uves_orderpos_exe_body(cpl_frameset *frames,
00882                bool flames,
00883                const char *recipe_id,
00884                const cpl_parameterlist *parameters,
00885                const char *starttime)
00886 {
00887     /*
00888      * Variables that will contain the values of the recipe parameters 
00889      */
00890 
00891     /* General */
00892     bool      DEBUG;
00893     /* Preprocessing */
00894     int      RADX, RADY;
00895     background_measure_method BM_METHOD;
00896     int      BACKSUBGRID;
00897     int      BACKSUBRADIUSY;
00898     double   BACKSUBKAPPA;
00899     int      BACKSUBDEGX;
00900     int      BACKSUBDEGY;
00901     /* Hough transform */
00902     int      SAMPLEWIDTH;
00903     double   MINSLOPE, MAXSLOPE;
00904     int      SLOPERES;
00905     int      NORDERS;
00906     double   PTHRES;
00907     /* Order following */
00908     int      TRACESTEP;
00909     double   MINTHRESH;
00910     double   MAXGAP;
00911     /* Rejection */
00912     double   MAXRMS;
00913     int      DEFPOL1;
00914     int      DEFPOL2;
00915     double   KAPPA;
00916 
00917     /* Input image */
00918     cpl_image        *raw_image[2]      = {NULL, NULL};
00919     uves_propertylist *raw_header[2]     = {NULL, NULL};
00920     uves_propertylist *rotated_header[2] = {NULL, NULL};
00921     cpl_image        *raw_image_int     = NULL;
00922 
00923     /* Input guess table */
00924     uves_propertylist *guess_header      = NULL; 
00925     cpl_table        *guess_table       = NULL; 
00926 
00927     /* Output table */
00928     cpl_table        *tracetable        = NULL;
00929     polynomial       *bivariate_fit     = NULL;
00930     cpl_table        *traces            = NULL;  /* FLAMES/UVES compatibility */
00931     uves_propertylist *product_header    = NULL;
00932     cpl_table* qclog[2] = {NULL, NULL};
00933 
00934     /* Local variables */
00935     const char *raw_filename = "";
00936     char *product_filename = NULL;
00937     int ord_predict = 0;
00938     bool norders_is_guess = false;               /* Was norders read from guess table? */
00939     bool blue;
00940     enum uves_chip chip;
00941     int binx = 0;
00942     int biny = 0;
00943     
00944     /* Read recipe parameters */
00945     {
00946     /* General */
00947     check( uves_get_parameter(parameters, NULL, "uves", "debug", CPL_TYPE_BOOL, &DEBUG), 
00948            "Could not read parameter");
00949 
00950     /* Preprocessing */
00951     check( uves_get_parameter(parameters, NULL, recipe_id, "preproc.radx",
00952                   CPL_TYPE_INT   , &RADX), "Could not read parameter");
00953     check( uves_get_parameter(parameters, NULL, recipe_id, "preproc.rady", 
00954                   CPL_TYPE_INT   , &RADY), "Could not read parameter");
00955 
00956     check( BM_METHOD = uves_get_bm_method(parameters, recipe_id, "preproc"),
00957            "Could not read background measuring method");
00958 
00959     check( uves_get_parameter(parameters, NULL, recipe_id, "preproc.backsubgrid", 
00960                   CPL_TYPE_INT  , &BACKSUBGRID), 
00961            "Could not read parameter");
00962     check( uves_get_parameter(parameters, NULL, recipe_id, "preproc.backsubradiusy",
00963                   CPL_TYPE_INT, &BACKSUBRADIUSY), "Could not read parameter");
00964     check( uves_get_parameter(parameters, NULL, recipe_id, "preproc.backsubkappa", 
00965                   CPL_TYPE_DOUBLE,&BACKSUBKAPPA), "Could not read parameter");
00966     check( uves_get_parameter(parameters, NULL, recipe_id, "preproc.backsubdegx", 
00967                   CPL_TYPE_INT  , &BACKSUBDEGX), "Could not read parameter");
00968     check( uves_get_parameter(parameters, NULL, recipe_id, "preproc.backsubdegy", 
00969                   CPL_TYPE_INT  , &BACKSUBDEGY), "Could not read parameter");
00970     /* Hough */
00971     check( uves_get_parameter(parameters, NULL, recipe_id, "hough.samplewidth"  , 
00972                   CPL_TYPE_INT   , &SAMPLEWIDTH), "Could not read parameter");
00973     check( uves_get_parameter(parameters, NULL, recipe_id, "hough.minslope"     , 
00974                   CPL_TYPE_DOUBLE, &MINSLOPE   ), "Could not read parameter");
00975     check( uves_get_parameter(parameters, NULL, recipe_id, "hough.maxslope"     , 
00976                   CPL_TYPE_DOUBLE, &MAXSLOPE   ), "Could not read parameter");
00977     check( uves_get_parameter(parameters, NULL, recipe_id, "hough.sloperes"     , 
00978                   CPL_TYPE_INT   , &SLOPERES   ), "Could not read parameter");
00979     check( uves_get_parameter(parameters, NULL, recipe_id, "hough.norders"      , 
00980                   CPL_TYPE_INT   , &NORDERS    ), "Could not read parameter");
00981     check( uves_get_parameter(parameters, NULL, recipe_id, "hough.pthres"       , 
00982                   CPL_TYPE_DOUBLE, &PTHRES     ), "Could not read parameter");
00983     /* Tracing */
00984     check( uves_get_parameter(parameters, NULL, recipe_id, "trace.tracestep"    , 
00985                   CPL_TYPE_INT   , &TRACESTEP  ), "Could not read parameter");
00986     check( uves_get_parameter(parameters, NULL, recipe_id, "trace.minthresh"    , 
00987                   CPL_TYPE_DOUBLE, &MINTHRESH  ), "Could not read parameter");
00988     check( uves_get_parameter(parameters, NULL, recipe_id, "trace.maxgap"       , 
00989                   CPL_TYPE_DOUBLE, &MAXGAP     ), "Could not read parameter");
00990     /* Reject */
00991     check( uves_get_parameter(parameters, NULL, recipe_id, "reject.maxrms"      , 
00992                   CPL_TYPE_DOUBLE, &MAXRMS     ), "Could not read parameter");
00993     check( uves_get_parameter(parameters, NULL, recipe_id, "reject.defpol1"     , 
00994                   CPL_TYPE_INT   , &DEFPOL1    ), "Could not read parameter");
00995     check( uves_get_parameter(parameters, NULL, recipe_id, "reject.defpol2"     , 
00996                   CPL_TYPE_INT   , &DEFPOL2    ), "Could not read parameter");
00997     check( uves_get_parameter(parameters, NULL, recipe_id, "reject.kappa"       , 
00998                   CPL_TYPE_DOUBLE, &KAPPA      ), "Could not read parameter");
00999     
01000     /* The range of parameters have already been checked by the caller */
01001     /* Do some additional checking */
01002     assure( MINSLOPE  < MAXSLOPE , CPL_ERROR_ILLEGAL_INPUT, 
01003         "Minimum slope must be smaller than maximum slope (min = %f; max = %f)",
01004         MINSLOPE, MAXSLOPE);
01005     if (MAXSLOPE > 0.5){
01006         uves_msg_warning("Hough transformation might fail when searching for "
01007                  "lines with slope larger than 0.5 (maxslope = %f)", MAXSLOPE);
01008     }
01009 
01010     if (DEFPOL1 >= 6 || DEFPOL2 >= 6)
01011         {
01012         uves_msg_warning("Polynomial fitting might be unstable with "
01013                  "polynomial degrees higher than 5");
01014         }
01015     
01016     }
01017     
01018     /* Load raw image and header, and identify input frame as red or blue */
01019     check( uves_load_orderpos(frames, 
01020                               flames, 
01021                               &raw_filename, raw_image,
01022                   raw_header, rotated_header, &blue), "Error loading raw frame");
01023     
01024     /* Normalize the range of slopes to match the binning of the input image */
01025     check (binx = uves_pfits_get_binx(raw_header[0]),
01026        "Could not read x binning factor from input header");
01027     check (biny = uves_pfits_get_biny(raw_header[0]),
01028        "Could not read y binning factor from input header");
01029     /* If, for instance, BINX = 2, the slope of a line in the input frame is
01030        twice the slope of the line on the (unbinned) chip, and generally we need
01031        to change SLOPE := BINX/BINY * SLOPE, when going from unbinned to binned
01032        data.
01033        Additionally, when rotating a UVES frame into standard orientation, x- and y-
01034        directions are swapped, so the parameters MINSLOPE and MAXSLOPE must be
01035        multiplied by BINY/BINX to correct for binning. */
01036     MINSLOPE = (MINSLOPE*biny)/binx;
01037     MAXSLOPE = (MAXSLOPE*biny)/binx;
01038     
01039     ord_predict = NORDERS;
01040     
01041     /* Loop over one or two chips */
01042     for (chip = uves_chip_get_first(blue); 
01043      chip != UVES_CHIP_INVALID; 
01044      chip = uves_chip_get_next(chip))
01045     {
01046         const char *guess_filename = "";
01047         const char *chip_name = "";
01048         
01049         int raw_index = uves_chip_get_index(chip);
01050         int norders = 0;                           /* Number of orders detected */
01051         
01052         uves_msg("Processing %s chip in '%s'",
01053              uves_chip_tostring_upper(chip), raw_filename);
01054 
01055         check_nomsg( chip_name = uves_pfits_get_chipid(raw_header[raw_index], chip));
01056 
01057         uves_msg_debug("Binning = %dx%d", binx, biny);
01058 
01059         /* If user didn't specify number of orders, then
01060          *   Load the DRS-table (MIDAS), or if not present,
01061          *   load the guess order table, or if not present,
01062          *   auto-detect number of orders
01063          */
01064         if (NORDERS == 0)
01065         {
01066             /* The number of orders to detect will 
01067                be read from input guess table (if available),
01068                and it is just a guess: */
01069             norders_is_guess = true;
01070 
01071             uves_free_propertylist(&guess_header);
01072             
01073             if (irplib_frameset_find(frames, UVES_DRS_SETUP(flames, chip)) != NULL)
01074             {
01075                 uves_msg_low("No guess order table found");
01076                 
01077                 check( uves_load_drs(frames, flames, chip_name, &guess_filename, 
01078                          &guess_header, chip),
01079                    "Error loading setup table");
01080                 
01081                 uves_msg("Using setup table in '%s'", guess_filename);
01082 
01083                 check( ord_predict = uves_pfits_get_ordpred(guess_header), 
01084                    "Could not read predicted number "
01085                    "of orders from DRS table header");
01086             }
01087             else if (irplib_frameset_find(frames,
01088                            UVES_ORDER_TABLE(flames, chip)) != NULL ||
01089                  irplib_frameset_find(frames,
01090                            UVES_GUESS_ORDER_TABLE(flames, chip)) != NULL)
01091             {
01092                 bool load_guess = (
01093                 irplib_frameset_find(frames,
01094                           UVES_GUESS_ORDER_TABLE(flames, chip))
01095                 != NULL);
01096                 
01097                 uves_free_table(&guess_table);
01098                 
01099                 check( uves_load_ordertable(
01100                        frames,
01101                        flames,
01102                        chip_name,
01103                        &guess_filename, 
01104                        &guess_table,
01105                        &guess_header,
01106                                        NULL,
01107                                        NULL,  /* Don't read order polynomial */
01108                        NULL,  /* Don't read fibre traces */
01109                        NULL, NULL,  /* oshift, yshift */
01110                                        NULL, NULL, /* fibre_pos,fibre_mask */
01111                        chip,
01112                        load_guess),
01113                    "Error loading guess order table");
01114                 
01115                 uves_msg("Using guess order table in '%s'", guess_filename);
01116                 
01117                 check( ord_predict = uves_pfits_get_ordpred(guess_header), 
01118                    "Could not read predicted number of orders from "
01119                    "guess order table header");
01120                         }
01121             else
01122             { 
01123                 uves_msg("No guess table found");
01124             }
01125         }
01126         else
01127         {
01128             /* The user has specified the number of orders to detect.
01129              * The user is always right, so don't allow the
01130              * detection algorithm to detect fewer orders. 
01131              */
01132             norders_is_guess = false;
01133         }
01134         
01135         /* Execute macro steps */
01136         check((uves_free_table       (&tracetable),
01137            uves_polynomial_delete(&bivariate_fit),
01138            tracetable = uves_orderpos_process_chip(
01139                raw_image[raw_index], 
01140                raw_header[raw_index], 
01141                rotated_header[raw_index],
01142                chip, binx, biny,
01143                DEBUG,
01144                RADX, RADY,
01145                BM_METHOD,
01146                BACKSUBGRID,
01147                BACKSUBRADIUSY,
01148                BACKSUBKAPPA,
01149                BACKSUBDEGX, BACKSUBDEGY,
01150                SAMPLEWIDTH,
01151                MINSLOPE, MAXSLOPE,
01152                SLOPERES,
01153                ord_predict,
01154                norders_is_guess,
01155                PTHRES,
01156                TRACESTEP,
01157                MINTHRESH,
01158                MAXGAP,
01159                MAXRMS,
01160                DEFPOL1,
01161                DEFPOL2,
01162                KAPPA,
01163                &bivariate_fit,
01164                &norders,
01165                        guess_table)),
01166           "Error processing chip");
01167         
01168         /* Finished. Save the products */
01169         uves_msg("Saving products...");
01170         
01171         /* QC parameters should go here.
01172            Other mandatory keywords (FITS + dfs) are
01173            automatically added. */
01174         uves_free_propertylist(&product_header);
01175         product_header = uves_propertylist_new();
01176 
01177         /* Write number of detected orders */
01178         check( uves_pfits_set_ordpred( product_header, norders),
01179            "Error writing number of detected orders");
01180 
01181         if (flames)
01182         {
01183             int plate_no;
01184 
01185             check( plate_no = uves_flames_pfits_get_plateid(raw_header[raw_index]),
01186                "Error reading plate id");
01187 
01188             uves_flames_pfits_set_newplateid(product_header, plate_no);
01189         }
01190 
01191         /* Save order trace table */
01192         {
01193         int samples_per_order = 
01194             cpl_image_get_size_x(raw_image[raw_index]) / TRACESTEP;
01195             
01196         uves_qclog_delete(&qclog[0]);
01197         qclog[0] = uves_qclog_init(raw_header[raw_index], chip);
01198         check_nomsg( uves_orderpos_qclog(tracetable,
01199                          flames,
01200                          ord_predict,
01201                          norders,
01202                          samples_per_order,
01203                          raw_header[raw_index],chip,qclog[0]));
01204         }
01205         
01206         check(( cpl_free(product_filename),
01207             product_filename = uves_order_table_filename(chip),
01208             uves_frameset_insert(frames,
01209                      tracetable,
01210                      CPL_FRAME_GROUP_PRODUCT,
01211                      CPL_FRAME_TYPE_TABLE,
01212                      CPL_FRAME_LEVEL_INTERMEDIATE,
01213                      product_filename,
01214                      flames ?   /* Then this is the 2nd guess table */
01215                      UVES_GUESS_ORDER_TABLE(flames, chip) :
01216                      /* If UVES this is the final order table */
01217                      UVES_ORDER_TABLE(flames, chip),
01218                      raw_header[raw_index],
01219                      product_header,
01220                      NULL,
01221                      parameters,
01222                      recipe_id,
01223                      PACKAGE "/" PACKAGE_VERSION,
01224                      qclog,
01225                      starttime, true, 0)),
01226            "Could not add trace table %s to frameset", product_filename);
01227             uves_qclog_delete(&qclog[0]);
01228         uves_msg("Trace table %s added to frameset", product_filename);
01229         
01230         /* Save polynomial in next extension (don't add header keywords) */
01231         check( uves_save_polynomial(bivariate_fit, product_filename, NULL),
01232            "Could not write polynomial to file %s", product_filename);
01233         
01234         /* For compatibility with FLAMES/UVES, create the extension defining
01235            that there is only one trace which has zero offset, and that 
01236            this trace is enabled */
01237         {
01238         /* fixme: What to write for FLAMES data? */
01239 
01240         uves_free_table(&traces);
01241         traces = uves_ordertable_traces_new();
01242         uves_ordertable_traces_add(traces, 0, 0.0, 1);
01243         
01244         check( cpl_table_save(traces,
01245                       NULL,            /* Primary header, 
01246                               ignored when mode is IO_EXTEND */
01247                       NULL,            /* Extension header               */
01248                       product_filename,/* This file already exists
01249                               (or an error occurs)           */
01250                       CPL_IO_EXTEND),  /* Append to existing file        */
01251                "Error appending table to file '%s'", product_filename);
01252         }
01253         /* Finished saving order table */
01254         
01255         if (flames)
01256         /* Make two calibration frames out of the input frame,
01257            to be used later by the recipe ??? */
01258         {
01259 
01260             /* Save as integer */
01261             uves_free_image(&raw_image_int);
01262             raw_image_int = cpl_image_cast(raw_image[raw_index],
01263                            CPL_TYPE_INT);
01264 
01265             check(( cpl_free(product_filename),
01266                 product_filename = uves_ordef_filename(chip),
01267                 uves_frameset_insert(frames,
01268                          raw_image_int,
01269                          CPL_FRAME_GROUP_PRODUCT,
01270                          CPL_FRAME_TYPE_IMAGE,
01271                          CPL_FRAME_LEVEL_INTERMEDIATE,
01272                          product_filename,
01273                          FLAMES_ORDEF(flames, chip),
01274                          raw_header[raw_index],     /* raw header    */
01275                          rotated_header[raw_index], /* output header */
01276                          NULL,
01277                          parameters,
01278                          recipe_id,
01279                          PACKAGE "/" PACKAGE_VERSION,
01280                          NULL, /* No QC */
01281                          starttime, false,
01282                          CPL_STATS_MIN | CPL_STATS_MAX)),
01283               "Could not add raw frame %s to frameset", product_filename);
01284 
01285             uves_msg("Raw frame %s added to frameset", product_filename);
01286             uves_free_image(&raw_image_int);
01287         }
01288         
01289     } /* For each chip */
01290 
01291   cleanup:
01292      /* Raw */
01293      uves_free_image(&(raw_image[0]));
01294      uves_free_image(&(raw_image[1]));
01295      uves_free_image(&raw_image_int);
01296      uves_free_propertylist(&(raw_header[0]));
01297      uves_free_propertylist(&(raw_header[1]));
01298      uves_free_propertylist(&(rotated_header[0]));
01299      uves_free_propertylist(&(rotated_header[1]));
01300      
01301      /* Calibration */
01302      uves_free_propertylist(&guess_header);
01303      uves_free_table       (&guess_table);
01304      
01305      /* Product */
01306      uves_qclog_delete(&qclog[0]);
01307      uves_free_table       (&tracetable);
01308      uves_polynomial_delete(&bivariate_fit);
01309      uves_free_table       (&traces);
01310      uves_free_propertylist(&product_header);
01311      cpl_free(product_filename);
01312      
01313      return;
01314 }
01325 static void uves_orderpos_qclog(cpl_table* table,
01326                 bool flames,
01327                 int pord, 
01328                 int dord,
01329                 int samples_per_order,
01330                 uves_propertylist* raw_header, 
01331                 enum uves_chip chip,
01332                 cpl_table* qclog)
01333 {
01334     const char* chip_name;
01335     const char* grat_name;
01336     const char* ins_mode;
01337     double grat_wlen=0;
01338 
01339     uves_qclog_add_string(qclog,
01340               "QC TEST1 ID",
01341               flames ? 
01342               "Fibre-Order-Definition-Results" :
01343               "Order-Definition-Results",
01344               "Name of QC test",
01345               "%s");
01346 
01347     check_nomsg( chip_name=uves_pfits_get_chip_name(raw_header,chip) );
01348     /* chip_name = UVES_QC_CHIP_VAL(chip); */
01349 
01350   uves_qclog_add_string(qclog,
01351                         uves_remove_string_prefix(UVES_CHIP_NAME(chip),"ESO "),
01352                         chip_name,
01353                         "Grating unique ID",
01354                         "%s");
01355 
01356 
01357   check_nomsg(grat_name=uves_pfits_get_gratname(raw_header,chip));
01358 
01359 
01360 
01361   uves_qclog_add_string(qclog,
01362                         uves_remove_string_prefix(UVES_GRATNAME(chip),"ESO "),
01363                         grat_name,
01364                         "Cross disperser ID",
01365                         "%s");
01366 
01367 
01368   check_nomsg(ins_mode=uves_pfits_get_insmode(raw_header));
01369   uves_qclog_add_string(qclog,
01370                         uves_remove_string_prefix(UVES_INSMODE,"ESO "),
01371                         ins_mode,
01372                         "Instrument mode used.",
01373                         "%s");
01374 
01375 
01376   check_nomsg(grat_wlen=uves_pfits_get_gratwlen(raw_header,chip));
01377   uves_qclog_add_double(qclog,
01378                         uves_remove_string_prefix(UVES_GRATWLEN(chip),"ESO "),
01379                         grat_wlen,
01380                         "Grating central wavelength [nm]",
01381                         "%.1f");
01382 
01383   uves_msg_debug("chip_name=%s grat_name=%s ins_mode=%s grat_wlen=%f",
01384          chip_name,grat_name,ins_mode,grat_wlen);
01385 
01386   uves_qclog_add_double(qclog,
01387                         "QC ORD RESIDMIN",
01388                         cpl_table_get_column_min(table,"Residual"),
01389                         "min resid in ord def",
01390                         "%8.4f");
01391 
01392   uves_qclog_add_double(qclog,
01393                         "QC ORD RESIDMAX",
01394                         cpl_table_get_column_max(table,"Residual"),
01395                         "max resid in ord def",
01396                         "%8.4f");
01397 
01398   uves_qclog_add_double(qclog,
01399                         "QC ORD RESIDAVG",
01400                         cpl_table_get_column_mean(table,"Residual"),
01401                         "mean resid in ord def",
01402                         "%8.4f");
01403 
01404   uves_qclog_add_double(qclog,
01405                         "QC ORD RESIDRMS",
01406                         cpl_table_get_column_stdev(table,"Residual"),
01407                         "rms resid in ord def",
01408                         "%8.4f");
01409 
01410   uves_qclog_add_int(qclog,
01411                         "QC ORD NPRED",
01412                         pord,
01413                         "predicted number of orders",
01414                         "%d");
01415 
01416   uves_qclog_add_int(qclog,
01417                         "QC ORD NDET",
01418                         dord,
01419                         "detected number of orders",
01420                         "%d");
01421 
01422   uves_qclog_add_int(qclog,
01423              "QC ORD NPOSALL",
01424              dord * samples_per_order,
01425              "Number of position found",
01426              "%d");
01427   
01428   uves_qclog_add_int(qclog,
01429              "QC ORD NPOSSEL",
01430              cpl_table_get_nrow(table),
01431              "Number of position selected",
01432              "%d");
01433 
01434   uves_qclog_add_int(qclog,
01435                         "QC ORDMIN",
01436                         cpl_table_get_column_min(table,"Order"),
01437                         "Number of position selected",
01438                         "%d");
01439 
01440   uves_qclog_add_int(qclog,
01441                         "QC ORDMAX",
01442                         cpl_table_get_column_max(table,"Order"),
01443                         "Number of position selected",
01444                         "%d");
01445 
01446 
01447 
01448   /* In later MIDAS versions, these were added: */
01449 
01450   check_nomsg(uves_qclog_add_string(qclog,
01451                     uves_remove_string_prefix(UVES_READ_SPEED,"ESO "),
01452                     uves_pfits_get_readspeed(raw_header),
01453                     "Readout speed",
01454                     "%s"));
01455   
01456   check_nomsg(uves_qclog_add_int(qclog,
01457                  uves_remove_string_prefix(UVES_BINX, "ESO "),
01458                  uves_pfits_get_binx(raw_header),
01459                  "Binning factor along X",
01460                  "%d"));
01461   
01462   check_nomsg(uves_qclog_add_int(qclog,
01463                  uves_remove_string_prefix(UVES_BINY, "ESO "),
01464                  uves_pfits_get_biny(raw_header),
01465                  "Binning factor along Y",
01466                  "%d"));
01467   
01468   check_nomsg(uves_qclog_add_string(qclog,
01469                     uves_remove_string_prefix(UVES_INSPATH,"ESO "),
01470                     uves_pfits_get_inspath(raw_header),
01471                     "Optical path used (h).",
01472                     "%s"));
01473     
01474  cleanup:
01475   return;
01476 
01477 }

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