Changeset 6957 for trunk/psModules/src/detrend/pmFringeStats.c
- Timestamp:
- Apr 21, 2006, 5:21:00 PM (20 years ago)
- File:
-
- 1 edited
-
trunk/psModules/src/detrend/pmFringeStats.c (modified) (11 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psModules/src/detrend/pmFringeStats.c
r6921 r6957 3 3 * @author Eugene Magnier, IfA 4 4 * 5 * @version $Revision: 1. 3$ $Name: not supported by cvs2svn $6 * @date $Date: 2006-04-2 0 04:28:00 $5 * @version $Revision: 1.4 $ $Name: not supported by cvs2svn $ 6 * @date $Date: 2006-04-22 03:21:00 $ 7 7 * 8 8 * Copyright 2004 IfA 9 9 */ 10 10 11 #include <stdio.h> 12 #include <assert.h> 11 13 #include "pslib.h" 12 14 #include "pmFPA.h" … … 15 17 #define MAX(x,y) ((x) > (y) ? (x) : (y)) 16 18 #define MIN(x,y) ((x) < (y) ? (x) : (y)) 19 20 21 // Future optimisations for speed: 22 // 23 // 1. Clipping --- don't re-do the matrix setup again, but carry matrix and vector around, subtract 24 // contributions from clipped data points. 25 // 2. Faster psImageStats (use memcpy?) 26 27 28 29 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// 30 // pmFringeRegions 31 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// 17 32 18 33 static void fringeRegionsFree(pmFringeRegions *fringe) … … 44 59 } 45 60 46 47 static void fringeStatsFree(pmFringeStats *stats) 48 { 49 psFree(stats->regions); 50 psFree(stats->f); 51 psFree(stats->df); 52 } 53 54 pmFringeStats *pmFringeStatsAlloc(pmFringeRegions *regions) 55 { 56 pmFringeStats *stats = psAlloc(sizeof(pmFringeStats)); 57 (void)psMemSetDeallocator(stats, (psFreeFunc)fringeStatsFree); 58 59 stats->regions = psMemIncrRefCounter(regions); 60 stats->f = psVectorAlloc(regions->x->n, PS_TYPE_F32); 61 stats->f->n = regions->x->n; 62 stats->df = psVectorAlloc(regions->x->n, PS_TYPE_F32); 63 stats->df->n = regions->x->n; 64 65 return stats; 66 } 67 68 69 static void fringeScaleFree(pmFringeScale *scale) 70 { 71 psFree(scale->coeff); 72 psFree(scale->coeffErr); 73 return; 74 } 75 76 pmFringeScale *pmFringeScaleAlloc(int nFringeFrames) 77 { 78 pmFringeScale *scale = psAlloc(sizeof(pmFringeScale)); 79 (void)psMemSetDeallocator(scale, (psFreeFunc)fringeScaleFree); 80 81 scale->nFringeFrames = nFringeFrames; 82 scale->coeff = psVectorAlloc(nFringeFrames + 1, PS_TYPE_F32); 83 scale->coeffErr = psVectorAlloc(nFringeFrames + 1, PS_TYPE_F32); 84 scale->coeff->n = nFringeFrames + 1; 85 scale->coeff->n = nFringeFrames + 1; 86 87 return scale; 88 } 89 90 bool pmFringeRegionsCreatePoints(pmFringeRegions *fringe, psImage *image) 61 bool pmFringeRegionsCreatePoints(pmFringeRegions *fringe, const psImage *image) 91 62 { 92 63 … … 100 71 fringe->mask = psVectorRecycle(fringe->mask, fringe->nRequested, PS_TYPE_U8); 101 72 fringe->x->n = fringe->y->n = fringe->mask->n = fringe->nRequested; 73 psVectorInit(fringe->mask, 0); 102 74 103 75 int nX = image->numCols; … … 120 92 } 121 93 94 95 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// 96 // pmFringeStats 97 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// 98 99 static void fringeStatsFree(pmFringeStats *stats) 100 { 101 psFree(stats->regions); 102 psFree(stats->f); 103 psFree(stats->df); 104 } 105 106 pmFringeStats *pmFringeStatsAlloc(pmFringeRegions *regions) 107 { 108 pmFringeStats *stats = psAlloc(sizeof(pmFringeStats)); 109 (void)psMemSetDeallocator(stats, (psFreeFunc)fringeStatsFree); 110 111 int numRegions = regions->x->n; // Number of regions 112 stats->regions = psMemIncrRefCounter(regions); 113 stats->f = psVectorAlloc(numRegions, PS_TYPE_F32); 114 stats->df = psVectorAlloc(numRegions, PS_TYPE_F32); 115 stats->f->n = stats->df->n = numRegions; 116 117 return stats; 118 } 119 122 120 pmFringeStats *pmFringeStatsMeasure(pmFringeRegions *fringe, pmReadout *readout, psMaskType maskVal) 123 121 { … … 143 141 psImage *mask = readout->mask; 144 142 145 psStats *stats = psStatsAlloc(PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV); 143 psStats *median = psStatsAlloc(PS_STAT_SAMPLE_MEDIAN); // Median statistics only 144 psStats *medianSd = psStatsAlloc(PS_STAT_SAMPLE_MEDIAN | PS_STAT_SAMPLE_STDEV); // Median and SD 145 146 // Measure the sky over the image 147 psImage *sky = psImageAlloc(fringe->nX, fringe->nY, PS_TYPE_F32); 148 for (int i = 0; i < fringe->nY; i++) { 149 int y0 = (float)i * (float)image->numRows / (float)fringe->nY; 150 int y1 = (float)(i + 1) * (float)image->numRows / (float)fringe->nY; 151 for (int j = 0; j < fringe->nX; j++) { 152 int x0 = (float)j * (float)image->numCols / (float)fringe->nX; 153 int x1 = (float)(j + 1) * (float)image->numCols / (float)fringe->nX; 154 psRegion region = psRegionSet(x0, x1, y0, y1); 155 psImage *subImage = psImageSubset(image, region); // Subimage of the sky region 156 psImage *subMask = psImageSubset(mask, region); // Subimage of the sky region 157 psImageStats(median, subImage, subMask, maskVal); 158 sky->data.F32[i][j] = median->sampleMedian; 159 } 160 } 146 161 147 162 for (int i = 0; i < fringe->x->n; i++) { … … 150 165 psImage *subImage = psImageSubset(image, region); 151 166 psImage *subMask = psImageSubset(mask, region); 152 psImageStats(stats, subImage, subMask, maskVal); 153 154 fPt[i] = stats->robustMedian; 155 dfPt[i] = stats->robustStdev; 156 157 psTrace(__func__, 7, "[%d:%d,%d:%d]: %f %f\n", region.x0, region.x1, region.y0, region.y1, 158 fPt[i], dfPt[i]); 167 psImageStats(medianSd, subImage, subMask, maskVal); 168 psFree(subImage); 169 psFree(subMask); 170 171 int xSky = xPt[i] / (float)image->numCols * (float)sky->numCols; 172 int ySky = yPt[i] / (float)image->numRows * (float)sky->numRows; 173 174 fPt[i] = medianSd->sampleMedian - sky->data.F32[ySky][xSky]; 175 dfPt[i] = 1.0 / medianSd->sampleStdev; 176 177 psTrace(__func__, 7, "[%d:%d,%d:%d]: %f %f\n", (int)region.x0, (int)region.x1, 178 (int)region.y0, (int)region.y1, fPt[i], dfPt[i]); 159 179 } 160 180 … … 162 182 } 163 183 164 // XXX include the fringe error (fringe->df) in the fit? 165 pmFringeScale *pmFringeScaleMeasure(pmFringeStats *science, psArray *fringes) 166 { 167 pmFringeScale *scale = pmFringeScaleAlloc(fringes->n); // The resultant fringe scales 168 169 int numCoeffs = fringes->n + 1; 170 int numPoints = science->f->n; 171 172 psImage *A = psImageAlloc(numCoeffs, numCoeffs, PS_TYPE_F64); 173 psVector *B = psVectorAlloc(numCoeffs, PS_TYPE_F64); 184 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// 185 // pmFringeScale 186 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// 187 188 static void fringeScaleFree(pmFringeScale *scale) 189 { 190 psFree(scale->coeff); 191 psFree(scale->coeffErr); 192 return; 193 } 194 195 pmFringeScale *pmFringeScaleAlloc(int nFringeFrames) 196 { 197 pmFringeScale *scale = psAlloc(sizeof(pmFringeScale)); 198 (void)psMemSetDeallocator(scale, (psFreeFunc)fringeScaleFree); 199 200 scale->nFringeFrames = nFringeFrames; 201 scale->coeff = psVectorAlloc(nFringeFrames + 1, PS_TYPE_F32); 202 scale->coeffErr = psVectorAlloc(nFringeFrames + 1, PS_TYPE_F32); 203 scale->coeff->n = nFringeFrames + 1; 204 scale->coeff->n = nFringeFrames + 1; 205 206 return scale; 207 } 208 209 // Determine the fringe scales through solving the least-squares problem 210 static bool scaleMeasure(pmFringeScale *scale, // Scale to return 211 pmFringeStats *science, // The fringe measurements for the science image 212 psArray *fringes // Array of fringe measurements for the templates 213 ) 214 { 215 assert(scale); 216 assert(science); 217 assert(fringes); 218 assert(scale->nFringeFrames == fringes->n); 219 220 psVector *mask = science->regions->mask; // The region mask 221 222 int numCoeffs = fringes->n + 1; // Number of coefficients: scales for the templates plus a background 223 int numPoints = science->regions->nRequested; // Number of points (i.e., fringe measurements) 224 225 psImage *A = psImageAlloc(numCoeffs, numCoeffs, PS_TYPE_F64); // The least-squares matrix 226 psVector *B = psVectorAlloc(numCoeffs, PS_TYPE_F64); // The least-squares vector 174 227 B->n = numCoeffs; 175 228 229 // Generate the least-squares matrix and vector 176 230 for (int i = 0; i < numCoeffs; i++) { 177 psVector *fringe1 = NULL; 231 psVector *fringe1 = NULL; // A fringe measurement 178 232 if (i != 0) { 179 233 pmFringeStats *fringe = fringes->data[i - 1]; 180 234 fringe1 = fringe->f; 181 235 } 182 for (int j = 0; j < numCoeffs; j++) { 183 psVector *fringe2 = NULL; 236 237 // Fill in the upper part of the matrix 238 for (int j = i; j < numCoeffs; j++) { 239 psVector *fringe2 = NULL; // Another fringe measurement 184 240 if (j != 0) { 185 241 pmFringeStats *fringe = fringes->data[j - 1]; … … 187 243 } 188 244 189 double sum = 0.0;245 double matrix = 0.0; // The matrix sum 190 246 for (int k = 0; k < numPoints; k++) { 191 psF32 f1 = (fringe1 == NULL) ? 1.0 : fringe1->data.F32[k]; 192 psF32 f2 = (fringe2 == NULL) ? 1.0 : fringe2->data.F32[k]; 193 sum += f1*f2; 194 } 195 A->data.F64[i][j] = sum; 196 } 197 198 double sum = 0.0; 199 for (int j = 0; j < numPoints; j++) { 200 psF32 f1 = (fringe1 == NULL) ? 1.0 : fringe1->data.F32[j]; 201 psF32 f2 = science->f->data.F32[j]; 202 sum += f1*f2; 203 } 204 B->data.F64[i] = sum; 205 } 206 247 if (!mask->data.U8[k]) { 248 psF32 f1 = (fringe1) ? fringe1->data.F32[k] : 1.0; // Contribution from i fringe 249 psF32 f2 = (fringe2) ? fringe2->data.F32[k] : 1.0; // Contribution from j fringe 250 psF32 dsInv = science->df->data.F32[k]; // 1 / sigma 251 matrix += f1 * f2 * dsInv * dsInv; 252 } 253 } 254 A->data.F64[i][j] = matrix; 255 } 256 257 // Use symmetry to fill in the lower part of the matrix 258 for (int j = 0; j < i; j++) { 259 A->data.F64[i][j] = A->data.F64[j][i]; 260 } 261 262 double vector = 0.0; // The vector sum 263 for (int k = 0; k < numPoints; k++) { 264 if (!mask->data.U8[k]) { 265 psF32 f1 = (fringe1) ? fringe1->data.F32[k] : 1.0; // Contribution from fringe 1 266 psF32 s = science->f->data.F32[k]; // Contribution from science measurement 267 psF32 dsInv = science->df->data.F32[k]; // 1 / sigma 268 vector += f1 * s * dsInv * dsInv; 269 } 270 } 271 B->data.F64[i] = vector; 272 } 273 274 if (psTraceGetLevel(__func__) >= 5) { 275 printf("From %d points:\n", numPoints); 276 for (int i = 0; i < numCoeffs; i++) { 277 for (int j = 0; j < numCoeffs; j++) { 278 printf("%.2e ", A->data.F64[i][j]); 279 } 280 printf("\n"); 281 } 282 } 283 284 // Solve the least-squares equation 207 285 if (! psGaussJordan(A, B)) { 208 286 psError(PS_ERR_UNKNOWN, false, "Could not solve linear equations. Returning NULL.\n"); 209 } 210 287 return false; 288 } 289 290 // Copy the results over 211 291 for (int i = 0; i < numCoeffs; i++) { 212 292 scale->coeff->data.F32[i] = B->data.F64[i]; … … 214 294 } 215 295 296 return true; 297 } 298 299 // Measure the fringe differences for each region 300 static bool fringeScaleDiffs(psVector *diff, // Vector of differences 301 pmFringeStats *science, // Science fringe measurements 302 psArray *fringes, // Template fringe measurements 303 pmFringeScale *scale // Fringe scales 304 ) 305 { 306 assert(diff); 307 assert(diff->type.type == PS_TYPE_F32); 308 assert(science); 309 assert(fringes); 310 assert(scale); 311 assert(diff->n == science->regions->nRequested); 312 assert(fringes->n == scale->nFringeFrames); 313 314 psVector *mask = science->regions->mask; // The region mask 315 316 for (int i = 0; i < diff->n; i++) { 317 if (!mask->data.U8[i]) { 318 float difference = science->f->data.F32[i] - scale->coeff->data.F32[0]; 319 for (int j = 0; j < fringes->n; j++) { 320 pmFringeStats *fringe = fringes->data[j]; // The fringe of interest 321 difference -= scale->coeff->data.F32[j + 1] * fringe->f->data.F32[i]; 322 } 323 diff->data.F32[i] = difference * difference * science->df->data.F32[i] * science->df->data.F32[i]; 324 } 325 } 326 327 return true; 328 } 329 330 // Clip regions based on the differences; return the number masked 331 static int clipRegions(psVector *diffs, // Differences 332 psVector *mask, // Region mask 333 float rej // Rejection limit in standard deviations 334 ) 335 { 336 assert(diffs); 337 assert(diffs->type.type == PS_TYPE_F32); 338 assert(mask); 339 assert(mask->type.type == PS_TYPE_U8); 340 assert(diffs->n == mask->n); 341 342 psStats *stats = psStatsAlloc(PS_STAT_SAMPLE_MEDIAN | PS_STAT_SAMPLE_QUARTILE); // Statistics 343 psVectorStats(stats, diffs, NULL, mask, 1); 344 float middle = stats->sampleMedian; // The middle of the distribution 345 float thresh = rej * 0.74 * (stats->sampleUQ - stats->sampleLQ); // The rejection threshold 346 psFree(stats); 347 348 int numClipped = 0; // Number clipped 349 for (int i = 0; i < diffs->n; i++) { 350 psTrace(__func__, 10, "Region %d (%d): %f\n", i, mask->data.U8[i], diffs->data.F32[i]); 351 if (!mask->data.U8[i] && fabs(diffs->data.F32[i]) > middle + thresh) { 352 psTrace(__func__, 5, "Masking %d: %f\n", i, diffs->data.F32[i]); 353 mask->data.U8[i] = 1; 354 numClipped++; 355 } 356 } 357 358 return numClipped; 359 } 360 361 362 // XXX include the fringe error (fringe->df) in the fit? 363 pmFringeScale *pmFringeScaleMeasure(pmFringeStats *science, psArray *fringes, float rej, 364 unsigned int nIter, float keepFrac) 365 { 366 pmFringeRegions *regions = science->regions; // The fringe regions 367 int numRegions = regions->nRequested; // Number of regions 368 if (!regions->mask) { 369 regions->mask = psVectorAlloc(numRegions, PS_TYPE_U8); 370 regions->mask->n = numRegions; 371 psVectorInit(regions->mask, 0); 372 } 373 374 psVector *mask = regions->mask; // The region mask 375 psStats *median = psStatsAlloc(PS_STAT_SAMPLE_MEDIAN); // Median statistics 376 unsigned int numClipped = 0; // Total number clipped 377 psVector *diff = psVectorAlloc(numRegions, PS_TYPE_F32); // The differences between obs. and pred. 378 diff->n = numRegions; 379 380 pmFringeScale *scale = pmFringeScaleAlloc(fringes->n); // The fringe scales 381 382 // Get rid of bad data points 383 for (int i = 0; i < fringes->n; i++) { 384 pmFringeStats *fringe = fringes->data[i]; // The fringe of interest 385 for (int j = 0; j < numRegions; j++) { 386 if (!finite(fringe->f->data.F32[j])) { 387 mask->data.U8[j] = 1; 388 psTrace(__func__, 9, "Masking region %d because not finite in fringe %d.\n", j, i); 389 } 390 } 391 } 392 393 // Get rid of the extreme outliers by assuming most of the points are somewhat clustered 394 psVectorStats(median, science->f, NULL, NULL, 0); 395 scale->coeff->data.F32[0] = median->sampleMedian; 396 for (int i = 0; i < fringes->n; i++) { 397 pmFringeStats *fringe = fringes->data[i]; // The fringe of interest 398 psVectorStats(median, fringe->f, NULL, NULL, 0); 399 scale->coeff->data.F32[0] -= median->sampleMedian; 400 scale->coeff->data.F32[i] = 0.0; 401 } 402 psFree(median); 403 fringeScaleDiffs(diff, science, fringes, scale); 404 numClipped = clipRegions(diff, mask, 3.0*rej); 405 psTrace(__func__, 4, "%d regions clipped in initial pass.\n", numClipped); 406 407 unsigned int iter = 0; // Iteration number 408 unsigned int iterClip = 0; // Number clipped in this iteration 409 do { 410 iter++; 411 scaleMeasure(scale, science, fringes); // The scales 412 psTrace(__func__, 1, "Fringe scales after iteration %d:\n", iter); 413 psTrace(__func__, 1, "Background: %f %f\n", scale->coeff->data.F32[0], scale->coeffErr->data.F32[0]); 414 for (int i = 0; i < scale->nFringeFrames; i++) { 415 psTrace(__func__, 1, "%d: %f %f\n", i, scale->coeff->data.F32[i + 1], 416 scale->coeffErr->data.F32[i + 1]); 417 } 418 419 fringeScaleDiffs(diff, science, fringes, scale); 420 iterClip = clipRegions(diff, mask, rej); // Number clipped 421 numClipped += iterClip; 422 psTrace(__func__, 9, "Clipped: %d\tFrac: %f\n", iterClip, (float)numClipped/(float)numRegions); 423 } while (iterClip > 0 && iter < nIter && (float)numClipped/(float)numRegions <= 1.0 - keepFrac); 424 psFree(diff); 425 426 // A final iteration with the last clipping 427 scaleMeasure(scale, science, fringes); 428 216 429 return scale; 217 430 } 218 431 432 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// 433 // Fringe correction 434 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// 435 219 436 // XXX note that this modifies the input fringe images 220 psImage *pmFringeCorrect(pmReadout *readout, pmFringeRegions *fringes, psArray *fringeImages, psArray *fringeStats, psMaskType maskVal) 437 psImage *pmFringeCorrect(pmReadout *readout, pmFringeRegions *fringes, psArray *fringeImages, 438 psArray *fringeStats, psMaskType maskVal, float rej, 439 unsigned int nIter, float keepFrac) 221 440 { 222 441 // measure the fringe stats for the science frame and solve for the scales 223 442 pmFringeStats *scienceStats = pmFringeStatsMeasure(fringes, readout, maskVal); 224 pmFringeScale *scale = pmFringeScaleMeasure(scienceStats, fringeStats); 443 444 if (psTraceGetLevel(__func__) > 9) { 445 for (int i = 0; i < fringes->nRequested; i++) { 446 printf("%f", scienceStats->f->data.F32[i]); 447 for (int j = 0; j < fringeStats->n; j++) { 448 pmFringeStats *fringe = fringeStats->data[j]; 449 printf("\t%f", fringe->f->data.F32[i]); 450 } 451 printf("\n"); 452 } 453 } 454 455 pmFringeScale *scale = pmFringeScaleMeasure(scienceStats, fringeStats, rej, nIter, keepFrac); 225 456 psFree(scienceStats); 226 457 227 458 psTrace(__func__, 7, "Fringe solution:\n"); 228 for (int i = 0; i < fringeImages->n ; i++) {459 for (int i = 0; i < fringeImages->n + 1; i++) { 229 460 psTrace(__func__, 7, "%d: %f %f\n", i, scale->coeff->data.F32[i], 230 461 scale->coeffErr->data.F32[i]); … … 234 465 // XXX we could save data space by making the first image the output image 235 466 psImage *sumFringe = psImageAlloc(readout->image->numCols, readout->image->numRows, PS_TYPE_F32); 467 //psBinaryOp(sumFringe, sumFringe, "+", psScalarAlloc(scale->coeff->data.F32[0], PS_TYPE_F32)); 236 468 for (int i = 0; i < fringeImages->n; i++) { 237 469
Note:
See TracChangeset
for help on using the changeset viewer.
