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: 2010/12/13 08:21:36 $
00023  * $Revision: 1.48 $
00024  * $Name: uves-4_9_1 $
00025  * $Log: uves_orderpos_body.c,v $
00026  * Revision 1.48  2010/12/13 08:21:36  amodigli
00027  * fixed mem leak
00028  *
00029  * Revision 1.47  2010/09/27 15:22:34  amodigli
00030  * removed 'norders' parameter
00031  *
00032  * Revision 1.46  2010/09/24 09:32:04  amodigli
00033  * put back QFITS dependency to fix problem spot by NRI on FIBER mode (with MIDAS calibs) data
00034  *
00035  * Revision 1.44  2010/06/09 08:50:23  amodigli
00036  * In case USE_GUESS_TAB==2, make check if temporary order table start order numbering from 1. If not correct it appropriately before calling uves_locate_orders. Then put back orders numbering as it was. This to prevent a problem possibly found in case USE_GUESS_TAB==2 and an input guess table is provided with order numbering not starting at 1
00037  *
00038  * Revision 1.43  2010/05/11 10:49:09  amodigli
00039  * Fixed typo on param description
00040  *
00041  * Revision 1.42  2010/05/06 14:55:00  amodigli
00042  * increased min allowed val of backsubgrid to 10 and changed default of kappa to 4
00043  *
00044  * Revision 1.41  2009/10/29 17:16:54  amodigli
00045  * added param to specify if red cdd is new/old in call to uves_get_badpix
00046  *
00047  * Revision 1.40  2009/02/18 12:06:06  amodigli
00048  * fixed mem leak
00049  *
00050  * Revision 1.39  2008/09/29 06:57:52  amodigli
00051  * add #include <string.h>
00052  *
00053  * Revision 1.38  2008/05/01 09:51:42  amodigli
00054  * fixed compiler warnings
00055  *
00056  * Revision 1.37  2008/02/15 12:43:49  amodigli
00057  * allow lower/upper chip for parameter process_chip
00058  *
00059  * Revision 1.36  2007/12/17 07:41:41  amodigli
00060  * added some descriptors to pipe products
00061  *
00062  * Revision 1.35  2007/12/03 08:00:19  amodigli
00063  * added HIERARCH keys to 'debug' product
00064  *
00065  * Revision 1.34  2007/11/13 16:19:17  amodigli
00066  * product order table in case of FIBER mode is now FIB_ORD_TAB_x
00067  *
00068  * Revision 1.33  2007/10/23 06:48:57  amodigli
00069  * Master bias is subtracted if provided
00070  *
00071  * Revision 1.32  2007/10/05 16:01:45  amodigli
00072  * using proces_chip parameter to process or not a given RED chip
00073  *
00074  * Revision 1.31  2007/09/19 14:13:02  amodigli
00075  * Fibre-Order-Definition-Results-->Single-Fibre-Order-Definition-Results
00076  *
00077  * Revision 1.30  2007/08/23 15:14:14  amodigli
00078  * fixed DFS04255: the value of ymax in the search of orders was improperly set
00079  *
00080  * Revision 1.29  2007/08/21 13:08:26  jmlarsen
00081  * Removed irplib_access module, largely deprecated by CPL-4
00082  *
00083  * Revision 1.28  2007/08/02 15:21:06  amodigli
00084  * added parameter --use_guess_tab and possibility to use the input guess table as it was in  MIDAS (default option). Kept optional also current behaviour
00085  *
00086  * Revision 1.27  2007/07/17 12:40:04  jmlarsen
00087  * Fixed bug in update of DEFPOL variables
00088  *
00089  * Revision 1.26  2007/06/28 09:17:40  jmlarsen
00090  * Write polynomial in MIDAS format if FLAMES
00091  *
00092  * Revision 1.25  2007/06/22 09:28:51  jmlarsen
00093  * Changed interface of uves_save_image
00094  *
00095  * Revision 1.24  2007/06/06 08:17:33  amodigli
00096  * replace tab with 4 spaces
00097  *
00098  * Revision 1.23  2007/05/22 14:34:32  jmlarsen
00099  * Removed unnecessary includes
00100  *
00101  * Revision 1.22  2007/04/24 16:45:17  amodigli
00102  * changed interface of calls to uves_load_ordertable to match new interface
00103  *
00104  * Revision 1.21  2007/04/24 12:50:29  jmlarsen
00105  * Replaced cpl_propertylist -> uves_propertylist which is much faster
00106  *
00107  * Revision 1.20  2007/04/17 09:34:38  jmlarsen
00108  * Parametrize the assumption about consecutive orders (for FLAMES support)
00109  *
00110  * Revision 1.19  2007/04/12 12:01:44  jmlarsen
00111  * Skip Hough transform if guess table is provided
00112  *
00113  * Revision 1.18  2007/04/03 06:29:21  amodigli
00114  * changed interface to uves_load_ordertable
00115  *
00116  * Revision 1.17  2007/03/28 14:02:18  jmlarsen
00117  * Removed unused parameter
00118  *
00119  * Revision 1.16  2007/03/28 11:38:55  jmlarsen
00120  * Killed MIDAS flag, removed dead code
00121  *
00122  * Revision 1.15  2006/12/11 12:34:58  jmlarsen
00123  * Fixed QC bugs
00124  *
00125  * Revision 1.14  2006/12/11 11:06:44  jmlarsen
00126  * Read QC chip name from input header
00127  *
00128  * Revision 1.13  2006/12/07 08:24:21  jmlarsen
00129  * Factored some common QC parameters
00130  *
00131  * Revision 1.12  2006/12/01 12:26:51  jmlarsen
00132  * Factored out FLAMES plate-id code
00133  *
00134  * Revision 1.11  2006/11/16 14:12:21  jmlarsen
00135  * Changed undefined trace number from 0 to -1, to support zero as an actual trace number
00136  *
00137  * Revision 1.10  2006/11/16 09:49:25  jmlarsen
00138  * Fixed doxygen bug
00139  *
00140  * Revision 1.9  2006/11/15 15:02:14  jmlarsen
00141  * Implemented const safe workarounds for CPL functions
00142  *
00143  * Revision 1.7  2006/11/15 14:04:08  jmlarsen
00144  * Removed non-const version of parameterlist_get_first/last/next which is 
00145  * already in CPL, added const-safe wrapper, unwrapper and deallocator functions
00146  *
00147  * Revision 1.6  2006/11/13 12:46:26  jmlarsen
00148  * Added doc.
00149  *
00150  * Revision 1.5  2006/11/06 15:19:41  jmlarsen
00151  * Removed unused include directives
00152  *
00153  * Revision 1.4  2006/10/26 14:03:33  jmlarsen
00154  * Fixed position of const modifier
00155  *
00156  * Revision 1.3  2006/10/25 07:22:59  jmlarsen
00157  * Fixed wrong parameter context: hough -> trace
00158  *
00159  * Revision 1.2  2006/10/24 14:42:26  jmlarsen
00160  * Added plate number logging
00161  *
00162  * Revision 1.34  2006/10/17 12:33:02  jmlarsen
00163  * Added semicolon at UVES_RECIPE_DEFINE invocation
00164  *
00165  * Revision 1.33  2006/10/09 13:01:13  jmlarsen
00166  * Use macro to define recipe interface functions
00167  *
00168  * Revision 1.32  2006/09/20 12:53:57  jmlarsen
00169  * Replaced stringcat functions with uves_sprintf()
00170  *
00171  * Revision 1.31  2006/09/19 14:31:10  jmlarsen
00172  * uves_insert_frame(): use bitmap to specify which image statistics keywords must be computed
00173  *
00174  * Revision 1.30  2006/09/19 06:55:11  jmlarsen
00175  * Changed interface of uves_frameset to optionally write image statistics kewwords
00176  *
00177  * Revision 1.29  2006/08/24 11:36:37  jmlarsen
00178  * Write recipe start/stop time to header
00179  *
00180  * Revision 1.28  2006/08/18 13:35:42  jmlarsen
00181  * Fixed/changed QC parameter formats
00182  *
00183  * Revision 1.27  2006/08/11 14:56:05  amodigli
00184  * removed Doxygen warnings
00185  *
00186  * Revision 1.26  2006/08/07 11:35:35  jmlarsen
00187  * Disabled parameter environment variable mode
00188  *
00189  * Revision 1.25  2006/07/14 12:19:28  jmlarsen
00190  * Support multiple QC tests per product
00191  *
00192  * Revision 1.24  2006/07/03 14:20:39  jmlarsen
00193  * Exclude bad pixels from order tracing
00194  *
00195  * Revision 1.23  2006/07/03 13:09:24  amodigli
00196  * adjusted description display layout
00197  *
00198  * Revision 1.22  2006/07/03 12:46:34  amodigli
00199  * updated description
00200  *
00201  * Revision 1.21  2006/06/22 12:13:10  amodigli
00202  * removed ESO prefix
00203  *
00204  * Revision 1.20  2006/06/22 06:44:06  amodigli
00205  * added some QC param
00206  *
00207  * Revision 1.19  2006/06/16 08:25:34  jmlarsen
00208  * Do the order tracing on non-median filtered frame
00209  *
00210  * Revision 1.18  2006/06/13 11:57:02  jmlarsen
00211  * Check that calibration frames are from the same chip ID
00212  *
00213  * Revision 1.17  2006/06/08 11:40:50  amodigli
00214  * added check to have output order table as input guess, if provided
00215  *
00216  * Revision 1.16  2006/06/08 08:42:53  jmlarsen
00217  * Added support for computing Hough transform on image subwindow
00218  *
00219  * Revision 1.15  2006/06/07 13:06:28  jmlarsen
00220  * Changed doxygen tag addtogroup -> defgroup
00221  *
00222  * Revision 1.14  2006/06/07 09:01:28  amodigli
00223  * added some doc
00224  *
00225  * Revision 1.13  2006/06/06 08:40:10  jmlarsen
00226  * Shortened max line length
00227  *
00228  * Revision 1.12  2006/05/09 15:42:00  amodigli
00229  * added QC log
00230  *
00231  * Revision 1.11  2006/05/08 15:41:32  amodigli
00232  * added order table chopping (commented out)
00233  *
00234  * Revision 1.10  2006/05/05 13:55:17  jmlarsen
00235  * Minor doc update
00236  *
00237  * Revision 1.9  2006/04/20 10:47:39  amodigli
00238  * added qclog
00239  *
00240  * Revision 1.8  2006/04/06 09:48:15  amodigli
00241  * changed uves_frameset_insert interface to have QC log
00242  *
00243  * Revision 1.7  2006/04/06 08:46:40  jmlarsen
00244  * Changed default polynomial degrees to auto
00245  *
00246  * Revision 1.6  2006/03/24 14:04:14  jmlarsen
00247  * Changed background subtraction sample density default parameter value
00248  *
00249  * Revision 1.5  2006/03/09 10:53:41  jmlarsen
00250  * Changed default bivariate degrees to MIDAS values
00251  *
00252  * Revision 1.4  2006/03/03 13:54:11  jmlarsen
00253  * Changed syntax of check macro
00254  *
00255  * Revision 1.3  2006/02/28 09:15:22  jmlarsen
00256  * Minor update
00257  *
00258  * Revision 1.2  2006/02/21 14:26:54  jmlarsen
00259  * Minor changes
00260  *
00261  * Revision 1.1  2006/02/03 07:46:30  jmlarsen
00262  * Moved recipe implementations to ./uves directory
00263  *
00264  * Revision 1.63  2006/01/19 08:47:24  jmlarsen
00265  * Inserted missing doxygen end tag
00266  *
00267  * Revision 1.62  2006/01/05 14:31:31  jmlarsen
00268  * Checking for guess DRS table before guess order table
00269  *
00270  * Revision 1.61  2005/12/20 16:10:32  jmlarsen
00271  * Added some documentation
00272  *
00273  * Revision 1.60  2005/12/19 16:17:55  jmlarsen
00274  * Replaced bool -> int
00275  *
00276  */
00277 #ifdef HAVE_CONFIG_H
00278 #  include <config.h>
00279 #endif
00280 
00281 /*----------------------------------------------------------------------------*/
00285 /*----------------------------------------------------------------------------*/
00286 
00287 /*-----------------------------------------------------------------------------
00288                                 Includes
00289  -----------------------------------------------------------------------------*/
00290 
00291 #include <uves_orderpos_body.h>
00292 
00293 #include <uves_orderpos_hough.h>
00294 #include <uves_orderpos_follow.h>
00295 
00296 #include <uves_physmod_chop_otab.h>
00297 #include <uves_corrbadpix.h>
00298 #include <uves_utils.h>
00299 #include <uves_recipe.h>
00300 #include <uves_parameters.h>
00301 #include <uves_backsub.h>
00302 #include <uves_pfits.h>
00303 #include <uves_dfs.h>
00304 #include <uves_qclog.h>
00305 #include <uves_utils_wrappers.h>
00306 #include <uves_utils_cpl.h>
00307 #include <uves_error.h>
00308 #include <uves_msg.h>
00309 
00310 #include <cpl.h>
00311 
00312 #include <float.h>
00313 #include <string.h>
00314 /*-----------------------------------------------------------------------------
00315                             Functions prototypes
00316  -----------------------------------------------------------------------------*/
00317 /* compute qclog */
00318 static void uves_orderpos_qclog(cpl_table* table,
00319                 bool flames,
00320                 int pord, 
00321                 int dord,
00322                 int samples_per_order,
00323                 uves_propertylist* rhead, 
00324                 enum uves_chip chip,
00325                 cpl_table* qclog);
00326 
00329 /*-----------------------------------------------------------------------------
00330                             Exported variables
00331  -----------------------------------------------------------------------------*/
00332 
00333 const char * const uves_orderpos_desc_short = "Defines echelle order positions";
00334 const char * const uves_orderpos_desc =
00335 "The recipe defines the order positions in an echelle image. The orders are\n"
00336 "initially detected by means of a Hough transformation, the orders are then \n"
00337 "traced, and the positions are finally fitted with a global polynomial.\n"
00338 "\n"
00339 "Expected input frames are narrow flat fields, ORDER_FLAT_xxx, or standard \n"
00340 "stars, STANDARD_xxx, where xxx is 'BLUE' or 'RED', and optionally for each \n"
00341 "chip a DRS setup table (DRS_TABLE_BLUE, DRS_TABLE_REDL, DRS_TABLE_REDU) or \n"
00342 "guess order table (ORDER_GUESS_TAB_BLUE, ORDER_GUESS_TAB_REDL, \n"
00343 "ORDER_GUESS_TAB_REDU, \n"
00344 "or, for backward compatibility, ORDER_TABLE_BLUE, ORDER_TABLE_REDL, \n"
00345 "ORDER_TABLE_REDU). The recipe processes only the first raw frame found.\n"
00346 "\n"
00347 "Output is one (or two if input is a red frame) order table(s) \n"
00348 "(UVES: ORDER_TABLE_(BLUE|REDL|REDU); FLAMES: FIB_ORDEF_(REDL|REDU) contaning\n"
00349 "the columns:\n"
00350 "X                : Position along x\n"
00351 "Order            : Relative order number\n"
00352 "Y                : Order line centroid location\n"
00353 "Yfit             : The fitted order location\n"
00354 "dY               : Uncertainty of Y\n"
00355 "dYfit_Square     : Variance of Yfit\n"
00356 "Residual         : Y - Yfit\n"
00357 "Residual_Square  : Residual^2\n"
00358 "OrderRMS         : Root mean squared residual of initial\n"
00359 "                   one-dimensional linear fit of order\n"
00360 "\n"
00361 "The bivariate fit polynomial itself is stored in table extension no. 2.\n"
00362 "The 3rd table extension contains a table that defines the active fibre traces\n"
00363 "and their positions (for support of FLAMES/UVES)\n";
00364 
00365 
00366 /*-----------------------------------------------------------------------------
00367                               Functions code
00368  -----------------------------------------------------------------------------*/
00369 /*----------------------------------------------------------------------------*/
00376 /*----------------------------------------------------------------------------*/
00377 int
00378 uves_orderpos_define_parameters_body(cpl_parameterlist *parameters,
00379                      const char *recipe_id)
00380 {
00381     const char *subcontext;
00382 
00383     /*****************
00384      *    General    *
00385      *****************/
00386     
00387     if (uves_define_global_parameters(parameters) != CPL_ERROR_NONE)
00388     {
00389         return -1;
00390     }
00391     
00392     /*****************
00393      * Preprocessing *
00394      *****************/
00395 
00396     subcontext = "preproc";
00397 
00398     /* Use of Guess sol */
00399     uves_par_new_enum("use_guess_tab", 
00400               CPL_TYPE_INT,
00401                "If a Guess order table is provided this parameter set how it is used:"
00402                "0: No usage, "
00403                "1: use it to set lower/upper Y raws where order are searched "
00404               "2: the order table try to fully match the guess",
00405               1, 3, 0, 1, 2);
00406     
00407 
00408     
00409     /* Radx, Rady */
00410     uves_par_new_range("radx", 
00411                CPL_TYPE_INT,
00412                "Half X size of median filtering window",
00413                2, 0, INT_MAX);
00414     
00415     uves_par_new_range("rady",
00416                CPL_TYPE_INT,
00417                "Half Y size of median filtering window",
00418                1, 0, INT_MAX);
00419 
00420     /* Mmethod */
00421     uves_par_new_enum("mmethod",
00422               CPL_TYPE_STRING,
00423               "Background subtraction method. If equal "
00424               "to 'median' the background is sampled using "
00425               "the median of a sub-window. If 'minimum', "
00426               "the minimum sub-window value is used. If "
00427               "'no', no background subtraction is done.",
00428               "median",                        /* Default */
00429               3,                               /* Number of options */
00430               "median", "minimum", "no");      /* List of options */
00431   
00432     /* Backsubgrid */
00433     uves_par_new_range("backsubgrid",
00434                CPL_TYPE_INT,
00435                "Number of grid points (in x- and y-direction) "
00436                "used to estimate "
00437                "the background (mode=poly).",
00438                50, 10, INT_MAX);
00439     
00440     /* Backsubradiusy */
00441     uves_par_new_range("backsubradiusy",
00442                CPL_TYPE_INT,
00443                "The height (in pixels) of the background "
00444                "sampling window is (2*radiusy + 1). "
00445                "This parameter is not corrected for binning.",
00446                2, 0, INT_MAX);
00447     
00448     /* Backsubkappa */
00449     uves_par_new_range("backsubkappa",
00450                CPL_TYPE_DOUBLE,
00451                "The value of kappa in the one-sided kappa-sigma "
00452                "clipping used to "
00453                "estimate the background (mode=poly).",
00454                4.0, 0.0, DBL_MAX);
00455     
00456     /* Backsubdegx, backsubdegy */
00457     uves_par_new_range("backsubdegx",
00458                CPL_TYPE_INT,
00459                "Degree (in x) of polynomial used "
00460                "to estimate the background (mode=poly).",
00461                2, 1, INT_MAX);
00462     
00463     uves_par_new_range("backsubdegy",
00464                CPL_TYPE_INT,
00465                "Degree (in y) of polynomial used "
00466                "to estimate the background (mode=poly).",
00467                2, 1, INT_MAX);
00468     
00469     /*******************
00470      * Hough detection *
00471      *******************/
00472     subcontext = "hough";  
00473 
00474     /* Samplewidth */
00475     uves_par_new_range("samplewidth",
00476                CPL_TYPE_INT,
00477                "Separation of sample traces "
00478                "(used by Hough transform) in input image",
00479                50, 1, INT_MAX);
00480     
00481     /* Minslope, Maxslope */
00482     uves_par_new_range("minslope",
00483                CPL_TYPE_DOUBLE,
00484                "Minimum possible line slope. This should "
00485                "be the 'physical' slope on the chip, "
00486                "i.e. not taking binning factors into "
00487                "account, which is handled by the recipe",
00488                0.0, 0.0, DBL_MAX);
00489     
00490     uves_par_new_range("maxslope",
00491                CPL_TYPE_DOUBLE,
00492                "Maximum possible line slope",
00493                0.2, 0.0, DBL_MAX);
00494     
00495     /* Sloperes */
00496     uves_par_new_range("sloperes",
00497                CPL_TYPE_INT,
00498                "Resolution (width in pixels) of Hough space",
00499                120, 1, INT_MAX);
00500     
00501     /* Norders */
00502     /* decided to temporally remove this as only option 0 works
00503        later one need to fix the behaviour for this parameter
00504  
00505     uves_par_new_range("norders",
00506                CPL_TYPE_INT,
00507                "Number of echelle orders to detect. If "
00508                "set to 0 the predicted number of orders will "
00509                "be read from the guess order table. If no "
00510                "guess order table is given, the recipe will "
00511                "try to autodetect the number of orders. If "
00512                "the raw frame is a red chip and this parameter "
00513                "is specified, the given value will be used "
00514                "for both red chips",
00515                0, 0, INT_MAX);
00516  
00517     */   
00518     /* Pthres */
00519     uves_par_new_range("pthres",
00520                CPL_TYPE_DOUBLE,
00521                "In automatic mode, or if the number of orders "
00522                "to detect is read from a guess table, the detection "
00523                "of new lines stops when the intensity of a candidate "
00524                "line drops to less than 'pthres' times the intensity "
00525                "of the previous detection. "
00526 /* Text applicable only if 'norders' parameter is present 
00527                "Otherwise - i.e. if the "
00528                "number of orders to detect was specified by setting "
00529                "the 'norders' parameters - this parameter is "
00530                "ignored."
00531 */
00532                ,
00533                0.2, 0.0, 1.0);
00534     
00535     /*******************
00536      * Order tracing   *
00537      *******************/
00538     subcontext = "trace";
00539 
00540     /* Tracestep */
00541     uves_par_new_range("tracestep",
00542                CPL_TYPE_INT,
00543                "The step size used when tracing the orders",
00544                10, 1, INT_MAX);
00545     
00546     /* Minthres */
00547     uves_par_new_range("minthresh",
00548                        CPL_TYPE_DOUBLE,
00549                        "The minimum threshold value is (min + "
00550                        "minthres*(max - min)). Here 'min' "
00551                "and 'max' are the lowest and highest pixel "
00552                "values in the central bin of the order",
00553                        0.2, 0.0, 1.0);
00554     
00555     /* Maxgap */
00556     uves_par_new_range("maxgap",
00557                        CPL_TYPE_DOUBLE,
00558                        "If the order line drops below detection "
00559                        "threshold, the order tracing algorithm "
00560                        "will try to jump a gap of maximum size 'maxgap' "
00561                        "multiplied by the image width",
00562                        .2, 0.0, 1.0);
00563 
00564     /***************
00565      *  Rejection  *
00566      ***************/
00567 
00568     subcontext = "reject";
00569 
00570     /* Maxrms */   /* In uves/midas default is 3.5 */
00571     uves_par_new_range("maxrms",
00572                  CPL_TYPE_DOUBLE,
00573                  "When fitting the orders with straight lines, "
00574                  "this is the maximum allowed RMS relative to "
00575                  "the median RMS of all orders",
00576                  100.0, 0.0, DBL_MAX);
00577 
00578     /* In MIDAS,  defpol=2,3 is used which is not optimal
00579        but faster than (-1,-1)               */
00580     /* Defpol1 */
00581     uves_par_new_range("defpol1",
00582                  CPL_TYPE_INT,
00583                  "The degree of the bivarite fit (cross "
00584                  "dispersion direction). If negative, "
00585                  "the degree is optimized to give the best fit",
00586                  -1,
00587                  -1, INT_MAX);
00588     
00589     /* Defpol2 */
00590     uves_par_new_range("defpol2",
00591                  CPL_TYPE_INT,
00592                  "The degree of the bivarite fit (order number). "
00593                  "If negative, "
00594                  "the degree is optimized to give the best fit",
00595                  -1,
00596                  -1, INT_MAX);
00597     
00598     /* Kappa */
00599     uves_par_new_range("kappa",
00600                  CPL_TYPE_DOUBLE,
00601                  "Used for kappa-sigma clipping of the final "
00602                  "polynomial fit. If negative, no clipping is done",
00603                  4.0, -2.0, DBL_MAX);
00604 
00605     return (cpl_error_get_code() != CPL_ERROR_NONE);
00606 }
00607 
00608 /*----------------------------------------------------------------------------*/
00658 /*----------------------------------------------------------------------------*/
00659 static cpl_table *
00660 uves_orderpos_process_chip(const cpl_image *raw_image, 
00661                            uves_propertylist *raw_header,
00662                            const uves_propertylist *rotated_header, 
00663                            enum uves_chip chip, 
00664                            int binx, int biny,
00665                           /* General */
00666                bool      DEBUG,
00667                /* Preprocessing */
00668                int      USE_GUESS_TAB,
00669                int      RADX,
00670                int      RADY,
00671                background_measure_method BM_METHOD,
00672                int      BACKSUBGRID,
00673                int      BACKSUBRADIUSY,
00674                double   BACKSUBKAPPA,
00675                int      BACKSUBDEGX,
00676                int      BACKSUBDEGY,
00677                /* Hough transform */
00678                int      SAMPLEWIDTH,
00679                double   MINSLOPE,
00680                double   MAXSLOPE,
00681                int      SLOPERES,
00682                int      NORDERS,
00683                bool      norders_is_guess,
00684                double   PTHRES,
00685                /* Order following */
00686                int      TRACESTEP,
00687                double   MINTHRESH,
00688                double   MAXGAP,
00689                /* Rejection */
00690                double   MAXRMS,
00691                int      *DEFPOL1,
00692                int      *DEFPOL2,
00693                double   KAPPA,
00694                /* Output */
00695                polynomial **bivariate_fit,
00696                int *norders,
00697                            cpl_table* guess_table)
00698 {
00699     /* Result */
00700     cpl_table   *tracetable     = NULL;
00701 
00702     cpl_image   *noise          = NULL;    /* Image defining the noise
00703                            of the current image */
00704     cpl_image   *back_subbed    = NULL;
00705     cpl_image   *hough_trans    = NULL;
00706     polynomial  *guess_locations = NULL;
00707     
00708     /* Debug objects */
00709     cpl_image   *inputlines     = NULL; /* Hough solution drawn
00710                         on top of input image */
00711     cpl_table   *ordertable     = NULL; /* A preliminary order table
00712                         containing one row per order */
00713     cpl_image   *hough_original = NULL;
00714     int abs_ord_min=0;
00715     int abs_ord_max=0;
00716     int badpixels_marked = 0;
00717     int ymin = 0;
00718     int ymax = 0;
00719     int ord_min=0;
00720     bool red_ccd_is_new=0;
00721     check_nomsg(red_ccd_is_new=uves_ccd_is_new(raw_header));
00722 
00723     check( back_subbed = cpl_image_duplicate(raw_image), "Error duplicating image");
00724     ymin = 1;
00725     ymax = cpl_image_get_size_y(back_subbed);
00726     uves_msg("===============");
00727     /* uves_msg("guess order tab=%p",guess_table); */
00728     /* Calculate the basic order table */
00729     if(guess_table != NULL) 
00730     {
00731       if(USE_GUESS_TAB == 1) {
00732     int ymin_guess=ymin;
00733     int ymax_guess=ymax;
00734         int omin=0;
00735         int omax=0;
00736     cpl_table* tmp_tbl=NULL;
00737 
00738         uves_msg("Use input guess order table to define the detector area");
00739         uves_msg("where to locate orders");
00740  
00741 
00742         tmp_tbl=cpl_table_duplicate(guess_table);
00743         uves_physmod_chop_otab(raw_header,chip,&tmp_tbl,"Order",&omin,&omax);
00744  
00745     uves_msg("On Guess Found %d orders.",omax-omin+1);
00746     if(omax < cpl_table_get_column_max(guess_table,"Order")) {
00747       uves_free_table(&tmp_tbl);
00748           check(tmp_tbl=uves_extract_table_rows(guess_table,"Order",
00749                         CPL_EQUAL_TO,omax+1),
00750         "Error selecting Order");
00751 
00752       check(ymax_guess=(int)cpl_table_get_column_min(tmp_tbl,"Yfit")-1,
00753         "error getting ymax_guess");
00754       uves_free_table(&tmp_tbl);
00755     }
00756 
00757     if(omin > cpl_table_get_column_min(guess_table,"Order")) {
00758       uves_free_table(&tmp_tbl);
00759       check(tmp_tbl=uves_extract_table_rows(guess_table,"Order",
00760                         CPL_EQUAL_TO,omin-1),
00761         "Error selecting Order");
00762 
00763       check(ymin_guess=(int)cpl_table_get_column_max(tmp_tbl,"Yfit")+1,
00764         "error getting ymin_guess");
00765 
00766       uves_free_table(&tmp_tbl);
00767     }
00768         ymin = (ymin_guess>ymin) ? ymin_guess : ymin;
00769         ymax = (ymax_guess<ymax) ? ymax_guess : ymax;
00770 
00771         uves_msg("Serching them in the region [ymin,ymax]=[%d,%d]",ymin,ymax);
00772         uves_free_table(&tmp_tbl);
00773 
00774 
00775       } else if (USE_GUESS_TAB == 2) {
00776 
00777       // Create a table with order lines in the same format as the
00778       // Hough transform would do it, i.e. intersept + slope for each order.
00779             
00780             int minorder = uves_round_double(
00781                 cpl_table_get_column_min(guess_table, "Order"));
00782             int maxorder = uves_round_double(
00783                 cpl_table_get_column_max(guess_table, "Order"));
00784             int nx = cpl_image_get_size_x(back_subbed);
00785             int order;
00786 
00787 
00788         uves_msg("Create a table with order lines in the same format as the");
00789         uves_msg("Hough transform would do it, ");
00790     uves_msg("i.e. intersept + slope for each order.");
00791 
00792             {
00793                 double kappa = 4;
00794                 int max_degree = 6;
00795                 double min_rms = 0.1; /* pixels */
00796                 double mse;
00797                 check( guess_locations = uves_polynomial_regression_2d_autodegree(
00798                            guess_table,
00799                            "X", "Order", "Yfit", NULL,
00800                            NULL, NULL, NULL,
00801                            &mse, NULL, NULL,
00802                            kappa,
00803                            max_degree, max_degree, min_rms, -1,
00804                            false,
00805                            NULL, NULL, -1, NULL),
00806                    "Could not fit polynomial to provided table");
00807 
00808             uves_msg("Provided table contains orders %d - %d. RMS = %.3f pixels",
00809                      minorder, maxorder, sqrt(mse));
00810             }
00811 
00812 
00813             
00814             ordertable = cpl_table_new(maxorder - minorder + 1);
00815             cpl_table_new_column(ordertable, "Order", CPL_TYPE_INT);
00816             cpl_table_new_column(ordertable, "Intersept", CPL_TYPE_DOUBLE);
00817             cpl_table_new_column(ordertable, "Slope", CPL_TYPE_DOUBLE);
00818             cpl_table_new_column(ordertable, "Spacing", CPL_TYPE_INT);
00819 
00820             for (order = minorder; order <= maxorder; order++)
00821                 {
00822                     int row = order - minorder;
00823                     double slope = 
00824                         uves_polynomial_derivative_2d(guess_locations, nx/2, order, 1);
00825                     double intersept = uves_polynomial_evaluate_2d(guess_locations, nx/2, order)
00826                         - slope*(nx/2);
00827                     int spacing = 
00828                         uves_round_double(uves_polynomial_derivative_2d(
00829                                               guess_locations, nx/2, order, 2));
00830                     
00831                     cpl_table_set_int   (ordertable, "Order", row, order);
00832                     cpl_table_set_double(ordertable, "Slope", row, slope);
00833                     cpl_table_set_int   (ordertable, "Spacing", row, spacing);
00834                     cpl_table_set_double(ordertable, "Intersept", row, intersept);
00835                 }
00836 
00837       } 
00838 
00839     }
00840     if( (guess_table == NULL) || (USE_GUESS_TAB != 2) )
00841         {
00842   
00843             /* Detect orders from scratch */
00844       uves_msg("Detect orders from scratch ");
00845 
00846 
00847 
00848           /* Remove bad/hot pixels with a median filter.
00849              * This is needed for the Hough transform, but
00850              * we trace the orders on the raw image (gives better fit).
00851              */
00852             {
00853                 bool extrapolate_border = true;     /* This is needed to avoid a sudden
00854                                                        intensity increase near the image
00855                                                        borders (which will confuse the Hough
00856                                                        transform) */
00857                 
00858                 uves_msg("Applying %dx%d median filter", RADX*2+1, RADY*2+1);
00859                 check( uves_filter_image_median(&back_subbed, RADX, RADY, extrapolate_border), 
00860                        "Could not filter image");
00861             }
00862 
00863             /* Subtract background */
00864             uves_msg("Subtracting background (grid sampling)");
00865             
00866             check( uves_backsub_poly(back_subbed,
00867                                      NULL, NULL,            /* Order locations are unknown */
00868                                      BM_METHOD,
00869                                      BACKSUBGRID,
00870                                      BACKSUBRADIUSY,
00871                                      BACKSUBDEGX,
00872                                      BACKSUBDEGY,
00873                                      BACKSUBKAPPA),
00874                    "Could not subtract background");
00875 
00876             check( ordertable = uves_hough(back_subbed,
00877                                            ymin, ymax,
00878                                            NORDERS, norders_is_guess,
00879                                            SAMPLEWIDTH,
00880                                            PTHRES,
00881                                            MINSLOPE,
00882                                            MAXSLOPE,
00883                                            SLOPERES,
00884                                            true,  /* Consecutive orders? */
00885                                            &hough_trans,
00886                                            &hough_original), 
00887                    "Could not locate echelle orders");
00888             
00889             if (DEBUG)
00890                 {
00891 
00892                    check(uves_propertylist_copy_property_regexp((uves_propertylist*)rotated_header,                                                raw_header,
00893                             "^ESO ", 0),
00894               "Error copying hieararch keys");
00895 
00896                     check( uves_save_image_local("Hough transform", "hough", 
00897                                                  hough_original, chip, -1, -1, 
00898                                                  rotated_header, true),
00899                            "Error saving hough image");
00900                     
00901                     check( uves_save_image_local("Hough transform (peaks deleted)", 
00902                                                  "hough_delete", hough_trans, 
00903                                                  chip, -1, -1, rotated_header, 
00904                                                  true),
00905                            "Error saving hough image");
00906                     
00907                     /* For debugging, draw Hough detected orders
00908                        (straight lines) on top of the input image */
00909                     check( inputlines = cpl_image_duplicate(raw_image), 
00910                            "Could not duplicate image");
00911                     check( uves_draw_orders(ordertable, inputlines), 
00912                            "Could not draw hough orders on image");
00913                     
00914                     check( uves_save_image_local("Lines detected by Hough transform",
00915                                                  "inputlines", inputlines, chip, -1, -1, rotated_header, true),
00916                            "Error saving hough image");
00917                     
00918                     uves_free_image(&inputlines);
00919                 }
00920 
00921             /* Clean up */
00922             uves_free_image(&hough_trans);
00923             uves_free_image(&hough_original);
00924         }
00925     /* Initial order detection done */
00926 
00927     /* Subtract background, but this time sample the interorder space */
00928     check(( uves_free_image(&back_subbed),
00929             back_subbed = cpl_image_duplicate(raw_image)),
00930           "Error duplicating image");
00931     
00932     uves_msg("Subtracting background (inter-order sampling)");
00933     check( uves_backsub_poly(back_subbed,
00934                              ordertable, NULL,
00935                              BM_METHOD,
00936                              BACKSUBGRID,
00937                              BACKSUBRADIUSY,
00938                              BACKSUBDEGX,
00939                              BACKSUBDEGY,
00940                              BACKSUBKAPPA),
00941            "Could not subtract background");
00942     
00943     /* Create noise image (readout + photonic noise) 
00944      * We need to do this *after* background subtraction,
00945      * because we cannot distinguish bias from scattered light
00946      * (if master bias was explicitly subtracted, we should
00947      *  define the noise model before background subtraction)
00948      */
00949     check( noise = uves_define_noise(back_subbed, raw_header, 1, chip),
00950        "Error creating noise image");
00951     
00952     if (DEBUG)
00953     {
00954         /* Save pre-processed (cropped, rotated, median filtered, 
00955            backgr. subtracted) input image  */
00956         check( uves_save_image_local("Pre-processed raw frame", "preproc", 
00957                      back_subbed, chip, -1, -1, rotated_header, true), 
00958            "Error saving image");
00959         
00960         /* Save noise of pre-processed input image */
00961         check( uves_save_image_local("Noise of pre-processed image", 
00962                      "preproc_noise", 
00963                      noise, chip, -1, -1, rotated_header, true),
00964            "Error saving image");
00965     }
00966     
00967     /* Mark bad pixels */
00968     check( badpixels_marked = 
00969        uves_correct_badpix_all(back_subbed,   /* MIDAS uses raw_image here */
00970                    raw_header, 
00971                    chip, 
00972                    binx, biny, 
00973                    true,           /* Mark, don't interpolate bad pixels */
00974                                red_ccd_is_new
00975            ),
00976        "Error marking bad pixels");
00977     
00978     uves_msg("%d pixels marked as bad", badpixels_marked);
00979 
00980     /* Trace the orders
00981        (using the background subtracted image or not if MIDAS) */
00982     uves_msg("norders=%d",*norders);
00983     if(USE_GUESS_TAB==2) {
00984        ord_min=cpl_table_get_column_min(ordertable,"Order");
00985        if (ord_min>1) {
00986           cpl_table_subtract_scalar(ordertable,"Order",ord_min-1);
00987        }
00988     }
00989 
00990     check( tracetable = uves_locate_orders(back_subbed,    /* MIDAS uses raw_image here */
00991                        noise,
00992                        ordertable,
00993                        TRACESTEP,
00994                        MINTHRESH,
00995                        MAXGAP,
00996                        MAXRMS,
00997                        DEFPOL1, DEFPOL2,
00998                        KAPPA,
00999                        bivariate_fit,
01000                        norders), "Could not trace orders");
01001     
01002     if(USE_GUESS_TAB==2) {
01003        if (ord_min>1) {
01004           cpl_table_add_scalar(ordertable,"Order",ord_min-1);
01005        }
01006     }
01007 
01008     if (false)
01009         /* This is a workaround for a broken wavecal recipe in the MIDAS
01010            pipeline. There is no reason to do this in the CPL pipeline,
01011            where the wavecal recipe is able to deal with partial orders */
01012         {
01013             check(uves_physmod_chop_otab(raw_header,chip,&tracetable,"Order",
01014                                          &abs_ord_min,&abs_ord_max),
01015                   "Could not run uves_physmod_chop_otab on trace order table");
01016         }
01017 
01018 
01019     /* add QC log */
01020 
01021 
01022     /* Save basic info about orders */
01023     if (DEBUG) check( uves_save_table_local("Basic order table", "basic",
01024                         ordertable, chip, -1, -1, raw_header, NULL),
01025               "Error saving table");
01026     
01027   cleanup:
01028     uves_free_image(&back_subbed);
01029     uves_free_image(&noise);
01030     uves_free_image(&hough_trans);
01031     uves_polynomial_delete(&guess_locations);
01032 
01033     /* Debug objects */
01034     uves_free_image(&hough_original);
01035     uves_free_image(&inputlines);
01036     uves_free_table(&ordertable);
01037     
01038     return tracetable;
01039 }
01040 
01041 /*----------------------------------------------------------------------------*/
01056 /*----------------------------------------------------------------------------*/
01057 void
01058 uves_orderpos_exe_body(cpl_frameset *frames,
01059                bool flames,
01060                const char *recipe_id,
01061                const cpl_parameterlist *parameters,
01062                const char *starttime)
01063 {
01064     /*
01065      * Variables that will contain the values of the recipe parameters 
01066      */
01067 
01068     /* General */
01069     bool      DEBUG;
01070     /* Preprocessing */
01071     int      USE_GUESS_TAB, RADX, RADY;
01072     background_measure_method BM_METHOD;
01073     int      BACKSUBGRID;
01074     int      BACKSUBRADIUSY;
01075     double   BACKSUBKAPPA;
01076     int      BACKSUBDEGX;
01077     int      BACKSUBDEGY;
01078     /* Hough transform */
01079     int      SAMPLEWIDTH;
01080     double   MINSLOPE, MAXSLOPE;
01081     int      SLOPERES;
01082     int      NORDERS=0;
01083     double   PTHRES;
01084     /* Order following */
01085     int      TRACESTEP;
01086     double   MINTHRESH;
01087     double   MAXGAP;
01088     /* Rejection */
01089     double   MAXRMS;
01090     int      DEFPOL1_par; /* Recipe parameter */
01091     int      DEFPOL2_par;
01092     double   KAPPA;
01093     const char* PROCESS_CHIP=NULL;
01094 
01095     /* Master bias */
01096     cpl_image *master_bias               = NULL;
01097     uves_propertylist *master_bias_header = NULL;
01098 
01099 
01100     /* Input image */
01101     cpl_image        *raw_image[2]      = {NULL, NULL};
01102     uves_propertylist *raw_header[2]     = {NULL, NULL};
01103     uves_propertylist *rotated_header[2] = {NULL, NULL};
01104     cpl_image        *raw_image_int     = NULL;
01105 
01106     /* Input guess table */
01107     uves_propertylist *guess_header      = NULL; 
01108     cpl_table        *guess_table       = NULL; 
01109 
01110     /* Output table */
01111     cpl_table        *tracetable        = NULL;
01112     polynomial       *bivariate_fit     = NULL;
01113     cpl_table        *traces            = NULL;  /* FLAMES/UVES compatibility */
01114     uves_propertylist *product_header    = NULL;
01115     cpl_table* qclog[2] = {NULL, NULL};
01116 
01117     /* Local variables */
01118     const char *raw_filename = "";
01119     char *product_filename = NULL;
01120     int ord_predict = 0;
01121     bool norders_is_guess = false;               /* Was norders read from guess table? */
01122     bool blue;
01123     enum uves_chip chip;
01124     int binx = 0;
01125     int biny = 0;
01126 
01127 
01128     const char *guess_filename = "";
01129     const char *chip_name = "";
01130     const char *master_bias_filename = "";
01131 
01132     int raw_index =0;
01133     int norders = 0;                           /* Number of orders detected */
01134         
01135     int DEFPOL1 = 0;
01136     int DEFPOL2 = 0;
01137 
01138     bool load_guess = false;
01139 
01140     int plate_no;
01141 
01142     int samples_per_order =0;
01143     char values[80];
01144 
01145     int i=0;
01146     int j=0;
01147 
01148 
01149     /* Read recipe parameters */
01150     {
01151     /* General */
01152     check( uves_get_parameter(parameters, NULL, "uves", "debug", CPL_TYPE_BOOL, &DEBUG), 
01153            "Could not read parameter");
01154     check( uves_get_parameter(parameters, NULL, "uves", "process_chip", CPL_TYPE_STRING, &PROCESS_CHIP),
01155                "Could not read parameter");
01156     uves_string_toupper((char*)PROCESS_CHIP);
01157 
01158     /* Preprocessing */
01159     check( uves_get_parameter(parameters, NULL, recipe_id, "preproc.use_guess_tab",
01160                   CPL_TYPE_INT   , &USE_GUESS_TAB), "Could not read parameter");
01161     check( uves_get_parameter(parameters, NULL, recipe_id, "preproc.radx",
01162                   CPL_TYPE_INT   , &RADX), "Could not read parameter");
01163     check( uves_get_parameter(parameters, NULL, recipe_id, "preproc.rady", 
01164                   CPL_TYPE_INT   , &RADY), "Could not read parameter");
01165 
01166     check( BM_METHOD = uves_get_bm_method(parameters, recipe_id, "preproc"),
01167            "Could not read background measuring method");
01168 
01169     check( uves_get_parameter(parameters, NULL, recipe_id, "preproc.backsubgrid", 
01170                   CPL_TYPE_INT  , &BACKSUBGRID), 
01171            "Could not read parameter");
01172     check( uves_get_parameter(parameters, NULL, recipe_id, "preproc.backsubradiusy",
01173                   CPL_TYPE_INT, &BACKSUBRADIUSY), "Could not read parameter");
01174     check( uves_get_parameter(parameters, NULL, recipe_id, "preproc.backsubkappa", 
01175                   CPL_TYPE_DOUBLE,&BACKSUBKAPPA), "Could not read parameter");
01176     check( uves_get_parameter(parameters, NULL, recipe_id, "preproc.backsubdegx", 
01177                   CPL_TYPE_INT  , &BACKSUBDEGX), "Could not read parameter");
01178     check( uves_get_parameter(parameters, NULL, recipe_id, "preproc.backsubdegy", 
01179                   CPL_TYPE_INT  , &BACKSUBDEGY), "Could not read parameter");
01180     /* Hough */
01181     check( uves_get_parameter(parameters, NULL, recipe_id, "hough.samplewidth"  , 
01182                   CPL_TYPE_INT   , &SAMPLEWIDTH), "Could not read parameter");
01183     check( uves_get_parameter(parameters, NULL, recipe_id, "hough.minslope"     , 
01184                   CPL_TYPE_DOUBLE, &MINSLOPE   ), "Could not read parameter");
01185     check( uves_get_parameter(parameters, NULL, recipe_id, "hough.maxslope"     , 
01186                   CPL_TYPE_DOUBLE, &MAXSLOPE   ), "Could not read parameter");
01187     check( uves_get_parameter(parameters, NULL, recipe_id, "hough.sloperes"     , 
01188                   CPL_TYPE_INT   , &SLOPERES   ), "Could not read parameter");
01189 /* hough.norders parameter has been temporally removed 
01190     check( uves_get_parameter(parameters, NULL, recipe_id, "hough.norders"      , 
01191                   CPL_TYPE_INT   , &NORDERS    ), "Could not read parameter");
01192 */
01193     check( uves_get_parameter(parameters, NULL, recipe_id, "hough.pthres"       , 
01194                   CPL_TYPE_DOUBLE, &PTHRES     ), "Could not read parameter");
01195     /* Tracing */
01196     check( uves_get_parameter(parameters, NULL, recipe_id, "trace.tracestep"    , 
01197                   CPL_TYPE_INT   , &TRACESTEP  ), "Could not read parameter");
01198     check( uves_get_parameter(parameters, NULL, recipe_id, "trace.minthresh"    , 
01199                   CPL_TYPE_DOUBLE, &MINTHRESH  ), "Could not read parameter");
01200     check( uves_get_parameter(parameters, NULL, recipe_id, "trace.maxgap"       , 
01201                   CPL_TYPE_DOUBLE, &MAXGAP     ), "Could not read parameter");
01202     /* Reject */
01203     check( uves_get_parameter(parameters, NULL, recipe_id, "reject.maxrms"      , 
01204                   CPL_TYPE_DOUBLE, &MAXRMS     ), "Could not read parameter");
01205     check( uves_get_parameter(parameters, NULL, recipe_id, "reject.defpol1"     , 
01206                   CPL_TYPE_INT   , &DEFPOL1_par ), "Could not read parameter");
01207     check( uves_get_parameter(parameters, NULL, recipe_id, "reject.defpol2"     , 
01208                   CPL_TYPE_INT   , &DEFPOL2_par), "Could not read parameter");
01209     check( uves_get_parameter(parameters, NULL, recipe_id, "reject.kappa"       , 
01210                   CPL_TYPE_DOUBLE, &KAPPA      ), "Could not read parameter");
01211     
01212     /* The range of parameters have already been checked by the caller */
01213     /* Do some additional checking */
01214     assure( MINSLOPE  < MAXSLOPE , CPL_ERROR_ILLEGAL_INPUT, 
01215         "Minimum slope must be smaller than maximum slope (min = %f; max = %f)",
01216         MINSLOPE, MAXSLOPE);
01217     if (MAXSLOPE > 0.5){
01218         uves_msg_warning("Hough transformation might fail when searching for "
01219                  "lines with slope larger than 0.5 (maxslope = %f)", MAXSLOPE);
01220     }
01221 
01222     if (DEFPOL1_par >= 6 || DEFPOL2_par >= 6)
01223         {
01224         uves_msg_warning("Polynomial fitting might be unstable with "
01225                  "polynomial degrees higher than 5");
01226         }
01227     
01228     }
01229     
01230     /* Load raw image and header, and identify input frame as red or blue */
01231     check( uves_load_orderpos(frames, 
01232                               flames, 
01233                               &raw_filename, raw_image,
01234                   raw_header, rotated_header, &blue), "Error loading raw frame");
01235     
01236     /* Normalize the range of slopes to match the binning of the input image */
01237     check (binx = uves_pfits_get_binx(raw_header[0]),
01238        "Could not read x binning factor from input header");
01239     check (biny = uves_pfits_get_biny(raw_header[0]),
01240        "Could not read y binning factor from input header");
01241     /* If, for instance, BINX = 2, the slope of a line in the input frame is
01242        twice the slope of the line on the (unbinned) chip, and generally we need
01243        to change SLOPE := BINX/BINY * SLOPE, when going from unbinned to binned
01244        data.
01245        Additionally, when rotating a UVES frame into standard orientation, x- and y-
01246        directions are swapped, so the parameters MINSLOPE and MAXSLOPE must be
01247        multiplied by BINY/BINX to correct for binning. */
01248     MINSLOPE = (MINSLOPE*biny)/binx;
01249     MAXSLOPE = (MAXSLOPE*biny)/binx;
01250     
01251     ord_predict = NORDERS;
01252     
01253     /* Loop over one or two chips */
01254     for (chip = uves_chip_get_first(blue); 
01255      chip != UVES_CHIP_INVALID; 
01256      chip = uves_chip_get_next(chip))
01257     {
01258 
01259       if(strcmp(PROCESS_CHIP,"REDU") == 0) {
01260     chip = uves_chip_get_next(chip);
01261       }
01262 
01263 
01264 
01265         raw_index = uves_chip_get_index(chip);
01266         norders = 0;                           /* Number of orders detected */
01267         
01268         DEFPOL1 = DEFPOL1_par;
01269         DEFPOL2 = DEFPOL2_par;
01270         
01271         uves_msg("Processing %s chip in '%s'",
01272              uves_chip_tostring_upper(chip), raw_filename);
01273 
01274         check_nomsg( chip_name = uves_pfits_get_chipid(raw_header[raw_index], chip));
01275 
01276         uves_msg_debug("Binning = %dx%d", binx, biny);
01277 
01278         /* If user didn't specify number of orders, then
01279          *   Load the DRS-table (MIDAS), or if not present,
01280          *   load the guess order table, or if not present,
01281          *   auto-detect number of orders
01282          */
01283         if (NORDERS == 0)
01284         {
01285             /* The number of orders to detect will 
01286                be read from input guess table (if available),
01287                and it is just a guess: */
01288             norders_is_guess = true;
01289 
01290             uves_free_propertylist(&guess_header);
01291             
01292             if (cpl_frameset_find(frames, UVES_DRS_SETUP(flames, chip)) != NULL)
01293             {
01294                 uves_msg_low("No guess order table found");
01295                 
01296                 check( uves_load_drs(frames, flames, chip_name, &guess_filename, 
01297                          &guess_header, chip),
01298                    "Error loading setup table");
01299                 
01300                 uves_msg("Using setup table in '%s'", guess_filename);
01301 
01302                 check( ord_predict = uves_pfits_get_ordpred(guess_header), 
01303                    "Could not read predicted number "
01304                    "of orders from DRS table header");
01305             }
01306             else if (cpl_frameset_find(frames,
01307                            UVES_ORDER_TABLE(flames, chip)) != NULL ||
01308                  cpl_frameset_find(frames,
01309                            UVES_GUESS_ORDER_TABLE(flames, chip)) != NULL)
01310             {
01311                 load_guess = (
01312                 cpl_frameset_find(frames,
01313                           UVES_GUESS_ORDER_TABLE(flames, chip))
01314                 != NULL);
01315                 
01316                 uves_free_table(&guess_table);
01317                 
01318                 check( uves_load_ordertable(
01319                        frames,
01320                        flames,
01321                        chip_name,
01322                        &guess_filename, 
01323                        &guess_table,
01324                        &guess_header,
01325                                        NULL,
01326                                        NULL,  /* Don't read order polynomial */
01327                        NULL,  /* Don't read fibre traces */
01328                        NULL, NULL,  /* oshift, yshift */
01329                                        NULL, NULL, /* fibre_pos,fibre_mask */
01330                        chip,
01331                        load_guess),
01332                    "Error loading guess order table");
01333                 
01334                 uves_msg("Using guess order table in '%s'", guess_filename);
01335                 
01336                 check( ord_predict = uves_pfits_get_ordpred(guess_header), 
01337                    "Could not read predicted number of orders from "
01338                    "guess order table header");
01339                         }
01340             else
01341             { 
01342                 uves_msg("No guess table found");
01343             }
01344         }
01345         else
01346         {
01347             /* The user has specified the number of orders to detect.
01348              * The user is always right, so don't allow the
01349              * detection algorithm to detect fewer orders. 
01350              */
01351             norders_is_guess = false;
01352         }
01353 
01354         /* Load master bias, set pointer to NULL if not present */
01355         uves_free_image(&master_bias);
01356         uves_free_propertylist(&master_bias_header);
01357         if (cpl_frameset_find(frames, UVES_MASTER_BIAS(chip)) != NULL)
01358         {
01359             uves_free_image(&master_bias);
01360             uves_free_propertylist(&master_bias_header);
01361             check( uves_load_mbias(frames,
01362                        chip_name,
01363                        &master_bias_filename, &master_bias,
01364                        &master_bias_header, chip), 
01365                "Error loading master bias");
01366             
01367             uves_msg_low("Using master bias in '%s'", master_bias_filename);
01368         cpl_image_subtract(raw_image[raw_index],master_bias);        
01369 
01370         }
01371         else
01372         {
01373             uves_msg_low("No master bias in SOF. Bias subtraction not done");
01374         }
01375 
01376         /* Execute macro steps */
01377         check((uves_free_table       (&tracetable),
01378            uves_polynomial_delete(&bivariate_fit),
01379            tracetable = uves_orderpos_process_chip(
01380                raw_image[raw_index], 
01381                raw_header[raw_index], 
01382                rotated_header[raw_index],
01383                chip, binx, biny,
01384                DEBUG,
01385                USE_GUESS_TAB,
01386                RADX, RADY,
01387                BM_METHOD,
01388                BACKSUBGRID,
01389                BACKSUBRADIUSY,
01390                BACKSUBKAPPA,
01391                BACKSUBDEGX, BACKSUBDEGY,
01392                SAMPLEWIDTH,
01393                MINSLOPE, MAXSLOPE,
01394                SLOPERES,
01395                ord_predict,
01396                norders_is_guess,
01397                PTHRES,
01398                TRACESTEP,
01399                MINTHRESH,
01400                MAXGAP,
01401                MAXRMS,
01402                &DEFPOL1,
01403                &DEFPOL2,
01404                KAPPA,
01405                &bivariate_fit,
01406                &norders,
01407                        guess_table)),
01408           "Error processing chip");
01409         
01410         /* Finished. Save the products */
01411         uves_msg("Saving products...");
01412         
01413         /* QC parameters should go here.
01414            Other mandatory keywords (FITS + dfs) are
01415            automatically added. */
01416         uves_free_propertylist(&product_header);
01417         product_header = uves_propertylist_new();
01418 
01419         /* Write number of detected orders */
01420         check( uves_pfits_set_ordpred( product_header, norders),
01421            "Error writing number of detected orders");
01422 
01423         if (flames)
01424         {
01425 
01426             check( plate_no = uves_flames_pfits_get_plateid(raw_header[raw_index]),
01427                "Error reading plate id");
01428 
01429             uves_flames_pfits_set_newplateid(product_header, plate_no);
01430         }
01431 
01432         /* Save order trace table */
01433         {
01434         samples_per_order = 
01435             cpl_image_get_size_x(raw_image[raw_index]) / TRACESTEP;
01436             
01437         uves_qclog_delete(&qclog[0]);
01438         qclog[0] = uves_qclog_init(raw_header[raw_index], chip);
01439         check_nomsg( uves_orderpos_qclog(tracetable,
01440                          flames,
01441                          ord_predict,
01442                          norders,
01443                          samples_per_order,
01444                          raw_header[raw_index],chip,qclog[0]));
01445         }
01446 
01447         if (flames) {
01448             /* Write polynomial in MIDAS format, as expected 
01449                by flames_cal_prep_sff_ofpos */
01450 
01451             /* Only COEFFI(6) and COEFFI(7) are used */
01452             snprintf(values, 80, "-1 -1 -1 -1 -1 %d %d", DEFPOL1, DEFPOL2);
01453             
01454             uves_propertylist_append_string(product_header, 
01455                                             "HISTORY", "'COEFFI','I*4'");
01456             uves_propertylist_append_string(product_header,
01457                                             "HISTORY", values);
01458             uves_propertylist_append_string(product_header,
01459                                             "HISTORY", " ");
01460 
01461             /* Polynomial coeffients */
01462             uves_propertylist_append_string(product_header, 
01463                                             "HISTORY", "'COEFFD','R*8'");
01464             {
01465 
01466                 for (j = 0; j <= DEFPOL2; j++) {
01467                     for (i = 0; i <= DEFPOL1; i++) {
01468                         snprintf(values, 80, "%g",
01469                                  uves_polynomial_get_coeff_2d(bivariate_fit, i, j));
01470                         uves_propertylist_append_string(product_header,
01471                                                         "HISTORY", values);
01472                     }
01473                 }
01474             }
01475             uves_propertylist_append_string(product_header,
01476                                             "HISTORY", " ");
01477 
01478             /* Min - max values */
01479             uves_propertylist_append_string(product_header, 
01480                                             "HISTORY", "'COEFFR','R*4'");
01481             snprintf(values, 80, "%g %g", 
01482                      cpl_table_get_column_min(tracetable, "X"),
01483                     cpl_table_get_column_max(tracetable, "X"));            
01484             uves_propertylist_append_string(product_header,
01485                                             "HISTORY", values);
01486 
01487             snprintf(values, 80, "%g %g", 
01488                      cpl_table_get_column_min(tracetable, "Order"),
01489                      cpl_table_get_column_max(tracetable, "Order"));
01490             uves_propertylist_append_string(product_header,
01491                                             "HISTORY", values);
01492 
01493             uves_propertylist_append_string(product_header,
01494                                             "HISTORY", " ");
01495         }
01496         
01497         check(( cpl_free(product_filename),
01498             product_filename = uves_order_table_filename(chip),
01499             uves_frameset_insert(frames,
01500                      tracetable,
01501                      CPL_FRAME_GROUP_PRODUCT,
01502                      CPL_FRAME_TYPE_TABLE,
01503                      CPL_FRAME_LEVEL_INTERMEDIATE,
01504                      product_filename,
01505                      UVES_ORD_TAB(flames, chip),
01506                      raw_header[raw_index],
01507                      product_header,
01508                      NULL,
01509                      parameters,
01510                      recipe_id,
01511                      PACKAGE "/" PACKAGE_VERSION,
01512                      qclog,
01513                      starttime, true, 0)),
01514            "Could not add trace table %s to frameset", product_filename);
01515             uves_qclog_delete(&qclog[0]);
01516         uves_msg("Trace table %s added to frameset", product_filename);
01517         
01518         /* Save polynomial in next extension (don't add header keywords) */
01519         check( uves_save_polynomial(bivariate_fit, product_filename, NULL),
01520            "Could not write polynomial to file %s", product_filename);
01521         
01522         /* Original comment:
01523            For compatibility with FLAMES/UVES, create the extension defining
01524            that there is only one trace which has zero offset, and that 
01525            this trace is enabled.
01526 
01527            Update after the implementation of FLAMES support:
01528            This extension is not used by FLAMES and is therefore redundant.
01529            But for simplicity, keep it as it was
01530         */
01531         {
01532 
01533         uves_free_table(&traces);
01534         traces = uves_ordertable_traces_new();
01535         uves_ordertable_traces_add(traces, 0, 0.0, 1);
01536         
01537         check( cpl_table_save(traces,
01538                       NULL,            /* Primary header, 
01539                               ignored when mode is IO_EXTEND */
01540                       NULL,            /* Extension header               */
01541                       product_filename,/* This file already exists
01542                               (or an error occurs)           */
01543                       CPL_IO_EXTEND),  /* Append to existing file        */
01544                "Error appending table to file '%s'", product_filename);
01545         }
01546         /* Finished saving order table */
01547         
01548         if (flames) {
01549             /* Make two calibration frames out of the input frame */
01550 
01551             /* Save as integer */
01552             uves_free_image(&raw_image_int);
01553             raw_image_int = cpl_image_cast(raw_image[raw_index],
01554                            CPL_TYPE_INT);
01555 
01556             check(( cpl_free(product_filename),
01557                 product_filename = uves_ordef_filename(chip),
01558                 uves_frameset_insert(frames,
01559                          raw_image_int,
01560                          CPL_FRAME_GROUP_PRODUCT,
01561                          CPL_FRAME_TYPE_IMAGE,
01562                          CPL_FRAME_LEVEL_INTERMEDIATE,
01563                          product_filename,
01564                          FLAMES_ORDEF(flames, chip),
01565                          raw_header[raw_index],     /* raw header    */
01566                          rotated_header[raw_index], /* output header */
01567                          NULL,
01568                          parameters,
01569                          recipe_id,
01570                          PACKAGE "/" PACKAGE_VERSION,
01571                          NULL, /* No QC */
01572                          starttime, false,
01573                          CPL_STATS_MIN | CPL_STATS_MAX)),
01574               "Could not add raw frame %s to frameset", product_filename);
01575 
01576             uves_msg("Raw frame %s added to frameset", product_filename);
01577             uves_free_image(&raw_image_int);
01578         }
01579 
01580       if(strcmp(PROCESS_CHIP,"REDL") == 0) {
01581     chip = uves_chip_get_next(chip);
01582       }
01583 
01584         
01585     } /* For each chip */
01586 
01587   cleanup:
01588      /* Raw */
01589      uves_free_image(&(raw_image[0]));
01590      uves_free_image(&(raw_image[1]));
01591      uves_free_image(&raw_image_int);
01592      uves_free_propertylist(&(raw_header[0]));
01593      uves_free_propertylist(&(raw_header[1]));
01594      uves_free_propertylist(&(rotated_header[0]));
01595      uves_free_propertylist(&(rotated_header[1]));
01596 
01597     /* Master bias */
01598     uves_free_image(&master_bias);
01599     uves_free_propertylist(&master_bias_header);
01600 
01601      /* Calibration */
01602      uves_free_propertylist(&guess_header);
01603      uves_free_table       (&guess_table);
01604      
01605      /* Product */
01606      uves_qclog_delete(&qclog[0]);
01607      uves_free_table       (&tracetable);
01608      uves_polynomial_delete(&bivariate_fit);
01609      uves_free_table       (&traces);
01610      uves_free_propertylist(&product_header);
01611      cpl_free(product_filename);
01612      
01613      return;
01614 }
01625 static void uves_orderpos_qclog(cpl_table* table,
01626                 bool flames,
01627                 int pord, 
01628                 int dord,
01629                 int samples_per_order,
01630                 uves_propertylist* raw_header, 
01631                 enum uves_chip chip,
01632                 cpl_table* qclog)
01633 {
01634     const char* chip_name;
01635     const char* grat_name;
01636     const char* ins_mode;
01637     double grat_wlen=0;
01638 
01639     uves_qclog_add_string(qclog,
01640               "QC TEST1 ID",
01641               flames ? 
01642               "Single-Fibre-Order-Definition-Results" :
01643               "Order-Definition-Results",
01644               "Name of QC test",
01645               "%s");
01646 
01647     check_nomsg( chip_name=uves_pfits_get_chip_name(raw_header,chip) );
01648     /* chip_name = UVES_QC_CHIP_VAL(chip); */
01649 
01650   uves_qclog_add_string(qclog,
01651                         uves_remove_string_prefix(UVES_CHIP_NAME(chip),"ESO "),
01652                         chip_name,
01653                         "Grating unique ID",
01654                         "%s");
01655 
01656 
01657   check_nomsg(grat_name=uves_pfits_get_gratname(raw_header,chip));
01658 
01659 
01660 
01661   uves_qclog_add_string(qclog,
01662                         uves_remove_string_prefix(UVES_GRATNAME(chip),"ESO "),
01663                         grat_name,
01664                         "Cross disperser ID",
01665                         "%s");
01666 
01667 
01668   check_nomsg(ins_mode=uves_pfits_get_insmode(raw_header));
01669   uves_qclog_add_string(qclog,
01670                         uves_remove_string_prefix(UVES_INSMODE,"ESO "),
01671                         ins_mode,
01672                         "Instrument mode used.",
01673                         "%s");
01674 
01675 
01676   check_nomsg(grat_wlen=uves_pfits_get_gratwlen(raw_header,chip));
01677   uves_qclog_add_double(qclog,
01678                         uves_remove_string_prefix(UVES_GRATWLEN(chip),"ESO "),
01679                         grat_wlen,
01680                         "Grating central wavelength [nm]",
01681                         "%.1f");
01682 
01683   uves_msg_debug("chip_name=%s grat_name=%s ins_mode=%s grat_wlen=%f",
01684          chip_name,grat_name,ins_mode,grat_wlen);
01685 
01686   uves_qclog_add_double(qclog,
01687                         "QC ORD RESIDMIN",
01688                         cpl_table_get_column_min(table,"Residual"),
01689                         "min resid in ord def",
01690                         "%8.4f");
01691 
01692   uves_qclog_add_double(qclog,
01693                         "QC ORD RESIDMAX",
01694                         cpl_table_get_column_max(table,"Residual"),
01695                         "max resid in ord def",
01696                         "%8.4f");
01697 
01698   uves_qclog_add_double(qclog,
01699                         "QC ORD RESIDAVG",
01700                         cpl_table_get_column_mean(table,"Residual"),
01701                         "mean resid in ord def",
01702                         "%8.4f");
01703 
01704   uves_qclog_add_double(qclog,
01705                         "QC ORD RESIDRMS",
01706                         cpl_table_get_column_stdev(table,"Residual"),
01707                         "rms resid in ord def",
01708                         "%8.4f");
01709 
01710   uves_qclog_add_int(qclog,
01711                         "QC ORD NPRED",
01712                         pord,
01713                         "predicted number of orders",
01714                         "%d");
01715 
01716   uves_qclog_add_int(qclog,
01717                         "QC ORD NDET",
01718                         dord,
01719                         "detected number of orders",
01720                         "%d");
01721 
01722   uves_qclog_add_int(qclog,
01723              "QC ORD NPOSALL",
01724              dord * samples_per_order,
01725              "Number of position found",
01726              "%d");
01727   
01728   uves_qclog_add_int(qclog,
01729              "QC ORD NPOSSEL",
01730              cpl_table_get_nrow(table),
01731              "Number of position selected",
01732              "%d");
01733 
01734   uves_qclog_add_int(qclog,
01735                         "QC ORDMIN",
01736                         cpl_table_get_column_min(table,"Order"),
01737                         "Number of position selected",
01738                         "%d");
01739 
01740   uves_qclog_add_int(qclog,
01741                         "QC ORDMAX",
01742                         cpl_table_get_column_max(table,"Order"),
01743                         "Number of position selected",
01744                         "%d");
01745 
01746 
01747 
01748   /* In later MIDAS versions, these were added: */
01749 
01750   check_nomsg(uves_qclog_add_string(qclog,
01751                     uves_remove_string_prefix(UVES_READ_SPEED,"ESO "),
01752                     uves_pfits_get_readspeed(raw_header),
01753                     "Readout speed",
01754                     "%s"));
01755   
01756   check_nomsg(uves_qclog_add_int(qclog,
01757                  uves_remove_string_prefix(UVES_BINX, "ESO "),
01758                  uves_pfits_get_binx(raw_header),
01759                  "Binning factor along X",
01760                  "%d"));
01761   
01762   check_nomsg(uves_qclog_add_int(qclog,
01763                  uves_remove_string_prefix(UVES_BINY, "ESO "),
01764                  uves_pfits_get_biny(raw_header),
01765                  "Binning factor along Y",
01766                  "%d"));
01767   
01768   check_nomsg(uves_qclog_add_string(qclog,
01769                     uves_remove_string_prefix(UVES_INSPATH,"ESO "),
01770                     uves_pfits_get_inspath(raw_header),
01771                     "Optical path used (h).",
01772                     "%s"));
01773     
01774  cleanup:
01775   return;
01776 
01777 }

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