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 #ifdef HAVE_CONFIG_H
00135 # include <config.h>
00136 #endif
00137 # include <assert.h>
00138
00145
00146
00149 #include <uves_utils_cpl.h>
00150
00151 #include <uves_utils.h>
00152 #include <uves_utils_wrappers.h>
00153 #include <uves_dump.h>
00154 #include <uves_error.h>
00155
00156 #include <cpl.h>
00157 #include <stdbool.h>
00158
00159 static cpl_image *filter_median(const cpl_image *image, int radx, int rady,
00160 bool extrapolate_border);
00161
00162
00163
00175
00176 const cpl_property *
00177 uves_find_property_const(const uves_propertylist *plist, const char *name,
00178 int number)
00179 {
00180 int i = 0;
00181 int size = uves_propertylist_get_size(plist);
00182
00183 assure( number >= 0, CPL_ERROR_ILLEGAL_INPUT, "Number (%d) must be non-negative",
00184 number);
00185
00186 for (i = 0; i < size; i++)
00187 {
00188 const cpl_property *p = uves_propertylist_get_const(plist, i);
00189
00190 if (strcmp(cpl_property_get_name(p), name) == 0)
00191 {
00192 if (number == 0)
00193 {
00194 return p;
00195 }
00196 else
00197
00198 {
00199 number--;
00200 }
00201 }
00202 }
00203
00204 cleanup:
00205 return NULL;
00206 }
00207 cpl_property *
00208 uves_find_property(uves_propertylist *plist, const char *name,
00209 int number)
00210 {
00211 return (cpl_property *) uves_find_property_const(plist, name, number);
00212 }
00213
00214
00226
00227 cpl_error_code
00228 uves_filter_image_average(cpl_image *image, int radius_x, int radius_y)
00229 {
00230 cpl_image *aux = NULL;
00231 double *image_data = NULL;
00232 double *aux_data = NULL;
00233 int nx, ny;
00234 int i;
00235
00236
00237
00238 assure( image != NULL, CPL_ERROR_NULL_INPUT, "Null image");
00239 assure( radius_x >= 0, CPL_ERROR_ILLEGAL_INPUT, "Negative x-radius (%d)", radius_x);
00240 assure( radius_y >= 0, CPL_ERROR_ILLEGAL_INPUT, "Negative y-radius (%d)", radius_y);
00241 assure( cpl_image_get_type(image) == CPL_TYPE_DOUBLE, CPL_ERROR_TYPE_MISMATCH,
00242 "Type is %s. double expected", uves_tostring_cpl_type(cpl_image_get_type(image)));
00243
00244 nx = cpl_image_get_size_x(image);
00245 ny = cpl_image_get_size_y(image);
00246 image_data = cpl_image_get_data_double(image);
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259 aux = cpl_image_new(nx+1, ny+1, CPL_TYPE_DOUBLE);
00260 aux_data = cpl_image_get_data(aux);
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270 for (i = 0; i < (nx+1)*(ny+1); i++)
00271 {
00272 int x = i % (nx+1);
00273 int y = i / (nx+1);
00274
00275 if ( x >= 1 && y >= 1)
00276 {
00277 aux_data[x + y*(nx+1)] = image_data[x-1 + (y-1) * nx]
00278 + aux_data [x-1 + y * (nx+1)]
00279 + aux_data [x + (y-1)* (nx+1)]
00280 - aux_data [x-1 + (y-1)* (nx+1)];
00281 }
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301 }
00302
00303 uves_msg_debug("Finished setting up auxillary image. Get average");
00304
00305
00306 for (i = 0; i < nx*ny; i++)
00307 {
00308 int x = (i % nx);
00309 int y = (i / nx);
00310
00311 int lower, upper;
00312 int left, right;
00313
00314 lower = y - radius_y; if (lower < 0) lower = 0;
00315 upper = y + radius_y; if (upper >= ny) upper = ny - 1;
00316
00317 left = x - radius_x; if (left < 0) left = 0;
00318 right = x + radius_x; if (right >= nx) right = nx - 1;
00319
00320 image_data[x + y*nx] =
00321 (
00322 aux_data[(right+1) + (upper+1)*(nx+1)] +
00323 aux_data[ left + lower *(nx+1)] -
00324 aux_data[ left + (upper+1)*(nx+1)] -
00325 aux_data[(right+1) + lower *(nx+1)]
00326 )
00327 /
00328 ( (double) (upper-lower+1) * (right-left+1) );
00329 }
00330
00331 cleanup:
00332 uves_free_image(&aux);
00333 return cpl_error_get_code();
00334 }
00335
00336
00337
00351
00352 cpl_error_code
00353 uves_filter_image_median(cpl_image **image, int xwindow, int ywindow, bool extrapolate_border)
00354 {
00355 cpl_matrix *id = NULL;
00356 cpl_image *temp = NULL;
00357
00358 assure( xwindow >= 0 && ywindow >= 0, CPL_ERROR_ILLEGAL_INPUT,
00359 "Illegal window radius: %d x %d",
00360 (2*xwindow + 1),
00361 (2*ywindow + 1));
00362
00363 UVES_TIME_START("median filter");
00364
00365 if (xwindow <= 1 && ywindow <= 1)
00366
00367 {
00368 check(( id = cpl_matrix_new(2*xwindow+1, 2*ywindow+1),
00369 cpl_matrix_fill(id, 1)), "Could not create kernel matrix");
00370
00371
00372 if (cpl_image_get_type(*image) == CPL_TYPE_INT)
00373 {
00374 temp = cpl_image_cast(*image, CPL_TYPE_DOUBLE);
00375 uves_free_image(image);
00376 }
00377 else
00378 {
00379 temp = *image;
00380 }
00381 check( *image = cpl_image_filter_median(temp, id), "Error applying median filter");
00382
00383
00384
00385 }
00386 else
00387 {
00388 temp = *image;
00389 check( *image = filter_median(temp, xwindow, ywindow, extrapolate_border),
00390 "Error applying median filter");
00391 uves_free_image(&temp);
00392 }
00393
00394 UVES_TIME_END;
00395
00396 cleanup:
00397 uves_free_matrix(&id);
00398 uves_free_image(&temp);
00399 return cpl_error_get_code();
00400 }
00401
00403 #define DOUBLE_SWAP(a,b) { register double t=(a);(a)=(b);(b)=t; }
00404
00415 inline
00416 double uves_utils_get_kth_double(
00417 double * a,
00418 int n,
00419 int k)
00420 {
00421 register double x ;
00422 register int i, j, l, m ;
00423
00424 l=0 ; m=n-1 ;
00425 while (l<m) {
00426 x=a[k] ;
00427 i=l ;
00428 j=m ;
00429 do {
00430 while (a[i]<x) i++ ;
00431 while (x<a[j]) j-- ;
00432 if (i<=j) {
00433 DOUBLE_SWAP(a[i],a[j]) ;
00434 i++ ; j-- ;
00435 }
00436 } while (i<=j) ;
00437 if (j<k) l=i ;
00438 if (k<i) m=j ;
00439 }
00440 return a[k] ;
00441 }
00442
00451 inline double
00452 uves_tools_get_median(double *a, int n)
00453 {
00454 if (n % 2 == 0)
00455 {
00456 return
00457 (uves_utils_get_kth_double(a, n, n/2) +
00458 uves_utils_get_kth_double(a, n, n/2-1))/2.0;
00459
00460 }
00461 else
00462 {
00463 return uves_utils_get_kth_double(a, n, (n-1)/2);
00464 }
00465 }
00466
00467
00468
00469
00491
00492 static cpl_image *
00493 filter_median(const cpl_image *image, int radx, int rady, bool extrapolate_border)
00494 {
00495 int x, y;
00496 int nx = cpl_image_get_size_x(image);
00497 int ny = cpl_image_get_size_y(image);
00498 cpl_image *result = cpl_image_new(nx, ny, CPL_TYPE_DOUBLE);
00499 double *result_data;
00500 const double *image_data;
00501 double *window = NULL;
00502
00503 window = cpl_malloc(sizeof(double) * (2*radx+1)*(2*rady+1));
00504 assure_mem( result );
00505 assure( cpl_image_get_type(image) == CPL_TYPE_DOUBLE,
00506 CPL_ERROR_UNSUPPORTED_MODE, "Type is %s",
00507 uves_tostring_cpl_type(cpl_image_get_type(image)));
00508
00509 result_data = cpl_image_get_data_double(result);
00510 image_data = cpl_image_get_data_double_const(image);
00511
00512 for (y = 1; y <= ny; y++)
00513 {
00514 for (x = 1; x <= nx; x++)
00515 {
00516 int x1, y_1, x2, y2;
00517
00518 x1 = x - radx; y_1 = y - rady;
00519 x2 = x + radx; y2 = y + rady;
00520
00521 if (extrapolate_border)
00522 {
00523
00524
00525 if (x1 < 1)
00526 {
00527 x2 += (1 - x1);
00528 x1 += (1 - x1);
00529 }
00530 if (nx < x2)
00531 {
00532 x1 -= (x2 - nx);
00533 x2 -= (x2 - nx);
00534 }
00535
00536 if (y_1 < 1)
00537 {
00538 y2 += (1 - y_1);
00539 y_1 += (1 - y_1);
00540 }
00541 if (ny < y2)
00542 {
00543 y_1 -= (y2 - ny);
00544 y2 -= (y2 - ny);
00545 }
00546 }
00547 else { }
00548
00549 #if 0
00550 result_data[(x-1) + (y-1)*nx] =
00551 cpl_image_get_median_window(image,
00552 uves_max_int(1, x1),
00553 uves_max_int(1, y_1),
00554 uves_min_int(nx, x2),
00555 uves_min_int(ny, y2));
00556
00557 #else
00558
00559 {
00560 int i, j, k;
00561
00562 k = 0;
00563 for (j = uves_max_int(1 , y_1)-1;
00564 j <= uves_min_int(ny, y2 )-1;
00565 j++)
00566 for (i = uves_max_int(1, x1)-1;
00567 i <= uves_min_int(nx, x2)-1;
00568 i++)
00569 {
00570 window[k++] = image_data[i + j*nx];
00571 }
00572
00573 result_data[(x-1) + (y-1)*nx] =
00574 uves_utils_get_kth_double(window,k,(((k)&1)?((k)/2):(((k)/2)-1))) ;
00575 }
00576 #endif
00577 }
00578 }
00579
00580
00581 assure( cpl_error_get_code() == CPL_ERROR_NONE, cpl_error_get_code(),
00582 "Error calculating %dx%d median filter", radx, rady);
00583
00584 cleanup:
00585 cpl_free(window);
00586 return result;
00587 }
00588
00589
00590
00618
00619
00620 cpl_error_code
00621 uves_fit_gaussian_2d_image(const cpl_image *image, const cpl_image *noise,
00622 int x1, int y_1,
00623 int x2, int y2,
00624 double *x0, double *y_0, double *sigmax, double *sigmay,
00625 double *amplitude,
00626 double *dx0, double *dy0
00627 )
00628 {
00629 cpl_image *marginal_x = NULL;
00630 cpl_image *marginal_y = NULL;
00631 cpl_image *marginal_x_noise = NULL;
00632 cpl_image *marginal_y_noise = NULL;
00633 cpl_image *variance = NULL;
00634 cpl_matrix *covariance = NULL;
00635
00636 int nx, ny;
00637 double norm_x, norm_y;
00638 double background_x, background_y;
00639
00640
00641 assure( image != NULL, CPL_ERROR_NULL_INPUT, "Null image");
00642 nx = cpl_image_get_size_x(image);
00643 ny = cpl_image_get_size_y(image);
00644 assure( noise != NULL || (dx0 == NULL && dy0 == NULL), CPL_ERROR_INCOMPATIBLE_INPUT,
00645 "Cannot compute uncertainty of fit with no noise image specified");
00646 assure( noise == NULL ||
00647 (cpl_image_get_size_x(noise) == nx &&
00648 cpl_image_get_size_y(noise) == ny),
00649 CPL_ERROR_INCOMPATIBLE_INPUT,
00650 "Size of input image (%dx%d) and noise image (%dx%d) differ",
00651 nx, ny,
00652 cpl_image_get_size_x(noise),
00653 cpl_image_get_size_y(noise));
00654 assure( 1 <= x1 && x1 <= x2 && x2 <= nx &&
00655 1 <= y_1 && y_1 <= y2 && y2 <= ny, CPL_ERROR_ILLEGAL_INPUT,
00656 "Illegal window: (%d, %d)-(%d, %d)", x1, y_1, x2, y2);
00657 assure( x0 != NULL, CPL_ERROR_NULL_INPUT, "Null x-center");
00658 assure( y_0 != NULL, CPL_ERROR_NULL_INPUT, "Null y-center");
00659 assure( sigmax != NULL, CPL_ERROR_NULL_INPUT, "Null sigma_x");
00660 assure( sigmay != NULL, CPL_ERROR_NULL_INPUT, "Null sigma_y");
00661
00662
00663 if (noise != NULL)
00664 {
00665
00666 check(( variance = cpl_image_extract(noise, x1, y_1, x2, y2),
00667 cpl_image_power(variance, 2.0)),
00668 "Error creating variance image");
00669 }
00670
00671
00672 check( marginal_x = cpl_image_collapse_window_create(image,
00673 x1, y_1, x2, y2,
00674 0),
00675 "Error collapsing window (%d, %d) - (%d, %d)", x1, y_1, x2, y2);
00676
00677 if (noise != NULL)
00678 {
00679
00680
00681 check( marginal_x_noise = cpl_image_collapse_window_create(variance,
00682 1, 1,
00683 x2-x1+1, y2-y_1+1,
00684 0),
00685 "Error collapsing window (1, 1) - (%d, %d)", x2-x1+1, y2-y_1+1);
00686
00687
00688 cpl_image_power(marginal_x_noise, 0.5);
00689 }
00690
00691
00692 check( marginal_y = cpl_image_collapse_window_create(image,
00693 x1, y_1, x2, y2,
00694 1),
00695 "Error collapsing window (%d, %d) - (%d, %d)", x1, y_1, x2, y2);
00696
00697 if (noise != NULL)
00698 {
00699 check( marginal_y_noise = cpl_image_collapse_window_create(variance,
00700 1, 1,
00701 x2-x1+1, y2-y_1+1,
00702 1),
00703 "Error collapsing window (1, 1) - (%d, %d)", x2-x1+1, y2-y_1+1);
00704
00705
00706 cpl_image_power(marginal_y_noise, 0.5);
00707 }
00708
00709
00710 uves_fit_1d_image(marginal_x, marginal_x_noise, NULL,
00711 true,
00712 false, false,
00713 1, x2 - x1 + 1, 1,
00714 x0, sigmax, &norm_x, &background_x, NULL,
00715 NULL, NULL,
00716 (dx0 != NULL) ? &covariance : NULL,
00717 uves_gauss, uves_gauss_derivative, 4);
00718
00719
00720 assure( cpl_error_get_code() != CPL_ERROR_CONTINUE ||
00721 cpl_error_get_code() != CPL_ERROR_SINGULAR_MATRIX,
00722 CPL_ERROR_CONTINUE, "Fitting along x failed");
00723 assure( cpl_error_get_code() == CPL_ERROR_NONE, cpl_error_get_code(),
00724 "Fitting along x failed");
00725
00726
00727 *x0 += (x1 - 1);
00728
00729 if (dx0 != NULL)
00730 {
00731 *dx0 = cpl_matrix_get(covariance, 0, 0);
00732 }
00733
00734
00735
00736 uves_free_matrix(&covariance);
00737 uves_fit_1d_image(marginal_y, marginal_y_noise, NULL,
00738 false,
00739 false, false,
00740 1, y2 - y_1 + 1, 1,
00741 y_0, sigmay, &norm_y, &background_y, NULL,
00742 NULL, NULL,
00743 (dy0 != NULL) ? &covariance : NULL,
00744 uves_gauss, uves_gauss_derivative, 4);
00745
00746
00747 assure( cpl_error_get_code() != CPL_ERROR_CONTINUE ||
00748 cpl_error_get_code() != CPL_ERROR_SINGULAR_MATRIX,
00749 CPL_ERROR_CONTINUE, "Fitting along y failed");
00750 assure( cpl_error_get_code() == CPL_ERROR_NONE, cpl_error_get_code(),
00751 "Fitting along y failed");
00752
00753
00754 *y_0 += (y_1 - 1);
00755
00756 if (dy0 != NULL)
00757 {
00758 *dy0 = cpl_matrix_get(covariance, 0, 0);
00759 }
00760
00761
00762
00763
00764
00765
00766 if (amplitude != NULL)
00767 {
00768 *amplitude = sqrt(norm_x * norm_y) / (2*M_PI * (*sigmax) * (*sigmay));
00769 }
00770
00771 cleanup:
00772 uves_free_matrix(&covariance);
00773 uves_free_image(&variance);
00774 uves_free_image(&marginal_x);
00775 uves_free_image(&marginal_x_noise);
00776 uves_free_image(&marginal_y);
00777 uves_free_image(&marginal_y_noise);
00778
00779 return cpl_error_get_code();
00780 }
00781
00782