00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifdef HAVE_CONFIG_H
00023 #include <config.h>
00024 #endif
00025
00026
00027
00028
00029 #include <inttypes.h>
00030 #include <complex.h>
00031 #include <math.h>
00032
00033 #include "muse_cplwrappers.h"
00034 #include "muse_utils.h"
00035 #include "muse_findstars.h"
00036
00037
00038
00039
00040 #define DEBUG_MUSE_FINDSTARS 0
00041
00042
00053
00054
00057
00058
00059
00060
00078 static cpl_matrix *
00079 _cpl_matrix_sum_columns(const cpl_matrix *self)
00080 {
00081
00082 cpl_matrix *vector = NULL;
00083
00084 if (self) {
00085
00086 cpl_size nr = cpl_matrix_get_nrow(self);
00087 cpl_size nc = cpl_matrix_get_ncol(self);
00088
00089 vector = cpl_matrix_extract(self, 0, 0, 1, 1, 1, nc);
00090
00091 const double *_self = cpl_matrix_get_data_const(self);
00092
00093 double *_vector = cpl_matrix_get_data(vector);
00094
00095 register cpl_size ir;
00096
00097
00098 for (ir = 1; ir < nr; ++ir) {
00099
00100 register cpl_size ic;
00101
00102 for (ic = 0; ic < nc; ++ic) {
00103 _vector[ic] += _self[ir * nc + ic];
00104 }
00105
00106 }
00107
00108 }
00109
00110 return vector;
00111
00112 }
00113
00114
00132 static cpl_matrix *
00133 _cpl_matrix_sum_rows(const cpl_matrix *self)
00134 {
00135
00136 cpl_matrix *vector = NULL;
00137
00138 if (self) {
00139
00140 cpl_size nr = cpl_matrix_get_nrow(self);
00141 cpl_size nc = cpl_matrix_get_ncol(self);
00142
00143 vector = cpl_matrix_extract(self, 0, 0, 1, 1, nr, 1);
00144
00145 const double *_self = cpl_matrix_get_data_const(self);
00146
00147 double *_vector = cpl_matrix_get_data(vector);
00148
00149 register cpl_size ir;
00150
00151
00152 for (ir = 0; ir < nr; ++ir) {
00153
00154 register cpl_size ic;
00155
00156 for (ic = 1; ic < nc; ++ic) {
00157 _vector[ir] += _self[ir * nc + ic];
00158 }
00159
00160 }
00161
00162 }
00163
00164 return vector;
00165
00166 }
00167
00168
00183 static double
00184 _cpl_matrix_sum(const cpl_matrix *self)
00185 {
00186
00187 double sum = 0.;
00188
00189 if (self) {
00190
00191 register cpl_size i;
00192
00193 cpl_size sz = cpl_matrix_get_nrow(self) * cpl_matrix_get_ncol(self);
00194
00195 const double *_self = cpl_matrix_get_data_const(self);
00196
00197
00198 for (i = 0; i < sz; ++i) {
00199 sum += _self[i];
00200 }
00201
00202 }
00203
00204 return sum;
00205
00206 }
00207
00208
00227 static cpl_error_code
00228 _cpl_matrix_modulo(cpl_matrix *self, long value)
00229 {
00230
00231 if (value == 0.) {
00232 return CPL_ERROR_DIVISION_BY_ZERO;
00233 }
00234
00235 cpl_size sz = cpl_matrix_get_nrow(self) * cpl_matrix_get_ncol(self);
00236
00237 double *m = cpl_matrix_get_data(self);
00238
00239
00240 while (sz--) {
00241 *m = (long)(*m) % value;
00242 ++m;
00243 }
00244
00245 return CPL_ERROR_NONE;
00246
00247 }
00248
00249
00250
00251
00252
00253
00254 typedef int (*_cpl_matrix_element_compare_func)(double aValue1, double aValue2);
00255
00256
00257
00266
00267 static int
00268 _muse_condition_not_equal(double aValue1, double aValue2)
00269 {
00270 return (aValue1 != aValue2) ? TRUE : FALSE;
00271 }
00272
00273
00282
00283 static int
00284 _muse_condition_greater_equal(double aValue1, double aValue2)
00285 {
00286 return (aValue1 >= aValue2) ? TRUE : FALSE;
00287 }
00288
00289
00290
00291
00322
00323 static int
00324 _muse_centroid_offset(double *offset, unsigned short axis,
00325 const cpl_matrix *mdata, const cpl_matrix *mwt,
00326 const cpl_matrix *mwtxy, const cpl_matrix *msgxy,
00327 const cpl_matrix *mdg, double sumg, double sumgsqr,
00328 double sgdg, double sdg, double sdgs,
00329 double p, double sigsqr)
00330 {
00331 double sddg = 0.;
00332 double sumd = 0.;
00333 double sumgd = 0.;
00334
00335 if ((axis != 1) && (axis != 2)) {
00336 return -1;
00337 }
00338
00339 cpl_matrix *mtmp = muse_cplmatrix_multiply_create(mdata, mwtxy);
00340
00341 cpl_matrix *sd;
00342 if (axis == 1) {
00343 sd = _cpl_matrix_sum_columns(mtmp);
00344 }
00345 else {
00346 cpl_matrix *_sd = _cpl_matrix_sum_rows(mtmp);
00347 sd = cpl_matrix_transpose_create(_sd);
00348 cpl_matrix_delete(_sd);
00349 }
00350 cpl_matrix_delete(mtmp);
00351
00352
00353 mtmp = muse_cplmatrix_multiply_create(mwt, sd);
00354 sumd = _cpl_matrix_sum(mtmp);
00355 cpl_matrix_delete(mtmp);
00356
00357 mtmp = muse_cplmatrix_multiply_create(mwt, msgxy);
00358 cpl_matrix_multiply(mtmp, sd);
00359 sumgd = _cpl_matrix_sum(mtmp);
00360 cpl_matrix_delete(mtmp);
00361
00362 mtmp = muse_cplmatrix_multiply_create(mwt, sd);
00363 cpl_matrix_multiply(mtmp, mdg);
00364 sddg = _cpl_matrix_sum(mtmp);
00365 cpl_matrix_delete(mtmp);
00366 cpl_matrix_delete(sd);
00367
00368
00369
00370 double height = (sumgd - sumg * sumd / p) / (sumgsqr - (sumg * sumg) / p);
00371 if (height <= 0.) {
00372 return 1;
00373 }
00374
00375 double skylvl = (sumd - height * sumg) / p;
00376 double _offset = (sgdg - (sddg - sdg * (height * sumg + skylvl * p))) /
00377 (height * sdgs / sigsqr);
00378
00379 if (isnan(_offset)) {
00380 return 2;
00381 }
00382
00383 *offset =_offset;
00384 return 0;
00385 }
00386
00387
00388
00389
00390 #define MUSE_SQR(x) ((x) * (x))
00391
00392
00453
00454 cpl_table *
00455 muse_find_stars(const cpl_image *aImage, double aHmin, double aFwhm,
00456 const double *aRoundLimits, const double *aSharpLimits)
00457 {
00458 cpl_ensure(aImage, CPL_ERROR_NULL_INPUT, NULL);
00459
00460
00461 const int kMaxBox = 13;
00462
00463
00464 const double kSharpLimits[2] = {0.2, 1.};
00465 const double kRoundLimits[2] = {-1., 1.};
00466
00467 cpl_size nx = cpl_image_get_size_x(aImage);
00468 cpl_size ny = cpl_image_get_size_y(aImage);
00469
00470 cpl_ensure(nx > 0 && ny > 0, CPL_ERROR_ILLEGAL_INPUT, NULL);
00471 cpl_ensure(nx % 2 == 0, CPL_ERROR_ILLEGAL_INPUT, NULL);
00472 cpl_ensure(aFwhm >= 0.5, CPL_ERROR_ILLEGAL_INPUT, NULL);
00473
00474
00475
00476
00477 if (!aRoundLimits) {
00478 aRoundLimits = kRoundLimits;
00479 }
00480
00481 if (!aSharpLimits) {
00482 aSharpLimits = kSharpLimits;
00483 }
00484
00485 cpl_msg_debug(__func__, "Settings: FWHM = %g, HMIN = %g, "
00486 "Roundness limits = [%g, %g], Sharpness limits = [%g, %g]",
00487 aFwhm, aHmin, aRoundLimits[0], aRoundLimits[1],
00488 aSharpLimits[0], aSharpLimits[1]);
00489
00490 const double radius = CPL_MAX(0.637 * aFwhm, 2.001);
00491 const double radsqr = MUSE_SQR(radius);
00492 const double sigsqr = MUSE_SQR(aFwhm / 2.35482);
00493
00494 cpl_size ipos;
00495 cpl_size nhalf = (cpl_size)CPL_MIN(radius, 0.5 * (kMaxBox - 1));
00496
00497
00498 cpl_size nbox = 2 * nhalf + 1;
00499
00500
00501 double *row2 = cpl_malloc(nbox * sizeof *row2);
00502 for (ipos = 0; ipos < nbox; ++ipos) {
00503 row2[ipos] = MUSE_SQR(ipos - nhalf);
00504 }
00505
00506 cpl_matrix *ckernel = cpl_matrix_new(nbox, nbox);
00507 for (ipos = 0; ipos <= nhalf; ++ipos) {
00508 cpl_size jpos;
00509 for (jpos = 0; jpos < nbox; ++jpos) {
00510 register double tmp = row2[jpos] + MUSE_SQR(ipos);
00511 cpl_matrix_set(ckernel, nhalf - ipos, jpos, tmp);
00512 cpl_matrix_set(ckernel, nhalf + ipos, jpos, tmp);
00513 }
00514 }
00515
00516
00517 cpl_matrix *mask = cpl_matrix_new(nbox, nbox);
00518
00519 for (ipos = 0; ipos < nbox; ++ipos) {
00520 cpl_size jpos;
00521 for (jpos = 0; jpos < nbox; ++jpos) {
00522 if (cpl_matrix_get(ckernel, ipos, jpos) > radsqr) {
00523 cpl_matrix_set(mask, ipos, jpos, 0.);
00524 }
00525 else {
00526 cpl_matrix_set(mask, ipos, jpos, 1.);
00527 }
00528 }
00529 }
00530
00531 cpl_array *positions = muse_cplmatrix_where(mask, 0.,
00532 _muse_condition_not_equal);
00533 cpl_size npixels = cpl_array_get_size(positions);
00534
00535 cpl_array_delete(positions);
00536 positions = NULL;
00537
00538
00539
00540 cpl_matrix_multiply_scalar(ckernel, -0.5 / sigsqr);
00541 cpl_matrix_exponential(ckernel, CPL_MATH_E);
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558 cpl_matrix *xwt = cpl_matrix_new(nbox, nbox);
00559
00560 for (ipos = 0; ipos < nbox; ++ipos) {
00561 cpl_size jpos;
00562 double tmp = nhalf - imaxabs(ipos - nhalf) + 1;
00563 for(jpos = 0; jpos < nbox; ++jpos) {
00564 cpl_matrix_set(xwt, jpos, ipos, tmp);
00565 }
00566 }
00567 cpl_matrix *ywt = cpl_matrix_transpose_create(xwt);
00568 cpl_matrix *wt = cpl_matrix_extract_row(xwt, 0);
00569 double p = _cpl_matrix_sum(wt);
00570
00571 cpl_matrix *mtmp = NULL;
00572
00573 mtmp = muse_cplmatrix_multiply_create(ckernel, xwt);
00574 cpl_matrix *sgx = _cpl_matrix_sum_rows(mtmp);
00575 cpl_matrix_delete(mtmp);
00576
00577
00578 mtmp = sgx;
00579 sgx = cpl_matrix_transpose_create(mtmp);
00580 cpl_matrix_delete(mtmp);
00581
00582 mtmp = muse_cplmatrix_multiply_create(ckernel, ywt);
00583 cpl_matrix *sgy = _cpl_matrix_sum_columns(mtmp);
00584 cpl_matrix_delete(mtmp);
00585
00586 cpl_matrix *wsgy = muse_cplmatrix_multiply_create(wt, sgy);
00587 double sumgx = _cpl_matrix_sum(wsgy);
00588
00589 mtmp = muse_cplmatrix_multiply_create(wsgy, sgy);
00590 double sumgsqy = _cpl_matrix_sum(mtmp);
00591 cpl_matrix_delete(mtmp);
00592
00593 cpl_matrix *wsgx = muse_cplmatrix_multiply_create(wt, sgx);
00594 double sumgy = _cpl_matrix_sum(wsgx);
00595
00596 mtmp = muse_cplmatrix_multiply_create(wsgx, sgx);
00597 double sumgsqx = _cpl_matrix_sum(mtmp);
00598 cpl_matrix_delete(mtmp);
00599
00600
00601 cpl_matrix *vec = cpl_matrix_new(1, nbox);
00602 for (ipos = 0; ipos < nbox; ++ipos) {
00603 cpl_matrix_set(vec, 0, ipos, nhalf - ipos);
00604 }
00605 cpl_matrix *dgdx = muse_cplmatrix_multiply_create(sgy, vec);
00606 cpl_matrix *dgdy = muse_cplmatrix_multiply_create(sgx, vec);
00607 cpl_matrix_delete(vec);
00608
00609 cpl_matrix *wdgdx = muse_cplmatrix_multiply_create(wt, dgdx);
00610 cpl_matrix *wdgdy = muse_cplmatrix_multiply_create(wt, dgdy);
00611
00612 mtmp = muse_cplmatrix_multiply_create(dgdx, dgdx);
00613 cpl_matrix *wdgdxs = muse_cplmatrix_multiply_create(wt, mtmp);
00614 cpl_matrix_delete(mtmp);
00615
00616 mtmp = muse_cplmatrix_multiply_create(dgdy, dgdy);
00617 cpl_matrix *wdgdys = muse_cplmatrix_multiply_create(wt, mtmp);
00618 cpl_matrix_delete(mtmp);
00619
00620
00621 double sdgdx = _cpl_matrix_sum(wdgdx);
00622 cpl_matrix_delete(wdgdx);
00623 wdgdx = NULL;
00624
00625 double sdgdy = _cpl_matrix_sum(wdgdy);
00626 cpl_matrix_delete(wdgdy);
00627 wdgdy = NULL;
00628
00629 double sdgdxs = _cpl_matrix_sum(wdgdxs);
00630 cpl_matrix_delete(wdgdxs);
00631 wdgdxs = NULL;
00632
00633 double sdgdys = _cpl_matrix_sum(wdgdys);
00634 cpl_matrix_delete(wdgdys);
00635 wdgdys = NULL;
00636
00637 mtmp = muse_cplmatrix_multiply_create(wsgy, dgdx);
00638 double sgdgdx = _cpl_matrix_sum(mtmp);
00639 cpl_matrix_delete(mtmp);
00640 cpl_matrix_delete(wsgy);
00641 wsgy = NULL;
00642
00643 mtmp = muse_cplmatrix_multiply_create(wsgx, dgdy);
00644 double sgdgdy = _cpl_matrix_sum(mtmp);
00645 cpl_matrix_delete(mtmp);
00646 cpl_matrix_delete(wsgx);
00647 wsgx = NULL;
00648
00649
00650
00651
00652
00653
00654
00655
00656 cpl_matrix_multiply(ckernel, mask);
00657
00658 double sumc = _cpl_matrix_sum(ckernel);
00659
00660 mtmp = muse_cplmatrix_multiply_create(ckernel, ckernel);
00661 double sumcsq = -MUSE_SQR(sumc) / npixels + _cpl_matrix_sum(mtmp);
00662 sumc /= npixels;
00663 cpl_matrix_delete(mtmp);
00664
00665 cpl_matrix *c1 = cpl_matrix_new(1, nbox);
00666 double sumc1 = 0.;
00667 double sumc1sq = 0.;
00668 for (ipos = 0; ipos < nbox; ++ipos) {
00669 double tmp = exp(-0.5 * row2[ipos] / sigsqr);
00670 sumc1 += tmp;
00671 sumc1sq += MUSE_SQR(tmp);
00672 cpl_matrix_set(c1, 0, ipos, tmp);
00673 }
00674 sumc1 /= nbox;
00675 sumc1sq -= sumc1;
00676 cpl_free(row2);
00677 row2 = NULL;
00678
00679 cpl_matrix_subtract_scalar(c1, sumc1);
00680 cpl_matrix_divide_scalar(c1, sumc1sq);
00681
00682 cpl_matrix_subtract_scalar(ckernel, sumc);
00683 cpl_matrix_divide_scalar(ckernel, sumcsq);
00684 cpl_matrix_multiply(ckernel, mask);
00685
00686 mtmp = muse_cplmatrix_multiply_create(ckernel, ckernel);
00687 cpl_msg_debug(__func__, "Relative error computed from the FWHM: %g",
00688 sqrt(_cpl_matrix_sum(mtmp)));
00689 cpl_matrix_delete(mtmp);
00690
00691
00692 cpl_msg_debug(__func__, "Beginning convolution of image.");
00693 cpl_image *himage = muse_convolve_image(aImage, ckernel);
00694
00695 cpl_matrix_delete(ckernel);
00696 ckernel = NULL;
00697
00698 if (!himage) {
00699 cpl_matrix_delete(c1);
00700 cpl_matrix_delete(dgdy);
00701 cpl_matrix_delete(dgdx);
00702 cpl_matrix_delete(sgy);
00703 cpl_matrix_delete(sgx);
00704 cpl_matrix_delete(wt);
00705 cpl_matrix_delete(ywt);
00706 cpl_matrix_delete(xwt);
00707 cpl_matrix_delete(mask);
00708
00709 cpl_error_set_message(__func__, CPL_ERROR_INCOMPATIBLE_INPUT,
00710 "Convolution of the input image failed!");
00711 return NULL;
00712 }
00713
00714 #if DEBUG_MUSE_FINDSTARS > 0
00715 cpl_image_save(himage, "convolved_image_initial.fits", CPL_TYPE_DOUBLE, NULL,
00716 CPL_IO_CREATE);
00717 #endif
00718
00719
00720
00721 double hmin = cpl_image_get_min(himage);
00722
00723 cpl_image_fill_window(himage, 1, 1, nhalf, ny, hmin);
00724 cpl_image_fill_window(himage, nx - nhalf + 1, 1, nx, ny, hmin);
00725 cpl_image_fill_window(himage, nhalf + 1, 1, nx - nhalf, nhalf, hmin);
00726 cpl_image_fill_window(himage, nhalf + 1, ny - nhalf + 1, nx - nhalf, ny, hmin);
00727
00728 #if DEBUG_MUSE_FINDSTARS > 0
00729 cpl_image_save(himage, "convolved_image_padded.fits", CPL_TYPE_DOUBLE, NULL,
00730 CPL_IO_CREATE);
00731 #endif
00732
00733 cpl_msg_debug(__func__, "Finished convolution of image.");
00734
00735
00736 cpl_matrix_set(mask, nhalf, nhalf, 0.);
00737 positions = muse_cplmatrix_where(mask, 0., _muse_condition_not_equal);
00738 npixels = cpl_array_get_size(positions);
00739
00740
00741 cpl_matrix *offset = cpl_matrix_new(1, npixels);
00742 for (ipos = 0; ipos < npixels; ++ipos) {
00743 cpl_matrix_set(offset, 0 , ipos,
00744 cpl_array_get_cplsize(positions, ipos, NULL));
00745 }
00746
00747 cpl_array_delete(positions);
00748 positions = NULL;
00749
00750 cpl_matrix *xx = cpl_matrix_duplicate(offset);
00751 _cpl_matrix_modulo(xx, nbox);
00752
00753 mtmp = cpl_matrix_duplicate(xx);
00754 cpl_matrix_multiply_scalar(mtmp, -1.);
00755 cpl_matrix_add(offset, mtmp);
00756 cpl_matrix_divide_scalar(offset, nbox);
00757 cpl_matrix_add_scalar(offset, -nhalf);
00758 cpl_matrix_delete(mtmp);
00759
00760 cpl_matrix_add_scalar(xx, -nhalf);
00761 cpl_matrix_multiply_scalar(offset, nx);
00762 cpl_matrix_add(offset, xx);
00763 cpl_matrix_delete(xx);
00764 xx = NULL;
00765
00766
00767 cpl_matrix *hmatrix = cpl_matrix_wrap(ny, nx, cpl_image_get_data_double(himage));
00768
00769
00770 cpl_msg_debug(__func__, "Selecting pixels exceeding threshold value %.6g",
00771 aHmin);
00772
00773 positions = muse_cplmatrix_where(hmatrix, aHmin, _muse_condition_greater_equal);
00774
00775 cpl_size nfound = cpl_array_get_size(positions);
00776 if (nfound == 0) {
00777 cpl_array_delete(positions);
00778 cpl_matrix_unwrap(hmatrix);
00779 cpl_matrix_delete(offset);
00780 cpl_image_delete(himage);
00781 cpl_matrix_delete(c1);
00782 cpl_matrix_delete(dgdy);
00783 cpl_matrix_delete(dgdx);
00784 cpl_matrix_delete(sgy);
00785 cpl_matrix_delete(sgx);
00786 cpl_matrix_delete(wt);
00787 cpl_matrix_delete(ywt);
00788 cpl_matrix_delete(xwt);
00789 cpl_matrix_delete(mask);
00790
00791 cpl_error_set_message(__func__, CPL_ERROR_DATA_NOT_FOUND,
00792 "No image pixel value exceeds threshold value!");
00793 return NULL;
00794 }
00795 else {
00796 cpl_msg_debug(__func__, "Found %" CPL_SIZE_FORMAT " pixels with values "
00797 "above the threshold value %.6g", nfound, aHmin);
00798 }
00799
00800 for (ipos = 0; ipos < npixels; ++ipos) {
00801
00802
00803 cpl_matrix *hindex = muse_cplmatrix_extract_selected(hmatrix, positions);
00804
00805 cpl_array *atmp = cpl_array_duplicate(positions);
00806 cpl_array_add_scalar(atmp, cpl_matrix_get(offset, 0, ipos));
00807
00808 cpl_matrix *hoffset = muse_cplmatrix_extract_selected(hmatrix, atmp);
00809 cpl_array_delete(atmp);
00810 atmp = NULL;
00811
00812 cpl_size tsize = cpl_matrix_get_ncol(hoffset);
00813 if (cpl_matrix_get_ncol(hindex) < tsize) {
00814 tsize = cpl_matrix_get_ncol(hindex);
00815 }
00816
00817 nfound = 0;
00818 cpl_size jpos = tsize;
00819 while (jpos--) {
00820 if (cpl_matrix_get(hindex, 0, jpos) < cpl_matrix_get(hoffset, 0, jpos)) {
00821 cpl_array_set_invalid(positions, jpos);
00822 }
00823 else {
00824 ++nfound;
00825 }
00826
00827 }
00828 cpl_matrix_delete(hoffset);
00829 cpl_matrix_delete(hindex);
00830
00831 if (nfound == 0) {
00832 cpl_array_delete(positions);
00833 cpl_matrix_unwrap(hmatrix);
00834 cpl_matrix_delete(offset);
00835 cpl_image_delete(himage);
00836 cpl_matrix_delete(c1);
00837 cpl_matrix_delete(dgdy);
00838 cpl_matrix_delete(dgdx);
00839 cpl_matrix_delete(sgy);
00840 cpl_matrix_delete(sgx);
00841 cpl_matrix_delete(wt);
00842 cpl_matrix_delete(ywt);
00843 cpl_matrix_delete(xwt);
00844 cpl_matrix_delete(mask);
00845
00846 cpl_error_set_message(__func__, CPL_ERROR_DATA_NOT_FOUND,
00847 "No local maximum exceeding the threshold value "
00848 "was found!");
00849 return NULL;
00850 }
00851
00852 muse_cplarray_erase_invalid(positions);
00853 }
00854 cpl_matrix_delete(offset);
00855 offset = NULL;
00856
00857 cpl_table *_sources = cpl_table_new(cpl_array_get_size(positions));
00858 #if DEBUG_MUSE_FINDSTARS > 0
00859 cpl_table_new_column(_sources, "xidx", CPL_TYPE_LONG_LONG);
00860 cpl_table_new_column(_sources, "yidx", CPL_TYPE_LONG_LONG);
00861 #endif
00862 cpl_table_new_column(_sources, "X", CPL_TYPE_DOUBLE);
00863 cpl_table_new_column(_sources, "Y", CPL_TYPE_DOUBLE);
00864 cpl_table_new_column(_sources, "Flux", CPL_TYPE_DOUBLE);
00865 cpl_table_new_column(_sources, "Sharpness", CPL_TYPE_DOUBLE);
00866 cpl_table_new_column(_sources, "Roundness", CPL_TYPE_DOUBLE);
00867
00868
00869 for (ipos = 0; ipos < cpl_table_get_nrow(_sources); ++ipos) {
00870 cpl_size _offset = cpl_array_get_cplsize(positions, ipos, NULL);
00871 cpl_size ix = _offset % nx;
00872 cpl_size iy = (_offset - ix) / nx;
00873
00874 cpl_size imin = ix - nhalf + 1;
00875 cpl_size imax = ix + nhalf + 1;
00876 cpl_size jmin = iy - nhalf + 1;
00877 cpl_size jmax = iy + nhalf + 1;
00878
00879 #if DEBUG_MUSE_FINDSTARS > 0
00880 cpl_table_set_long_long(_sources, "xidx", ipos, ix);
00881 cpl_table_set_long_long(_sources, "yidx", ipos, iy);
00882 #endif
00883
00884 if ((imin < 1) || (jmin < 1) || (imax >= nx) || (jmax >= ny)) {
00885
00886 cpl_table_unselect_row(_sources, ipos);
00887 continue;
00888 }
00889
00890 double flux = cpl_matrix_get(hmatrix, iy, ix);
00891 cpl_image *_image = cpl_image_extract(aImage, imin + 1, jmin + 1,
00892 imax + 1, jmax + 1);
00893 cpl_matrix *mimg = cpl_matrix_wrap(nbox, nbox,
00894 cpl_image_get_data_double(_image));
00895
00896
00897 mtmp = muse_cplmatrix_multiply_create(mask, mimg);
00898 double sharpness = (cpl_matrix_get(mimg, nhalf, nhalf) -
00899 _cpl_matrix_sum(mtmp) / npixels) / flux;
00900 cpl_matrix_delete(mtmp);
00901
00902 if ((sharpness < kSharpLimits[0]) || (sharpness > kSharpLimits[1])) {
00903 cpl_matrix_unwrap(mimg);
00904 cpl_image_delete(_image);
00905
00906
00907 cpl_table_unselect_row(_sources, ipos);
00908 continue;
00909 }
00910
00911
00912 mtmp = _cpl_matrix_sum_columns(mimg);
00913 cpl_matrix_multiply(mtmp, c1);
00914 double dx = _cpl_matrix_sum(mtmp);
00915 cpl_matrix_delete(mtmp);
00916
00917 cpl_matrix *_mtmp = _cpl_matrix_sum_rows(mimg);
00918 mtmp = cpl_matrix_transpose_create(_mtmp);
00919 cpl_matrix_multiply(mtmp, c1);
00920 double dy = _cpl_matrix_sum(mtmp);
00921 cpl_matrix_delete(mtmp);
00922 cpl_matrix_delete(_mtmp);
00923
00924 if ((dx <= 0.) || (dy <= 0.)) {
00925 cpl_matrix_unwrap(mimg);
00926 cpl_image_delete(_image);
00927
00928
00929 cpl_table_unselect_row(_sources, ipos);
00930 continue;
00931 }
00932
00933 double roundness = 2. * (dx - dy) / (dx + dy);
00934 if ((roundness < kRoundLimits[0]) || (roundness > kRoundLimits[1])) {
00935 cpl_matrix_unwrap(mimg);
00936 cpl_image_delete(_image);
00937
00938
00939 cpl_table_unselect_row(_sources, ipos);
00940 continue;
00941 }
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952 int status = 0;
00953
00954 double xoffset = 0;
00955 status = _muse_centroid_offset(&xoffset, 1, mimg, wt, ywt, sgy, dgdx,
00956 sumgx, sumgsqy, sgdgdx, sdgdx, sdgdxs, p,
00957 sigsqr);
00958 if (status != 0) {
00959 cpl_matrix_unwrap(mimg);
00960 cpl_image_delete(_image);
00961 cpl_table_unselect_row(_sources, ipos);
00962 continue;
00963 }
00964
00965 double yoffset = 0;
00966 status = _muse_centroid_offset(&yoffset, 2, mimg, wt, xwt, sgx, dgdy,
00967 sumgy, sumgsqx, sgdgdy, sdgdy, sdgdys, p,
00968 sigsqr);
00969 if (status != 0) {
00970 cpl_matrix_unwrap(mimg);
00971 cpl_image_delete(_image);
00972 cpl_table_unselect_row(_sources, ipos);
00973 continue;
00974 }
00975
00976
00977 if ((fabs(xoffset) >= nhalf) || (fabs(yoffset) >= nhalf)) {
00978 cpl_matrix_unwrap(mimg);
00979 cpl_image_delete(_image);
00980 cpl_table_unselect_row(_sources, ipos);
00981 continue;
00982 }
00983 cpl_matrix_unwrap(mimg);
00984 cpl_image_delete(_image);
00985
00986
00987
00988
00989
00990 double xcenter = (ix + 1) + xoffset;
00991 double ycenter = (iy + 1) + yoffset;
00992
00993 cpl_table_set_double(_sources, "X", ipos, xcenter);
00994 cpl_table_set_double(_sources, "Y", ipos, ycenter);
00995 cpl_table_set_double(_sources, "Flux", ipos, flux);
00996 cpl_table_set_double(_sources, "Sharpness", ipos, sharpness);
00997 cpl_table_set_double(_sources, "Roundness", ipos, roundness);
00998 }
00999
01000
01001 cpl_array_delete(positions);
01002 cpl_matrix_unwrap(hmatrix);
01003 cpl_image_delete(himage);
01004 cpl_matrix_delete(c1);
01005 cpl_matrix_delete(dgdy);
01006 cpl_matrix_delete(dgdx);
01007 cpl_matrix_delete(sgy);
01008 cpl_matrix_delete(sgx);
01009 cpl_matrix_delete(wt);
01010 cpl_matrix_delete(ywt);
01011 cpl_matrix_delete(xwt);
01012 cpl_matrix_delete(mask);
01013
01014
01015 #if DEBUG_MUSE_FINDSTARS > 0
01016 cpl_table_save(_sources, NULL, NULL, "detections.fits", CPL_IO_CREATE);
01017 #endif
01018
01019 cpl_table *sources = cpl_table_extract_selected(_sources);
01020 cpl_size ncandidates = cpl_table_get_nrow(_sources);
01021 cpl_size nselected = cpl_table_get_nrow(sources);
01022
01023 cpl_table_delete(_sources);
01024
01025 #if DEBUG_MUSE_FINDSTARS > 0
01026 cpl_table_erase_column(sources, "xidx");
01027 cpl_table_erase_column(sources, "yidx");
01028 #endif
01029
01030 if (ncandidates == 0) {
01031 cpl_msg_debug(__func__, "No candidate stars were found!");
01032 }
01033 else {
01034 cpl_msg_debug(__func__, "Total number of candidate stars %" CPL_SIZE_FORMAT
01035 "; no. selected candidates %" CPL_SIZE_FORMAT, ncandidates,
01036 nselected);
01037 }
01038
01039 if (nselected == 0) {
01040 cpl_table_delete(sources);
01041 sources = NULL;
01042 }
01043
01044 return sources;
01045 }
01046 #undef MUSE_SQR
01047