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