irplib_strehl.c

00001 /* $Id: irplib_strehl.c,v 1.35 2007/09/26 11:12:36 llundin Exp $
00002  *
00003  * This file is part of the irplib package
00004  * Copyright (C) 2002,2003 European Southern Observatory
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02111-1307  USA
00019  */
00020 
00021 /*
00022  * $Author: llundin $
00023  * $Date: 2007/09/26 11:12:36 $
00024  * $Revision: 1.35 $
00025  * $Name: uves-3_4_5 $
00026  */
00027 
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031 
00032 /*-----------------------------------------------------------------------------
00033                                    Includes
00034  -----------------------------------------------------------------------------*/
00035 
00036 #include <string.h>
00037 #include <assert.h>
00038 #include <math.h>
00039 #include <float.h>
00040 
00041 #include <cpl.h>
00042 
00043 #include "irplib_utils.h"
00044 #include "irplib_math_const.h"
00045 #include "irplib_strehl.h"
00046 
00047 /*----------------------------------------------------------------------------*/
00051 /*----------------------------------------------------------------------------*/
00052 
00053 /*-----------------------------------------------------------------------------
00054                                    Define
00055  -----------------------------------------------------------------------------*/
00056 
00057 #ifndef IRPLIB_STREHL_RAD_CENTRAL
00058 #define IRPLIB_STREHL_RAD_CENTRAL 5
00059 #endif
00060 
00061 #define IRPLIB_DISK_BG_MIN_PIX_NB    30
00062 #define IRPLIB_DISK_BG_REJ_LOW       0.1
00063 #define IRPLIB_DISK_BG_REJ_HIGH      0.1
00064 
00065 /*-----------------------------------------------------------------------------
00066                                    Functions prototypes
00067  -----------------------------------------------------------------------------*/
00068 
00069 static cpl_image * irplib_strehl_generate_otf(double, double, double, double, 
00070                                               int, double);
00071 static double PSF_H1(double, double, double);
00072 static double PSF_H2(double, double);
00073 static double PSF_G(double, double);
00074 static double PSF_sinc(double);
00075 static double PSF_TelOTF(double, double);
00076 
00077 
00078 /*-----------------------------------------------------------------------------
00079                                    Functions code
00080  -----------------------------------------------------------------------------*/
00083 /*----------------------------------------------------------------------------*/
00112 /*----------------------------------------------------------------------------*/
00113 cpl_error_code irplib_strehl_compute(const cpl_image *   im,
00114                                      double              m1,
00115                                      double              m2,
00116                                      double              lam,
00117                                      double              dlam,
00118                                      double              pscale,
00119                                      int                 size,
00120                                      double              xpos,
00121                                      double              ypos,
00122                                      double              r1,
00123                                      double              r2,
00124                                      double              r3,
00125                                      int                 noise_box_sz,
00126                                      int                 noise_nsamples,
00127                                      double          *   strehl,
00128                                      double          *   strehl_err,
00129                                      double          *   star_bg,
00130                                      double          *   star_peak,
00131                                      double          *   star_flux,
00132                                      double          *   psf_peak,
00133                                      double          *   psf_flux,
00134                                      double          *   bg_noise)
00135 {
00136     cpl_image  * psf;
00137     double       star_radius, max_radius;
00138 
00139     /* FIXME: Arbitrary choice of image border */
00140     const double window_size = (double)(IRPLIB_STREHL_RAD_CENTRAL);
00141 
00142     /* Determined empirically by C. Lidman for Strehl error computation */
00143     const double strehl_error_coefficient = IRPLIB_MATH_PI * 0.007 / 0.0271;
00144 
00145 #if defined CPL_VERSION_CODE && CPL_VERSION_CODE >= CPL_VERSION(4, 0, 0)
00146     double       ring[4];
00147 #else
00148     /* FIXME: Remove this branch once CPL 3.X is no longer supported */
00149     int          ring[4];
00150 #endif
00151 
00152     /* Check compile-time constant */
00153     cpl_ensure_code(window_size > 0.0,  CPL_ERROR_ILLEGAL_INPUT);
00154 
00155     /* Test inputs */
00156     cpl_ensure_code(im != NULL,         CPL_ERROR_NULL_INPUT);
00157     cpl_ensure_code(strehl != NULL,     CPL_ERROR_NULL_INPUT);
00158     cpl_ensure_code(strehl_err != NULL, CPL_ERROR_NULL_INPUT);
00159     cpl_ensure_code(star_bg != NULL,    CPL_ERROR_NULL_INPUT);
00160     cpl_ensure_code(star_peak != NULL,  CPL_ERROR_NULL_INPUT);
00161     cpl_ensure_code(star_flux != NULL,  CPL_ERROR_NULL_INPUT);
00162     cpl_ensure_code(psf_peak != NULL,   CPL_ERROR_NULL_INPUT);
00163     cpl_ensure_code(psf_flux != NULL,   CPL_ERROR_NULL_INPUT);
00164 
00165     cpl_ensure_code(pscale > 0.0,      CPL_ERROR_ILLEGAL_INPUT);
00166 
00167     cpl_ensure_code(r1 > 0.0,      CPL_ERROR_ILLEGAL_INPUT);
00168     cpl_ensure_code(r2 > 0.0,      CPL_ERROR_ILLEGAL_INPUT);
00169     cpl_ensure_code(r3 > r2,       CPL_ERROR_ILLEGAL_INPUT);
00170 
00171     /* Computing a Strehl ratio is a story between an ideal PSF */
00172     /* and a candidate image supposed to approximate this ideal PSF. */
00173 
00174     /* Generate first appropriate PSF to find max peak */
00175     psf = irplib_strehl_generate_psf(m1, m2, lam, dlam, pscale, size);
00176     cpl_ensure_code(psf != NULL,      CPL_ERROR_ILLEGAL_OUTPUT);
00177 
00178     /* Compute flux in PSF and find max peak */
00179     *psf_peak = cpl_image_get_max(psf);
00180     cpl_image_delete(psf);
00181 
00182     assert( *psf_peak > 0.0); /* The ideal PSF has a positive maximum */
00183     *psf_flux = 1.0; /* The psf flux, cpl_image_get_flux(psf), is always 1 */
00184 
00185     /* Measure the background in the candidate image */
00186     *star_bg = irplib_strehl_ring_background(im, xpos, ypos, r2/pscale, r3/pscale,
00187                                              IRPLIB_BG_METHOD_AVER_REJ);
00188 
00189     /* Compute star_radius in pixels */
00190     star_radius = r1/pscale;
00191 
00192     /* Measure the flux on the candidate image */
00193     *star_flux = irplib_strehl_disk_flux(im, xpos, ypos, star_radius, *star_bg);
00194 
00195     cpl_ensure_code(*star_flux > 0.0,      CPL_ERROR_ILLEGAL_OUTPUT);
00196 
00197     /* Find the peak value on the central part of the candidate image */
00198     max_radius = window_size < star_radius ? window_size : star_radius;
00199     cpl_ensure_code(!irplib_strehl_disk_max(im, xpos, ypos, max_radius,
00200                                             star_peak), cpl_error_get_code());
00201     *star_peak -= *star_bg;
00202 
00203     cpl_ensure_code(*star_peak > 0.0,      CPL_ERROR_ILLEGAL_OUTPUT);
00204 
00205     /* Compute Strehl */
00206     /* (StarPeak / StarFlux) / (PsfPeak / PsfFlux) */
00207     *strehl = (*star_peak * *psf_flux ) / ( *star_flux * *psf_peak);
00208 
00209     if (*strehl > 1)
00210         cpl_msg_warning(cpl_func, "Extreme Strehl-ratio=%g, star_peak=%g, "
00211                         "star_flux=%g, psf_peak=%g, psf_flux=%g", *strehl,
00212                         *star_peak, *star_flux, *psf_peak, *psf_flux);
00213 
00214     /* Compute Strehl error */
00215     ring[0] = xpos;
00216     ring[1] = ypos;
00217     ring[2] = r2/pscale;
00218     ring[3] = r3/pscale;
00219     cpl_ensure_code(!cpl_flux_get_noise_ring(im, ring, noise_box_sz,
00220                                              noise_nsamples, bg_noise, NULL),
00221                     cpl_error_get_code());
00222 
00223     *strehl_err = strehl_error_coefficient * (*bg_noise) * pscale * 
00224         star_radius * star_radius / *star_flux;
00225 
00226     /* This check should not be able to fail, but just to be sure */
00227     cpl_ensure_code(*strehl_err >= 0.0,       CPL_ERROR_ILLEGAL_OUTPUT);
00228 
00229     return CPL_ERROR_NONE;
00230 }
00231 
00232 /*----------------------------------------------------------------------------*/
00248 /*----------------------------------------------------------------------------*/
00249 double irplib_strehl_disk_flux(const cpl_image * im,
00250                                double            xpos,
00251                                double            ypos,
00252                                double            rad,
00253                                double            bg)
00254 {
00255     const double    sqr = rad * rad;
00256     double          sqrest;
00257     const float *   pim;
00258     double          flux = 0.0;
00259     double          yj, xi; 
00260     int             nx, ny;
00261     int             lx, ly, ux, uy;
00262     int             i, j;
00263 
00264 
00265     /* Check entries */
00266     cpl_ensure(im != NULL, CPL_ERROR_NULL_INPUT, 0.0);
00267     cpl_ensure(cpl_image_get_type(im) == CPL_TYPE_FLOAT,
00268                CPL_ERROR_UNSUPPORTED_MODE, 0.0);
00269     cpl_ensure(rad > 0.0, CPL_ERROR_ILLEGAL_INPUT, 0.0);
00270  
00271     nx = cpl_image_get_size_x(im);
00272     ny = cpl_image_get_size_y(im);
00273 
00274     /* Round down */
00275     lx = (int)(xpos - rad);
00276     ly = (int)(ypos - rad);
00277     if (lx < 0) lx = 0;
00278     if (ly < 0) ly = 0;
00279 
00280     /* Round up */
00281     ux = (int)(xpos + rad) + 1;
00282     uy = (int)(ypos + rad) + 1;
00283     if (ux > (nx-1)) ux = nx-1;
00284     if (uy > (ny-1)) uy = ny-1;
00285 
00286     /* im is actually not modified */
00287     pim = cpl_image_get_data_float((cpl_image*)im);
00288     for (j=ly ; j<uy ; j++) {
00289         yj = (double)j - ypos;
00290         sqrest = sqr - yj * yj;
00291         for (i=lx; i<ux ; i++) {
00292             xi = (double)i - xpos;
00293             if (sqrest >= xi * xi && irplib_isnan(pim[i+j*nx]) == 0) {
00294                 flux += (double)pim[i+j*nx] - bg;
00295             }
00296         }
00297     }
00298     return flux;
00299 }
00300 
00301 /*----------------------------------------------------------------------------*/
00315 /*----------------------------------------------------------------------------*/
00316 double irplib_strehl_ring_background(const cpl_image *       im,
00317                                      double                  xpos,
00318                                      double                  ypos,
00319                                      double                  rad_int,
00320                                      double                  rad_ext,
00321                                      irplib_strehl_bg_method mode)
00322 {
00323     int             npix;
00324     const double    sqr_int = rad_int * rad_int;
00325     const double    sqr_ext = rad_ext * rad_ext;
00326     double          dist;
00327     cpl_vector  *   pix_arr;
00328     const float *   pim;
00329     double          flux = 0.0;
00330     double          yj, xi; 
00331     int             lx, ly, ux, uy;
00332     int             nx, ny;
00333     int             i, j;
00334 
00335     /* Check entries */
00336     cpl_ensure(im != NULL, CPL_ERROR_NULL_INPUT, 0.0);
00337     cpl_ensure(cpl_image_get_type(im) == CPL_TYPE_FLOAT,
00338                CPL_ERROR_UNSUPPORTED_MODE, 0.0);
00339     cpl_ensure(rad_int > 0.0, CPL_ERROR_ILLEGAL_INPUT, 0.0);
00340     cpl_ensure(rad_ext > rad_int, CPL_ERROR_ILLEGAL_INPUT, 0.0);
00341 
00342     cpl_ensure(mode == IRPLIB_BG_METHOD_AVER_REJ ||
00343                mode == IRPLIB_BG_METHOD_MEDIAN,
00344                CPL_ERROR_UNSUPPORTED_MODE, 0.0);
00345 
00346     nx = cpl_image_get_size_x(im);
00347     ny = cpl_image_get_size_y(im);
00348 
00349     /* Round down */
00350     lx = (int)(xpos - rad_ext);
00351     ly = (int)(ypos - rad_ext);
00352     if (lx < 0) lx = 0;
00353     if (ly < 0) ly = 0;
00354 
00355     /* Round up */
00356     ux = (int)(xpos + rad_ext) + 1;
00357     uy = (int)(ypos + rad_ext) + 1;
00358     if (ux > (nx-1)) ux = nx-1;
00359     if (uy > (ny-1)) uy = ny-1;
00360 
00361     npix = (ux - lx + 1) * (uy - ly + 1);
00362     cpl_ensure(npix >= IRPLIB_DISK_BG_MIN_PIX_NB, CPL_ERROR_DATA_NOT_FOUND, 0.0);
00363 
00364     /* Allocate pixel array to hold values in the ring */
00365     pix_arr = cpl_vector_new(npix);
00366 
00367     /* Count number of pixels in the ring */
00368     /* Retrieve all pixels which belong to the ring */
00369     /* im is actually _not_ modified */
00370     pim = cpl_image_get_data_float((cpl_image*)im);
00371     npix = 0;
00372     for (j=ly ; j<uy ; j++) {
00373         yj = (double)j - ypos;
00374         for (i=lx ; i<ux; i++) {
00375             xi = (double)i - xpos;
00376             dist = yj * yj + xi * xi;
00377             if (sqr_int <= dist && dist <= sqr_ext && 
00378                 irplib_isnan(pim[i+j*nx]) == 0) {
00379                 cpl_vector_set(pix_arr, npix, (double)pim[i+j*nx]);
00380                 npix++;
00381             }
00382         }
00383     }
00384 
00385     if (npix < IRPLIB_DISK_BG_MIN_PIX_NB) {
00386         cpl_vector_delete(pix_arr);
00387         cpl_ensure(0, CPL_ERROR_DATA_NOT_FOUND, 0.0);
00388     }
00389 
00390     /* Should not be able to fail now */
00391 
00392     /* Resize pixel array to actual number of values within the ring */
00393     cpl_vector_set_size(pix_arr, npix);
00394 
00395     if (mode == IRPLIB_BG_METHOD_AVER_REJ) {
00396         const int low_ind  = (int)((double)npix * IRPLIB_DISK_BG_REJ_LOW);
00397         const int high_ind = (int)((double)npix
00398                                    * (1.0 - IRPLIB_DISK_BG_REJ_HIGH));
00399 
00400         /* Sort the array */
00401         cpl_vector_sort(pix_arr, 1);
00402 
00403         for (i=low_ind ; i<high_ind ; i++) {
00404             flux += cpl_vector_get(pix_arr, i);
00405         }
00406         if (high_ind - low_ind > 1) flux /= (double)(high_ind - low_ind);
00407     } else /* if (mode == IRPLIB_BG_METHOD_MEDIAN) */ {
00408         flux = cpl_vector_get_median(pix_arr);
00409     }
00410 
00411     cpl_vector_delete(pix_arr);
00412 
00413     return flux;
00414 }
00415 
00416 /*----------------------------------------------------------------------------*/
00436 /*----------------------------------------------------------------------------*/
00437 cpl_image * irplib_strehl_generate_psf(
00438         double   m1,
00439         double   m2,
00440         double   lam,
00441         double   dlam,
00442         double   pscale,
00443         int      size)
00444 {
00445     cpl_image * otf_image = irplib_strehl_generate_otf(m1, m2, lam, dlam, 
00446             size, pscale);
00447 
00448     if (otf_image == NULL) return NULL;
00449 
00450     /* Transform back to real space
00451        - Normalization is unnecessary, due to the subsequent normalisation.
00452        - An OTF is point symmetric about its center, i.e. it is even,
00453          i.e. the real space image is real.
00454        - Because of this a forward FFT works as well.
00455        - If the PSF ever needs to have its images halves swapped add
00456          CPL_FFT_SWAP_HALVES to the FFT call.
00457      */
00458 
00459     if (cpl_image_fft(otf_image, NULL, CPL_FFT_UNNORMALIZED) ||
00460 
00461         /* Compute absolute values of PSF */
00462         cpl_image_abs(otf_image) ||
00463 
00464         /* Normalize PSF to get flux=1  */
00465         cpl_image_normalise(otf_image, CPL_NORM_FLUX)) {
00466 
00467         cpl_image_delete(otf_image);
00468         return NULL;
00469     }
00470     
00471     return otf_image;
00472 }
00473 
00476 /*----------------------------------------------------------------------------*/
00492 /*----------------------------------------------------------------------------*/
00493 static cpl_image * irplib_strehl_generate_otf(
00494         double  m1,
00495         double  m2,
00496         double  lam,
00497         double  dlam,
00498         int     size,
00499         double  pscale)
00500 {
00501     cpl_image   *   otf_image;
00502     double      *   otf_data;
00503     double          obs_ratio ;  /* m1 / m2    */
00504     double          f_max ;      /* cut-off frequency        */
00505     int             pix0 ;      /* Pixel corresponding to the zero frequency */
00506     double          a, x, y;
00507     double          f, rsq, fc, invfc, lambda;
00508     double          sincy;
00509     double          invsize;
00510     register int    pos;
00511     int             i, j, k;
00512 
00513 
00514     cpl_ensure(m2   > 0.0,      CPL_ERROR_ILLEGAL_INPUT, NULL);
00515     cpl_ensure(m1   > m2,       CPL_ERROR_ILLEGAL_INPUT, NULL);
00516     cpl_ensure(lam  > 0.0,      CPL_ERROR_ILLEGAL_INPUT, NULL);
00517     cpl_ensure(dlam > 0.0,      CPL_ERROR_ILLEGAL_INPUT, NULL);
00518     cpl_ensure(size > 0,        CPL_ERROR_ILLEGAL_INPUT, NULL);
00519     cpl_ensure(pscale > 0.0,    CPL_ERROR_ILLEGAL_INPUT, NULL);
00520 
00521     /* Convert pixel scale from sec to radians, microns in meters    */
00522     pscale /= (double)206265;
00523     lam /= (double)1.0e6;
00524     dlam /= (double)1.0e6;
00525 
00526     /* Obscuration ratio    */
00527     obs_ratio = m2 / m1;
00528 
00529     /* Pixel corresponding to the zero frequency    */
00530     pix0 = size/2;
00531     invsize = (double)1.0 / (double)size;
00532 
00533     /* Cut-off frequency in pixels  */
00534     f_max = m1 * pscale * (double)size / lam;
00535 
00536     /* Allocate for output image    */
00537     otf_image = cpl_image_new(size, size, CPL_TYPE_DOUBLE);
00538     if (otf_image==NULL) return NULL;
00539     otf_data = cpl_image_get_data_double(otf_image);
00540 
00541     /* Now compute the OTF  */
00542     /* OPTIMIZED CODE !!! LIMITED READABILITY !!!   */
00543 
00544     for (k=1 ; k<=9 ; k++) {    /* iteration on the wavelength  */
00545         /* Compute intermediate cut-off frequency   */
00546         lambda = (double)(lam - dlam*(double)(k-5)/8.0);
00547         fc = (double)f_max * (double)lam / lambda;
00548         invfc = 1.0 / fc;
00549 
00550         /* Convolution with the detector pixels */
00551         pos = 0;
00552         for (j=0 ; j<size ; j++) {
00553             y = (double)(j-pix0);
00554             sincy = PSF_sinc(IRPLIB_MATH_PI * y * invsize);
00555             for (i=0 ; i<size ; i++) {
00556                 x = (double)(i-pix0);
00557                 rsq = x*x + y*y;
00558                 if (rsq < fc*fc) {
00559                     if (rsq < 0.01)
00560                         a = 1.0;
00561                     else {
00562                         f = sqrt(rsq) * invfc;
00563                         a = PSF_TelOTF(f,obs_ratio) *
00564                             PSF_sinc(IRPLIB_MATH_PI * x * invsize) * sincy;
00565                     }
00566                 } else {
00567                     a = 0.0;
00568                 }
00569                 otf_data[pos++] += a / 9.0;
00570             }
00571         }
00572     }
00573     return otf_image;
00574 }
00575 
00576 /*----------------------------------------------------------------------------*
00577  * H1 function
00578  *----------------------------------------------------------------------------*/
00579 static double PSF_H1(
00580         double  f,
00581         double  u,
00582         double  v)
00583 {
00584     const double e = fabs(1.0-v) > 0.0 ? -1.0 : 1.0; /* e = 1.0 iff v = 1.0 */
00585 
00586     return((v*v/IRPLIB_MATH_PI)*acos((f/v)*(1.0+e*(1.0-u*u)/(4.0*f*f))));
00587 }
00588 
00589 /*----------------------------------------------------------------------------*
00590  * H2 function
00591  *----------------------------------------------------------------------------*/
00592 static double PSF_H2(double  f,
00593                      double  u)
00594 {
00595     const double tmp1 = (2.0 * f) / (1.0 + u);
00596     const double tmp2 = (1.0 - u) / (2.0 * f);
00597 
00598     return -1.0 * (f/IRPLIB_MATH_PI) * (1.0+u)
00599         * sqrt((1.0-tmp1*tmp1)*(1.0-tmp2*tmp2));
00600 }   
00601 
00602 /*----------------------------------------------------------------------------*
00603  * G function
00604  *----------------------------------------------------------------------------*/
00605 static double PSF_G(double  f, 
00606                     double  u)
00607 {
00608     if (f <= (1.0-u)/2.0) return(u*u);
00609     if (f >= (1.0+u)/2.0) return(0.0);
00610     else return(PSF_H1(f,u,1.0) + PSF_H1(f,u,u) + PSF_H2(f,u));
00611 }   
00612 
00613 /*----------------------------------------------------------------------------*
00614  * sinc function
00615  *----------------------------------------------------------------------------*/
00616 static double PSF_sinc(double x)
00617 {
00618   return fabs(x) > fabs(sin(x)) ? sin(x)/x : 1.0;
00619 }
00620 
00621 /*----------------------------------------------------------------------------*
00622  * Telescope OTF function 
00623  *----------------------------------------------------------------------------*/
00624 static double PSF_TelOTF(double  f,  
00625                          double  u)
00626 {
00627     return((PSF_G(f,1.0)+u*u*PSF_G(f/u,1.0)-2.0*PSF_G(f,u))/(1.0-u*u));
00628 }
00629 
00630 /*----------------------------------------------------------------------------*/
00642 /*----------------------------------------------------------------------------*/
00643 cpl_error_code irplib_strehl_disk_max(const cpl_image * self,
00644                                              double            xpos,
00645                                              double            ypos,
00646                                              double            radius,
00647                                              double          * ppeak)
00648 {
00649 
00650     const double    sqr = radius * radius;
00651     double          sqrest;
00652     const float *   pself;
00653     float           peak = FLT_MAX;  /* Avoid (false) uninit warning */
00654     double          yj, xi; 
00655     int             nx, ny;
00656     int             lx, ly, ux, uy;
00657     int             i, j;
00658     cpl_boolean     first = CPL_TRUE;
00659 
00660 
00661     /* Check entries */
00662     cpl_ensure_code(ppeak != NULL, CPL_ERROR_NULL_INPUT);
00663     cpl_ensure_code(self  != NULL, CPL_ERROR_NULL_INPUT);
00664     cpl_ensure_code(cpl_image_get_type(self) == CPL_TYPE_FLOAT,
00665                     CPL_ERROR_UNSUPPORTED_MODE);
00666     cpl_ensure_code(radius > 0.0, CPL_ERROR_ILLEGAL_INPUT);
00667  
00668     nx = cpl_image_get_size_x(self);
00669     ny = cpl_image_get_size_y(self);
00670 
00671     /* Round down */
00672     lx = (int)(xpos - radius);
00673     ly = (int)(ypos - radius);
00674     if (lx < 0) lx = 0;
00675     if (ly < 0) ly = 0;
00676 
00677     /* Round up */
00678     ux = (int)(xpos + radius) + 1;
00679     uy = (int)(ypos + radius) + 1;
00680     if (ux > (nx-1)) ux = nx-1;
00681     if (uy > (ny-1)) uy = ny-1;
00682 
00683     /* im is actually not modified */
00684     pself = cpl_image_get_data_float((cpl_image*)self);
00685     for (j=ly ; j<uy ; j++) {
00686         yj = (double)j - ypos;
00687         sqrest = sqr - yj * yj;
00688         for (i=lx; i<ux ; i++) {
00689             xi = (double)i - xpos;
00690             if (sqrest >= xi * xi && irplib_isnan(pself[i+j*nx]) == 0) {
00691                 if (first || pself[i+j*nx] > peak) {
00692                     first = CPL_FALSE;
00693                     peak = pself[i+j*nx];
00694                 }
00695             }
00696         }
00697     }
00698 
00699     cpl_ensure_code(!first, CPL_ERROR_DATA_NOT_FOUND);
00700 
00701     *ppeak = (double)peak;
00702 
00703     return CPL_ERROR_NONE;
00704 }

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