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 <cpl.h>
00030 #include <math.h>
00031
00032 #include "muse_artifacts.h"
00033
00034 #include "muse_quality.h"
00035
00036
00043
00044
00047
00066
00067 static int
00068 muse_cosmics_dcr_subframe(muse_image *aImage,
00069 int aX1, int aX2, int aY1, int aY2,
00070 float aThres, unsigned short aDebug)
00071 {
00072 float *data = cpl_image_get_data_float(aImage->data);
00073 int *dq = cpl_image_get_data_int(aImage->dq);
00074
00075
00076 double dsum = 0., dsq = 0.,
00077 min = FLT_MAX, max = -FLT_MAX;
00078 int i, ngood = 0,
00079 nx = cpl_image_get_size_x(aImage->data),
00080 ny = cpl_image_get_size_y(aImage->data);
00081 for (i = aX1 - 1; i < aX2 && i < nx; i++) {
00082 int j;
00083 for (j = aY1 - 1; j < aY2 && j < ny; j++) {
00084 if (dq[i + j*nx]) {
00085 continue;
00086 }
00087 dsum += data[i + j*nx];
00088 dsq += data[i + j*nx]*data[i + j*nx];
00089 ngood++;
00090 if (data[i + j*nx] < min) {
00091 min = data[i + j*nx];
00092 }
00093 if (data[i + j*nx] > max) {
00094 max = data[i + j*nx];
00095 }
00096 }
00097 }
00098
00099 double mean = dsum / ngood,
00100 sigma = sqrt((dsq - dsum*dsum / ngood) / ngood),
00101 lo = mean - sigma * aThres,
00102 hi = mean + sigma * aThres;
00103 if (aDebug > 2) {
00104 printf(" stats(1): %f+/-%f -> limits=%f...%f, extremes=%f...%f\n",
00105 mean, sigma, lo, hi, min, max);
00106 fflush(stdout);
00107 }
00108 if (!isfinite(mean) || !isfinite(sigma) || !isfinite(lo) || !isfinite(hi) ||
00109 min == FLT_MAX || max == -FLT_MAX) {
00110 if (aDebug > 0) {
00111 printf("No good pixels found or statistics are infinite!\n"
00112 " stats: %f+/-%f -> limits=%f...%f, extremes=%f...%f\n",
00113 mean, sigma, lo, hi, min, max);
00114 fflush(stdout);
00115 }
00116 return 0;
00117 }
00118
00119
00120
00121 #define HIST_BIN_WIDTH 1.
00122 long hlength = lround((max - min) / HIST_BIN_WIDTH + 1);
00123 int *hist = cpl_calloc(hlength, sizeof(int));
00124 dsum = 0.;
00125 dsq = 0.;
00126 ngood = 0;
00127 for (i = aX1 - 1; i < aX2 && i < nx; i++) {
00128 int j;
00129 for (j = aY1 - 1; j < aY2 && j < ny; j++) {
00130 if (dq[i + j*nx]) {
00131 continue;
00132 }
00133
00134 hist[lround((data[i + j*nx] - min) / HIST_BIN_WIDTH)] += 1;
00135 if (data[i + j*nx] > lo && data[i + j*nx] < hi) {
00136
00137 dsum += data[i + j*nx];
00138 dsq += data[i + j*nx]*data[i + j*nx];
00139 ngood++;
00140 }
00141 }
00142 }
00143 mean = dsum / ngood;
00144 sigma = sqrt((dsq - dsum*dsum / ngood) / ngood);
00145
00146
00147
00148 cpl_array *histogram = cpl_array_wrap_int(hist, hlength);
00149 cpl_size nmaxpos;
00150 cpl_array_get_maxpos(histogram, &nmaxpos);
00151 if (aDebug > 2) {
00152 printf(" stats(2): %f+/-%f, histogram: length=%ld, peak=%.0f at %f "
00153 "(%"CPL_SIZE_FORMAT")\n", mean, sigma, hlength,
00154 cpl_array_get_max(histogram), (double)nmaxpos * HIST_BIN_WIDTH + min,
00155 nmaxpos);
00156 if (aDebug > 3) {
00157 printf(" histogram:\n entry value number\n");
00158 for (i = 0; i < hlength; i++) {
00159 printf(" %7d %10.3f %8d\n", i, i * HIST_BIN_WIDTH + min, hist[i]);
00160 }
00161 }
00162 fflush(stdout);
00163 }
00164
00165
00166
00167 double gapwidth = sigma * aThres;
00168
00169 for (i = nmaxpos ; i < hlength; i++) {
00170 if (hist[i] == 0) {
00171
00172 int j = i + 1;
00173 while (j < hlength && !hist[j]) {
00174 j++;
00175 }
00176 if (j >= hlength) {
00177
00178 cpl_array_delete(histogram);
00179 return 0;
00180 }
00181 double gap = (double)(j - i) * HIST_BIN_WIDTH;
00182 if (gap > gapwidth) {
00183
00184 break;
00185 }
00186 i = j;
00187 }
00188 }
00189 cpl_array_delete(histogram);
00190
00191
00192
00193 if (i >= hlength) {
00194 return 0;
00195 }
00196
00197
00198
00199 hi = i * HIST_BIN_WIDTH + min;
00200 if (aDebug > 2) {
00201 printf(" flagging pixels above %.3f counts (%d of %ld in histogram)\n",
00202 hi, i+1, hlength);
00203 fflush(stdout);
00204 }
00205 int ncr = 0;
00206 for (i = aX1 - 1; i < aX2 && i < nx; i++) {
00207 int j;
00208 for (j = aY1 - 1; j < aY2 && j < ny; j++) {
00209 if (!dq[i + j*nx] && data[i + j*nx] > hi) {
00210 dq[i + j*nx] |= EURO3D_COSMICRAY;
00211 ncr++;
00212 }
00213 }
00214 }
00215
00216 return ncr;
00217 }
00218
00219
00273
00274 int
00275 muse_cosmics_dcr(muse_image *aImage, unsigned int aXBox, unsigned int aYBox,
00276 unsigned int aPasses, float aThres)
00277 {
00278 cpl_ensure(aImage, CPL_ERROR_NULL_INPUT, -1);
00279 cpl_ensure(aThres > 0, CPL_ERROR_ILLEGAL_INPUT, -2);
00280 cpl_ensure(aPasses > 0, CPL_ERROR_ILLEGAL_INPUT, -3);
00281 int nx = cpl_image_get_size_x(aImage->data),
00282 ny = cpl_image_get_size_y(aImage->data);
00283 cpl_ensure(aXBox <= (unsigned int)nx, CPL_ERROR_ILLEGAL_INPUT, -4);
00284 cpl_ensure(aYBox <= (unsigned int)ny, CPL_ERROR_ILLEGAL_INPUT, -5);
00285
00286 if (aXBox * aYBox < 100) {
00287 cpl_msg_warning(__func__, "Boxes containing more than 100 pixels are "
00288 "recommended for DCR!");
00289 }
00290
00291 char *dodebug = getenv("MUSE_DEBUG_DCR");
00292 unsigned short debug = dodebug ? atoi(dodebug) : 0,
00293 sfdebug = debug > 1;
00294 if (debug) {
00295 cpl_msg_debug(__func__, "Cosmic ray rejection using DCR: subframe %dx%d "
00296 "(%d pixels/subframe), %d passes, threshold %.3f sigma)",
00297 aXBox, aYBox, aXBox * aYBox, aPasses, aThres);
00298 }
00299
00300 unsigned npass, ncr = 0;
00301 for (npass = 1; npass <= aPasses; npass++) {
00302
00303 int imax = 0, jmax = 0;
00304
00305 unsigned ncrpass = 0;
00306
00307
00308 unsigned i;
00309 for (i = 1; i <= nx - aXBox + 1; i+=aXBox/2) {
00310 unsigned j;
00311 for (j = 1; j <= ny - aYBox + 1; j+=aYBox/2) {
00312 if (i + aXBox > (unsigned)imax) {
00313 imax = i + aXBox;
00314 }
00315 if (j + aYBox > (unsigned)jmax) {
00316 jmax = j + aYBox;
00317 }
00318 if (debug > 1) {
00319 printf("subframe [%d:%d,%d:%d] (standard)\n",
00320 i, i + aXBox, j, j + aYBox);
00321 fflush(stdout);
00322 }
00323 int npx = muse_cosmics_dcr_subframe(aImage, i, i + aXBox, j, j + aYBox,
00324 aThres, debug);
00325 ncrpass += npx;
00326 if (debug > 1 && npx) {
00327 printf("%8d affected pixels\n", npx);
00328 fflush(stdout);
00329 }
00330 }
00331
00332 if (jmax < ny) {
00333
00334 if (debug > 1) {
00335 printf("subframe [%d:%d,%d:%d] (upper)\n",
00336 i, i + aXBox, ny - aYBox + 1, ny);
00337 fflush(stdout);
00338 }
00339 int npx = muse_cosmics_dcr_subframe(aImage, i, i + aXBox, ny - aYBox + 1, ny,
00340 aThres, debug);
00341 ncrpass += npx;
00342 if (debug > 1 && npx) {
00343 printf("%8d affected pixels\n", npx);
00344 fflush(stdout);
00345 }
00346 }
00347 }
00348 if (sfdebug) {
00349 printf("standard subframe coverage to [%d,%d] (image has %dx%d)\n",
00350 imax, jmax, nx, ny);
00351 fflush(stdout);
00352 sfdebug = 0;
00353 }
00354
00355 if (imax < nx) {
00356
00357 unsigned j;
00358 for (j = 1; j <= ny - aYBox + 1; j+=aYBox/2) {
00359 if (debug > 1) {
00360 printf("subframe [%d:%d,%d:%d] (right)\n",
00361 nx - aXBox + 1, nx, j, j + aYBox);
00362 fflush(stdout);
00363 }
00364 int npx = muse_cosmics_dcr_subframe(aImage, nx - aXBox + 1, nx, j, j + aYBox,
00365 aThres, debug);
00366 ncrpass += npx;
00367 if (debug > 1 && npx) {
00368 printf("%8d affected pixels\n", npx);
00369 fflush(stdout);
00370 }
00371 }
00372 }
00373
00374 if (imax < nx && jmax < ny) {
00375
00376 if (debug > 1) {
00377 printf("subframe [%d:%d,%d:%d] (corner)\n",
00378 nx - aXBox + 1, nx, ny - aXBox + 1, ny);
00379 fflush(stdout);
00380 }
00381 int npx = muse_cosmics_dcr_subframe(aImage, nx - aXBox + 1, nx, ny - aXBox + 1, ny,
00382 aThres, debug);
00383 ncrpass += npx;
00384 if (debug > 1 && npx) {
00385 printf("%8d affected pixels\n", npx);
00386 fflush(stdout);
00387 }
00388 }
00389
00390 ncr += ncrpass;
00391 if (debug) {
00392 cpl_msg_debug(__func__, "%d (%d new) pixels found after pass %d", ncr,
00393 ncrpass, npass);
00394 }
00395
00396 if (!ncrpass) {
00397 break;
00398 }
00399 }
00400
00401 return ncr;
00402 }
00403