- Timestamp:
- May 3, 2010, 8:41:49 AM (16 years ago)
- Location:
- branches/tap_branches
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/tap_branches
- Property svn:mergeinfo changed
-
branches/tap_branches/psModules
-
Property svn:mergeinfo
set to (toggle deleted branches)
/trunk/psModules merged eligible /branches/eam_branches/stackphot.20100406/psModules 27623-27653 /branches/pap_delete/psModules 27530-27595
-
Property svn:mergeinfo
set to (toggle deleted branches)
-
branches/tap_branches/psModules/src/imcombine/pmSubtraction.c
r25279 r27838 17 17 #include <pslib.h> 18 18 19 #include "pmErrorCodes.h" 19 20 #include "pmHDU.h" // Required for pmFPA.h 20 21 #include "pmFPA.h" 21 22 #include "pmSubtractionStamps.h" 22 23 #include "pmSubtractionEquation.h" 24 #include "pmSubtractionVisual.h" 23 25 #include "pmSubtractionThreads.h" 24 26 … … 29 31 #define PIXEL_LIST_BUFFER 100 // Number of entries to add to pixel list at a time 30 32 #define MIN_SAMPLE_STATS 7 // Minimum number to use sample statistics; otherwise use quartiles 33 #define USE_KERNEL_ERR // Use kernel error image? 31 34 32 35 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// … … 36 39 // Generate the kernel to apply to the variance from the normal kernel 37 40 static psKernel *varianceKernel(psKernel *out, // Output kernel 38 psKernel *normalKernel // Normal kernel41 const psKernel *normalKernel // Normal kernel 39 42 ) 40 43 { … … 48 51 49 52 // Take the square of the normal kernel 50 double sum Normal = 0.0, sumVariance = 0.0; // Sum of the normal andvariance kernels53 double sumVariance = 0.0; // Sum of the variance kernels 51 54 for (int v = yMin; v <= yMax; v++) { 52 55 for (int u = xMin; u <= xMax; u++) { 53 float value = normalKernel->kernel[v][u]; // Value of interest 54 float value2 = PS_SQR(value); // Value squared 55 sumNormal += value; 56 sumVariance += value2; 57 out->kernel[v][u] = value2; 56 sumVariance += out->kernel[v][u] = PS_SQR(normalKernel->kernel[v][u]); 58 57 } 59 58 } … … 65 64 return out; 66 65 } 66 67 // Contribute to an image of the solved kernel component using the preCalculated image 68 static void solvedKernelPreCalc(psKernel *kernel, // Kernel, updated 69 const pmSubtractionKernels *kernels, // Kernel basis functions 70 float value, // Normalisation value for basis function 71 int index // Index of basis function of interest 72 ) 73 { 74 int size = kernels->size; // Kernel half-size 75 pmSubtractionKernelPreCalc *preCalc = kernels->preCalc->data[index]; // Precalculated values 76 #if 0 77 // Iterating over the kernel 78 for (int y = 0, v = -size; v <= size; y++, v++) { 79 float yValue = value * preCalc->yKernel->data.F32[y]; 80 for (int x = 0, u = -size; u <= size; x++, u++) { 81 kernel->kernel[v][u] += yValue * preCalc->xKernel->data.F32[x]; 82 } 83 } 84 // Photometric scaling for even kernels only 85 if (kernels->u->data.S32[i] % 2 == 0 && kernels->v->data.S32[i] % 2 == 0) { 86 kernel->kernel[0][0] -= value; 87 } 88 #else 89 for (int v = -size; v <= size; v++) { 90 for (int u = -size; u <= size; u++) { 91 kernel->kernel[v][u] += value * preCalc->kernel->kernel[v][u]; 92 } 93 } 94 #endif 95 96 return; 97 } 98 67 99 68 100 // Generate an image of the solved kernel … … 70 102 const pmSubtractionKernels *kernels, // Kernel basis functions 71 103 const psImage *polyValues, // Spatial polynomial values 104 bool normalise, // Add normalisation? 72 105 bool wantDual // Want the dual (second) kernel? 73 106 ) … … 85 118 for (int i = 0; i < numKernels; i++) { 86 119 double value = p_pmSubtractionSolutionCoeff(kernels, polyValues, i, wantDual); // Polynomial value 120 if (wantDual) { 121 // The model is built with the dual convolution terms added, so to produce zero residual the 122 // equation results in negative coefficients which we must undo. 123 value *= -1.0; 124 } 87 125 88 126 switch (kernels->type) { … … 115 153 case PM_SUBTRACTION_KERNEL_GUNK: { 116 154 if (i < kernels->inner) { 117 // Using pre-calculated function 118 psKernel *preCalc = kernels->preCalc->data[i]; // Precalculated values 119 // Iterating over the kernel 120 for (int v = -size; v <= size; v++) { 121 for (int u = -size; u <= size; u++) { 122 kernel->kernel[v][u] += preCalc->kernel[v][u] * value; 123 // Photometric scaling is built into the preCalc kernel --- no subtraction! 124 } 125 } 155 solvedKernelPreCalc(kernel, kernels, value, i); 126 156 } else { 127 157 // Using delta function … … 133 163 break; 134 164 } 135 case PM_SUBTRACTION_KERNEL_ISIS: { 136 psArray *preCalc = kernels->preCalc->data[i]; // Precalculated values 137 psVector *xKernel = preCalc->data[0]; // Kernel in x 138 psVector *yKernel = preCalc->data[1]; // Kernel in y 139 // Iterating over the kernel 140 for (int y = 0, v = -size; v <= size; y++, v++) { 141 for (int x = 0, u = -size; u <= size; x++, u++) { 142 kernel->kernel[v][u] += value * xKernel->data.F32[x] * yKernel->data.F32[y]; 143 } 144 } 145 // Photometric scaling for even kernels only 146 if (kernels->u->data.S32[i] % 2 == 0 && kernels->v->data.S32[i] % 2 == 0) { 147 kernel->kernel[0][0] -= value; 148 } 165 case PM_SUBTRACTION_KERNEL_ISIS: 166 case PM_SUBTRACTION_KERNEL_ISIS_RADIAL: 167 case PM_SUBTRACTION_KERNEL_HERM: 168 case PM_SUBTRACTION_KERNEL_DECONV_HERM: { 169 solvedKernelPreCalc(kernel, kernels, value, i); 149 170 break; 150 171 } 151 172 case PM_SUBTRACTION_KERNEL_RINGS: { 152 psArray *preCalc = kernels->preCalc->data[i]; // Precalculated data 153 psVector *uCoords = preCalc->data[0]; // u coordinates 154 psVector *vCoords = preCalc->data[1]; // v coordinates 155 psVector *poly = preCalc->data[2]; // Polynomial values 156 int num = uCoords->n; // Number of pixels 173 pmSubtractionKernelPreCalc *preCalc = kernels->preCalc->data[i]; // Precalculated kernels 174 int num = preCalc->uCoords->n; // Number of pixels 157 175 158 176 for (int j = 0; j < num; j++) { 159 int u = uCoords->data.S32[j], v = vCoords->data.S32[j]; // Kernel coordinates 160 kernel->kernel[v][u] += poly->data.F32[j] * value; 177 int u = preCalc->uCoords->data.S32[j]; 178 int v = preCalc->vCoords->data.S32[j]; // Kernel coordinates 179 kernel->kernel[v][u] += preCalc->poly->data.F32[j] * value; 161 180 } 162 181 // Photometric scaling is built into the kernel --- no subtraction! … … 168 187 } 169 188 170 // Put in the normalisation component 171 kernel->kernel[0][0] += (wantDual ? 1.0 : p_pmSubtractionSolutionNorm(kernels)); 189 if (normalise) { 190 // Put in the normalisation component 191 kernel->kernel[0][0] += (wantDual ? 1.0 : p_pmSubtractionSolutionNorm(kernels)); 192 } 172 193 173 194 return kernel; … … 250 271 static void convolveVarianceFFT(psImage *target,// Place the result in here 251 272 psImage *variance, // Variance map to convolve 252 psImage * sys, // Systematicerror image273 psImage *kernelErr, // Kernel error image 253 274 psImage *mask, // Mask image 254 275 psImageMaskType maskVal, // Value to mask … … 262 283 263 284 psImage *subVariance = variance ? psImageSubset(variance, border) : NULL; // Variance map 264 psImage *sub Sys = sys ? psImageSubset(sys, border) : NULL; // Systematicerror image285 psImage *subKE = kernelErr ? psImageSubset(kernelErr, border) : NULL; // Kernel error image 265 286 psImage *subMask = mask ? psImageSubset(mask, border) : NULL; // Mask 266 287 267 288 // XXX Can trim this a little by combining the convolution: only have to take the FFT of the kernel once 268 289 psImage *convVariance = psImageConvolveFFT(NULL, subVariance, subMask, maskVal, kernel); // Convolved variance 269 psImage *conv Sys = subSys ? psImageConvolveFFT(NULL, subSys, subMask, maskVal, kernel) : NULL; // Conv sys290 psImage *convKE = subKE ? psImageConvolveFFT(NULL, subKE, subMask, maskVal, kernel) : NULL; // Conv KE 270 291 271 292 psFree(subVariance); 272 psFree(sub Sys);293 psFree(subKE); 273 294 psFree(subMask); 274 295 275 296 // Now, we have to stick it in where it belongs 276 297 int xMin = region.x0, xMax = region.x1, yMin = region.y0, yMax = region.y1; // Bounds of region 277 if (conv Sys) {298 if (convKE) { 278 299 for (int yTarget = yMin, ySource = size; yTarget < yMax; yTarget++, ySource++) { 279 300 for (int xTarget = xMin, xSource = size; xTarget < xMax; xTarget++, xSource++) { 280 301 target->data.F32[yTarget][xTarget] = convVariance->data.F32[ySource][xSource] + 281 conv Sys->data.F32[ySource][xSource];302 convKE->data.F32[ySource][xSource]; 282 303 } 283 304 } … … 290 311 291 312 psFree(convVariance); 292 psFree(conv Sys);313 psFree(convKE); 293 314 294 315 return; … … 326 347 psImage *image, // Image to convolve 327 348 psImage *variance, // Variance map to convolve, or NULL 328 psImage * sys, // Systematicerror image, or NULL349 psImage *kernelErr, // Kernel error image, or NULL 329 350 psImage *subMask, // Subtraction mask 330 351 const pmSubtractionKernels *kernels, // Kernels … … 339 360 ) 340 361 { 341 *kernelImage = solvedKernel(*kernelImage, kernels, polyValues, wantDual);362 *kernelImage = solvedKernel(*kernelImage, kernels, polyValues, true, wantDual); 342 363 if (variance || subMask) { 343 364 *kernelVariance = varianceKernel(*kernelVariance, *kernelImage); … … 363 384 convolveFFT(convImage, image, subMask, subBad, *kernelImage, region, background, kernels->size); 364 385 if (variance) { 365 convolveVarianceFFT(convVariance, variance, sys, subMask, subBad, *kernelVariance, region, kernels->size); 386 convolveVarianceFFT(convVariance, variance, kernelErr, subMask, subBad, *kernelVariance, 387 region, kernels->size); 366 388 } 367 389 } else { … … 373 395 } 374 396 375 // Convolve the mask for bad pixels397 // Convolve the mask for bad/poor pixels 376 398 if (subMask && convMask) { 377 399 int box = p_pmSubtractionBadRadius(*kernelImage, kernels, polyValues, 378 400 wantDual, poorFrac); // Size of bad box 401 psAssert(box >= 0, "Bad radius must be >= 0"); 402 403 int colMin = region.x0, colMax = region.x1, rowMin = region.y0, rowMax = region.y1; // Bounds 404 psImage *convolved = NULL; // Convolved subtraction mask 379 405 if (box > 0) { 380 int colMin = region.x0, colMax = region.x1, rowMin = region.y0, rowMax = region.y1; // Bounds 381 psRegion region = psRegionSet(colMin - box, colMax + box, 382 rowMin - box, rowMax + box); // Region to convolve 383 384 psImage *image = subMask ? psImageSubset(subMask, region) : NULL; // Mask to convolve 385 386 psImage *convolved = psImageConvolveMask(NULL, image, subBad, subConvBad, 387 -box, box, -box, box); // Convolved subtraction mask 388 406 psRegion maskRegion = psRegionSet(colMin - box, colMax + box, 407 rowMin - box, rowMax + box); // Region to convolve 408 psImage *image = subMask ? psImageSubset(subMask, maskRegion) : NULL; // Mask to convolve 409 convolved = psImageConvolveMask(NULL, image, subBad, subConvBad, -box, box, -box, box); 389 410 psFree(image); 390 391 psAssert(convolved->numCols - 2 * box == colMax - colMin, "Bad number of columns"); 392 psAssert(convolved->numRows - 2 * box == rowMax - rowMin, "Bad number of rows"); 393 394 for (int yTarget = rowMin, ySource = box; yTarget < rowMax; yTarget++, ySource++) { 395 // Dereference images 396 psImageMaskType *target = &convMask->data.PS_TYPE_IMAGE_MASK_DATA[yTarget][colMin]; // Target values 397 psImageMaskType *source = &convolved->data.PS_TYPE_IMAGE_MASK_DATA[ySource][box]; // Source values 398 for (int xTarget = colMin; xTarget < colMax; xTarget++, target++, source++) { 399 if (*source & subConvBad) { 400 *target |= maskBad; 401 } else if (*source & subConvPoor) { 402 *target |= maskPoor; 403 } 411 } else { 412 convolved = psImageSubset(subMask, region); 413 } 414 415 psAssert(convolved->numCols - 2 * box == colMax - colMin, "Bad number of columns"); 416 psAssert(convolved->numRows - 2 * box == rowMax - rowMin, "Bad number of rows"); 417 418 for (int yTarget = rowMin, ySource = box; yTarget < rowMax; yTarget++, ySource++) { 419 // Dereference images 420 psImageMaskType *target = &convMask->data.PS_TYPE_IMAGE_MASK_DATA[yTarget][colMin]; // Target values 421 psImageMaskType *source = &convolved->data.PS_TYPE_IMAGE_MASK_DATA[ySource][box]; // Source values 422 for (int xTarget = colMin; xTarget < colMax; xTarget++, target++, source++) { 423 if (*source & subConvBad) { 424 *target |= maskBad; 425 } else if (*source & subConvPoor) { 426 *target &= ~maskBad; 427 *target |= maskPoor; 428 } else { 429 *target &= ~maskBad & ~maskPoor; 404 430 } 405 431 } 406 407 // No need to lock: we own this 408 psFree(convolved); 409 } 432 } 433 434 psFree(convolved); 410 435 } 411 436 … … 413 438 } 414 439 415 // Generate an image that can be used to track systematic errors 416 static psImage *subtractionSysErrImage(const psImage *image, // Image from which to make sys err image 417 float sysError // Relative systematic error 418 ) 419 { 420 if (!isfinite(sysError) || sysError == 0.0) { 440 #ifdef USE_KERNEL_ERR 441 // Generate an image that can be used to track systematic errors in the kernel 442 static psImage *subtractionKernelErrImage(const psImage *image, // Image from which to make kernel error image 443 float kernelError // Relative systematic error in kernel 444 ) 445 { 446 if (!isfinite(kernelError) || kernelError == 0.0) { 421 447 return NULL; 422 448 } 423 449 424 450 int numCols = image->numCols, numRows = image->numRows; // Size of image 425 psImage * sys = psImageAlloc(numCols, numRows, PS_TYPE_F32); // Systematicerror image426 427 float sysError2 = PS_SQR(sysError); // Square of the systematicerror451 psImage *kernelErr = psImageAlloc(numCols, numRows, PS_TYPE_F32); // Kernel error image 452 453 float kernelError2 = PS_SQR(kernelError); // Square of the kernel error 428 454 for (int y = 0; y < numRows; y++) { 429 455 for (int x = 0; x < numCols; x++) { 430 sys->data.F32[y][x] = PS_SQR(image->data.F32[y][x]) * sysError2; 431 } 432 } 433 434 return sys; 456 kernelErr->data.F32[y][x] = PS_SQR(image->data.F32[y][x]) * kernelError2; 457 } 458 } 459 460 return kernelErr; 461 } 462 #endif 463 464 // Convolve a stamp using a pre-calculated kernel basis function 465 static psKernel *convolveStampPreCalc(const psKernel *image, // Image to convolve 466 const pmSubtractionKernels *kernels, // Kernel basis functions 467 int index, // Index of basis function of interest 468 int footprint // Half-size of stamp 469 ) 470 { 471 pmSubtractionKernelPreCalc *preCalc = kernels->preCalc->data[index]; // Precalculated data 472 #if 0 473 // Convolving using separable convolution 474 int size = kernels->size; // Size of kernel 475 476 // Convolve in x 477 // Need to convolve a bit more than the footprint, for the y convolution 478 int yMin = -size - footprint, yMax = size + footprint; // Range for y 479 psKernel *temp = psKernelAlloc(yMin, yMax, 480 -footprint, footprint); // Temporary convolution; NOTE: wrong way! 481 for (int y = yMin; y <= yMax; y++) { 482 for (int x = -footprint; x <= footprint; x++) { 483 float value = 0.0; // Value of convolved pixel 484 int uMin = x - size, uMax = x + size; // Range for u 485 psF32 *xKernelData = &preCalc->xKernel->data.F32[xKernel->n - 1]; // Kernel values 486 psF32 *imageData = &image->kernel[y][uMin]; // Image values 487 for (int u = uMin; u <= uMax; u++, xKernelData--, imageData++) { 488 value += *xKernelData * *imageData; 489 } 490 temp->kernel[x][y] = value; // NOTE: putting in wrong way! 491 } 492 } 493 494 // Convolve in y 495 psKernel *convolved = psKernelAlloc(-footprint, footprint, -footprint, footprint);// Convolved image 496 for (int x = -footprint; x <= footprint; x++) { 497 for (int y = -footprint; y <= footprint; y++) { 498 float value = 0.0; // Value of convolved pixel 499 int vMin = y - size, vMax = y + size; // Range for v 500 psF32 *yKernelData = &preCalc->yKernel->data.F32[yKernel->n - 1]; // Kernel values 501 psF32 *imageData = &temp->kernel[x][vMin]; // Image values; NOTE: wrong way! 502 for (int v = vMin; v <= vMax; v++, yKernelData--, imageData++) { 503 value += *yKernelData * *imageData; 504 } 505 convolved->kernel[y][x] = value; 506 } 507 } 508 psFree(temp); 509 510 // Photometric scaling for even kernels only 511 if (kernels->u->data.S32[index] % 2 == 0 && kernels->v->data.S32[index] % 2 == 0) { 512 convolveSub(convolved, image, footprint); 513 } 514 return convolved; 515 #else 516 // Convolving using precalculated kernel 517 return p_pmSubtractionConvolveStampPrecalc(image, preCalc->kernel); 518 #endif 435 519 } 436 520 … … 447 531 int x0 = - image->xMin, y0 = - image->yMin; // Position of centre of convolved image 448 532 psKernel *convolved = psKernelAllocFromImage(conv, x0, y0); // Kernel version 533 534 // pmSubtractionVisualShowSubtraction(image->image, kernel->image, conv); 535 449 536 psFree(conv); 450 537 return convolved; … … 456 543 psKernel *kernel; // Kernel to use 457 544 if (!preKernel) { 458 kernel = solvedKernel(NULL, kernels, polyValues, wantDual);545 kernel = solvedKernel(NULL, kernels, polyValues, true, wantDual); 459 546 } else { 460 547 kernel = psMemIncrRefCounter(preKernel); … … 491 578 } 492 579 580 void p_pmSubtractionPolynomialNormCoords(float *xOut, float *yOut, float xIn, float yIn, 581 int xMin, int xMax, int yMin, int yMax) 582 { 583 float xNormSize = xMax - xMin, yNormSize = yMax - yMin; // Size to use for normalisation 584 *xOut = 2.0 * (float)(xIn - xMin - xNormSize/2.0) / xNormSize; 585 *yOut = 2.0 * (float)(yIn - yMin - yNormSize/2.0) / yNormSize; 586 return; 587 } 588 493 589 psImage *p_pmSubtractionPolynomialFromCoords(psImage *output, const pmSubtractionKernels *kernels, 494 int numCols, int numRows, intx, int y)590 int x, int y) 495 591 { 496 592 assert(kernels); 497 assert(numCols > 0 && numRows > 0); 498 499 // Size to use when calculating normalised coordinates (different from actual size when convolving 500 // subimage) 501 int xNormSize = (kernels->numCols > 0 ? kernels->numCols : numCols); 502 int yNormSize = (kernels->numRows > 0 ? kernels->numRows : numRows); 503 504 // Normalised coordinates 505 float yNorm = 2.0 * (float)(y - yNormSize/2.0) / (float)yNormSize; 506 float xNorm = 2.0 * (float)(x - xNormSize/2.0) / (float)xNormSize; 507 593 594 float xNorm, yNorm; // Normalised coordinates 595 p_pmSubtractionPolynomialNormCoords(&xNorm, &yNorm, x, y, 596 kernels->xMin, kernels->xMax, kernels->yMin, kernels->yMax); 508 597 return p_pmSubtractionPolynomial(output, kernels->spatialOrder, xNorm, yNorm); 509 598 } … … 586 675 if (index < kernels->inner) { 587 676 // Photometric scaling is already built in to the precalculated kernel 588 return p_pmSubtractionConvolveStampPrecalc(image, kernels->preCalc->data[index]);677 return convolveStampPreCalc(image, kernels, index, footprint); 589 678 } 590 679 // Using delta function … … 595 684 return convolved; 596 685 } 597 case PM_SUBTRACTION_KERNEL_ISIS: { 598 psArray *preCalc = kernels->preCalc->data[index]; // Precalculated values 599 psVector *xKernel = preCalc->data[0]; // Kernel in x 600 psVector *yKernel = preCalc->data[1]; // Kernel in y 601 int size = kernels->size; // Size of kernel 602 603 // Convolve in x 604 // Need to convolve a bit more than the footprint, for the y convolution 605 int yMin = -size - footprint, yMax = size + footprint; // Range for y 606 psKernel *temp = psKernelAlloc(yMin, yMax, 607 -footprint, footprint); // Temporary convolution; NOTE: wrong way! 608 for (int y = yMin; y <= yMax; y++) { 609 for (int x = -footprint; x <= footprint; x++) { 610 float value = 0.0; // Value of convolved pixel 611 int uMin = x - size, uMax = x + size; // Range for u 612 psF32 *xKernelData = &xKernel->data.F32[xKernel->n - 1]; // Kernel values 613 psF32 *imageData = &image->kernel[y][uMin]; // Image values 614 for (int u = uMin; u <= uMax; u++, xKernelData--, imageData++) { 615 value += *xKernelData * *imageData; 616 } 617 temp->kernel[x][y] = value; // NOTE: putting in wrong way! 618 } 619 } 620 621 // Convolve in y 622 psKernel *convolved = psKernelAlloc(-footprint, footprint, -footprint, footprint);// Convolved image 623 for (int x = -footprint; x <= footprint; x++) { 624 for (int y = -footprint; y <= footprint; y++) { 625 float value = 0.0; // Value of convolved pixel 626 int vMin = y - size, vMax = y + size; // Range for v 627 psF32 *yKernelData = &yKernel->data.F32[yKernel->n - 1]; // Kernel values 628 psF32 *imageData = &temp->kernel[x][vMin]; // Image values; NOTE: wrong way! 629 for (int v = vMin; v <= vMax; v++, yKernelData--, imageData++) { 630 value += *yKernelData * *imageData; 631 } 632 convolved->kernel[y][x] = value; 633 } 634 } 635 psFree(temp); 636 637 // Photometric scaling for even kernels only 638 if (kernels->u->data.S32[index] % 2 == 0 && kernels->v->data.S32[index] % 2 == 0) { 639 convolveSub(convolved, image, footprint); 640 } 641 return convolved; 642 } 686 case PM_SUBTRACTION_KERNEL_ISIS: 687 case PM_SUBTRACTION_KERNEL_ISIS_RADIAL: 688 case PM_SUBTRACTION_KERNEL_HERM: 689 case PM_SUBTRACTION_KERNEL_DECONV_HERM: { 690 return convolveStampPreCalc(image, kernels, index, footprint); 691 } 643 692 case PM_SUBTRACTION_KERNEL_RINGS: { 644 psKernel *convolved = psKernelAlloc(-footprint, footprint, 645 -footprint, footprint); // Convolved image 646 psArray *preCalc = kernels->preCalc->data[index]; // Precalculated data 647 psVector *uCoords = preCalc->data[0]; // u coordinates 648 psVector *vCoords = preCalc->data[1]; // v coordinates 649 psVector *poly = preCalc->data[2]; // Polynomial values 650 int num = uCoords->n; // Number of pixels 651 psS32 *uData = uCoords->data.S32, *vData = vCoords->data.S32; // Dereference u,v coordinates 652 psF32 *polyData = poly->data.F32; // Dereference polynomial values 693 psKernel *convolved = psKernelAlloc(-footprint, footprint, -footprint, footprint); // Convolved image 694 pmSubtractionKernelPreCalc *preCalc = kernels->preCalc->data[index]; // Precalculated data 695 696 int num = preCalc->uCoords->n; // Number of pixels 697 psS32 *uData = preCalc->uCoords->data.S32; // Dereference v coordinate 698 psS32 *vData = preCalc->vCoords->data.S32; // Dereference u coordinate 699 psF32 *polyData = preCalc->poly->data.F32; // Dereference polynomial values 653 700 psF32 **imageData = image->kernel; // Dereference image 654 701 psF32 **convData = convolved->kernel; // Dereference convolved image … … 706 753 707 754 if (stamp->status != PM_SUBTRACTION_STAMP_CALCULATE) { 708 psError(P S_ERR_BAD_PARAMETER_VALUE, true, "Stamp not marked for calculation.");755 psError(PM_ERR_PROG, true, "Stamp not marked for calculation."); 709 756 return false; 710 757 } … … 730 777 731 778 732 733 734 779 int pmSubtractionRejectStamps(pmSubtractionKernels *kernels, pmSubtractionStampList *stamps, 735 780 const psVector *deviations, psImage *subMask, float sigmaRej) … … 764 809 765 810 if (numStamps == 0) { 766 psError(P S_ERR_UNKNOWN, true, "No good stamps found.");811 psError(PM_ERR_STAMPS, true, "No good stamps found."); 767 812 psFree(mask); 768 813 return -1; … … 772 817 PS_STAT_SAMPLE_MEDIAN | PS_STAT_SAMPLE_QUARTILE); // Statistics for deviatns 773 818 if (!psVectorStats(stats, deviations, NULL, mask, 0xff)) { 774 psError(P S_ERR_UNKNOWN, false, "Unable to measure statistics for deviations.");819 psError(PM_ERR_DATA, false, "Unable to measure statistics for deviations."); 775 820 psFree(stats); 776 821 psFree(mask); … … 825 870 int numGood = 0; // Number of good stamps 826 871 double newMean = 0.0; // New mean 872 psString log = NULL; // Log message 873 psStringAppend(&log, "Rejecting stamps, mean = %f, threshold = %f\n", mean, limit); 827 874 for (int i = 0; i < stamps->num; i++) { 828 875 pmSubtractionStamp *stamp = stamps->stamps->data[i]; // Stamp of interest … … 837 884 // Mask out the stamp in the image so you it's not found again 838 885 psTrace("psModules.imcombine", 3, "Rejecting stamp %d (%d,%d)\n", i, 839 (int)(stamp->x + 0.5), (int)(stamp->y + 0.5)); 886 (int)(stamp->x - 0.5), (int)(stamp->y - 0.5)); 887 psStringAppend(&log, "Stamp %d (%d,%d): %f\n", i, 888 (int)(stamp->x - 0.5), (int)(stamp->y - 0.5), 889 fabsf(deviations->data.F32[i] - mean)); 840 890 numRejected++; 841 891 for (int y = stamp->y - footprint; y <= stamp->y + footprint; y++) { … … 858 908 psFree(stamp->image1); 859 909 psFree(stamp->image2); 860 psFree(stamp->variance); 861 stamp->image1 = stamp->image2 = stamp->variance = NULL; 862 psFree(stamp->matrix1); 863 psFree(stamp->matrix2); 864 psFree(stamp->matrixX); 865 stamp->matrix1 = stamp->matrix2 = stamp->matrixX = NULL; 866 psFree(stamp->vector1); 867 psFree(stamp->vector2); 868 stamp->vector1 = stamp->vector2 = NULL; 910 psFree(stamp->weight); 911 stamp->image1 = stamp->image2 = stamp->weight = NULL; 912 psFree(stamp->matrix); 913 stamp->matrix = NULL; 914 psFree(stamp->vector); 915 stamp->vector = NULL; 869 916 } else { 870 917 numGood++; … … 875 922 } 876 923 newMean /= numGood; 924 925 if (numRejected == 0) { 926 psStringAppend(&log, "<none>\n"); 927 } 928 psLogMsg("psModules.imcombine", PS_LOG_DETAIL, "%s", log); 929 psFree(log); 877 930 878 931 if (ds9) { … … 901 954 902 955 psImage *polyValues = p_pmSubtractionPolynomial(NULL, kernels->spatialOrder, x, y); // Solved polynomial 903 psKernel *kernel = solvedKernel(NULL, kernels, polyValues, wantDual); // The appropriate kernel956 psKernel *kernel = solvedKernel(NULL, kernels, polyValues, true, wantDual); // The appropriate kernel 904 957 psFree(polyValues); 905 958 … … 932 985 psImage *polyValues = p_pmSubtractionPolynomial(NULL, kernels->spatialOrder, x, y); 933 986 934 psKernel *kernel = solvedKernel(NULL, kernels, polyValues, wantDual); // The appropriate kernel987 psKernel *kernel = solvedKernel(NULL, kernels, polyValues, true, wantDual); // The appropriate kernel 935 988 psFree(polyValues); 936 989 … … 949 1002 } 950 1003 951 #if 01004 #if 1 952 1005 psArray *pmSubtractionKernelSolutions(const pmSubtractionKernels *kernels, float x, float y, bool wantDual) 953 1006 { … … 957 1010 PS_ASSERT_FLOAT_WITHIN_RANGE(y, -1.0, 1.0, NULL); 958 1011 959 psArray *images = psArrayAlloc(kernels->solution1->n - 1); // Images of each kernel to return 960 psVector *fakeSolution = psVectorAlloc(kernels->solution1->n, PS_TYPE_F64); // Fake solution vector 961 psVectorInit(fakeSolution, 0.0); 962 963 for (int i = 0; i < kernels->solution1->n - 1; i++) { 964 fakeSolution->data.F64[i] = kernels->solution1->data.F64[i]; 965 images->data[i] = pmSubtractionKernelImage(kernels, x, y, wantDual); 966 fakeSolution->data.F64[i] = 0.0; 967 } 968 969 psFree(fakeSolution); 1012 psVector *solution = wantDual ? kernels->solution2 : kernels->solution1; // Solution of interest 1013 psVector *backup = psVectorCopy(NULL, solution, PS_TYPE_F64); // Backup version 1014 1015 int num = kernels->num; // Number of kernel basis functions 1016 1017 psImage *polyValues = p_pmSubtractionPolynomial(NULL, kernels->spatialOrder, x, y); // Solved polynomial 1018 psArray *images = psArrayAlloc(num + 1); // Images of each kernel to return 1019 1020 // The whole kernel 1021 { 1022 psKernel *kernel = solvedKernel(NULL, kernels, polyValues, true, wantDual); // The appropriate kernel 1023 images->data[0] = psMemIncrRefCounter(kernel->image); 1024 psFree(kernel); 1025 } 1026 1027 // The parts 1028 psVectorInit(solution, 0.0); 1029 for (int i = 0; i < num; i++) { 1030 solution->data.F64[i] = backup->data.F64[i]; 1031 psKernel *kernel = solvedKernel(NULL, kernels, polyValues, false, wantDual); // The appropriate kernel 1032 #if 0 1033 int size = kernels->size; 1034 double sum = 0.0; 1035 for (int v = -size; v <= size; v++) { 1036 for (int u = -size; u <= size; u++) { 1037 sum += kernel->kernel[v][u]; 1038 } 1039 } 1040 fprintf(stderr, "Kernel %d: %lf\n", i, sum); 1041 #endif 1042 images->data[i + 1] = psMemIncrRefCounter(kernel->image); 1043 psFree(kernel); 1044 solution->data.F64[i] = 0.0; 1045 } 1046 psFree(polyValues); 1047 psVectorCopy(solution, backup, PS_TYPE_F64); 1048 psFree(backup); 970 1049 971 1050 return images; … … 980 1059 psImage *convMask, // Output convolved mask 981 1060 const pmReadout *ro1, const pmReadout *ro2, // Input readouts 982 psImage * sys1, psImage *sys2, // Systematicerror images1061 psImage *kernelErr1, psImage *kernelErr2, // Kernel error images 983 1062 psImage *subMask, // Input subtraction mask 984 1063 psImageMaskType maskBad, // Mask value to give bad pixels … … 999 1078 // Only generate polynomial values every kernel footprint, since we have already assumed 1000 1079 // (with the stamps) that it does not vary rapidly on this scale. 1001 psImage *polyValues = p_pmSubtractionPolynomialFromCoords(NULL, kernels, numCols, numRows, 1002 xMin + x0 + size + 1, 1003 yMin + y0 + size + 1); 1080 psImage *polyValues = p_pmSubtractionPolynomialFromCoords(NULL, kernels, xMin + x0 + size + 1, 1081 yMin + y0 + size + 1); // Polynomial 1004 1082 float background = doBG ? p_pmSubtractionSolutionBackground(kernels, polyValues) : 0.0; // Background term 1005 1083 1006 1084 if (kernels->mode == PM_SUBTRACTION_MODE_1 || kernels->mode == PM_SUBTRACTION_MODE_DUAL) { 1007 convolveRegion(out1->image, out1->variance, convMask, &kernelImage, &kernelVariance,1008 ro1->image, ro1->variance, sys1, subMask, kernels, polyValues, background, *region,1009 maskBad, maskPoor, poorFrac, useFFT, false);1085 convolveRegion(out1->image, out1->variance, out1->mask, &kernelImage, &kernelVariance, 1086 ro1->image, ro1->variance, kernelErr1, subMask, kernels, polyValues, background, 1087 *region, maskBad, maskPoor, poorFrac, useFFT, false); 1010 1088 } 1011 1089 if (kernels->mode == PM_SUBTRACTION_MODE_2 || kernels->mode == PM_SUBTRACTION_MODE_DUAL) { 1012 convolveRegion(out2->image, out2->variance, convMask, &kernelImage, &kernelVariance, 1013 ro2->image, ro2->variance, sys2, subMask, kernels, polyValues, background, *region, 1014 maskBad, maskPoor, poorFrac, useFFT, kernels->mode == PM_SUBTRACTION_MODE_DUAL); 1090 convolveRegion(out2->image, out2->variance, out2->mask, &kernelImage, &kernelVariance, 1091 ro2->image, ro2->variance, kernelErr2, subMask, kernels, polyValues, background, 1092 *region, maskBad, maskPoor, poorFrac, useFFT, 1093 kernels->mode == PM_SUBTRACTION_MODE_DUAL); 1015 1094 } 1016 1095 … … 1020 1099 1021 1100 if ((kernels->mode == PM_SUBTRACTION_MODE_1 || kernels->mode == PM_SUBTRACTION_MODE_DUAL) && ro1->mask) { 1022 psImageMaskType **target = convMask->data.PS_TYPE_IMAGE_MASK_DATA; // Target mask1101 psImageMaskType **target = out1->mask->data.PS_TYPE_IMAGE_MASK_DATA; // Target mask 1023 1102 psImageMaskType **source = ro1->mask->data.PS_TYPE_IMAGE_MASK_DATA; // Source mask 1024 1103 … … 1030 1109 } 1031 1110 if ((kernels->mode == PM_SUBTRACTION_MODE_2 || kernels->mode == PM_SUBTRACTION_MODE_DUAL) && ro2->mask) { 1032 psImageMaskType **target = convMask->data.PS_TYPE_IMAGE_MASK_DATA; // Target mask1111 psImageMaskType **target = out2->mask->data.PS_TYPE_IMAGE_MASK_DATA; // Target mask 1033 1112 psImageMaskType **source = ro2->mask->data.PS_TYPE_IMAGE_MASK_DATA; // Source mask 1034 1113 … … 1057 1136 const pmReadout *ro1 = args->data[7]; // Input readout 1 1058 1137 const pmReadout *ro2 = args->data[8]; // Input readout 2 1059 psImage * sys1 = args->data[9]; // Systematicerror image 11060 psImage * sys2 = args->data[10]; // Systematicerror image 21138 psImage *kernelErr1 = args->data[9]; // Kernel error image 1 1139 psImage *kernelErr2 = args->data[10]; // Kernel error image 2 1061 1140 psImage *subMask = args->data[11]; // Subtraction mask 1062 1141 psImageMaskType maskBad = PS_SCALAR_VALUE(args->data[12], PS_TYPE_IMAGE_MASK_DATA); // Output mask value for bad pixels … … 1068 1147 bool useFFT = PS_SCALAR_VALUE(args->data[18], U8); // Use FFT for convolution? 1069 1148 1070 return subtractionConvolvePatch(numCols, numRows, x0, y0, out1, out2, convMask, ro1, ro2, sys1, sys2, 1071 subMask, maskBad, maskPoor, poorFrac, region, kernels, doBG, useFFT); 1149 return subtractionConvolvePatch(numCols, numRows, x0, y0, out1, out2, convMask, ro1, ro2, kernelErr1, 1150 kernelErr2, subMask, maskBad, maskPoor, poorFrac, region, kernels, 1151 doBG, useFFT); 1072 1152 } 1073 1153 1074 1154 bool pmSubtractionConvolve(pmReadout *out1, pmReadout *out2, const pmReadout *ro1, const pmReadout *ro2, 1075 1155 psImage *subMask, int stride, psImageMaskType maskBad, psImageMaskType maskPoor, 1076 float poorFrac, float sysError, const psRegion *region,1156 float poorFrac, float kernelError, float covarFrac, const psRegion *region, 1077 1157 const pmSubtractionKernels *kernels, bool doBG, bool useFFT) 1078 1158 { … … 1083 1163 PM_ASSERT_READOUT_NON_NULL(ro1, false); 1084 1164 PM_ASSERT_READOUT_IMAGE(ro1, false); 1165 PM_ASSERT_READOUT_IMAGE(out1, false); 1085 1166 numCols = ro1->image->numCols; 1086 1167 numRows = ro1->image->numRows; … … 1092 1173 PM_ASSERT_READOUT_NON_NULL(ro2, false); 1093 1174 PM_ASSERT_READOUT_IMAGE(ro2, false); 1175 PM_ASSERT_READOUT_IMAGE(out2, false); 1094 1176 if (numCols == 0 && numRows == 0) { 1095 1177 numCols = ro2->image->numCols; … … 1112 1194 PS_ASSERT_FLOAT_LARGER_THAN_OR_EQUAL(poorFrac, 0.0, false); 1113 1195 PS_ASSERT_FLOAT_LESS_THAN_OR_EQUAL(poorFrac, 1.0, false); 1114 PS_ASSERT_FLOAT_LARGER_THAN_OR_EQUAL(sysError, 0.0, false); 1115 PS_ASSERT_FLOAT_LESS_THAN_OR_EQUAL(sysError, 1.0, false); 1196 PS_ASSERT_FLOAT_LARGER_THAN_OR_EQUAL(kernelError, 0.0, false); 1197 PS_ASSERT_FLOAT_LESS_THAN_OR_EQUAL(kernelError, 1.0, false); 1198 PS_ASSERT_FLOAT_LARGER_THAN_OR_EQUAL(covarFrac, 0.0, false); 1199 PS_ASSERT_FLOAT_LESS_THAN(covarFrac, 1.0, false); 1116 1200 if (region && psRegionIsNaN(*region)) { 1117 1201 psString string = psRegionToString(*region); 1118 psError(P S_ERR_BAD_PARAMETER_VALUE, true, "Input region (%s) contains NAN values", string);1202 psError(PM_ERR_PROG, true, "Input region (%s) contains NAN values", string); 1119 1203 psFree(string); 1120 1204 return false; … … 1125 1209 bool threaded = pmSubtractionThreaded(); // Running threaded? 1126 1210 1127 // Outputs1128 if (kernels->mode == PM_SUBTRACTION_MODE_1 || kernels->mode == PM_SUBTRACTION_MODE_DUAL) {1129 if (!out1->image) {1130 out1->image = psImageAlloc(numCols, numRows, PS_TYPE_F32);1131 // XXX if (threaded) {1132 // XXX psMutexInit(out1->image);1133 // XXX }1134 }1135 if (ro1->variance) {1136 if (!out1->variance) {1137 out1->variance = psImageAlloc(numCols, numRows, PS_TYPE_F32);1138 // XXX if (threaded) {1139 // XXX psMutexInit(out1->variance);1140 // XXX }1141 }1142 psImageInit(out1->variance, 0.0);1143 }1144 }1145 if (kernels->mode == PM_SUBTRACTION_MODE_2 || kernels->mode == PM_SUBTRACTION_MODE_DUAL) {1146 if (!out2->image) {1147 out2->image = psImageAlloc(numCols, numRows, PS_TYPE_F32);1148 // XXX if (threaded) {1149 // XXX psMutexInit(out2->image);1150 // XXX }1151 }1152 if (ro2->variance) {1153 if (!out2->variance) {1154 out2->variance = psImageAlloc(numCols, numRows, PS_TYPE_F32);1155 // XXX if (threaded) {1156 // XXX psMutexInit(out2->variance);1157 // XXX }1158 }1159 psImageInit(out2->variance, 0.0);1160 }1161 }1162 1211 psImage *convMask = NULL; // Convolved mask image (common to inputs 1 and 2) 1163 1212 if (subMask) { 1164 // XXX if (threaded) {1165 // XXX psMutexInit(subMask);1166 // XXX }1167 1213 if (kernels->mode == PM_SUBTRACTION_MODE_1 || kernels->mode == PM_SUBTRACTION_MODE_DUAL) { 1168 if (!out1->mask) {1169 out1->mask = psImageAlloc(numCols, numRows, PS_TYPE_IMAGE_MASK);1170 }1171 1214 convMask = out1->mask; 1172 1215 } 1173 1216 if (kernels->mode == PM_SUBTRACTION_MODE_2 || kernels->mode == PM_SUBTRACTION_MODE_DUAL) { 1174 if (convMask) { 1175 if (out2->mask) { 1176 psFree(out2->mask); 1177 } 1178 out2->mask = psMemIncrRefCounter(convMask); 1179 } else { 1180 if (!out2->mask) { 1181 out2->mask = psImageAlloc(numCols, numRows, PS_TYPE_IMAGE_MASK); 1182 } 1217 if (!convMask) { 1183 1218 convMask = out2->mask; 1184 1219 } 1185 1220 } 1186 psImageInit(convMask, 0);1187 } 1188 1189 psImage *sys1 = NULL, *sys2 = NULL; // Systematic error images 1221 } 1222 1223 psImage *kernelErr1 = NULL, *kernelErr2 = NULL; // Kernel error images 1224 #ifdef USE_KERNEL_ERR 1190 1225 if (kernels->mode == PM_SUBTRACTION_MODE_1 || kernels->mode == PM_SUBTRACTION_MODE_DUAL) { 1191 sys1 = subtractionSysErrImage(ro1->image, sysError); 1192 // XXX if (threaded && sys1) { 1193 // XXX psMutexInit(sys1); 1194 // XXX } 1226 kernelErr1 = subtractionKernelErrImage(ro1->image, kernelError); 1195 1227 } 1196 1228 if (kernels->mode == PM_SUBTRACTION_MODE_2 || kernels->mode == PM_SUBTRACTION_MODE_DUAL) { 1197 sys2 = subtractionSysErrImage(ro2->image, sysError); 1198 // XXX if (threaded && sys2) { 1199 // XXX psMutexInit(sys2); 1200 // XXX } 1201 } 1229 kernelErr2 = subtractionKernelErrImage(ro2->image, kernelError); 1230 } 1231 #endif 1202 1232 1203 1233 int size = kernels->size; // Half-size of kernel 1204 1234 1205 1235 // Get region for convolution: [xMin:xMax,yMin:yMax] 1206 int xMin = size, xMax = numCols- size;1207 int yMin = size, yMax = numRows- size;1236 int xMin = kernels->xMin + size, xMax = kernels->xMax - size; 1237 int yMin = kernels->yMin + size, yMax = kernels->yMax - size; 1208 1238 if (region) { 1209 1239 xMin = PS_MAX(region->x0, xMin); … … 1248 1278 psArrayAdd(args, 1, (pmReadout*)ro1); // Casting away const 1249 1279 psArrayAdd(args, 1, (pmReadout*)ro2); // Casting away const 1250 // Since adding to the array can impact the reference count, we need to lock 1251 // XXX if (sys1) { 1252 // XXX psMutexLock(sys1); 1253 // XXX } 1254 psArrayAdd(args, 1, sys1); 1255 // XXX if (sys1) { 1256 // XXX psMutexUnlock(sys1); 1257 // XXX } 1258 // XXX if (sys2) { 1259 // XXX psMutexLock(sys2); 1260 // XXX } 1261 psArrayAdd(args, 1, sys2); 1262 // XXX if (sys2) { 1263 // XXX psMutexUnlock(sys2); 1264 // XXX } 1265 // XXX if (subMask) { 1266 // XXX psMutexLock(subMask); 1267 // XXX } 1280 psArrayAdd(args, 1, kernelErr1); 1281 psArrayAdd(args, 1, kernelErr2); 1268 1282 psArrayAdd(args, 1, subMask); 1269 // XXX if (subMask) {1270 // XXX psMutexUnlock(subMask);1271 // XXX }1272 1283 PS_ARRAY_ADD_SCALAR(args, maskBad, PS_TYPE_IMAGE_MASK); 1273 1284 PS_ARRAY_ADD_SCALAR(args, maskPoor, PS_TYPE_IMAGE_MASK); … … 1284 1295 psFree(job); 1285 1296 } else { 1286 subtractionConvolvePatch(numCols, numRows, x0, y0, out1, out2, convMask, ro1, ro2, sys1, sys2,1287 subMask, maskBad, maskPoor, poorFrac, subRegion, kernels, doBG,1288 useFFT);1297 subtractionConvolvePatch(numCols, numRows, x0, y0, out1, out2, convMask, ro1, ro2, 1298 kernelErr1, kernelErr2, subMask, maskBad, maskPoor, poorFrac, 1299 subRegion, kernels, doBG, useFFT); 1289 1300 } 1290 1301 psFree(subRegion); … … 1293 1304 1294 1305 if (!psThreadPoolWait(false)) { 1295 psError( PS_ERR_UNKNOWN, false, "Error waiting for threads.");1306 psError(psErrorCodeLast(), false, "Error waiting for threads."); 1296 1307 return false; 1297 1308 } … … 1308 1319 psFree(job); 1309 1320 } 1310 1311 // XXX if (subMask) {1312 // XXX psMutexDestroy(subMask);1313 // XXX }1314 // XXX if (sys1) {1315 // XXX psMutexDestroy(sys1);1316 // XXX }1317 // XXX if (sys2) {1318 // XXX psMutexDestroy(sys2);1319 // XXX }1320 1321 } 1321 1322 psImageConvolveSetThreads(oldThreads); 1322 1323 1323 psFree( sys1);1324 psFree( sys2);1324 psFree(kernelErr1); 1325 psFree(kernelErr2); 1325 1326 1326 1327 // Calculate covariances 1327 // This can take a while, so we only do it for a single instance 1328 // XXX psImageCovarianceCalculate could be multithreaded 1328 // This can be fairly involved, so we only do it for a single instance 1329 // Enable threads for covariance calculation, since we're not threading on top of it. 1330 oldThreads = psImageCovarianceSetThreads(true); 1329 1331 if (kernels->mode == PM_SUBTRACTION_MODE_1 || kernels->mode == PM_SUBTRACTION_MODE_DUAL) { 1330 1332 psKernel *kernel = pmSubtractionKernel(kernels, 0.0, 0.0, false); // Convolution kernel 1333 psKernelTruncate(kernel, covarFrac); 1331 1334 out1->covariance = psImageCovarianceCalculate(kernel, ro1->covariance); 1332 1335 psFree(kernel); … … 1335 1338 psKernel *kernel = pmSubtractionKernel(kernels, 0.0, 0.0, 1336 1339 kernels->mode == PM_SUBTRACTION_MODE_DUAL); // Conv. kernel 1340 psKernelTruncate(kernel, covarFrac); 1337 1341 out2->covariance = psImageCovarianceCalculate(kernel, ro2->covariance); 1338 1342 psFree(kernel); 1339 1343 } 1344 psImageCovarianceSetThreads(oldThreads); 1340 1345 1341 1346 // Copy anything that wasn't convolved … … 1377 1382 } 1378 1383 1379 1380 1384 psLogMsg("psModules.imcombine", PS_LOG_INFO, "Convolve image: %f sec", 1381 1385 psTimerClear("pmSubtractionConvolve"));
Note:
See TracChangeset
for help on using the changeset viewer.
