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

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