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-4_9_1 $ 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