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
1.5.1