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 #ifdef HAVE_CONFIG_H
00153 # include <config.h>
00154 #endif
00155 # include <assert.h>
00156
00163
00164
00167 #include <uves_utils_cpl.h>
00168
00169 #include <uves_utils.h>
00170 #include <uves_utils_wrappers.h>
00171 #include <uves_dump.h>
00172 #include <uves_error.h>
00173
00174 #include <cpl.h>
00175 #include <stdbool.h>
00176 #include <string.h>
00177
00178 static cpl_image *filter_median(const cpl_image *image, int radx, int rady,
00179 bool extrapolate_border);
00180
00181
00182
00194
00195 const cpl_property *
00196 uves_find_property_const(const uves_propertylist *plist, const char *name,
00197 int number)
00198 {
00199 int i = 0;
00200 int size = uves_propertylist_get_size(plist);
00201
00202 assure( number >= 0, CPL_ERROR_ILLEGAL_INPUT, "Number (%d) must be non-negative",
00203 number);
00204
00205 for (i = 0; i < size; i++)
00206 {
00207 const cpl_property *p = uves_propertylist_get_const(plist, i);
00208
00209 if (strcmp(cpl_property_get_name(p), name) == 0)
00210 {
00211 if (number == 0)
00212 {
00213 return p;
00214 }
00215 else
00216
00217 {
00218 number--;
00219 }
00220 }
00221 }
00222
00223 cleanup:
00224 return NULL;
00225 }
00226 cpl_property *
00227 uves_find_property(uves_propertylist *plist, const char *name,
00228 int number)
00229 {
00230 return (cpl_property *) uves_find_property_const(plist, name, number);
00231 }
00232
00233
00245
00246 cpl_error_code
00247 uves_filter_image_average(cpl_image *image, int radius_x, int radius_y)
00248 {
00249 cpl_image *aux = NULL;
00250 double *image_data = NULL;
00251 double *aux_data = NULL;
00252 int nx, ny;
00253 int i;
00254
00255
00256
00257 assure( image != NULL, CPL_ERROR_NULL_INPUT, "Null image");
00258 assure( radius_x >= 0, CPL_ERROR_ILLEGAL_INPUT, "Negative x-radius (%d)", radius_x);
00259 assure( radius_y >= 0, CPL_ERROR_ILLEGAL_INPUT, "Negative y-radius (%d)", radius_y);
00260 assure( cpl_image_get_type(image) == CPL_TYPE_DOUBLE, CPL_ERROR_TYPE_MISMATCH,
00261 "Type is %s. double expected", uves_tostring_cpl_type(cpl_image_get_type(image)));
00262
00263 nx = cpl_image_get_size_x(image);
00264 ny = cpl_image_get_size_y(image);
00265 image_data = cpl_image_get_data_double(image);
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278 aux = cpl_image_new(nx+1, ny+1, CPL_TYPE_DOUBLE);
00279 aux_data = cpl_image_get_data(aux);
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289 for (i = 0; i < (nx+1)*(ny+1); i++)
00290 {
00291 int x = i % (nx+1);
00292 int y = i / (nx+1);
00293
00294 if ( x >= 1 && y >= 1)
00295 {
00296 aux_data[x + y*(nx+1)] = image_data[x-1 + (y-1) * nx]
00297 + aux_data [x-1 + y * (nx+1)]
00298 + aux_data [x + (y-1)* (nx+1)]
00299 - aux_data [x-1 + (y-1)* (nx+1)];
00300 }
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320 }
00321
00322 uves_msg_debug("Finished setting up auxillary image. Get average");
00323
00324
00325 for (i = 0; i < nx*ny; i++)
00326 {
00327 int x = (i % nx);
00328 int y = (i / nx);
00329
00330 int lower, upper;
00331 int left, right;
00332
00333 lower = y - radius_y; if (lower < 0) lower = 0;
00334 upper = y + radius_y; if (upper >= ny) upper = ny - 1;
00335
00336 left = x - radius_x; if (left < 0) left = 0;
00337 right = x + radius_x; if (right >= nx) right = nx - 1;
00338
00339 image_data[x + y*nx] =
00340 (
00341 aux_data[(right+1) + (upper+1)*(nx+1)] +
00342 aux_data[ left + lower *(nx+1)] -
00343 aux_data[ left + (upper+1)*(nx+1)] -
00344 aux_data[(right+1) + lower *(nx+1)]
00345 )
00346 /
00347 ( (double) (upper-lower+1) * (right-left+1) );
00348 }
00349
00350 cleanup:
00351 uves_free_image(&aux);
00352 return cpl_error_get_code();
00353 }
00354
00355
00356
00370
00371 cpl_error_code
00372 uves_filter_image_median(cpl_image **image, int xwindow, int ywindow, bool extrapolate_border)
00373 {
00374 cpl_matrix *id = NULL;
00375 cpl_image *temp = NULL;
00376
00377 assure( xwindow >= 0 && ywindow >= 0, CPL_ERROR_ILLEGAL_INPUT,
00378 "Illegal window radius: %d x %d",
00379 (2*xwindow + 1),
00380 (2*ywindow + 1));
00381
00382 UVES_TIME_START("median filter");
00383
00384 if (xwindow <= 1 && ywindow <= 1)
00385
00386 {
00387 check(( id = cpl_matrix_new(2*xwindow+1, 2*ywindow+1),
00388 cpl_matrix_fill(id, 1)), "Could not create kernel matrix");
00389
00390
00391 if (cpl_image_get_type(*image) == CPL_TYPE_INT)
00392 {
00393 temp = cpl_image_cast(*image, CPL_TYPE_DOUBLE);
00394 uves_free_image(image);
00395 }
00396 else
00397 {
00398 temp = *image;
00399 }
00400 check( *image = uves_image_filter_median(temp, id), "Error applying median filter");
00401
00402
00403
00404 }
00405 else
00406 {
00407 temp = *image;
00408 check( *image = filter_median(temp, xwindow, ywindow, extrapolate_border),
00409 "Error applying median filter");
00410 uves_free_image(&temp);
00411 }
00412
00413 UVES_TIME_END;
00414
00415 cleanup:
00416 uves_free_matrix(&id);
00417 uves_free_image(&temp);
00418 return cpl_error_get_code();
00419 }
00420
00422 #define DOUBLE_SWAP(a,b) { register double t=(a);(a)=(b);(b)=t; }
00423
00434 double uves_utils_get_kth_double(
00435 double * a,
00436 int n,
00437 int k)
00438 {
00439 register double x ;
00440 register int i, j, l, m ;
00441
00442 l=0 ; m=n-1 ;
00443 while (l<m) {
00444 x=a[k] ;
00445 i=l ;
00446 j=m ;
00447 do {
00448 while (a[i]<x) i++ ;
00449 while (x<a[j]) j-- ;
00450 if (i<=j) {
00451 DOUBLE_SWAP(a[i],a[j]) ;
00452 i++ ; j-- ;
00453 }
00454 } while (i<=j) ;
00455 if (j<k) l=i ;
00456 if (k<i) m=j ;
00457 }
00458 return a[k] ;
00459 }
00460
00469 double
00470 uves_tools_get_median(double *a, int n)
00471 {
00472 if (n % 2 == 0)
00473 {
00474 return
00475 (uves_utils_get_kth_double(a, n, n/2) +
00476 uves_utils_get_kth_double(a, n, n/2-1))/2.0;
00477
00478 }
00479 else
00480 {
00481 return uves_utils_get_kth_double(a, n, (n-1)/2);
00482 }
00483 }
00484
00485
00486
00487
00509
00510 static cpl_image *
00511 filter_median(const cpl_image *image, int radx, int rady, bool extrapolate_border)
00512 {
00513 int x, y;
00514 int nx = cpl_image_get_size_x(image);
00515 int ny = cpl_image_get_size_y(image);
00516 cpl_image *result = cpl_image_new(nx, ny, CPL_TYPE_DOUBLE);
00517 double *result_data;
00518 const double *image_data;
00519 double *window = NULL;
00520
00521 window = cpl_malloc(sizeof(double) * (2*radx+1)*(2*rady+1));
00522 assure_mem( result );
00523 assure( cpl_image_get_type(image) == CPL_TYPE_DOUBLE,
00524 CPL_ERROR_UNSUPPORTED_MODE, "Type is %s",
00525 uves_tostring_cpl_type(cpl_image_get_type(image)));
00526
00527 result_data = cpl_image_get_data_double(result);
00528 image_data = cpl_image_get_data_double_const(image);
00529
00530 for (y = 1; y <= ny; y++)
00531 {
00532 for (x = 1; x <= nx; x++)
00533 {
00534 int x1, y_1, x2, y2;
00535
00536 x1 = x - radx; y_1 = y - rady;
00537 x2 = x + radx; y2 = y + rady;
00538
00539 if (extrapolate_border)
00540 {
00541
00542
00543 if (x1 < 1)
00544 {
00545 x2 += (1 - x1);
00546 x1 += (1 - x1);
00547 }
00548 if (nx < x2)
00549 {
00550 x1 -= (x2 - nx);
00551 x2 -= (x2 - nx);
00552 }
00553
00554 if (y_1 < 1)
00555 {
00556 y2 += (1 - y_1);
00557 y_1 += (1 - y_1);
00558 }
00559 if (ny < y2)
00560 {
00561 y_1 -= (y2 - ny);
00562 y2 -= (y2 - ny);
00563 }
00564 }
00565 else { }
00566
00567 #if 0
00568 result_data[(x-1) + (y-1)*nx] =
00569 cpl_image_get_median_window(image,
00570 uves_max_int(1, x1),
00571 uves_max_int(1, y_1),
00572 uves_min_int(nx, x2),
00573 uves_min_int(ny, y2));
00574
00575 #else
00576
00577 {
00578 int i, j, k;
00579
00580 k = 0;
00581 for (j = uves_max_int(1 , y_1)-1;
00582 j <= uves_min_int(ny, y2 )-1;
00583 j++)
00584 for (i = uves_max_int(1, x1)-1;
00585 i <= uves_min_int(nx, x2)-1;
00586 i++)
00587 {
00588 window[k++] = image_data[i + j*nx];
00589 }
00590
00591 result_data[(x-1) + (y-1)*nx] =
00592 uves_utils_get_kth_double(window,k,(((k)&1)?((k)/2):(((k)/2)-1))) ;
00593 }
00594 #endif
00595 }
00596 }
00597
00598
00599 assure( cpl_error_get_code() == CPL_ERROR_NONE, cpl_error_get_code(),
00600 "Error calculating %dx%d median filter", radx, rady);
00601
00602 cleanup:
00603 cpl_free(window);
00604 return result;
00605 }
00606
00607
00608
00636
00637
00638 cpl_error_code
00639 uves_fit_gaussian_2d_image(const cpl_image *image, const cpl_image *noise,
00640 int x1, int y_1,
00641 int x2, int y2,
00642 double *x0, double *y_0, double *sigmax, double *sigmay,
00643 double *amplitude,
00644 double *dx0, double *dy0
00645 )
00646 {
00647 cpl_image *marginal_x = NULL;
00648 cpl_image *marginal_y = NULL;
00649 cpl_image *marginal_x_noise = NULL;
00650 cpl_image *marginal_y_noise = NULL;
00651 cpl_image *variance = NULL;
00652 cpl_matrix *covariance = NULL;
00653
00654 int nx, ny;
00655 double norm_x, norm_y;
00656 double background_x, background_y;
00657
00658
00659 assure( image != NULL, CPL_ERROR_NULL_INPUT, "Null image");
00660 nx = cpl_image_get_size_x(image);
00661 ny = cpl_image_get_size_y(image);
00662 assure( noise != NULL || (dx0 == NULL && dy0 == NULL), CPL_ERROR_INCOMPATIBLE_INPUT,
00663 "Cannot compute uncertainty of fit with no noise image specified");
00664 assure( noise == NULL ||
00665 (cpl_image_get_size_x(noise) == nx &&
00666 cpl_image_get_size_y(noise) == ny),
00667 CPL_ERROR_INCOMPATIBLE_INPUT,
00668 "Size of input image (%dx%d) and noise image (%" CPL_SIZE_FORMAT "x%" CPL_SIZE_FORMAT ") differ",
00669 nx, ny,
00670 cpl_image_get_size_x(noise),
00671 cpl_image_get_size_y(noise));
00672 assure( 1 <= x1 && x1 <= x2 && x2 <= nx &&
00673 1 <= y_1 && y_1 <= y2 && y2 <= ny, CPL_ERROR_ILLEGAL_INPUT,
00674 "Illegal window: (%d, %d)-(%d, %d)", x1, y_1, x2, y2);
00675 assure( x0 != NULL, CPL_ERROR_NULL_INPUT, "Null x-center");
00676 assure( y_0 != NULL, CPL_ERROR_NULL_INPUT, "Null y-center");
00677 assure( sigmax != NULL, CPL_ERROR_NULL_INPUT, "Null sigma_x");
00678 assure( sigmay != NULL, CPL_ERROR_NULL_INPUT, "Null sigma_y");
00679
00680
00681 if (noise != NULL)
00682 {
00683
00684 check(( variance = cpl_image_extract(noise, x1, y_1, x2, y2),
00685 cpl_image_power(variance, 2.0)),
00686 "Error creating variance image");
00687 }
00688
00689
00690 check( marginal_x = cpl_image_collapse_window_create(image,
00691 x1, y_1, x2, y2,
00692 0),
00693 "Error collapsing window (%d, %d) - (%d, %d)", x1, y_1, x2, y2);
00694
00695 if (noise != NULL)
00696 {
00697
00698
00699 check( marginal_x_noise = cpl_image_collapse_window_create(variance,
00700 1, 1,
00701 x2-x1+1, y2-y_1+1,
00702 0),
00703 "Error collapsing window (1, 1) - (%d, %d)", x2-x1+1, y2-y_1+1);
00704
00705
00706 cpl_image_power(marginal_x_noise, 0.5);
00707 }
00708
00709
00710 check( marginal_y = cpl_image_collapse_window_create(image,
00711 x1, y_1, x2, y2,
00712 1),
00713 "Error collapsing window (%d, %d) - (%d, %d)", x1, y_1, x2, y2);
00714
00715 if (noise != NULL)
00716 {
00717 check( marginal_y_noise = cpl_image_collapse_window_create(variance,
00718 1, 1,
00719 x2-x1+1, y2-y_1+1,
00720 1),
00721 "Error collapsing window (1, 1) - (%d, %d)", x2-x1+1, y2-y_1+1);
00722
00723
00724 cpl_image_power(marginal_y_noise, 0.5);
00725 }
00726
00727
00728 uves_fit_1d_image(marginal_x, marginal_x_noise, NULL,
00729 true,
00730 false, false,
00731 1, x2 - x1 + 1, 1,
00732 x0, sigmax, &norm_x, &background_x, NULL,
00733 NULL, NULL,
00734 (dx0 != NULL) ? &covariance : NULL,
00735 uves_gauss, uves_gauss_derivative, 4);
00736
00737
00738 assure( cpl_error_get_code() != CPL_ERROR_CONTINUE ||
00739 cpl_error_get_code() != CPL_ERROR_SINGULAR_MATRIX,
00740 CPL_ERROR_CONTINUE, "Fitting along x failed");
00741 assure( cpl_error_get_code() == CPL_ERROR_NONE, cpl_error_get_code(),
00742 "Fitting along x failed");
00743
00744
00745 *x0 += (x1 - 1);
00746
00747 if (dx0 != NULL)
00748 {
00749 *dx0 = cpl_matrix_get(covariance, 0, 0);
00750 }
00751
00752
00753
00754 uves_free_matrix(&covariance);
00755 uves_fit_1d_image(marginal_y, marginal_y_noise, NULL,
00756 false,
00757 false, false,
00758 1, y2 - y_1 + 1, 1,
00759 y_0, sigmay, &norm_y, &background_y, NULL,
00760 NULL, NULL,
00761 (dy0 != NULL) ? &covariance : NULL,
00762 uves_gauss, uves_gauss_derivative, 4);
00763
00764
00765 assure( cpl_error_get_code() != CPL_ERROR_CONTINUE ||
00766 cpl_error_get_code() != CPL_ERROR_SINGULAR_MATRIX,
00767 CPL_ERROR_CONTINUE, "Fitting along y failed");
00768 assure( cpl_error_get_code() == CPL_ERROR_NONE, cpl_error_get_code(),
00769 "Fitting along y failed");
00770
00771
00772 *y_0 += (y_1 - 1);
00773
00774 if (dy0 != NULL)
00775 {
00776 *dy0 = cpl_matrix_get(covariance, 0, 0);
00777 }
00778
00779
00780
00781
00782
00783
00784 if (amplitude != NULL)
00785 {
00786 *amplitude = sqrt(norm_x * norm_y) / (2*M_PI * (*sigmax) * (*sigmay));
00787 }
00788
00789 cleanup:
00790 uves_free_matrix(&covariance);
00791 uves_free_image(&variance);
00792 uves_free_image(&marginal_x);
00793 uves_free_image(&marginal_x_noise);
00794 uves_free_image(&marginal_y);
00795 uves_free_image(&marginal_y_noise);
00796
00797 return cpl_error_get_code();
00798 }
00799
00800