uves_orderpos_body.c

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

Generated on Thu Nov 15 14:32:29 2007 for UVES Pipeline Reference Manual by  doxygen 1.5.1