00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158 #ifdef HAVE_CONFIG_H
00159 # include <config.h>
00160 #endif
00161
00162
00169
00170
00173 #include <uves_utils_cpl.h>
00174
00175 #include <uves_utils.h>
00176 #include <uves_utils_wrappers.h>
00177 #include <uves_dump.h>
00178 #include <uves_error.h>
00179
00180 #include <cpl.h>
00181 #include <stdbool.h>
00182 #include <string.h>
00183
00184 static cpl_image *filter_median(const cpl_image *image, int radx, int rady,
00185 bool extrapolate_border);
00186
00187
00188
00200
00201 const cpl_property *
00202 uves_find_property_const(const uves_propertylist *plist, const char *name,
00203 int number)
00204 {
00205 int i = 0;
00206 int size = uves_propertylist_get_size(plist);
00207
00208 assure( number >= 0, CPL_ERROR_ILLEGAL_INPUT, "Number (%d) must be non-negative",
00209 number);
00210
00211 for (i = 0; i < size; i++)
00212 {
00213 const cpl_property *p = uves_propertylist_get_const(plist, i);
00214
00215 if (strcmp(cpl_property_get_name(p), name) == 0)
00216 {
00217 if (number == 0)
00218 {
00219 return p;
00220 }
00221 else
00222
00223 {
00224 number--;
00225 }
00226 }
00227 }
00228
00229 cleanup:
00230 return NULL;
00231 }
00232 cpl_property *
00233 uves_find_property(uves_propertylist *plist, const char *name,
00234 int number)
00235 {
00236 return (cpl_property *) uves_find_property_const(plist, name, number);
00237 }
00238
00239
00251
00252 cpl_error_code
00253 uves_filter_image_average(cpl_image *image, int radius_x, int radius_y)
00254 {
00255 cpl_image *aux = NULL;
00256 double *image_data = NULL;
00257 double *aux_data = NULL;
00258 int nx, ny;
00259 int i;
00260
00261
00262
00263 assure( image != NULL, CPL_ERROR_NULL_INPUT, "Null image");
00264 assure( radius_x >= 0, CPL_ERROR_ILLEGAL_INPUT, "Negative x-radius (%d)", radius_x);
00265 assure( radius_y >= 0, CPL_ERROR_ILLEGAL_INPUT, "Negative y-radius (%d)", radius_y);
00266 assure( cpl_image_get_type(image) == CPL_TYPE_DOUBLE, CPL_ERROR_TYPE_MISMATCH,
00267 "Type is %s. double expected", uves_tostring_cpl_type(cpl_image_get_type(image)));
00268
00269 nx = cpl_image_get_size_x(image);
00270 ny = cpl_image_get_size_y(image);
00271 image_data = cpl_image_get_data_double(image);
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284 aux = cpl_image_new(nx+1, ny+1, CPL_TYPE_DOUBLE);
00285 aux_data = cpl_image_get_data(aux);
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295 for (i = 0; i < (nx+1)*(ny+1); i++)
00296 {
00297 int x = i % (nx+1);
00298 int y = i / (nx+1);
00299
00300 if ( x >= 1 && y >= 1)
00301 {
00302 aux_data[x + y*(nx+1)] = image_data[x-1 + (y-1) * nx]
00303 + aux_data [x-1 + y * (nx+1)]
00304 + aux_data [x + (y-1)* (nx+1)]
00305 - aux_data [x-1 + (y-1)* (nx+1)];
00306 }
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326 }
00327
00328 uves_msg_debug("Finished setting up auxillary image. Get average");
00329
00330
00331 for (i = 0; i < nx*ny; i++)
00332 {
00333 int x = (i % nx);
00334 int y = (i / nx);
00335
00336 int lower, upper;
00337 int left, right;
00338
00339 lower = y - radius_y; if (lower < 0) lower = 0;
00340 upper = y + radius_y; if (upper >= ny) upper = ny - 1;
00341
00342 left = x - radius_x; if (left < 0) left = 0;
00343 right = x + radius_x; if (right >= nx) right = nx - 1;
00344
00345 image_data[x + y*nx] =
00346 (
00347 aux_data[(right+1) + (upper+1)*(nx+1)] +
00348 aux_data[ left + lower *(nx+1)] -
00349 aux_data[ left + (upper+1)*(nx+1)] -
00350 aux_data[(right+1) + lower *(nx+1)]
00351 )
00352 /
00353 ( (double) (upper-lower+1) * (right-left+1) );
00354 }
00355
00356 cleanup:
00357 uves_free_image(&aux);
00358 return cpl_error_get_code();
00359 }
00360
00361
00362
00376
00377 cpl_error_code
00378 uves_filter_image_median(cpl_image **image, int xwindow, int ywindow, bool extrapolate_border)
00379 {
00380 cpl_matrix *id = NULL;
00381 cpl_image *temp = NULL;
00382
00383 assure( xwindow >= 0 && ywindow >= 0, CPL_ERROR_ILLEGAL_INPUT,
00384 "Illegal window radius: %d x %d",
00385 (2*xwindow + 1),
00386 (2*ywindow + 1));
00387
00388 UVES_TIME_START("median filter");
00389
00390 if (xwindow <= 1 && ywindow <= 1)
00391
00392 {
00393 check(( id = cpl_matrix_new(2*xwindow+1, 2*ywindow+1),
00394 cpl_matrix_fill(id, 1)), "Could not create kernel matrix");
00395
00396
00397 if (cpl_image_get_type(*image) == CPL_TYPE_INT)
00398 {
00399 temp = cpl_image_cast(*image, CPL_TYPE_DOUBLE);
00400 uves_free_image(image);
00401 }
00402 else
00403 {
00404 temp = cpl_image_duplicate(*image);
00405 uves_free_image(image);
00406 }
00407 check( *image = uves_image_filter_median(temp, id), "Error applying median filter");
00408 uves_free_image(&temp);
00409
00410
00411
00412 }
00413 else
00414 {
00415 temp = *image;
00416 check( *image = filter_median(temp, xwindow, ywindow, extrapolate_border),
00417 "Error applying median filter");
00418 uves_free_image(&temp);
00419 }
00420
00421 UVES_TIME_END;
00422
00423 cleanup:
00424 uves_free_matrix(&id);
00425 uves_free_image(&temp);
00426 return cpl_error_get_code();
00427 }
00428
00430 #define DOUBLE_SWAP(a,b) { register double t=(a);(a)=(b);(b)=t; }
00431
00442 double uves_utils_get_kth_double(
00443 double * a,
00444 int n,
00445 int k)
00446 {
00447 register double x ;
00448 register int i, j, l, m ;
00449
00450 l=0 ; m=n-1 ;
00451 while (l<m) {
00452 x=a[k] ;
00453 i=l ;
00454 j=m ;
00455 do {
00456 while (a[i]<x) i++ ;
00457 while (x<a[j]) j-- ;
00458 if (i<=j) {
00459 DOUBLE_SWAP(a[i],a[j]) ;
00460 i++ ; j-- ;
00461 }
00462 } while (i<=j) ;
00463 if (j<k) l=i ;
00464 if (k<i) m=j ;
00465 }
00466 return a[k] ;
00467 }
00468
00477 double
00478 uves_tools_get_median(double *a, int n)
00479 {
00480 if (n % 2 == 0)
00481 {
00482 return
00483 (uves_utils_get_kth_double(a, n, n/2) +
00484 uves_utils_get_kth_double(a, n, n/2-1))/2.0;
00485
00486 }
00487 else
00488 {
00489 return uves_utils_get_kth_double(a, n, (n-1)/2);
00490 }
00491 }
00492
00493
00494
00495
00517
00518 static cpl_image *
00519 filter_median(const cpl_image *image, int radx, int rady, bool extrapolate_border)
00520 {
00521 int x, y;
00522 int nx = cpl_image_get_size_x(image);
00523 int ny = cpl_image_get_size_y(image);
00524 cpl_image *result = cpl_image_new(nx, ny, CPL_TYPE_DOUBLE);
00525 double *result_data;
00526 const double *image_data;
00527 double *window = NULL;
00528
00529 window = cpl_malloc(sizeof(double) * (2*radx+1)*(2*rady+1));
00530 assure_mem( result );
00531 assure( cpl_image_get_type(image) == CPL_TYPE_DOUBLE,
00532 CPL_ERROR_UNSUPPORTED_MODE, "Type is %s",
00533 uves_tostring_cpl_type(cpl_image_get_type(image)));
00534
00535 result_data = cpl_image_get_data_double(result);
00536 image_data = cpl_image_get_data_double_const(image);
00537
00538 for (y = 1; y <= ny; y++)
00539 {
00540 for (x = 1; x <= nx; x++)
00541 {
00542 int x1, y_1, x2, y2;
00543
00544 x1 = x - radx; y_1 = y - rady;
00545 x2 = x + radx; y2 = y + rady;
00546
00547 if (extrapolate_border)
00548 {
00549
00550
00551 if (x1 < 1)
00552 {
00553 x2 += (1 - x1);
00554 x1 += (1 - x1);
00555 }
00556 if (nx < x2)
00557 {
00558 x1 -= (x2 - nx);
00559 x2 -= (x2 - nx);
00560 }
00561
00562 if (y_1 < 1)
00563 {
00564 y2 += (1 - y_1);
00565 y_1 += (1 - y_1);
00566 }
00567 if (ny < y2)
00568 {
00569 y_1 -= (y2 - ny);
00570 y2 -= (y2 - ny);
00571 }
00572 }
00573 else { }
00574
00575 #if 0
00576 result_data[(x-1) + (y-1)*nx] =
00577 cpl_image_get_median_window(image,
00578 uves_max_int(1, x1),
00579 uves_max_int(1, y_1),
00580 uves_min_int(nx, x2),
00581 uves_min_int(ny, y2));
00582
00583 #else
00584
00585 {
00586 int i, j, k;
00587
00588 k = 0;
00589 for (j = uves_max_int(1 , y_1)-1;
00590 j <= uves_min_int(ny, y2 )-1;
00591 j++)
00592 for (i = uves_max_int(1, x1)-1;
00593 i <= uves_min_int(nx, x2)-1;
00594 i++)
00595 {
00596 window[k++] = image_data[i + j*nx];
00597 }
00598
00599 result_data[(x-1) + (y-1)*nx] =
00600 uves_utils_get_kth_double(window,k,(((k)&1)?((k)/2):(((k)/2)-1))) ;
00601 }
00602 #endif
00603 }
00604 }
00605
00606
00607 assure( cpl_error_get_code() == CPL_ERROR_NONE, cpl_error_get_code(),
00608 "Error calculating %dx%d median filter", radx, rady);
00609
00610 cleanup:
00611 cpl_free(window);
00612 return result;
00613 }
00614
00615
00616
00644
00645
00646 cpl_error_code
00647 uves_fit_gaussian_2d_image(const cpl_image *image, const cpl_image *noise,
00648 int x1, int y_1,
00649 int x2, int y2,
00650 double *x0, double *y_0, double *sigmax, double *sigmay,
00651 double *amplitude,
00652 double *dx0, double *dy0
00653 )
00654 {
00655 cpl_image *marginal_x = NULL;
00656 cpl_image *marginal_y = NULL;
00657 cpl_image *marginal_x_noise = NULL;
00658 cpl_image *marginal_y_noise = NULL;
00659 cpl_image *variance = NULL;
00660 cpl_matrix *covariance = NULL;
00661
00662 int nx, ny;
00663 double norm_x, norm_y;
00664 double background_x, background_y;
00665
00666
00667 assure( image != NULL, CPL_ERROR_NULL_INPUT, "Null image");
00668 nx = cpl_image_get_size_x(image);
00669 ny = cpl_image_get_size_y(image);
00670 assure( noise != NULL || (dx0 == NULL && dy0 == NULL), CPL_ERROR_INCOMPATIBLE_INPUT,
00671 "Cannot compute uncertainty of fit with no noise image specified");
00672 assure( noise == NULL ||
00673 (cpl_image_get_size_x(noise) == nx &&
00674 cpl_image_get_size_y(noise) == ny),
00675 CPL_ERROR_INCOMPATIBLE_INPUT,
00676 "Size of input image (%dx%d) and noise image (%" CPL_SIZE_FORMAT "x%" CPL_SIZE_FORMAT ") differ",
00677 nx, ny,
00678 cpl_image_get_size_x(noise),
00679 cpl_image_get_size_y(noise));
00680 assure( 1 <= x1 && x1 <= x2 && x2 <= nx &&
00681 1 <= y_1 && y_1 <= y2 && y2 <= ny, CPL_ERROR_ILLEGAL_INPUT,
00682 "Illegal window: (%d, %d)-(%d, %d)", x1, y_1, x2, y2);
00683 assure( x0 != NULL, CPL_ERROR_NULL_INPUT, "Null x-center");
00684 assure( y_0 != NULL, CPL_ERROR_NULL_INPUT, "Null y-center");
00685 assure( sigmax != NULL, CPL_ERROR_NULL_INPUT, "Null sigma_x");
00686 assure( sigmay != NULL, CPL_ERROR_NULL_INPUT, "Null sigma_y");
00687
00688
00689 if (noise != NULL)
00690 {
00691
00692 check(( variance = cpl_image_extract(noise, x1, y_1, x2, y2),
00693 cpl_image_power(variance, 2.0)),
00694 "Error creating variance image");
00695 }
00696
00697
00698 check( marginal_x = cpl_image_collapse_window_create(image,
00699 x1, y_1, x2, y2,
00700 0),
00701 "Error collapsing window (%d, %d) - (%d, %d)", x1, y_1, x2, y2);
00702
00703 if (noise != NULL)
00704 {
00705
00706
00707 check( marginal_x_noise = cpl_image_collapse_window_create(variance,
00708 1, 1,
00709 x2-x1+1, y2-y_1+1,
00710 0),
00711 "Error collapsing window (1, 1) - (%d, %d)", x2-x1+1, y2-y_1+1);
00712
00713
00714 cpl_image_power(marginal_x_noise, 0.5);
00715 }
00716
00717
00718 check( marginal_y = cpl_image_collapse_window_create(image,
00719 x1, y_1, x2, y2,
00720 1),
00721 "Error collapsing window (%d, %d) - (%d, %d)", x1, y_1, x2, y2);
00722
00723 if (noise != NULL)
00724 {
00725 check( marginal_y_noise = cpl_image_collapse_window_create(variance,
00726 1, 1,
00727 x2-x1+1, y2-y_1+1,
00728 1),
00729 "Error collapsing window (1, 1) - (%d, %d)", x2-x1+1, y2-y_1+1);
00730
00731
00732 cpl_image_power(marginal_y_noise, 0.5);
00733 }
00734
00735
00736 uves_fit_1d_image(marginal_x, marginal_x_noise, NULL,
00737 true,
00738 false, false,
00739 1, x2 - x1 + 1, 1,
00740 x0, sigmax, &norm_x, &background_x, NULL,
00741 NULL, NULL,
00742 (dx0 != NULL) ? &covariance : NULL,
00743 uves_gauss, uves_gauss_derivative, 4);
00744
00745
00746 assure( cpl_error_get_code() != CPL_ERROR_CONTINUE ||
00747 cpl_error_get_code() != CPL_ERROR_SINGULAR_MATRIX,
00748 CPL_ERROR_CONTINUE, "Fitting along x failed");
00749 assure( cpl_error_get_code() == CPL_ERROR_NONE, cpl_error_get_code(),
00750 "Fitting along x failed");
00751
00752
00753 *x0 += (x1 - 1);
00754
00755 if (dx0 != NULL)
00756 {
00757 *dx0 = cpl_matrix_get(covariance, 0, 0);
00758 }
00759
00760
00761
00762 uves_free_matrix(&covariance);
00763 uves_fit_1d_image(marginal_y, marginal_y_noise, NULL,
00764 false,
00765 false, false,
00766 1, y2 - y_1 + 1, 1,
00767 y_0, sigmay, &norm_y, &background_y, NULL,
00768 NULL, NULL,
00769 (dy0 != NULL) ? &covariance : NULL,
00770 uves_gauss, uves_gauss_derivative, 4);
00771
00772
00773 assure( cpl_error_get_code() != CPL_ERROR_CONTINUE ||
00774 cpl_error_get_code() != CPL_ERROR_SINGULAR_MATRIX,
00775 CPL_ERROR_CONTINUE, "Fitting along y failed");
00776 assure( cpl_error_get_code() == CPL_ERROR_NONE, cpl_error_get_code(),
00777 "Fitting along y failed");
00778
00779
00780 *y_0 += (y_1 - 1);
00781
00782 if (dy0 != NULL)
00783 {
00784 *dy0 = cpl_matrix_get(covariance, 0, 0);
00785 }
00786
00787
00788
00789
00790
00791
00792 if (amplitude != NULL)
00793 {
00794 *amplitude = sqrt(norm_x * norm_y) / (2*M_PI * (*sigmax) * (*sigmay));
00795 }
00796
00797 cleanup:
00798 uves_free_matrix(&covariance);
00799 uves_free_image(&variance);
00800 uves_free_image(&marginal_x);
00801 uves_free_image(&marginal_x_noise);
00802 uves_free_image(&marginal_y);
00803 uves_free_image(&marginal_y_noise);
00804
00805 return cpl_error_get_code();
00806 }
00807
00808