uves_orderpos_hough.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/08/27 12:31:08 $
00023  * $Revision: 1.20 $
00024  * $Name: uves-4_2_2 $
00025  * $Log: uves_orderpos_hough.c,v $
00026  * Revision 1.20  2007/08/27 12:31:08  amodigli
00027  * uves_msg_progress should go from 0 to ymax as ymax is actually the maximum y pixel value where the Hoght transform should be computed. i fixed this and added more check statements
00028  *
00029  * Revision 1.19  2007/08/21 13:08:26  jmlarsen
00030  * Removed irplib_access module, largely deprecated by CPL-4
00031  *
00032  * Revision 1.18  2007/06/06 08:17:33  amodigli
00033  * replace tab with 4 spaces
00034  *
00035  * Revision 1.17  2007/04/24 12:50:29  jmlarsen
00036  * Replaced cpl_propertylist -> uves_propertylist which is much faster
00037  *
00038  * Revision 1.16  2007/04/20 14:44:47  jmlarsen
00039  * Minor output message change
00040  *
00041  * Revision 1.15  2007/04/17 09:34:38  jmlarsen
00042  * Parametrize the assumption about consecutive orders (for FLAMES support)
00043  *
00044  * Revision 1.14  2007/04/12 12:02:41  jmlarsen
00045  * Added assertions for documentation purposes
00046  *
00047  * Revision 1.13  2007/04/10 07:08:30  jmlarsen
00048  * Make sure that detected orders are always consecutive
00049  *
00050  * Revision 1.12  2006/11/15 15:02:14  jmlarsen
00051  * Implemented const safe workarounds for CPL functions
00052  *
00053  * Revision 1.10  2006/11/15 14:04:08  jmlarsen
00054  * Removed non-const version of parameterlist_get_first/last/next which is
00055  * already in CPL, added const-safe wrapper, unwrapper and deallocator functions
00056  *
00057  * Revision 1.9  2006/11/06 15:19:41  jmlarsen
00058  * Removed unused include directives
00059  *
00060  * Revision 1.8  2006/08/17 13:56:53  jmlarsen
00061  * Reduced max line length
00062  *
00063  * Revision 1.7  2006/06/08 08:42:53  jmlarsen
00064  * Added support for computing Hough transform on image subwindow
00065  *
00066  * Revision 1.6  2006/06/01 14:43:17  jmlarsen
00067  * Added missing documentation
00068  *
00069  * Revision 1.5  2006/04/06 08:45:15  jmlarsen
00070  * Changed number of significant digits when printing percentage
00071  *
00072  * Revision 1.4  2006/03/09 13:58:26  jmlarsen
00073  * Minor optimization of Hough calculation
00074  *
00075  * Revision 1.3  2006/03/03 13:54:11  jmlarsen
00076  * Changed syntax of check macro
00077  *
00078  * Revision 1.2  2006/02/15 13:19:15  jmlarsen
00079  * Reduced source code max. line length
00080  *
00081  * Revision 1.1  2006/02/03 07:46:30  jmlarsen
00082  * Moved recipe implementations to ./uves directory
00083  *
00084  * Revision 1.24  2005/12/19 16:17:55  jmlarsen
00085  * Replaced bool -> int
00086  *
00087  */
00088 #ifdef HAVE_CONFIG_H
00089 #  include <config.h>
00090 #endif
00091 
00092 /*----------------------------------------------------------------------------*/
00096 /*----------------------------------------------------------------------------*/
00097 
00098 /*-----------------------------------------------------------------------------
00099                                 Includes
00100  -----------------------------------------------------------------------------*/
00101 
00102 #include <uves_orderpos_hough.h>
00103 
00104 #include <uves_utils.h>
00105 #include <uves_utils_wrappers.h>
00106 #include <uves_error.h>
00107 #include <uves_msg.h>
00108 
00109 #include <cpl.h>
00110 
00111 /*-----------------------------------------------------------------------------
00112                                 Defines
00113  -----------------------------------------------------------------------------*/
00114 
00115 /* Define macros that map from x-coordinate (integer) in Hough space to slope 
00116    in image space (double) and the inverse function  */
00117 #define SLOPE(hx)    (   MINSLOPE + ( ((double)(hx)) / SLOPERES  )   ) * (MAXSLOPE - MINSLOPE)
00118 #define SLOPEINV(a) \
00119    uves_round_double( SLOPERES * ( ((double)(a)) - MINSLOPE ) / (MAXSLOPE - MINSLOPE))
00120 
00121 /* Convert from pixel coordinate to intersept, and the other way */
00122 #define INTERSEPT(hy) (minintersept + hy)
00123 #define INTERSEPTINV(b) (b - minintersept)
00124 
00126 /*-----------------------------------------------------------------------------
00127                                 Forward declarations
00128  -----------------------------------------------------------------------------*/
00129 
00130 static cpl_table *detect_lines(cpl_image *htrans, int minintersept,
00131                    const cpl_image *inputimage, 
00132                    int NORDERS, bool norders_is_guess, int SAMPLEWIDTH, 
00133                    double PTHRES, double MINSLOPE, double MAXSLOPE, int SLOPERES,
00134                                bool consecutive);
00135 static cpl_error_code delete_peak(cpl_image *htrans, int minintersept, int hxmax, int hymax,
00136                   int SPACING, int imagewidth, int SAMPLEWIDTH, 
00137                   double MINSLOPE, double MAXSLOPE, int SLOPERES);
00138 static int firsttrace(int nx, int SAMPLEWIDTH);
00139 static int calculate_spacing(const cpl_image *, int x);
00140 static double autocorr(const cpl_image *image, int x, int shift);
00141 static cpl_error_code update_max(const cpl_image *htrans, /* Hough image */
00142                  int *xmax,               /* peak location */
00143                  int *ymax,
00144                  int SPACING,       /* inter-order seperation */
00145                  int imagewidth,    /* width of input image */
00146                  int SAMPLEWIDTH,   /* seperation of traces in input image */
00147                  double MINSLOPE,
00148                  double MAXSLOPE,
00149                  int SLOPERES);
00150 
00151 /*----------------------------------------------------------------------------*/
00183 /*----------------------------------------------------------------------------*/
00184 
00185 cpl_table *uves_hough(const cpl_image *image, int ymin, int ymax, int NORDERS, 
00186               bool norders_is_guess,
00187               int SAMPLEWIDTH, double PTHRES, double MINSLOPE, double MAXSLOPE,
00188               int SLOPERES, bool consecutive,
00189                       cpl_image **htrans, cpl_image **htrans_original)
00190 {
00191 
00192     cpl_table *ordertable = NULL;   /* The result table */
00193     
00194     int nx = 0;   /* Dimensions of input image */
00195     int ny = 0;
00196     int minintersept = 0;  /* The intersepts represented by the Hough image are 
00197                   all integer values */
00198     int maxintersept = 0;  /* in the interval ] minintersept ; maxintersept ] */
00199     int firstcol;
00200     const double *image_data = NULL;    /* For efficiency */
00201     double *htrans_data = NULL;
00202 
00203     *htrans = NULL;                /* Hough transform image (peaks deleted), returned */
00204     *htrans_original = NULL;       /* Hough transform image, returned */
00205     
00206     /* Check input */
00207     assure_nomsg( image != NULL, CPL_ERROR_NULL_INPUT);
00208     assure( cpl_image_get_type(image) == CPL_TYPE_DOUBLE, CPL_ERROR_INVALID_TYPE, 
00209         "Input image has wrong type. Must be of type double");
00210     assure( 0 <= MINSLOPE, CPL_ERROR_ILLEGAL_INPUT,
00211             "minslope = %f must be non-negative", MINSLOPE);
00212     assure( 0 <= MAXSLOPE, CPL_ERROR_ILLEGAL_INPUT, 
00213             "maxslope = %f must be non-negative", MAXSLOPE);
00214     assure( MINSLOPE < MAXSLOPE, CPL_ERROR_INCOMPATIBLE_INPUT, "minslope = %f; maxslope = %f",
00215             MINSLOPE, MAXSLOPE);
00216     assure( 0 < SLOPERES, CPL_ERROR_ILLEGAL_INPUT,
00217             "Hough image width = %d, must be positive", SLOPERES);
00218 
00219     /* For efficiency don't support bad pixels (possible to do
00220        later if needed) */
00221     assure (cpl_image_count_rejected(image) == 0,
00222         CPL_ERROR_UNSUPPORTED_MODE, "Input image has %d bad pixels",
00223         cpl_image_count_rejected(image));
00224 
00225 
00226     if (MAXSLOPE > 0.5) 
00227     {
00228         uves_msg_warning("Max possible slope is %f, which is larger than 0.5. "
00229                  "Results might be unreliable", MAXSLOPE);
00230     }
00231     
00232     nx = cpl_image_get_size_x(image);
00233     ny = cpl_image_get_size_y(image);
00234 
00235     assure( 1 <= ymin && ymin <= ymax && ymax <= ny, CPL_ERROR_ILLEGAL_INPUT,
00236         "Illegal y-range: %d - %d (image height is %d)", ymin, ymax, ny);
00237 
00238     /* Calculate min. and max. intersepts represented.
00239        For simplicity, the Hough image is always full size,
00240        even if not (ymin == 1 && ymax == ny)  */
00241     maxintersept = ny;
00242     minintersept = uves_round_double(0 - nx*MAXSLOPE);
00243 
00244     /* Create the Hough image. Pixels are initialsed to zero */
00245     check( *htrans = cpl_image_new(SLOPERES,                      /* Image width */
00246                    maxintersept - minintersept,   /* Image height */
00247                    CPL_TYPE_DOUBLE),
00248        "Could not create image");
00249     
00250     check_nomsg( image_data = cpl_image_get_data_double_const(image) );
00251     check_nomsg( htrans_data = cpl_image_get_data_double(*htrans) );
00252 
00253     uves_msg("Calculating Hough transform");
00254     
00255     /* Locate the leftmost trace column */
00256     check_nomsg(firstcol = firsttrace(nx, SAMPLEWIDTH));    
00257 
00258     check_nomsg(UVES_TIME_START("The loop"));
00259 
00260     /* Loop through input image subwindow and calculate the Hough image */
00261     {
00262     int x, y;
00263     for (y = ymin; y <= ymax; y += 1)
00264         {
00265     //if use_guess_tab =1 it may happen that ymax< ny
00266     //uves_msg_progress should have first argoment which goes from 0 till the
00267     //second argument value, in our case from 0 to ymax. 
00268         check_nomsg(uves_msg_progress(y - 1, ymax, "Calculating Hough transform"));
00269      
00270         for (x = firstcol; x <= nx; x += SAMPLEWIDTH)
00271             {
00272             /* Transform image point at (x,y) to line in Hough space */
00273             double pixelvalue;
00274             int hx, hy;
00275 
00276             for (hx = 1; hx <= SLOPERES; hx++)
00277                 {
00278                 check_nomsg(hy = INTERSEPTINV(uves_round_double(y - x*SLOPE(hx))));
00279                 /* y = intersept + slope * x */
00280                 
00281                                 /* Slow: check( pixelvalue = 
00282                    cpl_image_get(image, x, y, &pis_rejected),
00283                    "Could not read pixel at (%d, %d) in input image", x, y); */
00284                 check_nomsg(pixelvalue = image_data[(x-1) + (y-1)*nx]);
00285                 
00286                 /* Add the pixelvalue to Hough image (hx, hy) */
00287                 /* Not supported for now: if (!pis_rejected) */
00288                 
00289                 /* Slow: check( current = 
00290                    cpl_image_get(*htrans, hx, hy, &pis_rejected),
00291                    "Could not read pixel at (%d, %d) in Hough image", hx, hy);
00292                    check(           
00293                    cpl_image_set(*htrans, hx, hy, current + pixelvalue), 
00294                    "Could not update pixel at (%d, %d) in Hough image", 
00295                    hx, hy); */
00296 
00297                 check_nomsg(htrans_data[(hx-1) + (hy-1)*SLOPERES] += pixelvalue);
00298                 }
00299             }
00300         }
00301     }
00302 
00303     UVES_TIME_END;
00304     
00305     check( *htrans_original = cpl_image_duplicate(*htrans), "Error copying hough image");
00306 
00307     /* Calculate order table from Hough image */
00308     check( ordertable = detect_lines(*htrans,
00309                      minintersept,
00310                      image,
00311                      NORDERS,
00312                      norders_is_guess,
00313                      SAMPLEWIDTH,
00314                      PTHRES,
00315                      MINSLOPE,
00316                      MAXSLOPE,
00317                      SLOPERES,
00318                                      consecutive),
00319        "Could not detect lines in hough image");
00320     
00321     passure( cpl_table_get_ncol(ordertable) == 4, "%d", cpl_table_get_ncol(ordertable));
00322     passure( cpl_table_has_column(ordertable, "Slope"), " ");
00323     passure( cpl_table_has_column(ordertable, "Intersept"), " ");
00324     passure( cpl_table_has_column(ordertable, "Spacing"), " ");
00325     passure( cpl_table_has_column(ordertable, "Order"), " ");
00326     
00327   cleanup:
00328     if (cpl_error_get_code() != CPL_ERROR_NONE)
00329     {
00330         uves_free_image(htrans);
00331         uves_free_image(htrans_original);
00332         uves_free_table(&ordertable);
00333     }
00334     return ordertable;
00335 }
00336 
00337 /*----------------------------------------------------------------------------*/
00386 /*----------------------------------------------------------------------------*/
00387 
00388 static cpl_table *detect_lines(cpl_image *htrans, int minintersept, 
00389                    const cpl_image *inputimage, int NORDERS,
00390                    bool norders_is_guess,
00391                    int SAMPLEWIDTH, double PTHRES, double MINSLOPE, 
00392                    double MAXSLOPE, int SLOPERES,
00393                                bool consecutive)
00394 {
00395     cpl_table *results = NULL;   /* The result order table */
00396     
00397     /* Local variables */
00398     cpl_stats *stats = NULL;      /* Used for finding peaks in Hough image */
00399     uves_propertylist *pl = NULL;  /* Used for sorting the order table */
00400     
00401     bool automatic = false;        /* Flag indicating automatic mode */
00402     int tablesize = 0;
00403     double intensity = 0;         /* Line intensity */
00404     double prev_intensity = 0;    /* Intensity of previously detected line */
00405     int norders_detected = 0;     /* Peaks detected so far */
00406     int SPACING = 0;              /* Interorder spacing   */
00407     double globmax = 0;           /* Global maximum value */
00408 
00409     /* Check input */
00410     passure( htrans != NULL, " ");
00411     passure( inputimage != NULL, " ");
00412     passure( NORDERS >= 0, "%d", NORDERS);
00413     passure( SAMPLEWIDTH > 0, "%d", SAMPLEWIDTH);
00414     passure( 0 <= PTHRES && PTHRES <= 1, "%f", PTHRES);
00415     passure( SLOPERES > 0, "%d", SLOPERES);
00416 
00417     /* Do we know how many orders to detect?
00418        If not, enter automatic mode */
00419     if (NORDERS == 0)
00420     {
00421         uves_msg("Could not find information about predicted number of orders. "
00422              "Entering automatic mode (threshold = %f)", PTHRES);
00423         automatic = true;
00424     }
00425     else
00426     {
00427         uves_msg("Searching for %d (%s) order lines", 
00428              NORDERS, (norders_is_guess) ? "or less" : "exactly");
00429         automatic = false;
00430     }
00431     
00432     /* Allocate memory */
00433     if (automatic)
00434     {
00435         /* The input image height is a (conservative) upper limit
00436            on the number of echelle orders in the image */
00437         tablesize = cpl_image_get_size_y(inputimage);
00438     }
00439     else 
00440     {
00441         tablesize = NORDERS;
00442     }
00443     
00444     /* Initialize order table */
00445     check(( results = cpl_table_new(tablesize),
00446         cpl_table_new_column(results, "Slope", CPL_TYPE_DOUBLE),
00447         cpl_table_new_column(results, "Intersept", CPL_TYPE_DOUBLE),
00448         cpl_table_new_column(results, "Spacing", CPL_TYPE_INT)),
00449        "Could not initialize order table");
00450     
00451     /* Find maximum in Hough image */
00452     check( stats = cpl_stats_new_from_image(htrans, CPL_STATS_MAX | CPL_STATS_MAXPOS), 
00453        "Could not get statistics on Hough image");
00454     
00455     /*
00456      *  Remember the first (i.e. global) maximum.
00457      *  In 1st iteration, prev_intensity == intensity 
00458      */
00459     check( globmax = cpl_stats_get_max(stats), 
00460        "Could not locate first maximum in hough image" );
00461 
00462     prev_intensity = globmax;
00463 
00464     /*  Repeat until the predicted number of orders is found,
00465      *   or (in automatic mode) until the line intensity is less than threshold 
00466      */
00467     while (   (!automatic && 
00468            (norders_detected < NORDERS &&
00469         (!norders_is_guess || cpl_stats_get_max(stats) >= PTHRES*prev_intensity)))
00470           || (automatic 
00471           && cpl_stats_get_max(stats) >= PTHRES*prev_intensity)
00472     )
00473     {
00474         int xmax = 0;
00475         int ymax = 0;
00476         double slope = 0;
00477         double isept = 0;
00478         
00479         norders_detected += 1;
00480         check((intensity = cpl_stats_get_max(stats),
00481            xmax      = cpl_stats_get_max_x(stats),
00482            ymax      = cpl_stats_get_max_y(stats)),
00483         "Could not locate maximum");
00484         
00485         /* Print (normalized) intensity of detection */
00486         uves_msg_debug("%d. detection: intensity = %f",
00487                norders_detected, intensity/globmax * 100);
00488 
00489         /* Warn if intensity suddenly dropped */
00490         if (intensity < PTHRES * prev_intensity)
00491         {
00492             uves_msg_warning("Intensity of %d. line is only "
00493                      "%f %% of %d. line. Detecting too many orders?",
00494                      norders_detected, intensity / prev_intensity * 100,
00495                      norders_detected - 1);
00496         }
00497         prev_intensity = intensity;
00498         
00499         /* After detecting the first peak, estimate the approximate average order spacing */
00500         if (norders_detected == 1) 
00501         {
00502             if (!automatic) 
00503             {
00504                 SPACING = uves_round_double( 
00505                 cpl_image_get_size_y(inputimage) / NORDERS );
00506             }
00507             else
00508             {  /* If the number of orders to detect is unknown, 
00509                   derive the interorder spacing from the peak locations
00510                   in the Hough image */
00511                 check( SPACING = calculate_spacing(htrans, xmax), 
00512                    "Could not estimate interorder spacing");
00513             }
00514             
00515             uves_msg("Estimated order spacing is %d pixels", SPACING);
00516         }
00517         
00518         /* Get a more precise peak location */
00519         check( update_max(htrans,
00520                   &xmax,
00521                   &ymax,
00522                   SPACING,
00523                   cpl_image_get_size_x(inputimage),
00524                   SAMPLEWIDTH,
00525                   MINSLOPE,
00526                   MAXSLOPE,
00527                   SLOPERES), "Could not update peak position");
00528         
00529         check( delete_peak(htrans, 
00530                    minintersept, xmax, ymax, SPACING,
00531                    cpl_image_get_size_x(inputimage), 
00532                    SAMPLEWIDTH, 
00533                    MINSLOPE, MAXSLOPE, SLOPERES), 
00534            "Could not delete peak in hough image");
00535 
00536         slope = SLOPE(xmax);
00537         isept = minintersept + ymax;
00538 
00539         /* Make sure that the detection terminates if caller specified 'bad' parameters */
00540         assure( norders_detected <= tablesize, CPL_ERROR_ILLEGAL_OUTPUT,
00541             "%d orders detected. This is way too many. "
00542             "Try to decrease NORDERS (from %d) or increase PTHRES (from %f)", 
00543             norders_detected, NORDERS, PTHRES);
00544         
00545         check(( cpl_table_set_double(results, "Slope"       , norders_detected - 1, slope),
00546             cpl_table_set_double(results, "Intersept"   , norders_detected - 1, isept),
00547             cpl_table_set_int   (results, "Spacing"     , norders_detected - 1, SPACING)),
00548            "Could add order line to order table");
00549         
00550         /* Locate the next potential line */
00551         check(( uves_free_stats(&stats),
00552             stats = cpl_stats_new_from_image(htrans, CPL_STATS_MAX | CPL_STATS_MAXPOS)), 
00553             "Could not get statistics on hough image");
00554     }
00555     
00556     uves_msg("The intensity of the faintest line is %f of "
00557          "the intensity of the brightest line", intensity / globmax);
00558     uves_msg("Intensity of next (undetected) line is %f of the "
00559          "intensity of the brightest line", cpl_stats_get_max(stats)/globmax);
00560 
00561     if ( cpl_stats_get_max(stats) > 0.5 * intensity )
00562     {
00563         uves_msg_warning("Brightest undetected line with intensity %.2f %% "
00564                  "of faintest line. Detecting too few orders?",
00565                  cpl_stats_get_max(stats) / intensity * 100);
00566     }
00567     
00568     /* Clean up table */
00569     check( cpl_table_set_size(results, norders_detected), 
00570        "Could not remove extra rows from order table");
00571 
00572     /* Sort the order table so that order numbers increase from 
00573        bottom (low y) to top (high y) of image */
00574     check( uves_sort_table_1(results, "Intersept", false),    /* reverse flag = false */
00575        "Could not sort order table");
00576 
00577     /* Number orders, starting from 1 */
00578     {
00579     int i;
00580     cpl_table_new_column(results, "Order", CPL_TYPE_INT);
00581     for (i = 0; i < cpl_table_get_nrow(results); i++)
00582         {
00583             cpl_table_set_int(results, "Order", i, i+1);
00584         }
00585     }
00586 
00587     if (consecutive)
00588     /* Make sure we have consecutive orders.
00589        This assumes that the order separation varies with less than
00590        50 % from one order to the next */
00591     {
00592         int i;
00593         double dist = 0;
00594         int minorder, maxorder;
00595         int n_removed;
00596 
00597         /* From middle and up */
00598         maxorder = -1;        
00599         for (i = cpl_table_get_nrow(results)/2;
00600              i <= cpl_table_get_nrow(results) - 2 && maxorder < 0; 
00601              i++)
00602             {
00603                 if (i == cpl_table_get_nrow(results)/2)
00604                     /* initialize dist */
00605                     {
00606                         dist =
00607                             cpl_table_get_double(results, "Intersept", i+1, NULL)-
00608                             cpl_table_get_double(results, "Intersept", i, NULL);
00609                     }
00610                 else
00611                     {
00612                         double new_dist = 
00613                             cpl_table_get_double(results, "Intersept", i+1, NULL)-
00614                             cpl_table_get_double(results, "Intersept", i, NULL);
00615                         
00616                         uves_msg_debug("Order %d - %d separation = %.4f pixels", 
00617                                        cpl_table_get_int(results, "Order", i, NULL),
00618                                        cpl_table_get_int(results, "Order", i+1, NULL),
00619                                        new_dist);
00620 
00621                         if (0.5*dist <= new_dist && new_dist <= 1.5*dist)
00622                             {
00623                                 /* OK. It's probably the next consecutive order */
00624                             }
00625                         else
00626                             {
00627                                 /* Something's wrong. Stop */
00628                                 maxorder = cpl_table_get_int(results, "Order", i, NULL);
00629                                 
00630                                 uves_msg_warning("Order separation jumps from %.2f pixels to "
00631                                                  "%.2f pixels. Discarding order(s) %d and above",
00632                                                  dist, new_dist, 
00633                                                  maxorder+1);
00634                             }
00635                     }
00636             }
00637 
00638         /* From middle and down */
00639         minorder = -1;
00640         for (i = cpl_table_get_nrow(results)/2;
00641              i >= 1 && minorder < 0;
00642              i--)
00643             {
00644                 if (i == cpl_table_get_nrow(results)/2)
00645                     /* initialize dist */
00646                     {
00647                         dist =
00648                             cpl_table_get_double(results, "Intersept", i, NULL)-
00649                             cpl_table_get_double(results, "Intersept", i-1, NULL);
00650                     }
00651                 else
00652                     {
00653                         double new_dist = 
00654                             cpl_table_get_double(results, "Intersept", i, NULL)-
00655                             cpl_table_get_double(results, "Intersept", i-1, NULL);
00656                         
00657                         uves_msg_debug("Order %d - %d separation = %.4f pixels", 
00658                                        cpl_table_get_int(results, "Order", i-1, NULL),
00659                                        cpl_table_get_int(results, "Order", i, NULL),
00660                                        new_dist);
00661 
00662                         if (0.5*dist <= new_dist && new_dist <= 1.5*dist)
00663                             {
00664                                 /* OK. It's probably the next consecutive order */
00665                             }
00666                         else
00667                             {
00668                                 /* Something's wrong. Stop */
00669                                 minorder = cpl_table_get_int(results, "Order", i, NULL);
00670                                 
00671                                 uves_msg_warning("Order separation jumps from %.2f pixels to "
00672                                                  "%.2f pixels. Discarding order(s) %d and below",
00673                                                  dist, new_dist, 
00674                                                  minorder-1);
00675                             }
00676                     }
00677             }
00678 
00679         n_removed = 0;
00680         if (maxorder > 0)
00681             {
00682                 check_nomsg( n_removed += uves_erase_table_rows(results, "Order",
00683                                                                 CPL_GREATER_THAN, maxorder));
00684             }
00685         if (minorder > 0)
00686             {
00687                 check_nomsg( n_removed += uves_erase_table_rows(results, "Order",
00688                                                                 CPL_LESS_THAN, minorder));
00689             }
00690         
00691         uves_msg_debug("%d order(s) removed", n_removed);
00692         norders_detected -= n_removed;
00693     }
00694 
00695     /* Renumber orders, starting from 1 */
00696     {
00697     int i;
00698     for (i = 0; i < cpl_table_get_nrow(results); i++)
00699         {
00700             cpl_table_set_int(results, "Order", i, i+1);
00701         }
00702     }
00703     
00704     uves_msg("Hough transform detected %d orders", norders_detected);
00705     
00706     passure( norders_detected == cpl_table_get_nrow(results), "%d %d", 
00707          norders_detected, cpl_table_get_nrow(results));
00708 
00709   cleanup:
00710     uves_free_stats(&stats);
00711     uves_free_propertylist(&pl);
00712     if (cpl_error_get_code() != CPL_ERROR_NONE)
00713     {
00714         uves_free_table(&results);
00715     }
00716     
00717     return results;
00718 }
00719 
00720     
00721 /*----------------------------------------------------------------------------*/
00745 /*----------------------------------------------------------------------------*/
00746 static cpl_error_code update_max(const cpl_image *htrans,
00747                  int *xmax,              
00748                  int *ymax,
00749                  int SPACING,
00750                  int imagewidth,
00751                  int SAMPLEWIDTH,
00752                  double MINSLOPE,
00753                  double MAXSLOPE,
00754                  int SLOPERES)
00755 {
00756     const int nx = cpl_image_get_size_x(htrans);
00757     const int ny = cpl_image_get_size_y(htrans);
00758     const int slope = -imagewidth/2;             /* slope of line in hough space */
00759     const double numberoftraces = 1 + imagewidth/SAMPLEWIDTH;
00760     int pis_rejected;
00761 
00762     /* Only look at pixel values above this threshold  */
00763     double threshold = (1 - 0.5 / numberoftraces) * 
00764     cpl_image_get(htrans, *xmax, *ymax, &pis_rejected);
00765     if (threshold < 0.99) threshold = 0.99;
00766     
00767     assure (cpl_error_get_code() == CPL_ERROR_NONE, cpl_error_get_code(), 
00768         "Could not read Hough image data");
00769     
00770     {
00771     double sum = 0;
00772     double mx  = 0;
00773     double my  = 0;
00774     int hx, hy;    
00775     for (hx = 1; hx <= SLOPERES; hx++)
00776         {
00777         int rowcenter = 
00778             uves_round_double(
00779             *ymax + slope*(hx - *xmax)/((double)SLOPERES)*(MAXSLOPE - MINSLOPE));
00780         
00781         /* It would be more correct to look at pixels from (rowcenter - LINEWIDTH/2)
00782            to (rowcenter + LINEWIDTH/2) where LINEWIDTH is the echelle line width 
00783            (i.e. different from SPACING) But empirically it doesn't really make
00784            a difference if we just use the pixel at rowcenter (for each x)    */
00785 
00786         for (hy = rowcenter - 0*SPACING/2; hy <= rowcenter + 0*SPACING/2; hy++) 
00787             {
00788             if (1 <= hx && hx <= nx &&
00789                 1 <= hy && hy <= ny)
00790                 {
00791                 double pixelvalue = cpl_image_get(
00792                     htrans, hx, hy, &pis_rejected);
00793                 if (!pis_rejected && pixelvalue >= threshold) 
00794                     {
00795                     mx  += hx*pixelvalue;
00796                     my  += hy*pixelvalue;
00797                     sum +=    pixelvalue;
00798                     }
00799                 }
00800             }
00801         
00802         }
00803     
00804     uves_msg_debug("Peak position in Hough space changed from (%d, %d)", *xmax, *ymax);
00805     *xmax = uves_round_double(mx/sum);
00806     *ymax = uves_round_double(my/sum);
00807     uves_msg_debug("to (%d, %d)", *xmax, *ymax);
00808     }
00809     
00810   cleanup:
00811     return cpl_error_get_code();
00812 }
00813 
00814 /*----------------------------------------------------------------------------*/
00825 /*----------------------------------------------------------------------------*/
00826 
00827 static int calculate_spacing(const cpl_image *image, int x)
00828 {
00829     int shift = 0;
00830     double autoc = autocorr(image, x, shift);
00831     double previous;
00832     assure (cpl_error_get_code() == CPL_ERROR_NONE, cpl_error_get_code(), 
00833         "Could not calculate autocorrelation function");
00834 
00835     uves_msg_debug("Autocorrelation(shift=%d) = %f", shift, autoc);
00836     
00837     do{
00838     previous = autoc;
00839     shift += 1;
00840     check( autoc = autocorr(image, x, shift), 
00841            "Could not calculate autocorrelation function");
00842     uves_msg_debug("Autocorrelation(shift=%d) = %f", shift, autoc);
00843     } while (autoc <= previous);
00844     
00845   cleanup:
00846     return 2*(shift - 1);
00847     /* First minimum of the autocorrelation function is half spacing */
00848 }
00849 
00850 
00851 /*----------------------------------------------------------------------------*/
00864 /*----------------------------------------------------------------------------*/
00865 static double autocorr(const cpl_image *image, const int x, const int shift)
00866 {
00867     double result = 0;
00868     const int ny = cpl_image_get_size_y(image);
00869     assure (cpl_error_get_code() == CPL_ERROR_NONE, cpl_error_get_code(), 
00870         "Could not read image dimensions");
00871     
00872     if( shift >= ny ) return 0;
00873     
00874     {
00875     double sum = 0;
00876     int y;    
00877     int number_of_points = 0;
00878     for (y = 1; y <= ny - shift; y++){
00879         int pis_rejected;
00880         double pixelvalue;
00881 
00882         pixelvalue = cpl_image_get(image, x, y,         &pis_rejected) *
00883                  cpl_image_get(image, x, y + shift, &pis_rejected);
00884 
00885         if (!pis_rejected){
00886         sum += pixelvalue;
00887         number_of_points += 1;
00888         }
00889     }
00890     assure( cpl_error_get_code() == CPL_ERROR_NONE, cpl_error_get_code(),
00891         "Error reading image pixel values");
00892     
00893     if (number_of_points > 0) 
00894         {
00895         result = sum / number_of_points;
00896         }
00897     else
00898         {
00899         result = 0;
00900         }
00901     }
00902     
00903   cleanup:
00904     return result;
00905 }
00906 
00907 /*----------------------------------------------------------------------------*/
00919 /*----------------------------------------------------------------------------*/
00920 static int firsttrace(int nx, int SAMPLEWIDTH)
00921 {
00922     int result = nx/2;
00923 
00924     while(result - SAMPLEWIDTH >= 1)
00925     {
00926         result -= SAMPLEWIDTH;
00927     }
00928 
00929     return result;
00930 }
00931 
00932 /*----------------------------------------------------------------------------*/
00955 /*----------------------------------------------------------------------------*/
00956 static cpl_error_code delete_peak(cpl_image *htrans, int minintersept,
00957                   int hxmax, int hymax, 
00958                   int SPACING, int imagewidth, int SAMPLEWIDTH, 
00959                   double MINSLOPE, double MAXSLOPE, int SLOPERES)
00960 {
00961     const int ny = cpl_image_get_size_y(htrans);
00962     int tracecol;
00963     int firstcol = firsttrace(imagewidth, SAMPLEWIDTH);
00964     
00965     assure (cpl_error_get_code() == CPL_ERROR_NONE, cpl_error_get_code(), 
00966         "Could not read hough image data");
00967     
00968     /* We reverse the calculation of the Hough transform */
00969     for (tracecol = firstcol; tracecol <= imagewidth; tracecol += SAMPLEWIDTH){
00970     /* Get y-coordinate in raw image */
00971     double slope = SLOPE(hxmax);
00972     double intersept = minintersept + hymax;
00973     double imagey = intersept + slope*tracecol;
00974     
00975     /* Now erase all points in the Hough image that were caused
00976        by the point (tracecol, imagey) in the input image */
00977     int hx, hy;
00978     for (hx = 1; hx <= SLOPERES; hx++){
00979         slope = SLOPE(hx);
00980         intersept = imagey - slope*tracecol;
00981         for (hy = (intersept - minintersept) - SPACING/3;
00982          hy <= (intersept - minintersept) + SPACING/3; 
00983          hy++) {
00984         if (0 < hy && hy <= ny) {
00985             check( cpl_image_set(htrans, hx, hy, 0), 
00986                "Could not write pixel at (%d, %d)", hx, hy);
00987         }
00988         }
00989     }
00990     }
00991     
00992   cleanup:
00993     return cpl_error_get_code();
00994 }
00995 
00996 /*----------------------------------------------------------------------------*/
01007 /*----------------------------------------------------------------------------*/
01008 cpl_error_code uves_draw_orders(const cpl_table *ordertable, cpl_image *image)
01009 {
01010     double penvalue;
01011     int nx;
01012     int ny;
01013     cpl_stats *stats = NULL;
01014     int nrows;
01015     int i;
01016 
01017     /* Check input */
01018     passure( image != NULL, " ");
01019     passure( ordertable != NULL, " ");
01020     passure( cpl_table_has_column(ordertable, "Intersept"), " ");
01021     passure( cpl_table_has_column(ordertable, "Slope"    ), " ");
01022 
01023     nx = cpl_image_get_size_x(image);
01024     ny = cpl_image_get_size_y(image);
01025     
01026     /* Calculate pen value */
01027     check( stats = cpl_stats_new_from_image(image, CPL_STATS_MAX), 
01028        "Could not get statistics on input image");
01029     check( penvalue = 2*cpl_stats_get_max(stats),
01030        "Could not find image maximum value" );
01031 
01032     /* Draw lines in ordertable on image */
01033     check  ( nrows = cpl_table_get_nrow(ordertable), 
01034          "Could not read number of rows in ordertable");
01035     for (i = 0; i < nrows; i++)
01036     {
01037         int x;
01038         double intersept, slope;
01039         
01040         check(( intersept = cpl_table_get_double(ordertable, "Intersept", i, NULL),
01041             slope     = cpl_table_get_double(ordertable, "Slope", i, NULL)),
01042            "Could not read 'Intersept' and 'Slope' from ordertable");
01043         
01044         for (x = 1; x <= nx; x++){
01045         double yd = intersept + x * slope;
01046         int y = uves_round_double(yd);
01047         
01048         if (0 < y && y <= ny)
01049             {
01050             cpl_image_set(image, x, y, penvalue);
01051             }
01052         }
01053         assure( cpl_error_get_code() == CPL_ERROR_NONE, cpl_error_get_code(),
01054             "Could not draw order in table row #%d", i);
01055     }
01056     
01057   cleanup:
01058     uves_free_stats(&stats);
01059     return cpl_error_get_code();
01060 }

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