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

Generated on Mon Apr 21 10:56:55 2008 for UVES Pipeline Reference Manual by  doxygen 1.5.1