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

Generated on 28 Feb 2012 for UVES Pipeline Reference Manual by  doxygen 1.6.1