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
1.4.6