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

Generated on 3 Mar 2013 for UVES Pipeline Reference Manual by  doxygen 1.6.1