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

Generated on 9 Mar 2012 for UVES Pipeline Reference Manual by  doxygen 1.6.1