uves_wavecal_search.c

00001 /*                                                                              *
00002  *   This file is part of the ESO UVES Pipeline                                 *
00003  *   Copyright (C) 2004,2005 European Southern Observatory                      *
00004  *                                                                              *
00005  *   This library is free software; you can redistribute it and/or modify       *
00006  *   it under the terms of the GNU General Public License as published by       *
00007  *   the Free Software Foundation; either version 2 of the License, or          *
00008  *   (at your option) any later version.                                        *
00009  *                                                                              *
00010  *   This program is distributed in the hope that it will be useful,            *
00011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of             *
00012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
00013  *   GNU General Public License for more details.                               *
00014  *                                                                              *
00015  *   You should have received a copy of the GNU General Public License          *
00016  *   along with this program; if not, write to the Free Software                *
00017  *   Foundation, 51 Franklin St, Fifth Floor, Boston, MA  02111-1307  USA       *
00018  *                                                                              */
00019 
00020 /*
00021  * $Author: amodigli $
00022  * $Date: 2010/09/24 09:32:10 $
00023  * $Revision: 1.28 $
00024  * $Name: uves-4_9_1 $
00025  * $Log: uves_wavecal_search.c,v $
00026  * Revision 1.28  2010/09/24 09:32:10  amodigli
00027  * put back QFITS dependency to fix problem spot by NRI on FIBER mode (with MIDAS calibs) data
00028  *
00029  * Revision 1.26  2007/08/21 13:08:26  jmlarsen
00030  * Removed irplib_access module, largely deprecated by CPL-4
00031  *
00032  * Revision 1.25  2007/06/06 08:17:34  amodigli
00033  * replace tab with 4 spaces
00034  *
00035  * Revision 1.24  2007/05/02 13:20:01  jmlarsen
00036  * Take error bars into account in line searching if arclamp was flat-fielded
00037  *
00038  * Revision 1.23  2007/04/24 12:50:29  jmlarsen
00039  * Replaced cpl_propertylist -> uves_propertylist which is much faster
00040  *
00041  * Revision 1.22  2007/04/20 14:46:45  jmlarsen
00042  * Added commented out code
00043  *
00044  * Revision 1.21  2007/03/05 10:25:08  jmlarsen
00045  * Include slope in Gaussian fit
00046  *
00047  * Revision 1.20  2007/02/23 13:33:38  jmlarsen
00048  * Added code to test unweighted fitting
00049  *
00050  * Revision 1.19  2007/02/22 15:38:26  jmlarsen
00051  * Use linear background term in Gaussian fit
00052  *
00053  * Revision 1.18  2006/11/15 15:02:15  jmlarsen
00054  * Implemented const safe workarounds for CPL functions
00055  *
00056  * Revision 1.16  2006/11/15 14:04:08  jmlarsen
00057  * Removed non-const version of parameterlist_get_first/last/next which is already
00058  * in CPL, added const-safe wrapper, unwrapper and deallocator functions
00059  *
00060  * Revision 1.15  2006/11/06 15:19:42  jmlarsen
00061  * Removed unused include directives
00062  *
00063  * Revision 1.14  2006/08/18 13:51:01  jmlarsen
00064  * Moved one message from info to debug level
00065  *
00066  * Revision 1.13  2006/08/17 13:56:53  jmlarsen
00067  * Reduced max line length
00068  *
00069  * Revision 1.12  2006/08/17 09:18:47  jmlarsen
00070  * Removed CPL2 code
00071  *
00072  * Revision 1.11  2006/08/11 14:38:24  jmlarsen
00073  * Minor text output change
00074  *
00075  * Revision 1.10  2006/08/11 09:01:17  jmlarsen
00076  * Set unextracted bins to zero flux rather than marking them as bad
00077  *
00078  * Revision 1.9  2006/07/14 12:45:58  jmlarsen
00079  * Removed a few messages
00080  *
00081  * Revision 1.8  2006/07/03 13:29:30  jmlarsen
00082  * Adapted to new 1d-fitting function interface
00083  *
00084  * Revision 1.7  2006/06/13 12:05:11  jmlarsen
00085  * Shortened max line length
00086  *
00087  * Revision 1.6  2006/05/12 15:06:30  jmlarsen
00088  * Killed code for method = gravity
00089  *
00090  * Revision 1.5  2006/04/24 09:34:26  jmlarsen
00091  * Adapted to new interface of gaussian fitting routine
00092  *
00093  * Revision 1.4  2006/03/03 13:54:11  jmlarsen
00094  * Changed syntax of check macro
00095  *
00096  * Revision 1.3  2006/02/15 13:19:15  jmlarsen
00097  * Reduced source code max. line length
00098  *
00099  * Revision 1.2  2006/02/08 07:52:16  jmlarsen
00100  * Added function returning library version
00101  *
00102  * Revision 1.34  2006/01/12 15:41:14  jmlarsen
00103  * Moved gauss. fitting to irplib
00104  *
00105  * Revision 1.33  2005/12/20 08:11:44  jmlarsen
00106  * Added CVS  entry
00107  *
00108  */
00109 
00110 /*----------------------------------------------------------------------------*/
00114 /*----------------------------------------------------------------------------*/
00117 #ifdef HAVE_CONFIG_H
00118 #  include <config.h>
00119 #endif
00120 
00121 #include <uves_wavecal_search.h>
00122 #include <uves_utils.h>
00123 #include <uves_utils_wrappers.h>
00124 #include <uves_utils_cpl.h>
00125 #include <uves_pfits.h>
00126 #include <uves_dump.h>
00127 #include <uves_error.h>
00128 #include <uves_msg.h>
00129 
00130 #include <cpl.h>
00131 #include <float.h>
00132 
00133 #define FIT_SLOPE 1
00134 #define WEIGHTED_FIT 1   /* Define to zero to get unweighted fit of emmision line
00135                             (like MIDAS) */
00136 
00137 static double
00138 xcenter(const cpl_image *image, const cpl_image *noise, int xlo, int xhi, int row,
00139     centering_method CENTERING_METHOD, int bin_disp,
00140     double *sigma, double *intensity, double *dx0, double *slope, double *background);
00141 
00142 static cpl_error_code
00143 detect_lines(const cpl_image *spectrum, const cpl_image *noise, 
00144          const uves_propertylist *spectrum_header, 
00145              bool flat_fielded,
00146          int RANGE, double THRESHOLD, centering_method CENTERING_METHOD, 
00147              int bin_disp,
00148          const polynomial *order_locations, cpl_image *arcframe, 
00149          cpl_table *linetable, 
00150          int *ndetected, int *nrows);
00151 
00152 /*----------------------------------------------------------------------------*/
00182 /*----------------------------------------------------------------------------*/
00183 cpl_table *
00184 uves_wavecal_search(const cpl_image *spectrum, const cpl_image *noise,
00185             const uves_propertylist *spectrum_header,
00186                     bool flat_fielded,
00187             const polynomial *order_locations, cpl_image *arcframe,
00188             int RANGE, int MINLINES, int MAXLINES,
00189             centering_method CENTERING_METHOD,
00190                     int bin_disp)
00191 {
00192     cpl_table *linetable = NULL;       /* Result */
00193 
00194     int nx, ny, norders;               /* Dimensions of raw image, number of orders */
00195     double threshold_low;              /* Threshold limits used for binary search */
00196     double threshold_high;
00197     double threshold = 0;             /* Current threshold */
00198     int lines_in_table;               /* Number of lines in line table */
00199     int lines_detected;               /* Number of lines actually found */
00200     bool max_thresh_found = false;    /* Is 'threshold_high' large enough? */
00201 
00202     passure( spectrum        != NULL, "Null input spectrum");
00203     passure( order_locations != NULL, "Null polynomial");
00204     passure( arcframe        != NULL, "Null raw image");
00205 
00206     if (flat_fielded) {
00207         assure( cpl_image_get_type(spectrum) == CPL_TYPE_DOUBLE,
00208                 CPL_ERROR_TYPE_MISMATCH,
00209                 "Spectrum image type is %s, must be double",
00210                 uves_tostring_cpl_type(cpl_image_get_type(spectrum)));
00211     }
00212     
00213     check(( nx      = cpl_image_get_size_x(spectrum),
00214         norders = cpl_image_get_size_y(spectrum)), "Error reading input spectrum");
00215     check( ny      = cpl_image_get_size_y(arcframe), "Error reading input image");
00216     assure(nx == cpl_image_get_size_x(arcframe), CPL_ERROR_INCOMPATIBLE_INPUT, 
00217        "Spectrum and image widths are different (%d and %d)",
00218        nx, cpl_image_get_size_x(arcframe));
00219     
00220     assure( MINLINES <= MAXLINES, CPL_ERROR_ILLEGAL_INPUT, 
00221         "minlines=%d maxlines=%d", MINLINES, MAXLINES );
00222     
00223     /* Initialize result line table */
00224     check(( linetable = cpl_table_new(MAXLINES),
00225         cpl_table_new_column(linetable, "X"     , CPL_TYPE_DOUBLE),
00226         cpl_table_new_column(linetable, "dX"    , CPL_TYPE_DOUBLE),
00227         cpl_table_new_column(linetable, "Xwidth", CPL_TYPE_DOUBLE),
00228         cpl_table_new_column(linetable, "Y"     , CPL_TYPE_INT),
00229         cpl_table_new_column(linetable, "Peak"  , CPL_TYPE_DOUBLE),
00230         cpl_table_new_column(linetable, "Background" , CPL_TYPE_DOUBLE),
00231         cpl_table_new_column(linetable, "Slope" , CPL_TYPE_DOUBLE)),
00232       "Could not create line table");
00233     
00234     uves_msg("Searching for emission lines");
00235 
00236     threshold_low  = 0.0;
00237 
00238     /* This start (guess) value is doubled until too few lines are detected */
00239     if (flat_fielded) {
00240         threshold_high = 10.0; /* dimensionless, number of stdevs above continuum */
00241     }
00242     else {
00243         threshold_high = cpl_image_get_mean(spectrum);
00244 
00245         assure( threshold_high > 0, CPL_ERROR_ILLEGAL_INPUT,
00246                 "Spectrum median flux is %e. Must be positive",
00247                 cpl_image_get_median(spectrum));
00248     }
00249     
00250     max_thresh_found = false;
00251 
00252     /* Detect lines and adjust threshold
00253        until MINLINES <= lines_detected <= MAXLINES */
00254     lines_detected = 0;
00255     while( (lines_detected < MINLINES || MAXLINES < lines_detected) && 
00256         fabs(threshold_low - threshold_high) > DBL_EPSILON )
00257     {
00258         threshold = (threshold_low + threshold_high)/2.0;
00259 
00260         check( detect_lines(spectrum, noise, spectrum_header,
00261                                 flat_fielded,
00262                 RANGE, threshold, CENTERING_METHOD,
00263                                 bin_disp,
00264                 order_locations,
00265                 NULL,
00266                 linetable,
00267                 &lines_detected,
00268                 &lines_in_table),
00269            "Could not search for emission lines");
00270         
00271         /* Update threshold */
00272         /* 'threshold_high' is doubled until the threshold is too high.
00273            Then a binary search is performed. */
00274         if (lines_detected < MINLINES)
00275         {
00276             max_thresh_found = true;
00277             threshold_high = threshold;
00278         }
00279         else if (MAXLINES < lines_detected) 
00280         {
00281             if (!max_thresh_found)
00282             {
00283                 threshold_high *= 2;
00284             }
00285             else
00286             {                
00287                 threshold_low = threshold;
00288             }
00289         }
00290     }
00291 
00292     assure( MINLINES <= lines_detected && lines_detected <= MAXLINES, 
00293         CPL_ERROR_CONTINUE,
00294         "Could not detect between %d and %d lines. Try to increase search range",
00295         MINLINES, MAXLINES);
00296     
00297     /* Draw detections on input image  */
00298     check( detect_lines(spectrum, noise, spectrum_header,
00299                         flat_fielded,
00300             RANGE, threshold, CENTERING_METHOD,
00301                         bin_disp,
00302             order_locations,
00303             arcframe,
00304             linetable,
00305             &lines_detected,
00306             &lines_in_table),
00307        "Could not search for emission lines");
00308     
00309     /* Remove the last part of the line table (garbage) */
00310     check( cpl_table_set_size(linetable, lines_in_table), 
00311        "Could not resize line table");
00312     
00313     uves_sort_table_1(linetable, "X", false);
00314     
00315   cleanup:
00316 #if 0 /* if flat-fielded */
00317     uves_free_image(&temp);
00318 #endif
00319     if (cpl_error_get_code() != CPL_ERROR_NONE)
00320     {
00321         uves_free_table(&linetable);
00322     }
00323     else
00324     {
00325         /* Returned is... */
00326         passure( cpl_table_get_ncol(linetable) == 7, "%d", 
00327              cpl_table_get_ncol(linetable));
00328         passure( cpl_table_has_column(linetable, "X"     ), " ");
00329         passure( cpl_table_has_column(linetable, "dX"    ), " ");
00330         passure( cpl_table_has_column(linetable, "Xwidth"), " ");
00331         passure( cpl_table_has_column(linetable, "Y"     ), " ");
00332         passure( cpl_table_has_column(linetable, "Peak"  ), " ");
00333         passure( cpl_table_has_column(linetable, "Background" ), " ");
00334         passure( cpl_table_has_column(linetable, "Slope" ), " ");
00335         
00336     }
00337     return linetable;
00338 }
00339 
00340 /*----------------------------------------------------------------------------*/
00391 /*----------------------------------------------------------------------------*/
00392 static cpl_error_code
00393 detect_lines(const cpl_image *spectrum, const cpl_image *noise, 
00394          const uves_propertylist *spectrum_header, 
00395              bool flat_fielded,
00396          int RANGE, double THRESHOLD, centering_method CENTERING_METHOD, 
00397              int bin_disp,
00398          const polynomial *order_locations, cpl_image *arcframe, 
00399          cpl_table *linetable, 
00400          int *ndetected, int *nrows)
00401 {
00402     int norders;      /* Number of orders */
00403     int minorder;     /* Relative order number of first row in spectrum image */
00404     int MAXLINES;     /* Number of rows in line table (max no. of 
00405              lines to search for) */
00406     int nx;           /* Width of spectrum (and raw image) */
00407     int x, order;     /* 'order' always counts from 1 */
00408     
00409     const double *spectrum_data;
00410     const double *noise_data;
00411 
00412     /* Check input */
00413     passure( spectrum        != NULL, " ");
00414     passure( noise           != NULL, " ");
00415     passure( spectrum_header != NULL, " ");
00416     nx      = cpl_image_get_size_x(spectrum);
00417     norders = cpl_image_get_size_y(spectrum);
00418     
00419     /* For efficiency reasons, get direct pointer to buffer,
00420        support only CPL_TYPE_DOUBLE */
00421     assure( cpl_image_get_type(spectrum) == CPL_TYPE_DOUBLE,
00422         CPL_ERROR_UNSUPPORTED_MODE,
00423         "Image type must be double. It is %s", 
00424         uves_tostring_cpl_type(cpl_image_get_type(spectrum)));
00425 
00426     spectrum_data = cpl_image_get_data_double_const(spectrum);
00427     noise_data    = cpl_image_get_data_double_const(noise);
00428 
00429     passure( RANGE > 0, "%d", RANGE);
00430 
00431     if (arcframe != NULL)
00432     {
00433         passure( order_locations != NULL, " ");
00434         passure( nx == cpl_image_get_size_x(arcframe), 
00435              "%d %d", nx, cpl_image_get_size_x(arcframe));
00436     }
00437     
00438     passure( linetable != NULL, " ");
00439     MAXLINES = cpl_table_get_nrow(linetable);
00440     passure( cpl_table_get_ncol(linetable) == 7, "%d", 
00441          cpl_table_get_ncol(linetable));
00442     passure( cpl_table_has_column(linetable, "X"     ), " ");
00443     passure( cpl_table_has_column(linetable, "dX"    ), " ");
00444     passure( cpl_table_has_column(linetable, "Xwidth"), " ");
00445     passure( cpl_table_has_column(linetable, "Y"     ), " ");
00446     passure( cpl_table_has_column(linetable, "Peak"  ), " ");
00447     passure( cpl_table_has_column(linetable, "Background" ), " ");
00448     passure( cpl_table_has_column(linetable, "Slope" ), " ");
00449     
00450     assure( THRESHOLD > 0, CPL_ERROR_ILLEGAL_INPUT, "Illegal threshold: %e",
00451         THRESHOLD);
00452 
00453     check( minorder = uves_pfits_get_crval2(spectrum_header), 
00454        "Error reading order number of first row");
00455 
00456     *ndetected = 0;    /* Counts the number of lines detected so far. */
00457     *nrows = 0;        /* A pointer to the first unused row in the
00458                   line table */
00459     
00460     for (order = minorder; order < minorder + norders; order++) {
00461         int spectrum_row = order - minorder + 1;
00462         int ndetected_order = 0;
00463         for (x = 1; x <= nx; x++) {
00464         double flux, dflux;
00465         int peak_width = 0;
00466         int xlo, xhi;
00467         double local_median;
00468         
00469         /* Check if there is a peak and determine its position and width */
00470         // flux = cpl_image_get(spectrum, x, spectrum_row, &pis_rejected);
00471         flux  = spectrum_data[(x-1) + (spectrum_row - 1) * nx];
00472                 dflux = noise_data   [(x-1) + (spectrum_row - 1) * nx];
00473         
00474         xlo = uves_max_int(x - RANGE, 1);
00475         xhi = uves_min_int(x + RANGE, nx);
00476         
00477         local_median = cpl_image_get_median_window(
00478             spectrum,
00479             uves_max_int(xlo, 1 ), spectrum_row,
00480             uves_min_int(xhi, nx), spectrum_row);
00481         
00482         while(x <= nx && 
00483                       (
00484                           (!flat_fielded && flux - local_median > THRESHOLD) 
00485                           ||
00486                           (flat_fielded && (flux - local_median) > THRESHOLD * dflux)
00487                           )
00488                     ) {
00489 #if WANT_BIG_LOGFILE
00490             uves_msg_debug("threshold = %f\tx = %d\tflux = %f\tmedian = %f", 
00491                    THRESHOLD, x, flux, local_median);
00492 #endif
00493             
00494             x += 1;
00495             peak_width += 1;
00496             
00497             if (x <= nx) {
00498             /* flux =
00499                cpl_image_get(spectrum, x,
00500                spectrum_row, &pis_rejected);
00501             */
00502             flux = spectrum_data[(x-1) + (spectrum_row - 1) * nx];
00503             xlo = uves_max_int(x - RANGE, 1);
00504             xhi = uves_min_int(x + RANGE, nx);
00505             local_median = cpl_image_get_median_window(
00506                 spectrum,
00507                 uves_max_int(xlo, 1 ), spectrum_row,
00508                 uves_min_int(xhi, nx), spectrum_row);
00509             }
00510         }
00511         /* x is now first position that is below (median + threshold) */
00512         
00513         if (peak_width > 0) {
00514             double x_peak, dx = 0, sigma, slope, back;
00515             check( x_peak = xcenter(spectrum, noise,
00516                         uves_max_int(1, x - peak_width), 
00517                         /* First position above threshold */ 
00518                         uves_max_int(1, x - 1),          
00519                         /* Last  position above threshold */ 
00520                         spectrum_row,
00521                         CENTERING_METHOD,
00522                                             bin_disp,
00523                         &sigma,
00524                         &flux,
00525                         &dx,
00526                                             &slope,
00527                                             &back),
00528                "Could not locate peak center");
00529             
00530 #if WANT_BIG_LOGFILE
00531             uves_msg_debug("(Order, x, flux) = (%d, %f, %f)", 
00532                    order, x_peak, flux);
00533 #endif        
00534             /* Add line to line table, but only if less
00535                lines that MAXLINES have been detected */
00536             if (*nrows < MAXLINES) {
00537             check(( cpl_table_set_int   (linetable, "Y"     , *nrows, order),
00538                 cpl_table_set_double(linetable, "X"     , *nrows, x_peak),
00539                 cpl_table_set_double(linetable, "dX"    , *nrows, dx),
00540                 cpl_table_set_double(linetable, "Xwidth", *nrows, sigma),
00541                 cpl_table_set_double(linetable, "Peak"  , *nrows, flux),
00542                 cpl_table_set_double(linetable, "Background" , *nrows, back),
00543                 cpl_table_set_double(linetable, "Slope" , *nrows, slope)),
00544                   "Could not update line table row %d", *nrows);
00545             (*nrows)++;
00546             }
00547             
00548             ndetected_order++;
00549             (*ndetected)++;
00550             
00551             if (arcframe != NULL) {
00552             int x1;
00553             int pen = 0;  /* Value to write */
00554             int ny = cpl_image_get_size_y(arcframe);
00555             /* We already know 'nx' from the width of the spectrum image */
00556             
00557             for (x1  = uves_max_int(
00558                  1 , uves_round_double(
00559                      x_peak - peak_width - 0*RANGE/2.0)); 
00560                  x1 <= uves_min_int(
00561                  nx, uves_round_double(
00562                      x_peak + peak_width + 0*RANGE/2.0)); 
00563                  x1++) {
00564                 check( cpl_image_set(
00565                        arcframe,
00566                        x1,
00567                        uves_min_int(
00568                        ny, 
00569                        uves_max_int(
00570                            1, 
00571                            (int) uves_polynomial_evaluate_2d(
00572                            order_locations, x1, order)     
00573                            )), 
00574                        pen),
00575                    "Error writing input image");
00576                 check( cpl_image_set(
00577                        arcframe,
00578                        uves_min_int(
00579                        nx,
00580                        uves_max_int((int) x_peak, 1)),
00581                        uves_min_int(
00582                        ny, 
00583                        uves_max_int(
00584                            1,
00585                            (int) uves_polynomial_evaluate_2d(
00586                            order_locations, x1, order)
00587                            - 10)), 
00588                        pen),
00589                    "Error writing input image");
00590             }
00591             }
00592         } /* line found */
00593         }/* for x */
00594         if (arcframe != NULL) uves_msg_debug("Order #%d: %d lines detected", 
00595                          order, ndetected_order);
00596     }/* for order */
00597     
00598     /* Remove doublets */
00599     {
00600     int i;
00601     int doublets_removed = 0;
00602     for (i = 0; i+1 < *nrows; i++) {
00603         if (fabs(cpl_table_get_double(linetable, "X", i  , NULL) - 
00604              cpl_table_get_double(linetable, "X", i+1, NULL))  < 2.0) 
00605         {
00606             /* If a doublet was found, delete it. 
00607                Make sure the table stays the same size
00608                by adding two rows at the end. */
00609 
00610             check( cpl_table_erase_window(linetable, i, 2),
00611                "Error removing rows");
00612             *nrows -= 2;
00613             *ndetected -= 2;
00614             
00615             check( cpl_table_set_size(linetable, 
00616                           cpl_table_get_nrow(linetable) + 2),
00617                "Could not resize line table");
00618             
00619             doublets_removed++;
00620         }
00621     }
00622     if (doublets_removed > 0)
00623         {
00624         uves_msg_debug("%d doublet%s removed", 
00625                    doublets_removed, doublets_removed > 1 ? "s" : "");
00626         }
00627     }
00628     
00629             uves_msg("Range = %d pixels; threshold = %.2f %s; %d lines detected", 
00630          RANGE, THRESHOLD, flat_fielded ? "stdev" : "ADU", *ndetected);
00631     
00632   cleanup:    
00633     return cpl_error_get_code();
00634 }
00635 
00636 /*----------------------------------------------------------------------------*/
00661 /*----------------------------------------------------------------------------*/
00662 static double
00663 xcenter(const cpl_image *image, const cpl_image *noise, int xlo, int xhi, int row,
00664     centering_method CENTERING_METHOD, int bin_disp,
00665     double *sigma, double *intensity, double *dx0, double *slope, double *background)
00666 {
00667     double x0;           /* Result */
00668     cpl_matrix *covariance = NULL;
00669     const double *image_data;
00670     bool converged;
00671     int lo_r, hi_r;
00672     
00673     int nx = cpl_image_get_size_x(image);
00674 
00675     passure(cpl_image_get_type(image) == CPL_TYPE_DOUBLE, " ");
00676 
00677     image_data = cpl_image_get_data_double_const(image);
00678 
00679     /* Make sure fit window is 13-19 pixels
00680        (7-9 pixels for binned CCD) */
00681     lo_r = 6;
00682     hi_r = 8;
00683     if (bin_disp >= 2) 
00684         {
00685             lo_r = 4;
00686             hi_r = 5;
00687         }
00688 
00689     {
00690         int xm = (xlo+xhi)/2;
00691 
00692         xlo = uves_max_int(1, xm - lo_r);
00693         xhi = uves_min_int(nx, xm + lo_r);
00694     }
00695 
00696     /* Increase fit window (up to 19 pixels) */
00697     do {
00698         converged = true;
00699         if (1 < xlo && 0 <
00700             //cpl_image_get(image, xlo - 1, row, &pis_rejected) &&
00701             //cpl_image_get(image, xlo - 1, row, &pis_rejected) <
00702             //cpl_image_get(image, xlo    , row, &pis_rejected) )
00703             image_data[(xlo-1-1) + (row - 1) * nx] &&
00704             image_data[(xlo-1-1) + (row - 1) * nx] <
00705             image_data[(xlo  -1) + (row - 1) * nx] )
00706             {
00707                 converged = false;
00708                 xlo -= 1;
00709             }
00710         
00711         if (xhi < nx && 0 <
00712             //cpl_image_get(image, xhi + 1, row, &pis_rejected) && 
00713             //cpl_image_get(image, xhi + 1, row, &pis_rejected) <
00714             //cpl_image_get(image, xhi    , row, &pis_rejected) )
00715             image_data[(xhi+1-1) + (row - 1) * nx] &&
00716             image_data[(xhi+1-1) + (row - 1) * nx] <
00717             image_data[(xhi  -1) + (row - 1) * nx] )
00718             {
00719                 converged = false;
00720                 xhi += 1;
00721             }
00722 
00723         if ((xhi-xlo+1) >= hi_r) 
00724             {
00725                 converged = true;
00726             }
00727 
00728     } while (!converged);
00729 
00730     /* Get precise location */
00731     if (CENTERING_METHOD == CENTERING_GAUSSIAN)
00732     {
00733 #if WEIGHTED_FIT
00734         uves_fit_1d_image(image, noise, NULL,
00735 #else /* Unweighted fit like MIDAS which gives larger sigma */
00736         uves_fit_1d_image(image, NULL, NULL,
00737 #endif
00738                   true, false, false,
00739                   xlo, xhi, row,
00740                   &x0, sigma, intensity, background, slope,
00741 #if WEIGHTED_FIT
00742                   NULL, NULL, &covariance,
00743 #else
00744                   NULL, NULL, NULL,
00745 #endif
00746 
00747 #if FIT_SLOPE
00748                               uves_gauss_linear, uves_gauss_linear_derivative, 5);
00749 #else
00750                               uves_gauss, uves_gauss_derivative, 4);
00751             *slope = 0;
00752 #endif
00753 
00754         /* The fitting routine sometimes (i.e. regularly) fails
00755          * because of low statistics.
00756          * Recover from specific fitting errors */
00757         if (cpl_error_get_code() == CPL_ERROR_NONE)
00758         {
00759             /* Variance is guaranteed to be positive */
00760 #if WEIGHTED_FIT
00761             *dx0 = sqrt(cpl_matrix_get(covariance, 0, 0));
00762 #else
00763             *dx0 = *sigma / sqrt(*intensity);
00764 #endif
00765 
00766 #if WANT_BIG_LOGFILE
00767              uves_msg_debug("Gaussian fit succeeded at (x, row, N) = (%f, %d, %d)",
00768                     x0, row, xhi-xlo+1);
00769 #endif
00770         }
00771         else if (cpl_error_get_code() == CPL_ERROR_CONTINUE)
00772         {
00773             /* Fitting failed */
00774             uves_error_reset();
00775 #if WANT_BIG_LOGFILE
00776             uves_msg_debug("Gaussian fit failed at (x, row, N) ="
00777                    " (%f, %d, %d), using centroid", 
00778                    x0, row, xhi-xlo+1);
00779 #endif
00780             *dx0 = *sigma / sqrt(*intensity);
00781         }
00782         else if (cpl_error_get_code() == CPL_ERROR_SINGULAR_MATRIX)
00783         {
00784             uves_error_reset();
00785             
00786             /* Fitting succeeded but covariance computation failed */
00787             uves_msg_debug("Covariance matrix computation failed");
00788             *dx0 = *sigma / sqrt(*intensity);
00789         }
00790         
00791         assure(cpl_error_get_code() == CPL_ERROR_NONE, cpl_error_get_code(),
00792            "Gaussian fitting failed");
00793 
00794 #if WANT_BIG_LOGFILE
00795         uves_msg_debug("Fit   = (x0=%f, sigma=%f, norm=%f, backg=%f, N=%d)", 
00796                x0,
00797                *sigma,
00798                *intensity,
00799                background,
00800                xhi - xlo + 1);
00801 #endif
00802 
00803         /* 'intensity' is the norm (area) of the gaussian fit.
00804            But we need to return the height above zero
00805            (for MIDAS compatibility). 
00806            height = f(x0) = background + norm/sqrt(2pi sigma^2)
00807         */
00808 
00809         *intensity = *background + (*intensity)/(sqrt(2*M_PI) * (*sigma));
00810 
00811     }
00812     else   /*  if (CENTERING_METHOD == CENTERING_GRAVITY) */
00813     {
00814         assure (false, CPL_ERROR_UNSUPPORTED_MODE,
00815             "Centering method (no. %d) is unsupported", 
00816             CENTERING_METHOD);
00817     }
00818 
00819   cleanup:
00820     uves_free_matrix(&covariance);
00821     return x0;
00822 }
00823 

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