uves_utils_cpl.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: 2013/02/12 10:56:25 $
00023  * $Revision: 1.92 $
00024  * $Name: HEAD $
00025  * $Log: uves_utils_cpl.c,v $
00026  * Revision 1.92  2013/02/12 10:56:25  amodigli
00027  * removed dependency from assert
00028  *
00029  * Revision 1.91  2012/10/27 15:26:23  amodigli
00030  * fixed mem leak
00031  *
00032  * Revision 1.90  2012/03/02 16:53:31  amodigli
00033  * fixed warning related to upgrade to CPL6
00034  *
00035  * Revision 1.89  2011/12/08 13:59:32  amodigli
00036  * Fox warnings with CPL6
00037  *
00038  * Revision 1.88  2010/09/24 09:32:08  amodigli
00039  * put back QFITS dependency to fix problem spot by NRI on FIBER mode (with MIDAS calibs) data
00040  *
00041  * Revision 1.86  2010/02/13 12:22:31  amodigli
00042  * removed inlines (let's do work to compiler)
00043  *
00044  * Revision 1.85  2010/01/07 07:49:17  amodigli
00045  * added some 'check_nomsg' statementsuves_utils.c
00046  *
00047  * Revision 1.84  2008/09/29 07:00:55  amodigli
00048  * add #include <string.h>
00049  *
00050  * Revision 1.83  2007/08/21 13:08:26  jmlarsen
00051  * Removed irplib_access module, largely deprecated by CPL-4
00052  *
00053  * Revision 1.82  2007/06/06 08:17:33  amodigli
00054  * replace tab with 4 spaces
00055  *
00056  * Revision 1.81  2007/04/24 12:50:29  jmlarsen
00057  * Replaced cpl_propertylist -> uves_propertylist which is much faster
00058  *
00059  * Revision 1.80  2007/04/10 07:11:35  jmlarsen
00060  * Added check on input image type
00061  *
00062  * Revision 1.79  2007/03/05 10:20:22  jmlarsen
00063  * Support slope parameter in 1d fitting
00064  *
00065  * Revision 1.78  2007/02/27 14:08:46  jmlarsen
00066  * Extended interface of uves_find_property
00067  *
00068  * Revision 1.77  2007/01/29 12:14:49  jmlarsen
00069  * Added uves_find_property()
00070  *
00071  * Revision 1.76  2007/01/15 08:48:20  jmlarsen
00072  * Exported get_kth function
00073  *
00074  * Revision 1.75  2006/12/07 08:28:18  jmlarsen
00075  * compute median as average of two middle elements
00076  *
00077  * Revision 1.74  2006/11/15 15:02:15  jmlarsen
00078  * Implemented const safe workarounds for CPL functions
00079  *
00080  * Revision 1.72  2006/11/15 14:04:08  jmlarsen
00081  * Removed non-const version of parameterlist_get_first/last/next which is already
00082  * in CPL, added const-safe wrapper, unwrapper and deallocator functions
00083  *
00084  * Revision 1.71  2006/11/06 15:19:42  jmlarsen
00085  * Removed unused include directives
00086  *
00087  * Revision 1.70  2006/09/19 07:17:08  jmlarsen
00088  * Reformatted line
00089  *
00090  * Revision 1.69  2006/09/08 14:06:04  jmlarsen
00091  * Added uves_tools_get_median()
00092  *
00093  * Revision 1.68  2006/08/23 09:33:03  jmlarsen
00094  * Renamed local variables shadowing POSIX reserved names
00095  *
00096  * Revision 1.67  2006/08/18 14:21:03  jmlarsen
00097  * Added code to support CPL3 median filtering
00098  *
00099  * Revision 1.66  2006/08/17 14:11:25  jmlarsen
00100  * Use assure_mem macro to check for memory allocation failure
00101  *
00102  * Revision 1.65  2006/08/17 13:56:53  jmlarsen
00103  * Reduced max line length
00104  *
00105  * Revision 1.64  2006/08/14 12:19:59  jmlarsen
00106  * Removed unused functions
00107  *
00108  * Revision 1.63  2006/08/11 14:56:06  amodigli
00109  * removed Doxygen warnings
00110  *
00111  * Revision 1.62  2006/08/10 10:54:09  jmlarsen
00112  * Removed CX_PI definition
00113  *
00114  * Revision 1.61  2006/08/08 11:27:18  amodigli
00115  * upgrade to CPL3
00116  *
00117  * Revision 1.60  2006/07/03 13:21:41  jmlarsen
00118  * Changed 1d-fit parameter estimation method when only sky needs to be determined
00119  *
00120  * Revision 1.59  2006/06/13 12:02:22  jmlarsen
00121  * Renamed y0 -> y_0
00122  *
00123  * Revision 1.58  2006/06/01 14:43:17  jmlarsen
00124  * Added missing documentation
00125  *
00126  * Revision 1.57  2006/05/12 15:13:04  jmlarsen
00127  * Pass image bpm as extra parameter to fitting routine for efficiency reasons
00128  *
00129  * Revision 1.56  2006/04/24 09:27:48  jmlarsen
00130  * Allow fixing background in gauss. fit
00131  *
00132  * Revision 1.55  2006/03/09 13:54:44  jmlarsen
00133  * Optimization of median computation
00134  *
00135  * Revision 1.54  2006/03/09 10:51:19  jmlarsen
00136  * Changed order of for loops
00137  *
00138  * Revision 1.53  2006/03/03 13:54:11  jmlarsen
00139  * Changed syntax of check macro
00140  *
00141  * Revision 1.52  2006/02/21 14:24:45  jmlarsen
00142  * Parameterized behaviour of median filter near image border
00143  *
00144  * Revision 1.51  2006/01/31 08:25:49  jmlarsen
00145  * Renamed uves_fit_gaussian_2d -> uves_fit_gaussian_2d_image
00146  *
00147  * Revision 1.50  2006/01/25 16:13:20  jmlarsen
00148  * Changed interface of gauss.fitting routine
00149  *
00150  * Revision 1.49  2006/01/12 15:41:14  jmlarsen
00151  * Moved gauss. fitting to irplib
00152  *
00153  * Revision 1.48  2005/12/20 08:11:44  jmlarsen
00154  * Added CVS  entry
00155  *
00156  */
00157 
00158 #ifdef HAVE_CONFIG_H
00159 #  include <config.h>
00160 #endif
00161 
00162 /*----------------------------------------------------------------------------*/
00169 /*----------------------------------------------------------------------------*/
00170 
00173 #include <uves_utils_cpl.h>
00174 
00175 #include <uves_utils.h>
00176 #include <uves_utils_wrappers.h>
00177 #include <uves_dump.h>
00178 #include <uves_error.h>
00179 
00180 #include <cpl.h>
00181 #include <stdbool.h>
00182 #include <string.h>
00183 
00184 static cpl_image *filter_median(const cpl_image *image, int radx, int rady,
00185                 bool extrapolate_border);
00186     
00187 
00188 /*----------------------------------------------------------------------------*/
00200 /*----------------------------------------------------------------------------*/
00201 const cpl_property *
00202 uves_find_property_const(const uves_propertylist *plist, const char *name,
00203                    int number)
00204 {
00205     int i = 0;
00206     int size = uves_propertylist_get_size(plist);
00207 
00208     assure( number >= 0, CPL_ERROR_ILLEGAL_INPUT, "Number (%d) must be non-negative",
00209             number);
00210 
00211     for (i = 0; i < size; i++)
00212     {
00213         const cpl_property *p = uves_propertylist_get_const(plist, i);
00214 
00215         if (strcmp(cpl_property_get_name(p), name) == 0)
00216         {
00217                     if (number == 0)
00218                         {
00219                             return p;
00220                         }
00221                     else
00222                         /* Continue search */
00223                         {
00224                             number--;
00225                         }
00226         }
00227     }
00228 
00229   cleanup:
00230     return NULL;
00231 }
00232 cpl_property *
00233 uves_find_property(uves_propertylist *plist, const char *name,
00234                    int number)
00235 {
00236     return (cpl_property *) uves_find_property_const(plist, name, number);
00237 }
00238 
00239 /*----------------------------------------------------------------------------*/
00251 /*----------------------------------------------------------------------------*/
00252 cpl_error_code
00253 uves_filter_image_average(cpl_image *image, int radius_x, int radius_y)
00254 {
00255     cpl_image *aux = NULL;
00256     double *image_data = NULL;
00257     double *aux_data = NULL;
00258     int nx, ny;
00259     int i;
00260 
00261     /* For bad pixel handling, create a similar auxillary image that counts the bad pixels */
00262     
00263     assure( image != NULL, CPL_ERROR_NULL_INPUT, "Null image");
00264     assure( radius_x >= 0, CPL_ERROR_ILLEGAL_INPUT, "Negative x-radius (%d)", radius_x);
00265     assure( radius_y >= 0, CPL_ERROR_ILLEGAL_INPUT, "Negative y-radius (%d)", radius_y);
00266     assure( cpl_image_get_type(image) == CPL_TYPE_DOUBLE, CPL_ERROR_TYPE_MISMATCH,
00267         "Type is %s. double expected", uves_tostring_cpl_type(cpl_image_get_type(image)));
00268     
00269     nx = cpl_image_get_size_x(image);
00270     ny = cpl_image_get_size_y(image);
00271     image_data = cpl_image_get_data_double(image);
00272     
00273     /* (Disabled:) To avoid problems with overflow (the total flux in the image might
00274        be larger than INT_MAX) subtract a constant (the average flux), apply the filter,
00275        then add the constant       */
00276     
00277     /* First build auxillary image:
00278      *
00279      * aux(x,y) = sum_{i=0,x-1} sum_{j=0,y-1}  image(i,j)
00280      *          = sum of rectangle (0,0)-(x-1,y-1)
00281      *
00282      */
00283 
00284     aux = cpl_image_new(nx+1, ny+1, CPL_TYPE_DOUBLE);          /* Initialized to zero */
00285     aux_data = cpl_image_get_data(aux);
00286 
00287     /* Column x=0 and row y=0 are already zero and need not be calculated,
00288      * start from 1.    */
00289 
00290 /* Slow:    for (x = 1; x < nx+1; x++)
00291             {
00292         for (y = 1; y < ny+1; y++)
00293         {
00294 */
00295     for (i = 0; i < (nx+1)*(ny+1); i++)
00296     {
00297         int x = i % (nx+1);
00298         int y = i / (nx+1);
00299         
00300         if ( x >= 1 && y >= 1)
00301         {
00302             aux_data[x + y*(nx+1)] = image_data[x-1 + (y-1) * nx]
00303             + aux_data  [x-1 +    y * (nx+1)]
00304             + aux_data  [x   + (y-1)* (nx+1)]
00305             - aux_data  [x-1 + (y-1)* (nx+1)];
00306         }
00307         
00308         /* Proof of induction step
00309          * (assume that formula holds up to (x-1,y) and (x,y-1) and prove formula for (x,y))
00310          *
00311          *  aux(x,y) = image(x-1, y-1) + aux(x-1, y) + aux(x, y-1) - aux(x-1, y-1)  (see code)
00312          *
00313          *  = image(x-1, y-1)
00314          *  + sum_{i=0,x-2}_{j=0,y-1} image(i,j)  _
00315          *  + sum_{i=0,x-1}_{j=0,y-2} image(i,j)   \_ sum_{j=0,y-2} image(x-1, j)  
00316          *  - sum_{i=0,x-2}_{j=0,y-2} image(i,j)  _/ 
00317          * 
00318          *  = sum_{i=0,x-2}_{j=0,y-1} image(i,j)
00319          *  + sum_          {j=0,y-1} image(x-1, j)  
00320          *  
00321          *  = sum_{j=0,y-1} [ ( sum_{i=0,x-2} image(i,j) ) + image(x-1,j) ]
00322          *  = sum_{j=0,y-1}     sum_{i=0,x-1} image(i,j)      q.e.d.
00323          *
00324          *  It's simpler when you draw it... 
00325          */
00326     }
00327 
00328     uves_msg_debug("Finished setting up auxillary image. Get average");
00329 
00330     /* Then calculate average = (flux in window) / (image size) */
00331     for (i = 0; i < nx*ny; i++)
00332     {
00333         int x = (i % nx);
00334         int y = (i / nx);
00335 
00336         int lower, upper;
00337         int left, right;
00338         
00339         lower = y - radius_y; if (lower <   0) lower = 0;
00340         upper = y + radius_y; if (upper >= ny) upper = ny - 1;
00341         
00342         left  = x - radius_x; if (left  <   0) left  = 0;
00343         right = x + radius_x; if (right >= nx) right = nx - 1;
00344         
00345         image_data[x + y*nx] =
00346         (
00347             aux_data[(right+1) + (upper+1)*(nx+1)] +
00348             aux_data[ left     +  lower   *(nx+1)] -
00349             aux_data[ left     + (upper+1)*(nx+1)] -
00350             aux_data[(right+1) +  lower   *(nx+1)]
00351             )
00352         /
00353         ( (double) (upper-lower+1) * (right-left+1) );
00354     }
00355     
00356   cleanup:
00357     uves_free_image(&aux);
00358     return cpl_error_get_code();
00359 }
00360 
00361 
00362 /*----------------------------------------------------------------------------*/
00376 /*----------------------------------------------------------------------------*/
00377 cpl_error_code
00378 uves_filter_image_median(cpl_image **image, int xwindow, int ywindow, bool extrapolate_border)
00379 {
00380     cpl_matrix *id = NULL;
00381     cpl_image *temp = NULL;
00382 
00383     assure( xwindow >= 0 && ywindow >= 0, CPL_ERROR_ILLEGAL_INPUT,
00384         "Illegal window radius: %d x %d", 
00385         (2*xwindow + 1),
00386         (2*ywindow + 1));
00387     
00388     UVES_TIME_START("median filter");
00389 
00390     if (xwindow <= 1 && ywindow <= 1)
00391 /* CPL 3 supports   if (xwindow <= 4 && ywindow <= 4) */
00392     {
00393         check(( id = cpl_matrix_new(2*xwindow+1, 2*ywindow+1),
00394             cpl_matrix_fill(id, 1)), "Could not create kernel matrix");
00395         
00396         /* Image to cpl_image_filter_median must be float or double */
00397         if (cpl_image_get_type(*image) == CPL_TYPE_INT)
00398         {
00399             temp = cpl_image_cast(*image, CPL_TYPE_DOUBLE);
00400             uves_free_image(image);
00401         }
00402         else
00403         {
00404       temp = cpl_image_duplicate(*image);
00405       uves_free_image(image);
00406         }
00407         check( *image = uves_image_filter_median(temp, id), "Error applying median filter");
00408         uves_free_image(&temp);
00409 
00410         /* fixme: the CPL function marks border pixels as bad. Do something
00411            depending on the extrapolate_border flag */
00412     }
00413     else
00414     {
00415         temp = *image;
00416         check( *image = filter_median(temp, xwindow, ywindow, extrapolate_border),
00417            "Error applying median filter");
00418         uves_free_image(&temp);
00419     }
00420 
00421     UVES_TIME_END;    
00422     
00423   cleanup:
00424     uves_free_matrix(&id);
00425     uves_free_image(&temp);
00426     return cpl_error_get_code();
00427 }
00428 
00430 #define DOUBLE_SWAP(a,b) { register double t=(a);(a)=(b);(b)=t; }
00431 
00442 double uves_utils_get_kth_double(
00443         double  *   a, 
00444         int         n, 
00445         int         k)
00446 {
00447     register double x ;
00448     register int    i, j, l, m ;
00449 
00450     l=0 ; m=n-1 ;
00451     while (l<m) {
00452         x=a[k] ;
00453         i=l ;
00454         j=m ;
00455         do {
00456             while (a[i]<x) i++ ;
00457             while (x<a[j]) j-- ;
00458             if (i<=j) {
00459                 DOUBLE_SWAP(a[i],a[j]) ;
00460                 i++ ; j-- ;
00461             }
00462         } while (i<=j) ;
00463         if (j<k) l=i ;
00464         if (k<i) m=j ;
00465     }
00466     return a[k] ;
00467 }
00468 
00477 double
00478 uves_tools_get_median(double *a, int n)
00479 {
00480     if (n % 2 == 0)
00481     {
00482         return
00483         (uves_utils_get_kth_double(a, n, n/2) +
00484          uves_utils_get_kth_double(a, n, n/2-1))/2.0;
00485         
00486     }
00487     else
00488     {
00489         return uves_utils_get_kth_double(a, n, (n-1)/2);
00490     }
00491 }
00492 
00493 
00494 
00495 /*----------------------------------------------------------------------------*/
00517 /*----------------------------------------------------------------------------*/
00518 static cpl_image *
00519 filter_median(const cpl_image *image, int radx, int rady, bool extrapolate_border)
00520 {
00521     int x, y;
00522     int nx = cpl_image_get_size_x(image);
00523     int ny = cpl_image_get_size_y(image);
00524     cpl_image *result = cpl_image_new(nx, ny, CPL_TYPE_DOUBLE);
00525     double *result_data;
00526     const double *image_data;
00527     double *window = NULL;
00528 
00529     window = cpl_malloc(sizeof(double) * (2*radx+1)*(2*rady+1));
00530     assure_mem( result );
00531     assure( cpl_image_get_type(image) == CPL_TYPE_DOUBLE,
00532             CPL_ERROR_UNSUPPORTED_MODE, "Type is %s", 
00533             uves_tostring_cpl_type(cpl_image_get_type(image)));
00534 
00535     result_data = cpl_image_get_data_double(result);
00536     image_data = cpl_image_get_data_double_const(image);
00537 
00538     for (y = 1; y <= ny; y++)
00539     {
00540         for (x = 1; x <= nx; x++)
00541         {
00542             int x1, y_1, x2, y2;
00543             
00544             x1 = x - radx; y_1 = y - rady;
00545             x2 = x + radx; y2  = y + rady;
00546 
00547             if (extrapolate_border)
00548             {
00549                 /* At edge of image, move median box, so
00550                    that entire box is inside of image */
00551                 if (x1 < 1)
00552                 {
00553                     x2 += (1 - x1);
00554                     x1 += (1 - x1);
00555                 }
00556                 if (nx < x2)
00557                 {
00558                     x1 -= (x2 - nx);
00559                     x2 -= (x2 - nx);
00560                 }
00561                 
00562                 if (y_1 < 1)
00563                 {
00564                     y2  += (1 - y_1);
00565                     y_1 += (1 - y_1);
00566                 }
00567                 if (ny < y2)
00568                 {
00569                     y_1 -= (y2 - ny);
00570                     y2  -= (y2 - ny);
00571                 }
00572             }
00573             else { /* Rely on the use of min/max below */ }
00574             
00575 #if 0
00576             result_data[(x-1) + (y-1)*nx] = 
00577             cpl_image_get_median_window(image,  
00578                             uves_max_int(1,  x1),
00579                             uves_max_int(1,  y_1),
00580                             uves_min_int(nx, x2),
00581                             uves_min_int(ny, y2));
00582 
00583 #else
00584             /* This saves a few (~10-20) percent execution time */
00585             {
00586             int i, j, k;
00587             
00588             k = 0;
00589             for (j  = uves_max_int(1 , y_1)-1;
00590                  j <= uves_min_int(ny, y2 )-1;
00591                  j++)
00592                 for (i  = uves_max_int(1,  x1)-1; 
00593                  i <= uves_min_int(nx, x2)-1; 
00594                  i++)
00595                 {
00596                     window[k++] = image_data[i + j*nx];
00597                 }
00598             
00599             result_data[(x-1) + (y-1)*nx] = 
00600                 uves_utils_get_kth_double(window,k,(((k)&1)?((k)/2):(((k)/2)-1))) ;
00601             }
00602 #endif        
00603         }
00604     }
00605     
00606 
00607     assure( cpl_error_get_code() == CPL_ERROR_NONE, cpl_error_get_code(), 
00608         "Error calculating %dx%d median filter", radx, rady);
00609     
00610   cleanup:
00611     cpl_free(window);
00612     return result;
00613 }
00614 
00615 
00616 /*----------------------------------------------------------------------------*/
00644 /*----------------------------------------------------------------------------*/
00645 
00646 cpl_error_code
00647 uves_fit_gaussian_2d_image(const cpl_image *image, const cpl_image *noise,
00648                int x1, int y_1,
00649                int x2, int y2,
00650                double *x0, double *y_0, double *sigmax, double *sigmay,
00651                double *amplitude,
00652                double *dx0, double *dy0
00653     )
00654 {
00655     cpl_image  *marginal_x = NULL;
00656     cpl_image  *marginal_y = NULL;
00657     cpl_image  *marginal_x_noise = NULL;
00658     cpl_image  *marginal_y_noise = NULL;
00659     cpl_image  *variance = NULL;
00660     cpl_matrix *covariance = NULL;
00661 
00662     int nx, ny;
00663     double norm_x, norm_y;
00664     double background_x, background_y;
00665 
00666     /* Check input */
00667     assure( image != NULL, CPL_ERROR_NULL_INPUT, "Null image");
00668     nx = cpl_image_get_size_x(image);
00669     ny = cpl_image_get_size_y(image);
00670     assure( noise != NULL || (dx0 == NULL && dy0 == NULL), CPL_ERROR_INCOMPATIBLE_INPUT,
00671         "Cannot compute uncertainty of fit with no noise image specified");
00672     assure( noise == NULL || 
00673         (cpl_image_get_size_x(noise) == nx &&
00674          cpl_image_get_size_y(noise) == ny),
00675         CPL_ERROR_INCOMPATIBLE_INPUT,
00676         "Size of input image (%dx%d) and noise image (%" CPL_SIZE_FORMAT "x%" CPL_SIZE_FORMAT ") differ", 
00677         nx, ny,
00678         cpl_image_get_size_x(noise),
00679         cpl_image_get_size_y(noise));
00680     assure( 1 <= x1 && x1 <= x2 && x2 <= nx &&
00681         1 <= y_1 && y_1 <= y2 && y2 <= ny, CPL_ERROR_ILLEGAL_INPUT,
00682         "Illegal window: (%d, %d)-(%d, %d)", x1, y_1, x2, y2);
00683     assure( x0 != NULL, CPL_ERROR_NULL_INPUT, "Null x-center");
00684     assure( y_0 != NULL, CPL_ERROR_NULL_INPUT, "Null y-center");
00685     assure( sigmax != NULL, CPL_ERROR_NULL_INPUT, "Null sigma_x");
00686     assure( sigmay != NULL, CPL_ERROR_NULL_INPUT, "Null sigma_y");
00687     /* amplitude, dx0, dy0 may be NULL */
00688 
00689     if (noise != NULL)
00690     {
00691         /* Variance = noise^2 */
00692         check(( variance = cpl_image_extract(noise, x1, y_1, x2, y2),
00693             cpl_image_power(variance, 2.0)),
00694            "Error creating variance image");
00695     }
00696     
00697     /* Collapse along columns (result is horizontal) */
00698     check( marginal_x = cpl_image_collapse_window_create(image,
00699                              x1, y_1, x2, y2,
00700                              0),           /* Sum of columns */
00701        "Error collapsing window (%d, %d) - (%d, %d)", x1, y_1, x2, y2);  
00702 
00703     if (noise != NULL)
00704     {
00705         /* Sigma of sum = sqrt [ sum sigma_i^2 ] */
00706         
00707         check( marginal_x_noise = cpl_image_collapse_window_create(variance,
00708                                        1, 1, 
00709                                        x2-x1+1, y2-y_1+1,
00710                                        0), /* Sum of columns */
00711            "Error collapsing window (1, 1) - (%d, %d)", x2-x1+1, y2-y_1+1);
00712 
00713         /* Sqrt */
00714         cpl_image_power(marginal_x_noise, 0.5);
00715     }
00716     
00717     /* Collapse along rows (result is vertical) */
00718     check( marginal_y = cpl_image_collapse_window_create(image,
00719                              x1, y_1, x2, y2,
00720                              1),           /* Sum of rows */
00721        "Error collapsing window (%d, %d) - (%d, %d)", x1, y_1, x2, y2);  
00722     
00723     if (noise != NULL)
00724     {
00725         check( marginal_y_noise = cpl_image_collapse_window_create(variance,
00726                                        1, 1,
00727                                        x2-x1+1, y2-y_1+1,
00728                                        1), /* Sum of rows */
00729            "Error collapsing window (1, 1) - (%d, %d)", x2-x1+1, y2-y_1+1);
00730 
00731         /* Sqrt */
00732         cpl_image_power(marginal_y_noise, 0.5);
00733     }
00734 
00735     /* Fit x-distribution */
00736     uves_fit_1d_image(marginal_x, marginal_x_noise, NULL,
00737               true,                       /* Horizontal ?                  */
00738               false, false,               /* Fix/fit background ?          */
00739               1, x2 - x1 + 1, 1,          /* xlo, xhi, y                   */
00740               x0, sigmax, &norm_x, &background_x, NULL,
00741               NULL, NULL,                 /* mse, red. chi^2               */
00742               (dx0 != NULL) ? &covariance : NULL,
00743               uves_gauss, uves_gauss_derivative, 4);
00744 
00745     /* Set code 'CPL_ERROR_CONTINUE' if fitting failed, check for unexpected errors */
00746     assure( cpl_error_get_code() != CPL_ERROR_CONTINUE ||
00747         cpl_error_get_code() != CPL_ERROR_SINGULAR_MATRIX,
00748         CPL_ERROR_CONTINUE, "Fitting along x failed");
00749     assure( cpl_error_get_code() == CPL_ERROR_NONE, cpl_error_get_code(), 
00750         "Fitting along x failed");
00751      
00752     /* Map to world-coordinates */
00753     *x0 += (x1 - 1);
00754     
00755     if (dx0 != NULL)
00756     {
00757         *dx0 = cpl_matrix_get(covariance, 0, 0);
00758     }
00759 
00760 
00761     /* Fit y-distribution */
00762     uves_free_matrix(&covariance);
00763     uves_fit_1d_image(marginal_y, marginal_y_noise, NULL,
00764               false,                      /* Horizontal ?                  */
00765               false, false,               /* Fix/fit background ?          */
00766               1, y2 - y_1 + 1, 1,          /* ylo, yhi, x                   */
00767               y_0, sigmay, &norm_y, &background_y, NULL,
00768               NULL, NULL,                 /* mse, red. chi^2               */
00769               (dy0 != NULL) ? &covariance : NULL,
00770               uves_gauss, uves_gauss_derivative, 4);
00771     
00772     /* Set code 'CPL_ERROR_CONTINUE' if fitting failed, check for unexpected errors */
00773     assure( cpl_error_get_code() != CPL_ERROR_CONTINUE ||
00774         cpl_error_get_code() != CPL_ERROR_SINGULAR_MATRIX,
00775         CPL_ERROR_CONTINUE, "Fitting along y failed");
00776     assure( cpl_error_get_code() == CPL_ERROR_NONE, cpl_error_get_code(), 
00777         "Fitting along y failed");
00778     
00779     /* Map to world-coordinates */
00780     *y_0 += (y_1 - 1);
00781     
00782     if (dy0 != NULL)
00783     {
00784         *dy0 = cpl_matrix_get(covariance, 0, 0);
00785     }
00786     
00787     /* Set amplitude  = N / [ sqrt(2pi sigmax^2) sqrt(2pi sigmay^2) ].
00788      *
00789      * The fitted norm (area), N, is the same (up to numerical errors) in both directions,
00790      * so use geometric average as an estimate of N.
00791      */
00792     if (amplitude != NULL)
00793     {
00794         *amplitude = sqrt(norm_x * norm_y) / (2*M_PI * (*sigmax) * (*sigmay));
00795     }
00796     
00797   cleanup:
00798     uves_free_matrix(&covariance);
00799     uves_free_image(&variance);
00800     uves_free_image(&marginal_x);
00801     uves_free_image(&marginal_x_noise);
00802     uves_free_image(&marginal_y);
00803     uves_free_image(&marginal_y_noise);
00804     
00805     return cpl_error_get_code();
00806 }
00807 
00808 

Generated on 3 Mar 2013 for UVES Pipeline Reference Manual by  doxygen 1.6.1