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

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