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