irplib_strehl.c

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

Generated on Tue Jun 19 14:39:14 2007 for UVES Pipeline Reference Manual by  doxygen 1.4.6