uves_extract_profile.c

00001 /*                                                                              *
00002  *   This file is part of the ESO UVES Pipeline                                 *
00003  *   Copyright (C) 2004,2005 European Southern Observatory                      *
00004  *                                                                              *
00005  *   This library is free software; you can redistribute it and/or modify       *
00006  *   it under the terms of the GNU General Public License as published by       *
00007  *   the Free Software Foundation; either version 2 of the License, or          *
00008  *   (at your option) any later version.                                        *
00009  *                                                                              *
00010  *   This program is distributed in the hope that it will be useful,            *
00011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of             *
00012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
00013  *   GNU General Public License for more details.                               *
00014  *                                                                              *
00015  *   You should have received a copy of the GNU General Public License          *
00016  *   along with this program; if not, write to the Free Software                *
00017  *   Foundation, 51 Franklin St, Fifth Floor, Boston, MA  02111-1307  USA       *
00018  *                                                                              */
00019 
00020 /*
00021  * $Author: amodigli $
00022  * $Date: 2007/08/30 07:56:54 $
00023  * $Revision: 1.3 $
00024  * $Name: uves-3_9_0 $
00025  * $Log: uves_extract_profile.c,v $
00026  * Revision 1.3  2007/08/30 07:56:54  amodigli
00027  * fixed some doxygen warnings
00028  *
00029  * Revision 1.2  2007/06/06 08:17:33  amodigli
00030  * replace tab with 4 spaces
00031  *
00032  * Revision 1.1  2007/05/02 13:43:46  jmlarsen
00033  * Added source
00034  *
00035  * Revision 1.141  2007/04/26 06:55:35  amodigli
00036  * fixed mem leak adding uves_free_image(&spectrum_order)
00037  *
00038  * Revision 1.140  2007/04/24 12:50:29  jmlarsen
00039  * Replaced cpl_propertylist -> uves_propertylist which is much faster
00040  *
00041  * Revision 1.139  2007/04/24 09:40:37  jmlarsen
00042  * Removed deprecated irplib_string_concatenate_all
00043  *
00044  * Revision 1.138  2007/04/20 14:44:20  jmlarsen
00045  * Implemented QC parameter to measure small scale ripples
00046  *
00047  * Revision 1.137  2007/04/12 12:00:35  jmlarsen
00048  * Added testing code
00049  *
00050  * Revision 1.136  2007/04/10 11:34:14  jmlarsen
00051  * Removed debug message
00052  *
00053  * Revision 1.135  2007/04/10 08:05:49  jmlarsen
00054  * Disabled optimization (reduced kappa-sigma iterations, caught by unit test)
00055  *
00056  * Revision 1.134  2007/04/10 07:23:20  jmlarsen
00057  * Added commented out code to spline interpolate virtually resampled profile
00058  *
00059  * Revision 1.133  2007/03/28 11:38:38  jmlarsen
00060  * Removed dead code
00061  *
00062  * Revision 1.132  2007/03/19 15:12:14  jmlarsen
00063  * Optimization: use doubles rather than zero deg. poly.
00064  *
00065  * Revision 1.131  2007/03/19 13:50:18  jmlarsen
00066  * Fixed serious bug happening when object is at +-15 pixels
00067  *
00068  * Revision 1.130  2007/03/15 12:33:37  jmlarsen
00069  * Minor message change
00070  *
00071  * Revision 1.129  2007/03/13 15:33:30  jmlarsen
00072  * Use autodegree polynomials for virtual profile, not zero degree
00073  *
00074  * Revision 1.128  2007/03/05 10:16:37  jmlarsen
00075  * Support slope parameter in 1d fitting
00076  *
00077  * Revision 1.127  2007/02/26 13:29:40  jmlarsen
00078  * Don't use Gauss-Legendre 3 point interpolation, for efficiency
00079  *
00080  * Revision 1.126  2007/02/26 11:55:47  jmlarsen
00081  * Renamed and generalized function uves_raise_to_median() -> uves_raise_to_median_frac()
00082  *
00083  * Revision 1.125  2007/02/22 15:33:56  jmlarsen
00084  * Optimization: use double's rather than constant 2d polynomials
00085  *
00086  * Revision 1.124  2007/02/09 13:37:06  jmlarsen
00087  * Added bug in 2d extraction mode
00088  *
00089  * Revision 1.123  2007/02/09 08:14:16  jmlarsen
00090  * Do not use CPL_PIXEL_MAXVAL which works only for integer images
00091  *
00092  * Revision 1.122  2007/02/08 07:33:56  jmlarsen
00093  * Added doc
00094  *
00095  * Revision 1.121  2007/01/31 13:10:33  jmlarsen
00096  * Changed message
00097  *
00098  * Revision 1.120  2007/01/29 12:09:42  jmlarsen
00099  * Compute QC parameters (pos, fwhm, s/n) also for simple extraction
00100  *
00101  * Revision 1.119  2007/01/26 13:49:43  jmlarsen
00102  * Fixed sky subtraction residuals for optimal sky subtraction
00103  *
00104  * Revision 1.118  2007/01/15 08:46:01  jmlarsen
00105  * Made more robust against extended objects
00106  *
00107  * Revision 1.117  2007/01/05 07:22:07  jmlarsen
00108  * Eliminated compiler warnings
00109  *
00110  * Revision 1.116  2007/01/04 13:55:21  jmlarsen
00111  * Implemented order-by-order object tracing (disabled)
00112  *
00113  * Revision 1.115  2006/12/08 07:41:43  jmlarsen
00114  * Minor doc. change
00115  *
00116  * Revision 1.114  2006/11/16 09:48:30  jmlarsen
00117  * Renamed data type position -> uves_iterate_position, for namespace reasons
00118  *
00119  * Revision 1.113  2006/11/15 15:02:14  jmlarsen
00120  * Implemented const safe workarounds for CPL functions
00121  *
00122  * Revision 1.111  2006/11/15 14:04:08  jmlarsen
00123  * Removed non-const version of parameterlist_get_first/last/next which is already
00124  * in CPL, added const-safe wrapper, unwrapper and deallocator functions
00125  *
00126  * Revision 1.110  2006/11/08 14:04:34  jmlarsen
00127  * Implemented flag to select sky subtraction method
00128  *
00129  * Revision 1.109  2006/11/06 15:19:41  jmlarsen
00130  * Removed unused include directives
00131  *
00132  * Revision 1.108  2006/10/31 09:14:58  jmlarsen
00133  * Man page doc fix
00134  *
00135  * Revision 1.107  2006/10/02 08:34:40  jmlarsen
00136  * Do not recompute variance in last iteration
00137  *
00138  * Revision 1.106  2006/09/27 15:08:45  jmlarsen
00139  * Fixed doc. bug
00140  *
00141  * Revision 1.105  2006/09/27 13:08:49  jmlarsen
00142  * Use dynamic memory allocation to store bad pixels
00143  *
00144  * Revision 1.104  2006/09/20 12:53:57  jmlarsen
00145  * Replaced stringcat functions with uves_sprintf()
00146  *
00147  * Revision 1.103  2006/09/20 07:25:30  jmlarsen
00148  * Doc. bug fix
00149  *
00150  * Revision 1.102  2006/09/19 14:29:05  jmlarsen
00151  * Measure object position QC parameter from bottom of slit
00152  *
00153  * Revision 1.101  2006/09/19 07:15:35  jmlarsen
00154  * Added chip to argument list of uves_extract()
00155  *
00156  * Revision 1.100  2006/09/11 14:19:28  jmlarsen
00157  * Updated documentation
00158  *
00159  * Revision 1.99  2006/09/11 13:57:46  jmlarsen
00160  * Remove usage of cpl_image_set after getting bpm pointer
00161  *
00162  * Revision 1.98  2006/09/08 14:02:34  jmlarsen
00163  * Simplified code by using iterators, sky subtraction much optimized
00164  *
00165  * Revision 1.97  2006/09/06 15:35:51  jmlarsen
00166  * Changed indentations
00167  *
00168  * Revision 1.96  2006/09/06 14:50:23  jmlarsen
00169  * Worked on code to globally measure spatial profile
00170  *
00171  * Revision 1.95  2006/09/01 13:56:46  jmlarsen
00172  * Added commented out code (alternative way of measuring spatial profile)
00173  *
00174  * Revision 1.94  2006/08/23 15:08:56  jmlarsen
00175  * Improved plot of spatial profile
00176  *
00177  * Revision 1.93  2006/08/23 09:33:03  jmlarsen
00178  * Renamed local variables shadowing POSIX reserved names
00179  *
00180  * Revision 1.92  2006/08/22 15:35:48  jmlarsen
00181  * Auto-select profile method based on S/N estimate
00182  *
00183  * Revision 1.91  2006/08/22 14:20:56  jmlarsen
00184  * Implemented simultaneous optimal extraction of obj+sky
00185  *
00186  * Revision 1.90  2006/08/17 14:40:06  jmlarsen
00187  * Added missing documentation
00188  *
00189  * Revision 1.89  2006/08/17 14:11:25  jmlarsen
00190  * Use assure_mem macro to check for memory allocation failure
00191  *
00192  * Revision 1.88  2006/08/17 13:59:11  jmlarsen
00193  * Removed CPL2 const bug workaround
00194  *
00195  * Revision 1.87  2006/08/17 13:56:52  jmlarsen
00196  * Reduced max line length
00197  *
00198  * Revision 1.86  2006/08/17 09:17:42  jmlarsen
00199  * Removed CPL2 code
00200  *
00201  * Revision 1.85  2006/08/14 12:16:31  jmlarsen
00202  * Moved defines to top of file
00203  *
00204  * Revision 1.84  2006/08/11 14:56:05  amodigli
00205  * removed Doxygen warnings
00206  *
00207  * Revision 1.83  2006/08/11 09:20:06  jmlarsen
00208  * Implemented workaround for slow cpl_image_set
00209  *
00210  * Revision 1.82  2006/08/10 10:49:28  jmlarsen
00211  * Removed workaround for cpl_image_get_bpm
00212  *
00213  * Revision 1.81  2006/08/08 11:02:43  jmlarsen
00214  * Make temporary copy of image bad pixel map
00215  *
00216  * Revision 1.80  2006/08/08 08:19:17  amodigli
00217  * update to CPL3
00218  *
00219  * Revision 1.79  2006/08/07 11:35:35  jmlarsen
00220  * Disabled parameter environment variable mode
00221  *
00222  * Revision 1.78  2006/07/14 12:21:36  jmlarsen
00223  * Take bad pixels into account in sky subtraction
00224  *
00225  * Revision 1.77  2006/07/03 13:01:22  jmlarsen
00226  * Use analytical-fit sky subtraction method to improve S/N, use a
00227  * global model of chi square
00228  *
00229  * Revision 1.76  2006/06/16 08:23:04  jmlarsen
00230  * Added comment
00231  *
00232  * Revision 1.75  2006/06/05 08:51:55  amodigli
00233  * cleaned some warnings from static checks
00234  *
00235  * Revision 1.74  2006/06/02 06:41:59  jmlarsen
00236  * Added missing error code
00237  *
00238  * Revision 1.73  2006/06/01 14:43:17  jmlarsen
00239  * Added missing documentation
00240  *
00241  * Revision 1.72  2006/05/16 12:13:07  amodigli
00242  * added QC log
00243  *
00244  * Revision 1.71  2006/05/15 08:15:52  jmlarsen
00245  * Changed default kappa to 10.0
00246  *
00247  * Revision 1.70  2006/05/15 07:21:50  jmlarsen
00248  * Changed default kappa 3.5 -> 5.0
00249  *
00250  * Revision 1.69  2006/05/12 15:04:09  jmlarsen
00251  * Changed gauss/moffat/virtual profile measuring methods to use
00252  * global polynomials (rather than one polynomial per order)
00253  *
00254  * Revision 1.68  2006/04/24 09:21:18  jmlarsen
00255  * Implemented virtual resampling algorithm
00256  *
00257  * Revision 1.67  2006/04/10 12:36:35  jmlarsen
00258  * Fixed bug that caused extraction to halt if an order is completely 
00259  * outside an image
00260  *
00261  * Revision 1.66  2006/04/07 12:29:21  jmlarsen
00262  * Bugfix: in opt_evaluate_profile
00263  *
00264  * Revision 1.65  2006/04/07 07:10:12  jmlarsen
00265  * Use Gauss-Legendre rather than Simpson for profile integration
00266  *
00267  * Revision 1.64  2006/04/06 11:49:24  jmlarsen
00268  * Minor msg change
00269  *
00270  * Revision 1.63  2006/04/06 08:36:40  jmlarsen
00271  * Re-factored optimal extraction, added loop to measure 
00272  * profile until high statistics is achieved
00273  *
00274  * Revision 1.62  2006/03/24 14:46:39  jmlarsen
00275  * Doc. bugfix
00276  *
00277  * Revision 1.61  2006/03/24 14:17:37  jmlarsen
00278  * Mirror input image before/after extraction
00279  *
00280  * Revision 1.60  2006/03/03 13:54:11  jmlarsen
00281  * Changed syntax of check macro
00282  *
00283  * Revision 1.59  2006/02/28 09:15:22  jmlarsen
00284  * Minor update
00285  *
00286  * Revision 1.58  2006/02/15 13:19:15  jmlarsen
00287  * Reduced source code max. line length
00288  *
00289  * Revision 1.57  2006/01/25 16:13:20  jmlarsen
00290  * Changed interface of gauss.fitting routine
00291  *
00292  * Revision 1.56  2006/01/12 15:41:14  jmlarsen
00293  * Moved gauss. fitting to irplib
00294  *
00295  * Revision 1.55  2005/12/20 16:10:32  jmlarsen
00296  * Added some documentation
00297  *
00298  * Revision 1.54  2005/12/19 16:17:56  jmlarsen
00299  * Replaced bool -> int
00300  *
00301  */
00302 
00303 #ifdef HAVE_CONFIG_H
00304 #  include <config.h>
00305 #endif
00306 
00307 /*----------------------------------------------------------------------------*/
00314 /*----------------------------------------------------------------------------*/
00315 
00316 /*-----------------------------------------------------------------------------
00317                                 Includes
00318  -----------------------------------------------------------------------------*/
00319 
00320 #include <uves_extract_profile.h>
00321 
00322 #include <uves_extract_iterate.h>
00323 #include <uves_error.h>
00324 
00325 /*-----------------------------------------------------------------------------
00326                             Implementation
00327  -----------------------------------------------------------------------------*/
00328 
00329 uves_extract_profile *
00330 uves_extract_profile_new_constant(double slit_length)
00331 {
00332     uves_extract_profile *p = NULL;  /* Result */
00333     
00334     p = cpl_malloc(sizeof(uves_extract_profile));
00335 
00336     p->constant = true;
00337     p->slit_length = slit_length;
00338 
00339     /* remaining members not used */
00340 
00341     return p;
00342 }
00343 
00344 /*----------------------------------------------------------------------------*/
00363 /*----------------------------------------------------------------------------*/
00364 uves_extract_profile *
00365 uves_extract_profile_new(int (*f)   (const double x[], const double a[], double *result),
00366                          int (*dfda)(const double x[], const double a[], double result[]),
00367                          int M,
00368                          double slit_length,
00369                          int sampling_factor)
00370 {
00371     uves_extract_profile *p = NULL;  /* Result */
00372     
00373     p = cpl_malloc(sizeof(uves_extract_profile));
00374 
00375     p->constant = false;
00376     p->f = f;
00377 
00378     if (f != NULL)
00379         {
00380             /* Zero resampling */
00381             p->dfda      = dfda;
00382             p->M         = M;
00383 #if ORDER_PER_ORDER
00384             p->y0        = cpl_calloc(sizeof(polynomial *), 100);  /* 1 poly. per order */
00385             p->sigma     = cpl_calloc(sizeof(polynomial *), 100);
00386             p->red_chisq = cpl_calloc(sizeof(polynomial *), 100);
00387 #else
00388             p->y0        = NULL;
00389             p->sigma     = NULL;
00390             p->red_chisq = NULL;
00391 #endif            
00392             /* Not used */
00393             p->spatial_bins    = 0;
00394             p->slit_length     = 0;
00395             p->sampling_factor = 0;
00396             p->is_zero_degree  = NULL;
00397             p->dy_poly         = NULL;
00398             p->dy_double       = NULL;
00399             p->current_profile = NULL;
00400             p->current_ypos    = NULL;
00401             p->current_interpolated  = NULL;
00402         }
00403     else
00404         {
00405             /* Virtual resampling */
00406             p->spatial_bins    = uves_extract_profile_get_nbins(slit_length, sampling_factor);
00407             p->slit_length     = slit_length;
00408             p->sampling_factor = sampling_factor;
00409             p->spatial_bins    = uves_extract_profile_get_nbins(slit_length, sampling_factor);
00410             p->is_zero_degree  = cpl_calloc(p->spatial_bins, sizeof(bool));
00411             p->dy_poly         = cpl_calloc(p->spatial_bins, sizeof(polynomial *));
00412             p->dy_double       = cpl_calloc(p->spatial_bins, sizeof(double));
00413             p->current_profile = cpl_calloc(p->spatial_bins, sizeof(double));
00414             p->current_ypos    = cpl_calloc(p->spatial_bins, sizeof(double));
00415             p->current_interpolated = cpl_calloc(slit_length + 3, sizeof(double));
00416 
00417             /* Not used */
00418             p->dfda  = NULL;
00419             p->M     = 0;
00420             p->y0    = NULL;
00421             p->sigma = NULL;
00422         }
00423     
00424     return p;
00425 }
00426 
00427 
00428 /*----------------------------------------------------------------------------*/
00435 /*----------------------------------------------------------------------------*/
00436 
00437 void
00438 uves_extract_profile_delete(uves_extract_profile **p)
00439 {
00440     if (*p == NULL) return;
00441     
00442     if ((*p)->constant) 
00443         {
00444             /* nothing to clean */
00445         }
00446     else if((*p)->f != NULL) 
00447         {
00448 #if ORDER_PER_ORDER
00449 /* Then leak some memory */
00450 #else
00451             uves_polynomial_delete(&((*p)->y0));
00452             uves_polynomial_delete(&((*p)->sigma));
00453             uves_polynomial_delete(&((*p)->red_chisq));
00454 #endif
00455         }
00456     else
00457         {
00458             /* Virtual resampling */
00459             int i;
00460             for (i = 0; i < (*p)->spatial_bins; i++)
00461                 {
00462                     uves_polynomial_delete(& ((*p)->dy_poly[i]) );
00463                 }
00464             cpl_free((*p)->is_zero_degree);
00465             cpl_free((*p)->dy_poly);
00466             cpl_free((*p)->dy_double);
00467             cpl_free((*p)->current_profile);
00468             cpl_free((*p)->current_ypos);
00469             cpl_free((*p)->current_interpolated);
00470         }
00471     
00472     cpl_free(*p);
00473     *p = NULL;
00474 }
00475 
00476 /*----------------------------------------------------------------------------*/
00483 /*----------------------------------------------------------------------------*/
00484 int
00485 uves_extract_profile_get_nbins(double slit_length, int sampling_factor)
00486 {
00487     return uves_round_double(slit_length + 3) * sampling_factor;
00488 }
00489 
00490 /*----------------------------------------------------------------------------*/
00501 /*----------------------------------------------------------------------------*/
00502 inline double
00503 uves_extract_profile_get_y(uves_iterate_position *pos,
00504                            double bin,
00505                            int sampling_factor)
00506 {
00507     return bin*1.0/sampling_factor + (pos->ycenter - pos->sg.length/2 - 1);
00508 }
00509 
00510 /*----------------------------------------------------------------------------*/
00521 /*----------------------------------------------------------------------------*/
00522 inline double
00523 uves_extract_profile_get_bin(const uves_iterate_position *pos,
00524                              int sampling_factor)
00525 {
00526     return sampling_factor*(pos->y - (pos->ycenter - pos->sg.length/2 - 1));
00527 }
00528 
00529 /*----------------------------------------------------------------------------*/
00547 /*----------------------------------------------------------------------------*/
00548 void
00549 uves_extract_profile_set(const uves_extract_profile *p, 
00550                          uves_iterate_position *pos,
00551                          int *warnings)
00552 {
00553     if (p->constant) {
00554         ((uves_extract_profile *)p)->current_area = pos->yhigh - pos->ylow + 1;
00555     }
00556     else if (p->f != NULL)
00557         /* Zero */
00558         {
00559             double min_sigma = 0.1;
00560 
00561             /* const cast: The profile itself doesn't change */
00562 #if ORDER_PER_ORDER
00563             check( ((uves_extract_profile *)p)->current_y0 = 
00564                    pos->ycenter + uves_polynomial_evaluate_1d(p->y0[pos->order-pos->minorder],
00565                                   pos->x),
00566                    "Error evaluating polynomial");
00567 #else
00568             check( ((uves_extract_profile *)p)->current_y0 = 
00569                    pos->ycenter + uves_polynomial_evaluate_2d(p->y0, pos->x, pos->order),
00570                    "Error evaluating polynomial");
00571 #endif
00572             
00573 #if ORDER_PER_ORDER
00574             check( ((uves_extract_profile *)p)->current_sigma =
00575                    uves_polynomial_evaluate_1d(p->sigma[pos->order-pos->minorder], pos->x),
00576                    "Error evaluating polynomial");
00577 #else
00578             check( ((uves_extract_profile *)p)->current_sigma =
00579                    uves_polynomial_evaluate_2d(p->sigma, pos->x, pos->order),
00580                    "Error evaluating polynomial");
00581 #endif
00582             
00583             /* Make sure that the inferred 
00584              * sigma is always 0.1 pixel or more. 
00585              * Smaller values are unrealistic (undersampled profile) and cause
00586              * numerical problems (~zero profile area), anyway.
00587              */
00588             
00589             if (p->current_sigma < min_sigma)
00590                 {
00591                     /* Print only 1 warning per order */
00592                     if (warnings != NULL && *warnings == 0)
00593                         {
00594                             (*warnings)++;
00595                             uves_msg_warning("Inferred spatial profile width (one sigma) is only "
00596                                              "%e pixels at (order, x) = (%d, %d). "
00597                                              "Setting sigma = %.2f pixels",
00598                                              p->current_sigma, pos->order, pos->x, min_sigma);
00599                         }
00600                     
00601                     ((uves_extract_profile *)p)->current_sigma = min_sigma;
00602                 }
00603 
00604             /* If the profile is well sampled, the 'area' calculated
00605                below would be 1, but for undersampled profiles (sigma
00606            much less than 1 pixel) the
00607                result might differ substantially. Therefore, compute
00608                the actual sum, and use the correction factor
00609                later in uves_extract_profile_evaluate().
00610 
00611                The empirical area depends critically upon
00612                the fractional part of y, so we must do it for every bin.
00613             */
00614             {
00615                 double area = 0;
00616                 
00617                 ((uves_extract_profile *)p)->current_area = 1;
00618                 
00619                 area = 0;
00620                 for (pos->y = pos->ylow; pos->y <= pos->yhigh; pos->y++)
00621                     {
00622             /* For analytical profiles the results of
00623                uves_extract_profile_evaluate()
00624                may range from 1e-300 to ~1
00625 
00626                Such a large range (300 orders of magnitude) is a
00627                source of problems in the weighted extraction of flat-fields,
00628                where the resulting flux may end up being only ~1e-300,
00629                which is "unphysical" and causes infinities after division.
00630 
00631                To always stay on the middle of the road, one might
00632                decide to approximate small values of the profile to zero,
00633                for example all values less than 1e-10
00634 
00635                And this would be the place to do it:
00636             */
00637                         area += uves_extract_profile_evaluate(p, pos);
00638                     }
00639 
00640                 /* This will not work:    if (area > 0)  
00641                    If area is very close to zero, we can still get inf.
00642                    when computing 1/current_area.
00643 
00644                    Therefore set the limit to something  much larger than machine
00645                    precision, and much less than 1.
00646                 */
00647                 if (area > 1e-10)
00648                     {
00649                         ((uves_extract_profile *)p)->current_area = area;
00650                     }
00651                 else
00652                     /* Well... the profile must be zero everywhere.
00653                        To avoid dividing by zero, set the area to something else */
00654                     {
00655                         ((uves_extract_profile *)p)->current_area = 1;
00656                     }
00657             }
00658         }
00659     else
00660         /* Virtual */
00661         {
00662             int i;
00663             double sum = 0;
00664 
00665             for (i = 0; i < p->spatial_bins; i++)
00666                 {
00667                     double prof;
00668                     if (p->is_zero_degree[i])
00669                         {
00670                             prof = uves_max_double(0, p->dy_double[i]);
00671                         }
00672                     else
00673                         {
00674                             /* This is slow */
00675                             prof = uves_max_double(
00676                                 0, uves_polynomial_evaluate_2d(p->dy_poly[i], 
00677                                                                pos->x, 
00678                                                                pos->order));
00679                         }
00680                     
00681                     p->current_ypos[i] = uves_extract_profile_get_y(pos, i, p->sampling_factor);
00682                     p->current_profile[i] = prof;
00683                     sum += prof;
00684                 }
00685 
00686             /* Interpolate profile at the positions needed, enforce normalization */
00687             i = 0;
00688             sum = 0;
00689             for (pos->y = pos->ylow; pos->y <= pos->yhigh; pos->y++) 
00690                 {
00691                     double pint; /* interpolated value */
00692                     if (false) 
00693                         /* Nearest bin interpolation (steps, for testing purposes only): */
00694                         {
00695                             double bin = uves_extract_profile_get_bin(pos, p->sampling_factor);
00696                             pint = p->current_profile[uves_round_double(bin)];
00697                         }
00698                     else if (true)
00699                         /* Linear interpolation */
00700                         /* Interpolate linearly, flux-conserving between two nearest bins 
00701                          *
00702                          *   |-----|--|
00703                          *   bl    b  bu
00704                          *
00705                          *  (bl = bin_lower (integer),
00706                          *   bu = bin_upper (integer), 
00707                          *   b  = bin       (floating))
00708                          *
00709                          *  interpolated = (bu-b)*prof(bl) + (b-bl)*prof(bu)
00710                          */
00711                         {
00712                             double bin = uves_extract_profile_get_bin(pos, 
00713                                                      p->sampling_factor);
00714                             
00715                             int bin_lower = (int) bin;
00716                             int bin_upper = bin_lower + 1;
00717                             
00718                             double prof_lower = p->current_profile[bin_lower];
00719                             double prof_upper = p->current_profile[bin_upper];
00720                             
00721                             double weight = bin_upper - bin;
00722                             
00723                             pint = weight*prof_lower + (1-weight)*prof_upper;
00724                         }
00725                     else
00726                         {
00727                             pint = uves_spline_hermite(
00728                                 pos->y,                         /* Where to interpolate */
00729                                 p->current_ypos, p->current_profile, /* Function */
00730                                 p->spatial_bins,
00731                                 &i);
00732                         }
00733                     
00734                     p->current_interpolated[pos->y - pos->ylow] = pint;
00735                     sum += pint;
00736                 }
00737 
00738             if ( !(sum > 0) )
00739                 {
00740                     /* In the exceptional case when sum == 0, 
00741                        do linear extraction */
00742                     sum = 1;
00743                 }
00744 
00745             for (pos->y = pos->ylow; pos->y <= pos->yhigh; pos->y++)
00746                 {
00747                     p->current_interpolated[pos->y - pos->ylow] /= sum;
00748                 }
00749         }
00750             
00751   cleanup:
00752     return;
00753 }
00754 
00755 /*----------------------------------------------------------------------------*/
00767 /*----------------------------------------------------------------------------*/
00768 double
00769 uves_extract_profile_evaluate(const uves_extract_profile *profile,
00770                               const uves_iterate_position *pos)
00771 {
00772     double result;
00773 
00774     if (profile->constant) {
00775         result = 1.0 / profile->current_area;
00776     }
00777     else if (profile->f != NULL)
00778         {
00779             double a[5];
00780             
00781             a[0] = profile->current_y0;
00782             a[1] = profile->current_sigma;
00783             a[2] = 1/profile->current_area; /* This is to get a sum of 1
00784                                                when the profile is summed over
00785                                                all bins. */
00786             a[3] = 0.0;                     /* Sky offset             */
00787             a[4] = 0.0;                     /* Sky offset linear term */
00788             
00789             {
00790                 /* Don't use gauss-legendre 3-point. It increases execution time,
00791                    and makes only extremely small (insignificant) difference on output.
00792                    
00793                    Also, the profile was measured using an unbinned analytical profile,
00794                    so such interpolation probably does not even make sense.
00795                 */
00796                 if (0)
00797                     {
00798                         double xp[3]     = {-0.387298334621, 0, 0.387298334621};
00799                         double weight[3] = {0.2777777777778, 0.444444444444, 0.2777777777778};
00800                         int i;
00801                         
00802                         result = 0;
00803                         for (i = 0; i < 3; i++)
00804                             {
00805                                 double val;
00806                                 double y = pos->y;
00807                                 
00808                                 a[0] = profile->current_y0 + xp[i];
00809                                 profile->f(&y, a, &val);
00810                                 result += weight[i] * val;
00811                             }
00812                     }
00813                 else
00814                     {
00815                         double y = pos->y;
00816                         
00817                         a[0] = profile->current_y0;
00818                         profile->f(&y, a, &result);
00819                     }
00820             }
00821         }
00822     else
00823         /* Virtual */
00824         {
00825             result = profile->current_interpolated[pos->y - pos->ylow];
00826         }
00827 
00828     return result;
00829 }
00830 

Generated on Fri Apr 18 14:11:42 2008 for UVES Pipeline Reference Manual by  doxygen 1.5.1