Changeset 15756
- Timestamp:
- Dec 6, 2007, 3:57:15 PM (18 years ago)
- Location:
- trunk/psModules/src
- Files:
-
- 4 added
- 14 edited
-
camera/pmReadoutFake.c (modified) (4 diffs)
-
camera/pmReadoutFake.h (modified) (1 diff)
-
imcombine/Makefile.am (modified) (2 diffs)
-
imcombine/pmStackReject.c (modified) (2 diffs)
-
imcombine/pmSubtraction.c (modified) (35 diffs)
-
imcombine/pmSubtraction.h (modified) (6 diffs)
-
imcombine/pmSubtractionEquation.c (added)
-
imcombine/pmSubtractionEquation.h (added)
-
imcombine/pmSubtractionKernels.c (modified) (31 diffs)
-
imcombine/pmSubtractionKernels.h (modified) (10 diffs)
-
imcombine/pmSubtractionMask.c (added)
-
imcombine/pmSubtractionMask.h (added)
-
imcombine/pmSubtractionMatch.c (modified) (19 diffs)
-
imcombine/pmSubtractionMatch.h (modified) (1 diff)
-
imcombine/pmSubtractionParams.c (modified) (3 diffs)
-
imcombine/pmSubtractionStamps.c (modified) (20 diffs)
-
imcombine/pmSubtractionStamps.h (modified) (9 diffs)
-
psmodules.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psModules/src/camera/pmReadoutFake.c
r15424 r15756 20 20 #include "pmSource.h" 21 21 #include "pmSourceUtils.h" 22 #include "pmModelUtils.h" 22 23 23 24 #define MODEL_TYPE "PS_MODEL_RGAUSS" // Type of model to use 24 25 25 26 26 pmReadout *pmReadoutFakeFromSources(int numCols, int numRows, const psArray *sources, 27 float fwhm, float minFlux) 27 bool pmReadoutFakeFromSources(pmReadout *readout, int numCols, int numRows, const psArray *sources, 28 const psVector *xOffset, const psVector *yOffset, pmPSF *psf, float minFlux, 29 int radius) 28 30 { 29 PS_ASSERT_INT_LARGER_THAN(numCols, 0, NULL); 30 PS_ASSERT_INT_LARGER_THAN(numRows, 0, NULL); 31 PS_ASSERT_ARRAY_NON_NULL(sources, NULL); 32 PS_ASSERT_FLOAT_LARGER_THAN(fwhm, 0.0, NULL); 33 PS_ASSERT_FLOAT_LARGER_THAN(minFlux, 0.0, NULL); 31 PS_ASSERT_PTR_NON_NULL(readout, false); 32 PS_ASSERT_INT_LARGER_THAN(numCols, 0, false); 33 PS_ASSERT_INT_LARGER_THAN(numRows, 0, false); 34 PS_ASSERT_ARRAY_NON_NULL(sources, false); 35 if (xOffset || yOffset) { 36 PS_ASSERT_VECTOR_NON_NULL(xOffset, false); 37 PS_ASSERT_VECTOR_NON_NULL(yOffset, false); 38 PS_ASSERT_VECTORS_SIZE_EQUAL(xOffset, yOffset, false); 39 PS_ASSERT_VECTOR_TYPE(xOffset, PS_TYPE_S32, false); 40 PS_ASSERT_VECTOR_TYPE_EQUAL(xOffset, yOffset, false); 41 if (xOffset->n != sources->n) { 42 psError(PS_ERR_BAD_PARAMETER_SIZE, true, 43 "Number of offset vectors (%ld) and sources (%ld) doesn't match", 44 xOffset->n, sources->n); 45 return false; 46 } 47 } 48 PS_ASSERT_PTR_NON_NULL(psf, false); 49 if (radius > 0 && isfinite(minFlux) && minFlux > 0.0) { 50 psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Cannot define both minimum flux and fixed radius."); 51 return false; 52 } 34 53 35 pmReadout *readout = pmReadoutAlloc(NULL); // Output readout 36 readout->image = psImage Alloc(numCols, numRows, PS_TYPE_F32);54 55 readout->image = psImageRecycle(readout->image, numCols, numRows, PS_TYPE_F32); 37 56 psImageInit(readout->image, 0); 38 57 39 58 int numSources = sources->n; // Number of stars 40 59 60 #if 0 41 61 pmModelType modelType = pmModelClassGetType(MODEL_TYPE); // Type of PSF model 42 62 assert(modelType >= 0); … … 65 85 psAbort("Unsupported model type: %d", modelType); 66 86 } 87 #endif 67 88 89 pmModel *fakeModel = pmModelFromPSFforXY(psf, (float)numCols / 2.0, (float)numRows / 2.0, 90 1.0); // Fake model, with central intensity of 1.0 68 91 float flux0 = fakeModel->modelFlux(fakeModel->params); // Flux for central intensity of 1.0 69 70 92 71 93 for (int i = 0; i < numSources; i++) { … … 93 115 pmSource *fakeSource = pmSourceAlloc(); // Fake source to generate 94 116 fakeSource->peak = pmPeakAlloc(x, y, fakeModel->params->data.F32[PM_PAR_I0], PM_PEAK_LONE); 95 float radius = fakeModel->modelRadius(fakeModel->params, minFlux); // Radius of interest for source117 float fakeRadius = radius > 0 ? radius : fakeModel->modelRadius(fakeModel->params, minFlux); // Radius 96 118 97 if (!pmSourceDefinePixels(fakeSource, readout, x, y, radius)) { 98 psError(PS_ERR_UNKNOWN, false, "Unable to define pixels for source."); 99 psFree(readout); 100 psFree(fakeModel); 101 return NULL; 102 } 103 104 if (!pmModelAdd(fakeSource->pixels, NULL, fakeModel, PM_MODEL_OP_FULL, 0)) { 105 psError(PS_ERR_UNKNOWN, false, "Unable to add model of source to image."); 106 psFree(readout); 107 psFree(fakeModel); 108 return NULL; 119 if (xOffset) { 120 if (!pmSourceDefinePixels(fakeSource, readout, x + xOffset->data.S32[i], 121 y + yOffset->data.S32[i], fakeRadius)) { 122 psError(PS_ERR_UNKNOWN, false, "Unable to define pixels for source."); 123 psFree(readout); 124 psFree(fakeModel); 125 return false; 126 } 127 if (!pmModelAddWithOffset(fakeSource->pixels, NULL, fakeModel, PM_MODEL_OP_FULL, 0, 128 - xOffset->data.S32[i], - yOffset->data.S32[i])) { 129 psError(PS_ERR_UNKNOWN, false, "Unable to add model of source to image."); 130 psFree(readout); 131 psFree(fakeModel); 132 return false; 133 } 134 } else { 135 if (!pmSourceDefinePixels(fakeSource, readout, x, y, fakeRadius)) { 136 psError(PS_ERR_UNKNOWN, false, "Unable to define pixels for source."); 137 psFree(readout); 138 psFree(fakeModel); 139 return false; 140 } 141 if (!pmModelAdd(fakeSource->pixels, NULL, fakeModel, PM_MODEL_OP_FULL, 0)) { 142 psError(PS_ERR_UNKNOWN, false, "Unable to add model of source to image."); 143 psFree(readout); 144 psFree(fakeModel); 145 return false; 146 } 109 147 } 110 148 psFree(fakeSource); … … 113 151 psFree(fakeModel); 114 152 115 return readout;153 return true; 116 154 } -
trunk/psModules/src/camera/pmReadoutFake.h
r15362 r15756 6 6 #include <pmFPA.h> 7 7 8 // Generate a fake readout from an array of sources 9 pmReadout *pmReadoutFakeFromSources(int numCols, int numRows, ///< Dimension of image 10 const psArray *sources, ///< Array of pmSource 11 float fwhm, ///< FWHM for sources 12 float minFlux ///< Minimum flux to bother about; for setting object size 8 #include <pmMoments.h> 9 #include <pmResiduals.h> 10 #include <pmGrowthCurve.h> 11 #include <pmTrend2D.h> 12 #include <pmPSF.h> 13 14 15 /// Generate a fake readout from an array of sources 16 bool pmReadoutFakeFromSources(pmReadout *readout, ///< Output readout, or NULL 17 int numCols, int numRows, ///< Dimension of image 18 const psArray *sources, ///< Array of pmSource 19 const psVector *xOffset, ///< x offsets for sources (source -> img), or NULL 20 const psVector *yOffset, ///< y offsets for sources (source -> img), or NULL 21 pmPSF *psf, ///< PSF for sources 22 float minFlux, ///< Minimum flux to bother about; for setting source radius 23 int radius ///< Fixed radius for sources 13 24 ); 14 25 15 16 17 18 26 #endif -
trunk/psModules/src/imcombine/Makefile.am
r14886 r15756 9 9 pmStackReject.c \ 10 10 pmSubtraction.c \ 11 pmSubtractionEquation.c \ 11 12 pmSubtractionKernels.c \ 13 pmSubtractionMask.c \ 14 pmSubtractionMatch.c \ 15 pmSubtractionParams.c \ 12 16 pmSubtractionStamps.c \ 13 pmSubtractionMatch.c \ 14 pmSubtractionParams.c 17 pmPSFEnvelope.c 15 18 16 19 pkginclude_HEADERS = \ … … 20 23 pmStackReject.h \ 21 24 pmSubtraction.h \ 25 pmSubtractionEquation.h \ 22 26 pmSubtractionKernels.h \ 27 pmSubtractionMask.h \ 28 pmSubtractionMatch.h \ 29 pmSubtractionParams.h \ 23 30 pmSubtractionStamps.h \ 24 pmSubtractionMatch.h \ 25 pmSubtractionParams.h 31 pmPSFEnvelope.h 26 32 27 33 CLEANFILES = *~ -
trunk/psModules/src/imcombine/pmStackReject.c
r15449 r15756 57 57 for (int i = 0; i < numRegions; i++) { 58 58 psRegion *region = regions->data[i]; // Region of interest 59 psVector *solution = solutions->data[i]; // Solution of interest 60 if (!pmSubtractionConvolve(convRO, inRO, NULL, NULL, 0, region, solution, kernels, 61 PM_SUBTRACTION_MODE_1, true)) { 59 if (!pmSubtractionConvolve(convRO, NULL, inRO, NULL, NULL, 0, region, kernels, true)) { 62 60 psError(PS_ERR_UNKNOWN, false, "Unable to convolve mask image in region %d.", i); 63 61 psFree(convRO); … … 72 70 float xNorm = (region->x0 + 0.5 * (region->x1 - region->x0) - numCols/2.0) / (float)numCols; 73 71 float yNorm = (region->y0 + 0.5 * (region->y1 - region->y0) - numRows/2.0) / (float)numRows; 74 psImage *kernel = pmSubtractionKernelImage( solution, kernels, xNorm, yNorm);72 psImage *kernel = pmSubtractionKernelImage(kernels, xNorm, yNorm, false); 75 73 if (!kernel) { 76 74 psError(PS_ERR_UNKNOWN, false, "Unable to generate kernel image."); -
trunk/psModules/src/imcombine/pmSubtraction.c
r15455 r15756 4 4 * @author GLG, MHPCC 5 5 * 6 * @version $Revision: 1.7 3$ $Name: not supported by cvs2svn $7 * @date $Date: 2007-1 1-05 23:43:38$6 * @version $Revision: 1.74 $ $Name: not supported by cvs2svn $ 7 * @date $Date: 2007-12-07 01:57:15 $ 8 8 * 9 9 * Copyright 2004-2007 Institute for Astronomy, University of Hawaii … … 23 23 #include "pmFPA.h" 24 24 #include "pmSubtractionStamps.h" 25 #include "pmSubtractionEquation.h" 25 26 26 27 #include "pmSubtraction.h" … … 34 35 // Private (file-static) functions 35 36 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// 36 37 // Return the number of polynomial terms there are for a given order38 static inline long polyTerms(int order // Order of polynomial39 )40 {41 return (order + 1) * (order + 2) / 2;42 }43 44 // Given a stamp coordinates (x,y), generate a matrix where the elements (i,j) are x^i * y^j45 static psImage *spatialPolyValues(int spatialOrder, // Maximum spatial polynomial order46 float x, float y // Normalised position of interest, [-1,1]47 )48 {49 assert(spatialOrder >= 0);50 assert(x >= -1 && x <= 1);51 assert(y >= -1 && y <= 1);52 53 psImage *polyValues = psImageAlloc(spatialOrder + 1, spatialOrder + 1, PS_TYPE_F64); // Matrix to return54 polyValues->data.F64[0][0] = 1.0;55 56 double value = 1.0;57 for (int i = 1; i <= spatialOrder; i++) {58 value *= x;59 polyValues->data.F64[0][i] = value;60 }61 62 value = 1.0;63 for (int j = 1; j <= spatialOrder; j++) {64 value *= y;65 polyValues->data.F64[j][0] = value;66 }67 68 for (int j = 1; j <= spatialOrder; j++) {69 for (int i = 1; i <= spatialOrder - j; i++) {70 polyValues->data.F64[j][i] = polyValues->data.F64[j][0] * polyValues->data.F64[0][i];71 }72 }73 74 return polyValues;75 }76 37 77 38 // Generate the kernel to apply to the variance from the normal kernel … … 108 69 109 70 // Generate an image of the solved kernel 110 static inline psKernel *solvedKernel(psKernel *kernel, // Kernel, to return 111 const psVector *solution, // Solution to the least-squares problem 112 const pmSubtractionKernels *kernels, // Kernel basis functions 113 const psImage *polyValues // Spatial polynomial values 114 ) 115 { 71 static psKernel *solvedKernel(psKernel *kernel, // Kernel, to return 72 const pmSubtractionKernels *kernels, // Kernel basis functions 73 const psImage *polyValues, // Spatial polynomial values 74 bool wantDual // Want the dual (second) kernel? 75 ) 76 { 77 assert(kernels); 78 assert(polyValues); 79 116 80 int numKernels = kernels->num; // Number of kernel basis functions 117 assert(kernels->u->n == numKernels);118 assert(kernels->v->n == numKernels);119 int spatialOrder = kernels->spatialOrder; // Maximum spatial polynomial order120 assert(solution->n == numKernels * polyTerms(spatialOrder) + polyTerms(kernels->bgOrder));121 122 // Ensure the subIndex for POIS kernels is what is expected123 assert((kernels->type != PM_SUBTRACTION_KERNEL_POIS &&124 kernels->type != PM_SUBTRACTION_KERNEL_SPAM &&125 kernels->type != PM_SUBTRACTION_KERNEL_FRIES &&126 kernels->type != PM_SUBTRACTION_KERNEL_GUNK &&127 kernels->type != PM_SUBTRACTION_KERNEL_RINGS) ||128 (kernels->u->data.S32[kernels->subIndex] == 0 && kernels->v->data.S32[kernels->subIndex] == 0));129 130 81 int size = kernels->size; // Kernel half-size 131 82 if (!kernel) { … … 135 86 136 87 for (int i = 0; i < numKernels; i++) { 137 double value = 0.0; // Value of this component, from the sum of multiple polynomial terms 138 for (int yOrder = 0, index = i; yOrder <= spatialOrder; yOrder++) { 139 for (int xOrder = 0; xOrder <= spatialOrder - yOrder; xOrder++, index += numKernels) { 140 value += polyValues->data.F64[yOrder][xOrder] * solution->data.F64[index]; 141 } 142 } 88 double value = p_pmSubtractionSolutionCoeff(kernels, polyValues, i, wantDual); // Polynomial value 143 89 144 90 switch (kernels->type) { … … 147 93 int v = kernels->v->data.S32[i]; // Offset in y 148 94 kernel->kernel[v][u] += value; 149 if (kernels->spatialOrder > 0 && i != kernels->subIndex) { 150 // The (0,0) element is subtracted from most kernels to preserve photometric scaling 151 kernel->kernel[0][0] -= value; 152 } 95 kernel->kernel[0][0] -= value; 153 96 break; 154 97 } … … 167 110 for (int u = uStart; u <= uStop; u++) { 168 111 kernel->kernel[v][u] += norm * value; 169 if (kernels->spatialOrder > 0 && i != kernels->subIndex) { 170 // The (0,0) element is subtracted from most kernels to preserve photometric scaling 171 kernel->kernel[0][0] -= value; 172 } 112 kernel->kernel[0][0] -= value; 173 113 } 174 114 } … … 188 128 } else { 189 129 // Using delta function 190 bool subtract = (kernels->spatialOrder > 0 && i != kernels->subIndex); // Subtract (0,0)?191 130 int u = kernels->u->data.S32[i]; // Offset in x 192 131 int v = kernels->v->data.S32[i]; // Offset in y 193 132 kernel->kernel[v][u] += value; 194 if (subtract) { 195 // The (0,0) element is subtracted from most kernels to preserve photometric scaling 196 kernel->kernel[0][0] -= value; 197 } 133 kernel->kernel[0][0] -= value; 198 134 } 199 135 break; … … 211 147 } 212 148 case PM_SUBTRACTION_KERNEL_RINGS: { 213 if (i == kernels->subIndex) {214 kernel->kernel[0][0] += value;215 break;216 }217 149 psArray *preCalc = kernels->preCalc->data[i]; // Precalculated data 218 150 psVector *uCoords = preCalc->data[0]; // u coordinates … … 232 164 } 233 165 } 166 167 if (!wantDual) { 168 // Put in the normalisation component 169 kernel->kernel[0][0] += p_pmSubtractionSolutionNorm(kernels); 170 } 171 234 172 235 173 return kernel; … … 328 266 } 329 267 330 // Mark a pixel as blank in the image, mask and weight 331 static inline void markBlank(psImage *image, // Image to mark as blank 332 psImage *mask, // Mask to mark as blank (or NULL) 333 psImage *weight, // Weight map to mark as blank (or NULL) 334 int x, int y, // Coordinates to mark blank 335 psMaskType blank // Blank mask value 268 // Convolve a region of an image 269 static inline void convolveRegion(psImage *convImage, // Convolved image (output) 270 psImage *convWeight, // Convolved weight map (output), or NULL 271 psKernel **kernelImage, // Convolution kernel for the image 272 psKernel **kernelWeight, // Convolution kernel for the weight map, or NULL 273 const psImage *image, // Image to convolve 274 const psImage *weight, // Weight map to convolve, or NULL 275 const psImage *subMask, // Subtraction mask 276 psMaskType maskVal, // Mask value to apply in convolution 277 const pmSubtractionKernels *kernels, // Kernels 278 psImage *polyValues, // Polynomial values 279 float background, // Background value to apply 280 psRegion region, // Region to convolve 281 bool useFFT // Use FFT to convolve? 336 282 ) 337 283 { 338 image->data.F32[y][x] = NAN; 339 if (mask) { 340 mask->data.PS_TYPE_MASK_DATA[y][x] |= blank; 341 } 284 *kernelImage = solvedKernel(*kernelImage, kernels, polyValues, false); 342 285 if (weight) { 343 weight->data.F32[y][x] = NAN; 344 } 286 *kernelWeight = varianceKernel(*kernelWeight, *kernelImage); 287 } 288 289 if (useFFT) { 290 // Use Fast Fourier Transform to do the convolution 291 // This provides a big speed-up for large kernels 292 convolveFFT(convImage, image, subMask, maskVal, *kernelImage, region, background, kernels->size); 293 if (weight) { 294 convolveFFT(convWeight, weight, subMask, maskVal, *kernelWeight, region, 0.0, kernels->size); 295 } 296 } else { 297 convolveDirect(convImage, image, *kernelImage, region, background, kernels->size); 298 if (weight) { 299 convolveDirect(convWeight, weight, *kernelWeight, region, 0.0, kernels->size); 300 } 301 } 302 345 303 return; 346 304 } … … 350 308 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// 351 309 352 // Generate the convolution given a precalculated kernel353 310 psKernel *p_pmSubtractionConvolveStampPrecalc(const psKernel *image, const psKernel *kernel) 354 311 { … … 363 320 } 364 321 322 psImage *p_pmSubtractionPolynomial(psImage *output, int spatialOrder, float x, float y) 323 { 324 assert(spatialOrder >= 0); 325 assert(x >= -1 && x <= 1); 326 assert(y >= -1 && y <= 1); 327 328 output = psImageRecycle(output, spatialOrder + 1, spatialOrder + 1, PS_TYPE_F64); 329 output->data.F64[0][0] = 1.0; 330 331 double value = 1.0; 332 for (int i = 1; i <= spatialOrder; i++) { 333 value *= x; 334 output->data.F64[0][i] = value; 335 } 336 337 value = 1.0; 338 for (int j = 1; j <= spatialOrder; j++) { 339 value *= y; 340 output->data.F64[j][0] = value; 341 } 342 343 for (int j = 1; j <= spatialOrder; j++) { 344 for (int i = 1; i <= spatialOrder - j; i++) { 345 output->data.F64[j][i] = output->data.F64[j][0] * output->data.F64[0][i]; 346 } 347 } 348 349 return output; 350 } 365 351 366 352 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// … … 368 354 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// 369 355 370 psImage *pmSubtractionMask(const psImage *mask1, const psImage *mask2, psMaskType maskVal,371 int size, int footprint, float badFrac, bool useFFT)372 {373 PS_ASSERT_IMAGE_NON_NULL(mask1, NULL);374 PS_ASSERT_IMAGE_TYPE(mask1, PS_TYPE_MASK, NULL);375 if (mask2) {376 PS_ASSERT_IMAGE_NON_NULL(mask2, NULL);377 PS_ASSERT_IMAGE_TYPE(mask2, PS_TYPE_MASK, NULL);378 PS_ASSERT_IMAGES_SIZE_EQUAL(mask2, mask1, NULL);379 }380 PS_ASSERT_INT_NONNEGATIVE(size, NULL);381 PS_ASSERT_INT_NONNEGATIVE(footprint, NULL);382 if (isfinite(badFrac)) {383 PS_ASSERT_FLOAT_LARGER_THAN(badFrac, 0.0, NULL);384 PS_ASSERT_FLOAT_LESS_THAN_OR_EQUAL(badFrac, 1.0, NULL);385 }386 387 int numCols = mask1->numCols, numRows = mask1->numRows; // Size of the images388 389 // Dereference inputs for convenience390 psMaskType **data1 = mask1->data.PS_TYPE_MASK_DATA;391 psMaskType **data2 = NULL;392 if (mask2) {393 data2 = mask2->data.PS_TYPE_MASK_DATA;394 }395 396 // First, a pass through to determine the fraction of bad pixels397 if (isfinite(badFrac) && badFrac != 1.0) {398 int numBad = 0; // Number of bad pixels399 for (int y = 0; y < numRows; y++) {400 for (int x = 0; x < numCols; x++) {401 if (data1[y][x] & maskVal) {402 numBad++;403 continue;404 }405 if (data2 && data2[y][x] & maskVal) {406 numBad++;407 }408 }409 }410 if (numBad > badFrac * numCols * numRows) {411 psError(PS_ERR_BAD_PARAMETER_VALUE, true,412 "Fraction of bad pixels (%d/%d=%f) exceeds limit (%f)\n",413 numBad, numCols * numRows, (float)numBad/(float)(numCols * numRows), badFrac);414 return NULL;415 }416 }417 418 // Worried about the masks for bad pixels and bad stamps colliding, so make our own mask419 psImage *mask = psImageAlloc(numCols, numRows, PS_TYPE_MASK); // The global mask420 psImageInit(mask, 0);421 psMaskType **maskData = mask->data.PS_TYPE_MASK_DATA; // Dereference for convenience422 423 // Block out a border around the edge of the image424 425 // Bottom stripe426 for (int y = 0; y < PS_MIN(size + footprint, numRows); y++) {427 for (int x = 0; x < numCols; x++) {428 maskData[y][x] |= PM_SUBTRACTION_MASK_BORDER;429 }430 }431 // Either side432 for (int y = PS_MIN(size + footprint, numRows); y < numRows - size - footprint; y++) {433 for (int x = 0; x < PS_MIN(size + footprint, numCols); x++) {434 maskData[y][x] |= PM_SUBTRACTION_MASK_BORDER;435 }436 for (int x = PS_MAX(numCols - size - footprint, 0); x < numCols; x++) {437 maskData[y][x] |= PM_SUBTRACTION_MASK_BORDER;438 }439 }440 // Top stripe441 for (int y = PS_MAX(numRows - size - footprint, 0); y < numRows; y++) {442 for (int x = 0; x < numCols; x++) {443 maskData[y][x] |= PM_SUBTRACTION_MASK_BORDER;444 }445 }446 447 // XXX Could do something smarter here --- we will get images that are predominantly masked (where the448 // skycell isn't overlapped by a large fraction by the observation), so that convolving around every bad449 // pixel is wasting time. As a first cut, I've put in a check on the fraction of bad pixels, but we could450 // imagine looking for the edge of big regions and convolving just at the edge. As a second cut, allow451 // use of FFT convolution.452 453 for (int y = 0; y < numRows; y++) {454 for (int x = 0; x < numCols; x++) {455 if (data1[y][x] & maskVal) {456 maskData[y][x] |= PM_SUBTRACTION_MASK_BAD_1;457 }458 if (data2 && data2[y][x] & maskVal) {459 maskData[y][x] |= PM_SUBTRACTION_MASK_BAD_2;460 }461 }462 }463 464 // Block out the entire stamp footprint around bad input pixels.465 466 // We want to block out with the CONVOLVE mask anything that would be bad if we convolved with a bad467 // reference pixel (within 'size'). Then we want to block out with the FOOTPRINT mask everything within a468 // footprint's distance of those (within 'footprint').469 470 if (useFFT) {471 if (!psImageConvolveMaskFFT(mask, mask, PM_SUBTRACTION_MASK_BAD_1 | PM_SUBTRACTION_MASK_BAD_2,472 PM_SUBTRACTION_MASK_CONVOLVE_1 | PM_SUBTRACTION_MASK_FOOTPRINT_1,473 -size, size, -size, size, 0.5)) {474 psError(PS_ERR_UNKNOWN, false, "Unable to convolve bad pixels from mask 1.");475 psFree(mask);476 return NULL;477 }478 if (!psImageConvolveMaskFFT(mask, mask, PM_SUBTRACTION_MASK_BAD_2,479 PM_SUBTRACTION_MASK_CONVOLVE_2 | PM_SUBTRACTION_MASK_FOOTPRINT_2,480 -size, size, -size, size, 0.5)) {481 psError(PS_ERR_UNKNOWN, false, "Unable to convolve bad pixels from mask 2.");482 psFree(mask);483 return NULL;484 }485 if (!psImageConvolveMaskFFT(mask, mask, PM_SUBTRACTION_MASK_CONVOLVE_1,486 PM_SUBTRACTION_MASK_FOOTPRINT_1,487 -footprint, footprint, -footprint, footprint, 0.5)) {488 psError(PS_ERR_UNKNOWN, false, "Unable to reconvolve bad pixels from mask 1.");489 psFree(mask);490 return NULL;491 }492 if (!psImageConvolveMaskFFT(mask, mask, PM_SUBTRACTION_MASK_CONVOLVE_2,493 PM_SUBTRACTION_MASK_FOOTPRINT_2,494 -footprint, footprint, -footprint, footprint, 0.5)) {495 psError(PS_ERR_UNKNOWN, false, "Unable to reconvolve bad pixels from mask 2.");496 psFree(mask);497 return NULL;498 }499 } else {500 if (!psImageConvolveMaskDirect(mask, mask, PM_SUBTRACTION_MASK_BAD_1,501 PM_SUBTRACTION_MASK_CONVOLVE_1 | PM_SUBTRACTION_MASK_FOOTPRINT_1,502 -size, size, -size, size)) {503 psError(PS_ERR_UNKNOWN, false, "Unable to convolve bad pixels from mask 1.");504 psFree(mask);505 return NULL;506 }507 if (!psImageConvolveMaskDirect(mask, mask, PM_SUBTRACTION_MASK_BAD_2,508 PM_SUBTRACTION_MASK_CONVOLVE_2 | PM_SUBTRACTION_MASK_FOOTPRINT_2,509 -size, size, -size, size)) {510 psError(PS_ERR_UNKNOWN, false, "Unable to convolve bad pixels from mask 2.");511 psFree(mask);512 return NULL;513 }514 if (!psImageConvolveMaskDirect(mask, mask, PM_SUBTRACTION_MASK_CONVOLVE_1,515 PM_SUBTRACTION_MASK_FOOTPRINT_1,516 -footprint, footprint, -footprint, footprint)) {517 psError(PS_ERR_UNKNOWN, false, "Unable to reconvolve bad pixels from mask 1.");518 psFree(mask);519 return NULL;520 }521 if (!psImageConvolveMaskDirect(mask, mask, PM_SUBTRACTION_MASK_CONVOLVE_2,522 PM_SUBTRACTION_MASK_FOOTPRINT_2,523 -footprint, footprint, -footprint, footprint)) {524 psError(PS_ERR_UNKNOWN, false, "Unable to reconvolve bad pixels from mask 2.");525 psFree(mask);526 return NULL;527 }528 }529 530 return mask;531 }532 356 533 357 // Convolve a stamp by a single kernel basis function … … 538 362 ) 539 363 { 364 #if 0 365 if (index == kernels->num) { 366 // Normalisation component 367 return convolveOffset(image, 0, 0, footprint); 368 } 369 #endif 370 540 371 switch (kernels->type) { 541 372 case PM_SUBTRACTION_KERNEL_POIS: { … … 543 374 int v = kernels->v->data.S32[index]; // Offset in y 544 375 psKernel *convolved = convolveOffset(image, u, v, footprint); // Convolved image 545 if (kernels->spatialOrder > 0 && index != kernels->subIndex) { 546 convolveSub(convolved, image, footprint); 547 } 376 convolveSub(convolved, image, footprint); 548 377 return convolved; 549 378 } … … 569 398 } 570 399 } 571 if (kernels->spatialOrder > 0 && index != kernels->subIndex) { 572 convolveSub(convolved, image, footprint); 573 } 400 convolveSub(convolved, image, footprint); 574 401 return convolved; 575 402 } … … 583 410 int v = kernels->v->data.S32[index]; // Offset in y 584 411 psKernel *convolved = convolveOffset(image, u, v, footprint); // Convolved image 585 if (kernels->spatialOrder > 0 && index != kernels->subIndex) { 586 convolveSub(convolved, image, footprint); 587 } 412 convolveSub(convolved, image, footprint); 588 413 return convolved; 589 414 } … … 593 418 } 594 419 case PM_SUBTRACTION_KERNEL_RINGS: { 595 if (index == kernels->subIndex) {596 // Simply copying over the image597 return convolveOffset(image, 0, 0, footprint);598 }599 420 psKernel *convolved = psKernelAlloc(-footprint, footprint, 600 421 -footprint, footprint); // Convolved image … … 650 471 651 472 652 bool pmSubtractionConvolveStamp(pmSubtractionStamp *stamp, const pmSubtractionKernels *kernels, int footprint, 653 pmSubtractionMode mode) 473 bool pmSubtractionConvolveStamp(pmSubtractionStamp *stamp, const pmSubtractionKernels *kernels, int footprint) 654 474 { 655 475 PS_ASSERT_PTR_NON_NULL(stamp, false); 656 PS_ASSERT_PTR_NON_NULL(kernels, false); 657 PS_ASSERT_VECTORS_SIZE_EQUAL(kernels->u, kernels->v, false); 476 PM_ASSERT_SUBTRACTION_KERNELS_NON_NULL(kernels, false); 658 477 PS_ASSERT_INT_NONNEGATIVE(footprint, false); 659 478 … … 663 482 } 664 483 665 switch ( mode) {484 switch (kernels->mode) { 666 485 case PM_SUBTRACTION_MODE_TARGET: 667 486 case PM_SUBTRACTION_MODE_1: … … 677 496 break; 678 497 default: 679 psAbort("Unsupported subtraction mode: %x", mode);498 psAbort("Unsupported subtraction mode: %x", kernels->mode); 680 499 } 681 500 … … 684 503 685 504 686 bool pmSubtractionCalculateEquation(pmSubtractionStampList *stamps, const pmSubtractionKernels *kernels,687 int footprint, pmSubtractionMode mode)688 {689 PM_ASSERT_SUBTRACTION_STAMP_LIST_NON_NULL(stamps, false);690 PS_ASSERT_PTR_NON_NULL(kernels, false);691 PS_ASSERT_VECTORS_SIZE_EQUAL(kernels->u, kernels->v, false);692 PS_ASSERT_INT_NONNEGATIVE(footprint, false);693 694 int spatialOrder = kernels->spatialOrder; // Maximum order of spatial variation695 int numKernels = kernels->num; // Number of kernel basis functions696 int numSpatial = polyTerms(spatialOrder); // Number of spatial variations697 int numBackground = polyTerms(kernels->bgOrder); // Number of background terms698 699 // Total number of parameters to solve for: coefficient of each kernel basis function, multipled by the700 // number of coefficients for the spatial polynomial, and a constant background offset.701 int numParams = numKernels * numSpatial + numBackground;702 int bgIndex = numParams - numBackground; // Index in matrix for the background703 704 // We iterate over each stamp, allocate the matrix and vectors if705 // necessary, and then calculate those matrix/vectors.706 for (int i = 0; i < stamps->num; i++) {707 pmSubtractionStamp *stamp = stamps->stamps->data[i]; // Stamp of interest708 if (stamp->status != PM_SUBTRACTION_STAMP_CALCULATE) {709 continue;710 }711 712 psImage *stampMatrix = stamp->matrix; // Least-squares matrix for this stamp713 psVector *stampVector = stamp->vector; // Least-squares vector for this stamp714 715 if (!stampMatrix) {716 stamp->matrix = stampMatrix = psImageAlloc(numParams, numParams, PS_TYPE_F64);717 }718 assert(stampMatrix->type.type == PS_TYPE_F64);719 assert(stampMatrix->numCols == numParams && stampMatrix->numRows == numParams);720 psImageInit(stampMatrix, 0.0);721 722 if (!stampVector) {723 stamp->vector = stampVector = psVectorAlloc(numParams, PS_TYPE_F64);724 }725 assert(stampVector->type.type == PS_TYPE_F64);726 assert(stampVector->n == numParams);727 psVectorInit(stampVector, 0.0);728 729 // Generate convolutions730 if (!pmSubtractionConvolveStamp(stamp, kernels, footprint, mode)) {731 psError(PS_ERR_UNKNOWN, false, "Unable to convolve stamp %d.", i);732 return NULL;733 }734 735 psKernel *weight = stamp->weight; // Weight map postage stamp736 psKernel *target; // Target postage stamp737 psArray *convolutions; // Convolutions for each kernel738 739 switch (mode) {740 case PM_SUBTRACTION_MODE_TARGET:741 case PM_SUBTRACTION_MODE_1:742 target = stamp->image2;743 convolutions = stamp->convolutions1;744 break;745 case PM_SUBTRACTION_MODE_2:746 target = stamp->image1;747 convolutions = stamp->convolutions2;748 break;749 default:750 psAbort("Unsupported subtraction mode: %x", mode);751 }752 753 psImage *polyValues = spatialPolyValues(spatialOrder, stamp->xNorm, stamp->yNorm); // Polynomial terms754 755 #ifdef TESTING756 for (int j = 0; j < numKernels; j++) {757 psKernel *conv = convolutions->data[j]; // Convolution of interest758 psString filename = NULL; // Filename for output759 psStringAppend(&filename, "conv_%03d_%03d.fits", i, j);760 psFits *fits = psFitsOpen(filename, "w"); // FITS file pointer761 psFree(filename);762 psFitsWriteImage(fits, NULL, conv->image, 0, NULL);763 psFitsClose(fits);764 }765 #endif766 767 // Generate least-squares vector and matrix768 bool bad = false; // Are there bad values?769 psString badString = NULL; // Details on bad values770 for (int j = 0; j < numKernels && !bad; j++) {771 psKernel *jConv = convolutions->data[j]; // Convolution for j-th element772 773 // Generate matrix774 for (int k = j; k < numKernels && !bad; k++) {775 psKernel *kConv = convolutions->data[k]; // Convolution for k-th element776 double sumCC = 0.0; // Sum of the convolution products777 for (int y = - footprint; y <= footprint; y++) {778 for (int x = - footprint; x <= footprint; x++) {779 sumCC += jConv->kernel[y][x] * kConv->kernel[y][x] / weight->kernel[y][x];780 }781 }782 if (!isfinite(sumCC)) {783 psStringAppend(&badString, "\nBad sumCC at %d, %d", j, k);784 bad = true;785 continue;786 }787 // Generate the pseudo-convolutions from the spatial polynomial terms788 for (int jyOrder = 0, jIndex = j; jyOrder <= spatialOrder; jyOrder++) {789 for (int jxOrder = 0; jxOrder <= spatialOrder - jyOrder;790 jxOrder++, jIndex += numKernels) {791 for (int kyOrder = 0, kIndex = k; kyOrder <= spatialOrder; kyOrder++) {792 for (int kxOrder = 0; kxOrder <= spatialOrder - kyOrder;793 kxOrder++, kIndex += numKernels) {794 double convPoly = sumCC * polyValues->data.F64[jyOrder][jxOrder] *795 polyValues->data.F64[kyOrder][kxOrder]; // Temporary value796 stampMatrix->data.F64[jIndex][kIndex] = convPoly;797 stampMatrix->data.F64[kIndex][jIndex] = convPoly;798 }799 }800 }801 }802 }803 804 // Vector and background term for matrix805 double sumC = 0.0; // Sum of the convolution806 double sumTC = 0.0; // Sum of the convolution/target product807 for (int y = - footprint; y <= footprint; y++) {808 for (int x = - footprint; x <= footprint; x++) {809 double convProduct = jConv->kernel[y][x] / weight->kernel[y][x]; // Convolution / noise^2810 sumC += convProduct;811 sumTC += target->kernel[y][x] * convProduct;812 }813 }814 if (!isfinite(sumC)) {815 psStringAppend(&badString, "\nBad sumC at %d", j);816 bad = true;817 continue;818 }819 if (!isfinite(sumTC)) {820 psStringAppend(&badString, "\nBad sumIC detected at %d", j);821 bad = true;822 continue;823 }824 825 for (int jyOrder = 0, jIndex = j; jyOrder <= spatialOrder; jyOrder++) {826 for (int jxOrder = 0; jxOrder <= spatialOrder - jyOrder;827 jxOrder++, jIndex += numKernels) {828 stampVector->data.F64[jIndex] = sumTC * polyValues->data.F64[jyOrder][jxOrder];829 830 double convPoly = sumC * polyValues->data.F64[jyOrder][jxOrder]; // Value831 stampMatrix->data.F64[jIndex][bgIndex] = convPoly;832 stampMatrix->data.F64[bgIndex][jIndex] = convPoly;833 }834 }835 836 }837 psFree(polyValues);838 839 // Background only terms840 double sum1 = 0.0; // Sum of the weighting841 double sumT = 0.0; // Sum of the target842 for (int y = - footprint; y <= footprint; y++) {843 for (int x = - footprint; x <= footprint; x++) {844 double invNoise2 = 1.0 / weight->kernel[y][x]; // Inverse noise, squared845 sum1 += invNoise2;846 sumT += target->kernel[y][x] * invNoise2;847 }848 }849 if (!isfinite(sum1)) {850 psStringAppend(&badString, "\nBad sum1 detected");851 bad = true;852 } else if (!isfinite(sumT)) {853 psStringAppend(&badString, "\nBad sumI detected");854 bad = true;855 }856 857 stampMatrix->data.F64[bgIndex][bgIndex] = sum1;858 stampVector->data.F64[bgIndex] = sumT;859 860 if (bad) {861 stamp->status = PM_SUBTRACTION_STAMP_REJECTED;862 psWarning("Rejecting stamp %d (%d,%d) because of bad equation:%s",863 i, (int)(stamp->x + 0.5), (int)(stamp->y + 0.5), badString);864 psFree(badString);865 } else {866 stamp->status = PM_SUBTRACTION_STAMP_USED;867 }868 869 if (psTraceGetLevel("psModules.imcombine.equation") >= 10) {870 psString matrixName = NULL;871 psStringAppend(&matrixName, "matrix%d.fits", i);872 psFits *matrixFile = psFitsOpen(matrixName, "w");873 psFree(matrixName);874 psFitsWriteImage(matrixFile, NULL, stampMatrix, 0, NULL);875 psFitsClose(matrixFile);876 }877 878 }879 880 return true;881 }882 883 884 psVector *pmSubtractionSolveEquation(psVector *solution, const pmSubtractionStampList *stamps)885 {886 PM_ASSERT_SUBTRACTION_STAMP_LIST_NON_NULL(stamps, NULL);887 888 // Check inputs, while summing the stamp matrices and vectors889 long numParams = -1; // Number of parameters890 for (int i = 0; i < stamps->num; i++) {891 pmSubtractionStamp *stamp = stamps->stamps->data[i]; // Stamp of interest892 PS_ASSERT_PTR_NON_NULL(stamp, NULL);893 if (stamp->status != PM_SUBTRACTION_STAMP_USED) {894 continue;895 }896 if (numParams == -1) {897 numParams = stamp->vector->n;898 } else {899 PS_ASSERT_VECTOR_SIZE(stamp->vector, numParams, NULL);900 }901 PS_ASSERT_VECTOR_TYPE(stamp->vector, PS_TYPE_F64, NULL);902 PS_ASSERT_IMAGE_TYPE(stamp->matrix, PS_TYPE_F64, NULL);903 PS_ASSERT_IMAGE_SIZE(stamp->matrix, numParams, numParams, NULL);904 }905 if (numParams == -1) {906 psError(PS_ERR_BAD_PARAMETER_VALUE, true, "No suitable stamps found.");907 return NULL;908 }909 910 if (solution) {911 PS_ASSERT_VECTOR_TYPE(solution, PS_TYPE_F64, NULL);912 PS_ASSERT_VECTOR_SIZE(solution, numParams, NULL);913 }914 915 // Accumulate the least-squares matricies and vectors916 psImage *sumMatrix = psImageAlloc(numParams, numParams, PS_TYPE_F64); // Combined matrix for all stamps917 psVector *sumVector = psVectorAlloc(numParams, PS_TYPE_F64); // Combined vector for all stamps918 psVectorInit(sumVector, 0.0);919 psImageInit(sumMatrix, 0.0);920 for (int i = 0; i < stamps->num; i++) {921 pmSubtractionStamp *stamp = stamps->stamps->data[i]; // Stamp of interest922 if (stamp->status == PM_SUBTRACTION_STAMP_USED) {923 (void)psBinaryOp(sumMatrix, sumMatrix, "+", stamp->matrix);924 (void)psBinaryOp(sumVector, sumVector, "+", stamp->vector);925 }926 }927 928 psVector *permutation = NULL; // Permutation vector, required for LU decomposition929 psImage *luMatrix = psMatrixLUD(NULL, &permutation, sumMatrix);930 psFree(sumMatrix);931 if (!luMatrix) {932 psError(PS_ERR_UNKNOWN, true, "LU Decomposition of least-squares matrix failed.\n");933 psFree(sumVector);934 psFree(luMatrix);935 psFree(permutation);936 return NULL;937 }938 939 solution = psMatrixLUSolve(solution, luMatrix, sumVector, permutation);940 psFree(sumVector);941 psFree(luMatrix);942 psFree(permutation);943 if (!solution) {944 psError(PS_ERR_UNKNOWN, true, "Failed to solve the least-squares system.\n");945 return NULL;946 }947 948 if (psTraceGetLevel("psModules.imcombine") >= 7) {949 for (int i = 0; i < solution->n; i++) {950 psTrace("psModules.imcombine", 7, "Solution %d: %f\n", i, solution->data.F64[i]);951 }952 }953 954 return solution;955 }956 957 psVector *pmSubtractionCalculateDeviations(pmSubtractionStampList *stamps, const psVector *solution,958 int footprint, const pmSubtractionKernels *kernels,959 pmSubtractionMode mode)960 {961 PM_ASSERT_SUBTRACTION_STAMP_LIST_NON_NULL(stamps, NULL);962 PS_ASSERT_VECTOR_NON_NULL(solution, NULL);963 PS_ASSERT_VECTOR_TYPE(solution, PS_TYPE_F64, NULL);964 PS_ASSERT_PTR_NON_NULL(kernels, NULL);965 PS_ASSERT_VECTOR_SIZE(solution, kernels->num * polyTerms(kernels->spatialOrder) +966 polyTerms(kernels->bgOrder), NULL);967 PS_ASSERT_VECTOR_SIZE(kernels->u, kernels->num, NULL);968 PS_ASSERT_VECTORS_SIZE_EQUAL(kernels->u, kernels->v, NULL);969 970 psVector *deviations = psVectorAlloc(stamps->num, PS_TYPE_F32); // Mean deviation for stamps971 double devNorm = 1.0 / PS_SQR(2 * footprint + 1); // Normalisation for deviations972 int numKernels = kernels->num; // Number of kernels973 int spatialOrder = kernels->spatialOrder; // Order of kernel spatial variations974 float background = solution->data.F64[solution->n-1]; // The difference in background975 976 psVector *coeff = psVectorAlloc(numKernels, PS_TYPE_F64); // Coefficients for the kernel basis functions977 978 for (int i = 0; i < stamps->num; i++) {979 pmSubtractionStamp *stamp = stamps->stamps->data[i]; // The stamp of interest980 if (stamp->status != PM_SUBTRACTION_STAMP_USED) {981 deviations->data.F32[i] = NAN;982 continue;983 }984 985 // Calculate coefficients of the kernel basis functions986 psImage *polyValues = spatialPolyValues(kernels->spatialOrder,987 stamp->xNorm, stamp->yNorm); // Polynomial terms988 for (int j = 0; j < numKernels; j++) {989 double polynomial = 0.0; // Value of the polynomial990 for (int yOrder = 0, index = j; yOrder <= spatialOrder; yOrder++) {991 for (int xOrder = 0; xOrder <= spatialOrder - yOrder; xOrder++, index += numKernels) {992 polynomial += solution->data.F64[index] * polyValues->data.F64[yOrder][xOrder];993 }994 }995 coeff->data.F64[j] = polynomial;996 }997 psFree(polyValues);998 999 // Calculate residuals1000 psKernel *weight = stamp->weight; // Weight postage stamp1001 psKernel *target; // Target postage stamp1002 psArray *convolutions; // Convolution postage stamps for each kernel basis function1003 switch (mode) {1004 case PM_SUBTRACTION_MODE_TARGET:1005 case PM_SUBTRACTION_MODE_1:1006 target = stamp->image2;1007 convolutions = stamp->convolutions1;1008 break;1009 case PM_SUBTRACTION_MODE_2:1010 target = stamp->image1;1011 convolutions = stamp->convolutions2;1012 break;1013 default:1014 psAbort("Unsupported subtraction mode: %x", mode);1015 }1016 1017 #ifdef TESTING1018 psKernel *residual = psKernelAlloc(-footprint, footprint, -footprint, footprint);1019 #endif1020 float deviation = 0.0; // Deviation for this stamp1021 for (int y = - footprint; y <= footprint; y++) {1022 for (int x = - footprint; x <= footprint; x++) {1023 float conv = background; // The value of the convolution1024 for (int j = 0; j < numKernels; j++) {1025 psKernel *convolution = convolutions->data[j]; // Convolution1026 conv += convolution->kernel[y][x] * coeff->data.F64[j];1027 }1028 float diff = target->kernel[y][x] - conv;1029 deviation += PS_SQR(diff) / weight->kernel[y][x];1030 #ifdef TESTING1031 residual->kernel[y][x] = diff;1032 #endif1033 }1034 }1035 1036 deviations->data.F32[i] = sqrtf(devNorm * deviation);1037 psTrace("psModules.imcombine", 5, "Deviation for stamp %d (%d,%d): %f\n",1038 i, (int)(stamp->x + 0.5), (int)(stamp->y + 0.5), deviations->data.F32[i]);1039 if (!isfinite(deviations->data.F32[i])) {1040 stamp->status = PM_SUBTRACTION_STAMP_REJECTED;1041 psTrace("psModules.imcombine", 5,1042 "Rejecting stamp %d (%d,%d) because of non-finite deviation\n",1043 i, (int)(stamp->x + 0.5), (int)(stamp->y + 0.5));1044 continue;1045 }1046 1047 #ifdef TESTING1048 {1049 psString filename = NULL;1050 psStringAppend(&filename, "resid_%03d.fits", i);1051 psFits *fits = psFitsOpen(filename, "w");1052 psFree(filename);1053 psFitsWriteImage(fits, NULL, residual->image, 0, NULL);1054 psFitsClose(fits);1055 }1056 psFree(residual);1057 #endif1058 1059 }1060 psFree(coeff);1061 1062 return deviations;1063 }1064 505 1065 506 … … 1148 589 } 1149 590 1150 psImage *pmSubtractionKernelImage(const psVector *solution, const pmSubtractionKernels *kernels, 1151 float x, float y 1152 ) 1153 { 1154 PS_ASSERT_VECTOR_NON_NULL(solution, NULL); 1155 PS_ASSERT_PTR_NON_NULL(kernels, NULL); 1156 PS_ASSERT_VECTOR_SIZE(solution, kernels->num * polyTerms(kernels->spatialOrder) + 1157 polyTerms(kernels->bgOrder), NULL); 591 psImage *pmSubtractionKernelImage(const pmSubtractionKernels *kernels, float x, float y, bool wantDual) 592 { 593 PM_ASSERT_SUBTRACTION_KERNELS_NON_NULL(kernels, NULL); 594 PM_ASSERT_SUBTRACTION_KERNELS_SOLUTION(kernels, NULL); 1158 595 PS_ASSERT_FLOAT_WITHIN_RANGE(x, -1.0, 1.0, NULL); 1159 596 PS_ASSERT_FLOAT_WITHIN_RANGE(y, -1.0, 1.0, NULL); 1160 PS_ASSERT_VECTOR_SIZE(kernels->u, kernels->num, false);1161 PS_ASSERT_VECTORS_SIZE_EQUAL(kernels->u, kernels->v, NULL);1162 597 1163 598 // Precalulate polynomial values 1164 psImage *polyValues = spatialPolyValues(kernels->spatialOrder, x, y);599 psImage *polyValues = p_pmSubtractionPolynomial(NULL, kernels->spatialOrder, x, y); 1165 600 1166 601 // The appropriate kernel 1167 psKernel *kernel = solvedKernel(NULL, solution, kernels, polyValues);602 psKernel *kernel = solvedKernel(NULL, kernels, polyValues, wantDual); 1168 603 1169 604 psFree(polyValues); … … 1175 610 } 1176 611 1177 psArray *pmSubtractionKernelSolutions(const psVector *solution, const pmSubtractionKernels *kernels, 1178 float x, float y 1179 ) 1180 { 1181 PS_ASSERT_VECTOR_NON_NULL(solution, NULL); 1182 PS_ASSERT_PTR_NON_NULL(kernels, NULL); 1183 PS_ASSERT_VECTOR_SIZE(solution, kernels->num * polyTerms(kernels->spatialOrder) + 1184 polyTerms(kernels->bgOrder), NULL); 612 #if 0 613 psArray *pmSubtractionKernelSolutions(const pmSubtractionKernels *kernels, float x, float y, bool wantDual) 614 { 615 PM_ASSERT_SUBTRACTION_KERNELS_NON_NULL(kernels, NULL); 616 PM_ASSERT_SUBTRACTION_KERNELS_SOLUTION(kernels, NULL); 1185 617 PS_ASSERT_FLOAT_WITHIN_RANGE(x, -1.0, 1.0, NULL); 1186 618 PS_ASSERT_FLOAT_WITHIN_RANGE(y, -1.0, 1.0, NULL); 1187 PS_ASSERT_VECTOR_SIZE(kernels->u, kernels->num, false);1188 PS_ASSERT_VECTORS_SIZE_EQUAL(kernels->u, kernels->v, NULL);1189 619 1190 620 psArray *images = psArrayAlloc(solution->n - 1); // Images of each kernel to return … … 1194 624 for (int i = 0; i < solution->n - 1; i++) { 1195 625 fakeSolution->data.F64[i] = solution->data.F64[i]; 1196 images->data[i] = pmSubtractionKernelImage( fakeSolution, kernels, x, y);626 images->data[i] = pmSubtractionKernelImage(kernels, x, y, wantDual); 1197 627 fakeSolution->data.F64[i] = 0.0; 1198 628 } … … 1202 632 return images; 1203 633 } 1204 1205 bool pmSubtractionConvolve(pmReadout *out, const pmReadout *ro1, const pmReadout *ro2, 634 #endif 635 636 637 638 bool pmSubtractionConvolve(pmReadout *out1, pmReadout *out2, const pmReadout *ro1, const pmReadout *ro2, 1206 639 const psImage *subMask, psMaskType blank, const psRegion *region, 1207 const psVector *solution, const pmSubtractionKernels *kernels, 1208 pmSubtractionMode mode, bool useFFT) 1209 { 1210 PS_ASSERT_PTR_NON_NULL(out, false); 640 const pmSubtractionKernels *kernels, bool useFFT) 641 { 642 PS_ASSERT_PTR_NON_NULL(out1, false); 1211 643 PS_ASSERT_PTR_NON_NULL(ro1, false); 1212 644 PS_ASSERT_IMAGE_NON_NULL(ro1->image, false); … … 1217 649 PS_ASSERT_IMAGES_SIZE_EQUAL(ro1->weight, ro1->image, false); 1218 650 } 1219 if (mode != PM_SUBTRACTION_MODE_1) { 651 PM_ASSERT_SUBTRACTION_KERNELS_NON_NULL(kernels, false); 652 PM_ASSERT_SUBTRACTION_KERNELS_SOLUTION(kernels, false); 653 if (kernels->mode != PM_SUBTRACTION_MODE_1) { 654 PS_ASSERT_PTR_NON_NULL(out2, false); 1220 655 PS_ASSERT_PTR_NON_NULL(ro2, false); 1221 656 PS_ASSERT_IMAGE_NON_NULL(ro2->image, false); … … 1232 667 PS_ASSERT_IMAGES_SIZE_EQUAL(subMask, ro1->image, false); 1233 668 } 1234 if (out ->image) {1235 PS_ASSERT_IMAGE_NON_NULL(out ->image, false);1236 PS_ASSERT_IMAGES_SIZE_EQUAL(out ->image, ro1->image, false);1237 PS_ASSERT_IMAGE_TYPE(out ->image, PS_TYPE_F32, false);1238 } 1239 if (out ->mask) {1240 PS_ASSERT_IMAGE_NON_NULL(out ->mask, false);1241 PS_ASSERT_IMAGES_SIZE_EQUAL(out ->mask, ro1->image, false);1242 PS_ASSERT_IMAGE_TYPE(out ->mask, PS_TYPE_MASK, false);669 if (out1->image) { 670 PS_ASSERT_IMAGE_NON_NULL(out1->image, false); 671 PS_ASSERT_IMAGES_SIZE_EQUAL(out1->image, ro1->image, false); 672 PS_ASSERT_IMAGE_TYPE(out1->image, PS_TYPE_F32, false); 673 } 674 if (out1->mask) { 675 PS_ASSERT_IMAGE_NON_NULL(out1->mask, false); 676 PS_ASSERT_IMAGES_SIZE_EQUAL(out1->mask, ro1->image, false); 677 PS_ASSERT_IMAGE_TYPE(out1->mask, PS_TYPE_MASK, false); 1243 678 PS_ASSERT_IMAGE_NON_NULL(subMask, false); 1244 679 } 1245 if (out->weight) { 1246 PS_ASSERT_IMAGE_NON_NULL(out->weight, false); 1247 PS_ASSERT_IMAGES_SIZE_EQUAL(out->weight, ro1->image, false); 1248 PS_ASSERT_IMAGE_TYPE(out->weight, PS_TYPE_F32, false); 1249 } 1250 PS_ASSERT_VECTOR_NON_NULL(solution, false); 1251 PS_ASSERT_VECTOR_TYPE(solution, PS_TYPE_F64, false); 1252 PS_ASSERT_PTR_NON_NULL(kernels, false); 1253 PS_ASSERT_VECTOR_SIZE(solution, kernels->num * polyTerms(kernels->spatialOrder) + 1254 polyTerms(kernels->bgOrder), -1); 1255 PS_ASSERT_VECTOR_SIZE(kernels->u, kernels->num, false); 1256 PS_ASSERT_VECTORS_SIZE_EQUAL(kernels->u, kernels->v, false); 680 if (out1->weight) { 681 PS_ASSERT_IMAGE_NON_NULL(out1->weight, false); 682 PS_ASSERT_IMAGES_SIZE_EQUAL(out1->weight, ro1->image, false); 683 PS_ASSERT_IMAGE_TYPE(out1->weight, PS_TYPE_F32, false); 684 } 1257 685 if (region) { 1258 686 if (psRegionIsNaN(*region)) { … … 1273 701 1274 702 psImage *image, *weight; // Image and weight map to convolve 1275 switch ( mode) {703 switch (kernels->mode) { 1276 704 case PM_SUBTRACTION_MODE_TARGET: 1277 705 case PM_SUBTRACTION_MODE_1: 706 case PM_SUBTRACTION_MODE_DUAL: 1278 707 image = ro1->image; 1279 708 weight = ro1->weight; … … 1281 710 case PM_SUBTRACTION_MODE_2: 1282 711 image = ro2->image; 1283 weight = ro2-> image;712 weight = ro2->weight; 1284 713 break; 1285 714 default: 1286 psAbort("Unsupported subtraction mode: %x", mode); 1287 } 1288 1289 int numBackground = polyTerms(kernels->bgOrder); // Number of background terms 1290 float background = solution->data.F64[solution->n - numBackground]; // The difference in background 715 psAbort("Unsupported subtraction mode: %x", kernels->mode); 716 } 717 1291 718 int numCols = ro1->image->numCols, numRows = ro1->image->numRows; // Image dimensions 1292 719 1293 psImage *convImage = out->image; // Convolved image 1294 if (!convImage) { 1295 out->image = psImageAlloc(numCols, numRows, PS_TYPE_F32); 1296 convImage = out->image; 720 psImage *convImage1 = out1->image; // Convolved image 721 if (!convImage1) { 722 convImage1 = out1->image = psImageAlloc(numCols, numRows, PS_TYPE_F32); 1297 723 } 1298 724 psImage *convMask = NULL; // Convolved mask image 1299 725 if (subMask) { 1300 if (!out ->mask) {1301 out ->mask = psImageAlloc(numCols, numRows, PS_TYPE_MASK);1302 } 1303 convMask = out ->mask;726 if (!out1->mask) { 727 out1->mask = psImageAlloc(numCols, numRows, PS_TYPE_MASK); 728 } 729 convMask = out1->mask; 1304 730 psImageInit(convMask, 0); 1305 731 } 1306 psImage *convWeight = NULL; // Convolved weight (variance) image732 psImage *convWeight1 = NULL; // Convolved weight (variance) image 1307 733 if (weight) { 1308 if (!out->weight) { 1309 out->weight = psImageAlloc(numCols, numRows, PS_TYPE_F32); 1310 } 1311 convWeight = out->weight; 1312 psImageInit(convWeight, 0.0); 734 if (!out1->weight) { 735 out1->weight = psImageAlloc(numCols, numRows, PS_TYPE_F32); 736 } 737 convWeight1 = out1->weight; 738 psImageInit(convWeight1, 0.0); 739 } 740 741 psImage *convImage2, *convWeight2; // Convolved products for dual mode 742 if (kernels->mode == PM_SUBTRACTION_MODE_DUAL) { 743 convImage2 = out2->image; 744 if (!convImage2) { 745 convImage2 = out2->image = psImageAlloc(numCols, numRows, PS_TYPE_F32); 746 } 747 convWeight2 = NULL; // Convolved weight (variance) image 748 if (ro2->weight) { 749 if (!out2->weight) { 750 out2->weight = psImageAlloc(numCols, numRows, PS_TYPE_F32); 751 } 752 convWeight2 = out2->weight; 753 psImageInit(convWeight2, 0.0); 754 } 755 if (subMask) { 756 // Copying mask --- they're the same! 757 psFree(out2->mask); 758 out2->mask = psMemIncrRefCounter(convMask); 759 } 1313 760 } 1314 761 1315 762 int size = kernels->size; // Half-size of kernel 1316 763 int fullSize = 2 * size + 1; // Full size of kernel 1317 psImage *polyValues = NULL; // Pre-calculated polynomial values1318 1319 psKernel *kernelImage = NULL; // Kernel for the image1320 psKernel *kernelWeight = NULL; // Kernel for the weight map1321 764 1322 765 // Get region for convolution: [xMin:xMax,yMin:yMax] … … 1330 773 } 1331 774 1332 psMaskType maskSource, maskTarget; // Mask values for source and target 1333 switch (mode) { 775 psMaskType maskSource; // Mask these pixels when convolving 776 psMaskType maskTarget; // Mark these pixels as bad when propagating the subtractionMask 777 switch (kernels->mode) { 1334 778 case PM_SUBTRACTION_MODE_TARGET: 1335 779 case PM_SUBTRACTION_MODE_1: … … 1341 785 maskTarget = PM_SUBTRACTION_MASK_BAD_1 | PM_SUBTRACTION_MASK_CONVOLVE_2; 1342 786 break; 787 case PM_SUBTRACTION_MODE_DUAL: 788 maskSource = PM_SUBTRACTION_MASK_BAD_1 | PM_SUBTRACTION_MASK_BAD_2; 789 maskTarget = PM_SUBTRACTION_MASK_CONVOLVE_1 | PM_SUBTRACTION_MASK_CONVOLVE_2; 790 break; 1343 791 default: 1344 psAbort("Unsupported subtraction mode: %x", mode); 1345 } 792 psAbort("Unsupported subtraction mode: %x", kernels->mode); 793 } 794 795 psImage *polyValues = NULL; // Pre-calculated polynomial values 796 psKernel *kernelImage = NULL; // Kernel for the images 797 psKernel *kernelWeight = NULL; // Kernel for the weight maps 1346 798 1347 799 for (int j = yMin; j < yMax; j += fullSize) { 1348 800 int ySubMax = PS_MIN(j + fullSize, yMax); // Range for subregion of interest 801 float yNorm = 2.0 * (float)(j + size + 1 - numRows/2.0) / (float)numRows; // Normalised coordinate 1349 802 for (int i = xMin; i < xMax; i += fullSize) { 1350 803 int xSubMax = PS_MIN(i + fullSize, xMax); // Range for subregion of interest 804 float xNorm = 2.0 * (float)(i + size + 1 - numCols/2.0) / (float)numCols; // Normalised coordinate 1351 805 1352 806 // Only generate polynomial values every kernel footprint, since we have already assumed 1353 807 // (with the stamps) that it does not vary rapidly on this scale. 1354 psFree(polyValues); 1355 polyValues = spatialPolyValues(kernels->spatialOrder, 1356 2.0 * (float)(i + size + 1 - numCols/2.0) / (float)numCols, 1357 2.0 * (float)(j + size + 1 - numRows/2.0) / (float)numRows); 1358 1359 kernelImage = solvedKernel(kernelImage, solution, kernels, polyValues); 1360 if (weight) { 1361 kernelWeight = varianceKernel(kernelWeight, kernelImage); 1362 } 808 polyValues = p_pmSubtractionPolynomial(polyValues, kernels->spatialOrder, xNorm, yNorm); 809 float background = p_pmSubtractionSolutionBackground(kernels, polyValues); // Background term 1363 810 1364 811 psRegion subRegion = psRegionSet(i, xSubMax, j, ySubMax); // Sub-region to convolve 1365 if (useFFT) { 1366 // Use Fast Fourier Transform to do the convolution 1367 // This provides a big speed-up for large kernels 1368 convolveFFT(convImage, image, subMask, maskSource, kernelImage, subRegion, 1369 background, size); 1370 if (weight) { 1371 convolveFFT(convWeight, weight, subMask, maskSource, kernelWeight, subRegion, 1372 0.0, size); 1373 } 1374 } else { 1375 convolveDirect(convImage, image, kernelImage, subRegion, background, size); 1376 if (weight) { 1377 convolveDirect(convWeight, weight, kernelWeight, subRegion, 0.0, size); 1378 } 812 813 convolveRegion(convImage1, convWeight1, &kernelImage, &kernelWeight, image, weight, 814 subMask, maskSource, kernels, polyValues, background, subRegion, useFFT); 815 816 if (kernels->mode == PM_SUBTRACTION_MODE_DUAL) { 817 convolveRegion(convImage2, convWeight2, &kernelImage, &kernelWeight, ro2->image, ro2->weight, 818 subMask, maskSource, kernels, polyValues, background, subRegion, useFFT); 1379 819 } 1380 820 … … 1385 825 if (subMask->data.PS_TYPE_MASK_DATA[y][x] & maskTarget) { 1386 826 convMask->data.PS_TYPE_MASK_DATA[y][x] |= blank; 1387 convImage ->data.F32[y][x] = NAN;827 convImage1->data.F32[y][x] = NAN; 1388 828 if (weight) { 1389 convWeight ->data.F32[y][x] = NAN;829 convWeight1->data.F32[y][x] = NAN; 1390 830 } 1391 831 } … … 1402 842 return true; 1403 843 } 1404 1405 bool pmSubtractionBorder(psImage *image, psImage *weight, psImage *mask,1406 int size, psMaskType blank)1407 {1408 PS_ASSERT_IMAGE_NON_NULL(image, false);1409 PS_ASSERT_IMAGE_TYPE(image, PS_TYPE_F32, false);1410 if (mask) {1411 PS_ASSERT_IMAGE_NON_NULL(mask, false);1412 PS_ASSERT_IMAGES_SIZE_EQUAL(mask, image, false);1413 PS_ASSERT_IMAGE_TYPE(mask, PS_TYPE_MASK, false);1414 }1415 if (weight) {1416 PS_ASSERT_IMAGE_NON_NULL(weight, false);1417 PS_ASSERT_IMAGES_SIZE_EQUAL(weight, image, false);1418 PS_ASSERT_IMAGE_TYPE(weight, PS_TYPE_F32, false);1419 }1420 1421 int numCols = image->numCols, numRows = image->numRows; // Image dimensions1422 1423 for (int y = size; y < numRows - size; y++) {1424 for (int x = 0; x < size; x++) {1425 markBlank(image, mask, weight, x, y, blank);1426 }1427 for (int x = numCols - size; x < numCols; x++) {1428 markBlank(image, mask, weight, x, y, blank);1429 }1430 }1431 for (int y = 0; y < size; y++) {1432 for (int x = 0; x < numCols; x++) {1433 markBlank(image, mask, weight, x, y, blank);1434 }1435 }1436 for (int y = numRows - size; y < numRows; y++) {1437 for (int x = 0; x < numCols; x++) {1438 markBlank(image, mask, weight, x, y, blank);1439 }1440 }1441 1442 return true;1443 }1444 1445 -
trunk/psModules/src/imcombine/pmSubtraction.h
r15562 r15756 6 6 * @author GLG, MHPCC 7 7 * 8 * @version $Revision: 1.2 1$ $Name: not supported by cvs2svn $9 * @date $Date: 2007-1 1-10 01:09:20$8 * @version $Revision: 1.22 $ $Name: not supported by cvs2svn $ 9 * @date $Date: 2007-12-07 01:57:15 $ 10 10 * Copyright 2004-207 Institute for Astronomy, University of Hawaii 11 11 */ … … 37 37 } pmSubtractionMasks; 38 38 39 /// Generate a mask for use in the subtraction process 40 psImage *pmSubtractionMask(const psImage *refMask, ///< Mask for the reference image (will be convolved) 41 const psImage *inMask, ///< Mask for the input image, or NULL 42 psMaskType maskVal, ///< Value to mask out 43 int size, ///< Half-size of the kernel (pmSubtractionKernels.size) 44 int footprint, ///< Half-size of the kernel footprint 45 float badFrac, ///< Maximum fraction of bad input pixels to accept 46 bool useFFT ///< Use FFT to do convolution? 47 ); 39 40 /// Number of terms in a polynomial 41 #define PM_SUBTRACTION_POLYTERMS(ORDER) (((ORDER) + 1) * ((ORDER) + 2) / 2) 42 43 /// Set the indices for the normalisation and background terms 44 #define PM_SUBTRACTION_INDICES(NORM,BG,KERNELS) { \ 45 int numSpatial = PM_SUBTRACTION_POLYTERMS((KERNELS)->spatialOrder); /* Number of spatial terms */ \ 46 NORM = (KERNELS)->num * numSpatial; \ 47 BG = NORM + 1; \ 48 } 49 50 /// Return the index for the start of the normalisation terms 51 #define PM_SUBTRACTION_INDEX_NORM(KERNELS) \ 52 ((KERNELS)->num * PM_SUBTRACTION_POLYTERMS((KERNELS)->spatialOrder)) 53 54 /// Return the index for the start of the background terms 55 #define PM_SUBTRACTION_INDEX_BG(KERNELS) \ 56 (((KERNELS)->num * PM_SUBTRACTION_POLYTERMS((KERNELS)->spatialOrder)) + 1) 57 48 58 49 59 /// Convolve the reference stamp with the kernel components 50 60 bool pmSubtractionConvolveStamp(pmSubtractionStamp *stamp, ///< Stamp to convolve 51 61 const pmSubtractionKernels *kernels, ///< Kernel parameters 52 int footprint, ///< Half-size of region over which to calculate equation 53 pmSubtractionMode mode ///< Mode for subtraction (which to convolve) 54 ); 55 56 /// Calculate the least-squares equation to match the image quality 57 bool pmSubtractionCalculateEquation(pmSubtractionStampList *stamps, ///< Stamps 58 const pmSubtractionKernels *kernels, ///< Kernel parameters 59 int footprint, ///< Half-size of region over which to calculate equation 60 pmSubtractionMode mode ///< Mode for subtraction (which to convolve) 61 ); 62 63 /// Solve the least-squares equation to match the image quality 64 psVector *pmSubtractionSolveEquation(psVector *solution, ///< Solution vector, or NULL 65 const pmSubtractionStampList *stamps ///< Stamps 66 ); 67 68 /// Calculate deviations 69 psVector *pmSubtractionCalculateDeviations(pmSubtractionStampList *stamps, ///< Stamps 70 const psVector *solution, ///< Solution vector 71 int footprint, ///< Half-size of stamp 72 const pmSubtractionKernels *kernels, ///< Kernel parameters 73 pmSubtractionMode mode ///< Mode for subtraction 62 int footprint ///< Half-size of region over which to calculate equation 74 63 ); 75 64 … … 83 72 84 73 /// Generate an image of the convolution kernel 85 psImage *pmSubtractionKernelImage(const p sVector *solution, ///< Solution vector86 const pmSubtractionKernels *kernels, ///< Kernel parameters87 float x, float y ///< Normalised position [-1,1] for which to generate image74 psImage *pmSubtractionKernelImage(const pmSubtractionKernels *kernels, ///< Kernel parameters 75 float x, float y,///< Normalised position [-1,1] for which to generate image 76 bool wantDual ///< Calculate for the dual kernel? 88 77 ); 89 78 … … 95 84 96 85 /// Convolve image in preparation for subtraction 97 bool pmSubtractionConvolve(pmReadout *out, ///< Output image 86 bool pmSubtractionConvolve(pmReadout *out1, ///< Output image 1 87 pmReadout *out2, ///< Output image 2 (DUAL mode only) 98 88 const pmReadout *ro1, // Input image 1 99 89 const pmReadout *ro2, // Input image 2 … … 101 91 psMaskType blank, ///< Mask value for blank regions 102 92 const psRegion *region, ///< Region to convolve (or NULL) 103 const psVector *solution, ///< The solution vector104 93 const pmSubtractionKernels *kernels, ///< Kernel parameters 105 pmSubtractionMode mode, ///< Mode for subtraction106 94 bool useFFT ///< Use Fast Fourier Transform for the convolution? 107 );108 109 /// Mark the non-convolved part of the image as blank110 bool pmSubtractionBorder(psImage *image,///< Image111 psImage *weight, ///< Weight map (or NULL)112 psImage *mask, ///< Mask (or NULL)113 int size, ///< Kernel half-size114 psMaskType blank ///< Mask value for blank regions115 95 ); 116 96 … … 122 102 ); 123 103 104 /// Given (normalised) coordinates (x,y), generate a matrix where the elements (i,j) are x^i * y^j 105 psImage *p_pmSubtractionPolynomial(psImage *output, ///< Output matrix, or NULL 106 int spatialOrder, ///< Maximum spatial polynomial order 107 float x, float y ///< Normalised position of interest, [-1,1] 108 ); 109 124 110 /// @} 125 111 #endif -
trunk/psModules/src/imcombine/pmSubtractionKernels.c
r15432 r15756 4 4 5 5 #include <stdio.h> 6 #include <string.h> 6 7 #include <strings.h> 7 8 #include <pslib.h> 8 9 10 #include "pmSubtraction.h" 9 11 #include "pmSubtractionKernels.h" 10 12 … … 22 24 psFree(kernels->vStop); 23 25 psFree(kernels->preCalc); 24 } 25 26 // Raise a number to an integer power 26 psFree(kernels->solution1); 27 psFree(kernels->solution2); 28 } 29 30 // Raise an integer to an integer power 27 31 static inline long power(int value, // Value 28 32 int exp // Exponent … … 45 49 bool p_pmSubtractionKernelsAddGrid(pmSubtractionKernels *kernels, int start, int size) 46 50 { 47 PS_ASSERT_PTR_NON_NULL(kernels, false); 48 PS_ASSERT_VECTOR_NON_NULL(kernels->u, false); 49 PS_ASSERT_VECTOR_NON_NULL(kernels->v, false); 50 PS_ASSERT_VECTOR_NON_NULL(kernels->widths, false); 51 PS_ASSERT_VECTOR_TYPE(kernels->u, PS_TYPE_S32, false); 52 PS_ASSERT_VECTOR_TYPE(kernels->v, PS_TYPE_S32, false); 53 PS_ASSERT_VECTOR_TYPE(kernels->widths, PS_TYPE_F32, false); 54 PS_ASSERT_ARRAY_NON_NULL(kernels->preCalc, false); 51 PM_ASSERT_SUBTRACTION_KERNELS_NON_NULL(kernels, false); 55 52 PS_ASSERT_INT_NONNEGATIVE(start, false); 56 53 PS_ASSERT_INT_NONNEGATIVE(size, false); 57 54 58 int numNew = PS_SQR(2 * size + 1) ; // Number of new kernel parameters to add55 int numNew = PS_SQR(2 * size + 1) - 1; // Number of new kernel parameters to add 59 56 60 57 // Ensure the sizes match … … 68 65 for (int v = - size, index = start; v <= size; v++) { 69 66 for (int u = - size; u <= size; u++, index++) { 67 if (v == 0 && u == 0) { 68 // Skip normalisation component: added explicitly 69 index--; 70 continue; 71 } 70 72 kernels->widths->data.F32[index] = NAN; 71 73 kernels->u->data.S32[index] = u; … … 81 83 82 84 pmSubtractionKernels *p_pmSubtractionKernelsRawISIS(int size, int spatialOrder, 83 const psVector *fwhms, const psVector *orders) 85 const psVector *fwhms, const psVector *orders, 86 pmSubtractionMode mode) 84 87 { 85 88 PS_ASSERT_VECTOR_NON_NULL(fwhms, NULL); … … 97 100 for (int i = 0; i < numGaussians; i++) { 98 101 int gaussOrder = orders->data.S32[i]; // Polynomial order to apply to Gaussian 99 psStringAppend(¶ms, "(%. 2f,%d)", fwhms->data.F32[i], orders->data.S32[i]);102 psStringAppend(¶ms, "(%.1f,%d)", fwhms->data.F32[i], orders->data.S32[i]); 100 103 num += (gaussOrder + 1) * (gaussOrder + 2) / 2; 101 104 } 102 105 103 106 pmSubtractionKernels *kernels = pmSubtractionKernelsAlloc(num, PM_SUBTRACTION_KERNEL_ISIS, 104 size, spatialOrder ); // The kernels107 size, spatialOrder, mode); // The kernels 105 108 psStringAppend(&kernels->description, "ISIS(%d,%s,%d)", size, params, spatialOrder); 106 109 … … 149 152 } 150 153 151 kernels->subIndex = -1;152 153 154 return kernels; 154 155 } … … 159 160 160 161 pmSubtractionKernels *pmSubtractionKernelsAlloc(int numBasisFunctions, pmSubtractionKernelsType type, 161 int size, int spatialOrder )162 int size, int spatialOrder, pmSubtractionMode mode) 162 163 { 163 164 pmSubtractionKernels *kernels = psAlloc(sizeof(pmSubtractionKernels)); // Kernels, to return … … 173 174 kernels->uStop = NULL; 174 175 kernels->vStop = NULL; 175 kernels->subIndex = 0;176 176 kernels->size = size; 177 177 kernels->inner = 0; 178 178 kernels->spatialOrder = spatialOrder; 179 179 kernels->bgOrder = 0; 180 181 return kernels; 182 } 183 184 pmSubtractionKernels *pmSubtractionKernelsPOIS(int size, int spatialOrder) 180 kernels->mode = mode; 181 kernels->solution1 = NULL; 182 kernels->solution2 = NULL; 183 184 return kernels; 185 } 186 187 pmSubtractionKernels *pmSubtractionKernelsPOIS(int size, int spatialOrder, pmSubtractionMode mode) 185 188 { 186 189 PS_ASSERT_INT_POSITIVE(size, NULL); 187 190 PS_ASSERT_INT_NONNEGATIVE(spatialOrder, NULL); 188 191 189 int num = PS_SQR(2 * size + 1) ; // Number of basis functions192 int num = PS_SQR(2 * size + 1) - 1; // Number of basis functions 190 193 191 194 pmSubtractionKernels *kernels = pmSubtractionKernelsAlloc(num, PM_SUBTRACTION_KERNEL_POIS, 192 size, spatialOrder ); // The kernels195 size, spatialOrder, mode); // The kernels 193 196 psStringAppend(&kernels->description, "POIS(%d,%d)", size, spatialOrder); 194 197 psLogMsg("psModules.imcombine", PS_LOG_INFO, "POIS kernel: %d,%d --> %d elements", … … 199 202 } 200 203 201 kernels->subIndex = num / 2;202 assert(kernels->u->data.S32[kernels->subIndex] == 0 &&203 kernels->v->data.S32[kernels->subIndex] == 0);204 205 204 return kernels; 206 205 } … … 208 207 209 208 pmSubtractionKernels *pmSubtractionKernelsISIS(int size, int spatialOrder, 210 const psVector *fwhms, const psVector *orders) 209 const psVector *fwhms, const psVector *orders, 210 pmSubtractionMode mode) 211 211 { 212 212 pmSubtractionKernels *kernels = p_pmSubtractionKernelsRawISIS(size, spatialOrder, 213 fwhms, orders ); // Kernels213 fwhms, orders, mode); // Kernels 214 214 if (!kernels) { 215 215 return NULL; 216 216 } 217 217 218 // Subtract a reference kernelfrom all the others to maintain flux scaling218 // Subtract normalisation from all the others to maintain flux scaling 219 219 if (spatialOrder > 0) { 220 int subIndex = 0; // Index of kernel to subtract from others221 psKernel *subtract = kernels->preCalc->data[subIndex]; // Kernel to subtract from others222 220 int numGaussians = fwhms->n; // Number of Gaussians 223 221 for (int i = 0, index = 0; i < numGaussians; i++) { 224 222 for (int uOrder = 0; uOrder <= orders->data.S32[i]; uOrder++) { 225 223 for (int vOrder = 0; vOrder <= orders->data.S32[i] - uOrder; vOrder++, index++) { 226 if (uOrder % 2 == 0 && vOrder % 2 == 0 && index != subIndex) {224 if (uOrder % 2 == 0 && vOrder % 2 == 0) { 227 225 psKernel *kernel = kernels->preCalc->data[index]; // Kernel to subtract 228 psBinaryOp(kernel->image, kernel->image, "-", subtract->image);226 kernel->kernel[0][0] -= 1.0; 229 227 } 230 228 } … … 242 240 psFitsWriteImage(kernelFile, NULL, kernel->image, 0, NULL); 243 241 psFitsClose(kernelFile); 244 } 245 } 246 247 return kernels; 248 } 249 250 /// Generate SPAM kernels 251 pmSubtractionKernels *pmSubtractionKernelsSPAM(int size, ///< Half-size of the kernel 252 int spatialOrder, ///< Order of spatial variations 253 int inner, ///< Inner radius to preserve unbinned 254 int binning ///< Kernel binning factor 255 ) 242 double sum = 0.0; 243 for (int y = 0; y < kernel->image->numRows; y++) { 244 for (int x = 0; x < kernel->image->numCols; x++) { 245 sum += kernel->image->data.F32[y][x]; 246 } 247 } 248 psTrace("psModules.imcombine.kernel", 10, "Kernel %d sum: %lf\n", i, sum); 249 } 250 } 251 252 return kernels; 253 } 254 255 pmSubtractionKernels *pmSubtractionKernelsSPAM(int size, int spatialOrder, int inner, int binning, 256 pmSubtractionMode mode) 256 257 { 257 258 PS_ASSERT_INT_POSITIVE(size, NULL); … … 269 270 psTrace("psModules.imcombine", 3, "Inner: %d Outer: %d\n", numInner, numOuter); 270 271 271 int num = PS_SQR(2 * numTotal + 1) ; // Number of basis functions272 int num = PS_SQR(2 * numTotal + 1) - 1; // Number of basis functions 272 273 273 274 psTrace("psModules.imcombine", 3, "Number of basis functions: %d\n", num); 274 275 275 276 pmSubtractionKernels *kernels = pmSubtractionKernelsAlloc(num, PM_SUBTRACTION_KERNEL_SPAM, 276 size, spatialOrder ); // The kernels277 size, spatialOrder, mode); // The kernels 277 278 psStringAppend(&kernels->description, "SPAM(%d,%d,%d,%d)", size, inner, binning, spatialOrder); 278 279 … … 280 281 size, inner, binning, spatialOrder, num); 281 282 282 kernels->uStop = psVectorAlloc(num, PS_TYPE_ F32);283 kernels->vStop = psVectorAlloc(num, PS_TYPE_ F32);283 kernels->uStop = psVectorAlloc(num, PS_TYPE_S32); 284 kernels->vStop = psVectorAlloc(num, PS_TYPE_S32); 284 285 285 286 psVector *locations = psVectorAlloc(2 * numTotal + 1, PS_TYPE_S32); // Locations for each kernel element … … 314 315 315 316 for (int j = - numTotal; j <= numTotal; j++, index++) { 317 if (i == 0 && j == 0) { 318 // Skip normalisation component: added explicitly 319 index--; 320 continue; 321 } 316 322 int v = locations->data.S32[numTotal + j]; // Location of pixel 317 323 int vStop = v + widths->data.S32[numTotal + j]; // Width of pixel … … 327 333 } 328 334 329 kernels->subIndex = num / 2;330 assert(kernels->u->data.S32[kernels->subIndex] == 0 &&331 kernels->v->data.S32[kernels->subIndex] == 0 &&332 kernels->uStop->data.S32[kernels->subIndex] == 0 &&333 kernels->vStop->data.S32[kernels->subIndex] == 0);334 335 335 psFree(locations); 336 336 psFree(widths); … … 340 340 341 341 342 /// Generate FRIES kernels 343 pmSubtractionKernels *pmSubtractionKernelsFRIES(int size, ///< Half-size of the kernel 344 int spatialOrder, ///< Order of spatial variations 345 int inner ///< Inner radius to preserve unbinned 346 ) 342 pmSubtractionKernels *pmSubtractionKernelsFRIES(int size, int spatialOrder, int inner, pmSubtractionMode mode) 347 343 { 348 344 PS_ASSERT_INT_POSITIVE(size, NULL); … … 366 362 psTrace("psModules.imcombine", 3, "Inner: %d Outer: %d\n", numInner, numOuter); 367 363 368 int num = PS_SQR(2 * numTotal + 1) ; // Number of basis functions364 int num = PS_SQR(2 * numTotal + 1) - 1; // Number of basis functions 369 365 370 366 psTrace("psModules.imcombine", 3, "Number of basis functions: %d\n", num); 371 367 372 368 pmSubtractionKernels *kernels = pmSubtractionKernelsAlloc(num, PM_SUBTRACTION_KERNEL_FRIES, 373 size, spatialOrder ); // The kernels369 size, spatialOrder, mode); // The kernels 374 370 psStringAppend(&kernels->description, "FRIES(%d,%d,%d)", size, inner, spatialOrder); 375 371 … … 377 373 size, inner, spatialOrder, num); 378 374 379 kernels->uStop = psVectorAlloc(num, PS_TYPE_ F32);380 kernels->vStop = psVectorAlloc(num, PS_TYPE_ F32);375 kernels->uStop = psVectorAlloc(num, PS_TYPE_S32); 376 kernels->vStop = psVectorAlloc(num, PS_TYPE_S32); 381 377 382 378 psVector *start = psVectorAlloc(2 * numTotal + 1, PS_TYPE_S32); … … 409 405 int uStop = stop->data.S32[numTotal + i]; // Width of pixel 410 406 for (int j = - numTotal; j <= numTotal; j++, index++) { 407 if (i == 0 && j == 0) { 408 // Skip normalisation component: added explicitly 409 index--; 410 continue; 411 } 411 412 int v = start->data.S32[numTotal + j]; // Location of pixel 412 413 int vStop = stop->data.S32[numTotal + j]; // Width of pixel … … 422 423 } 423 424 424 kernels->subIndex = num / 2;425 assert(kernels->u->data.S32[kernels->subIndex] == 0 &&426 kernels->v->data.S32[kernels->subIndex] == 0 &&427 kernels->uStop->data.S32[kernels->subIndex] == 0 &&428 kernels->vStop->data.S32[kernels->subIndex] == 0);429 430 425 psFree(start); 431 426 psFree(stop); … … 436 431 // Grid United with Normal Kernel 437 432 pmSubtractionKernels *pmSubtractionKernelsGUNK(int size, int spatialOrder, const psVector *fwhms, 438 const psVector *orders, int inner )433 const psVector *orders, int inner, pmSubtractionMode mode) 439 434 { 440 435 PS_ASSERT_INT_POSITIVE(size, NULL); … … 449 444 450 445 pmSubtractionKernels *kernels = p_pmSubtractionKernelsRawISIS(size, spatialOrder, 451 fwhms, orders ); // Kernels446 fwhms, orders, mode); // Kernels 452 447 psStringPrepend(&kernels->description, "GUNK="); 453 448 psStringAppend(&kernels->description, "+POIS(%d,%d)", inner, spatialOrder); … … 469 464 470 465 int numISIS = kernels->num; // Number of ISIS kernels 471 int numInner = PS_SQR(2 * inner + 1); // Number of inner kernel elements472 466 473 467 if (!p_pmSubtractionKernelsAddGrid(kernels, numISIS, inner)) { … … 475 469 } 476 470 477 kernels->subIndex = numInner/2 + numISIS;478 assert(kernels->u->data.S32[kernels->subIndex] == 0 &&479 kernels->v->data.S32[kernels->subIndex] == 0);480 481 471 return kernels; 482 472 } 483 473 484 474 // RINGS --- just what it says 485 pmSubtractionKernels *pmSubtractionKernelsRINGS(int size, int spatialOrder, int inner, int ringsOrder) 475 pmSubtractionKernels *pmSubtractionKernelsRINGS(int size, int spatialOrder, int inner, int ringsOrder, 476 pmSubtractionMode mode) 486 477 { 487 478 PS_ASSERT_INT_POSITIVE(size, NULL); … … 505 496 } 506 497 507 int numInner = inner ;// Number of pixels in the inner region498 int numInner = inner - 1; // Number of pixels in the inner region 508 499 int numOuter = fibNum; // Number of summed pixels in the outer region 509 500 510 501 int numRings = numOuter + numInner; // Number of rings (not including the central pixel) 511 int numPoly = (ringsOrder + 1) * (ringsOrder + 2) / 2; // Number of polynomial variants of each ring512 513 int num = numRings * numPoly + 1; // Total number of basis functions502 int numPoly = PM_SUBTRACTION_POLYTERMS(ringsOrder); // Number of polynomial variants of each ring 503 504 int num = numRings * numPoly; // Total number of basis functions 514 505 515 506 pmSubtractionKernels *kernels = pmSubtractionKernelsAlloc(num, PM_SUBTRACTION_KERNEL_RINGS, 516 size, spatialOrder ); // The kernels507 size, spatialOrder, mode); // The kernels 517 508 psStringAppend(&kernels->description, "RINGS(%d,%d,%d,%d)", size, inner, ringsOrder, spatialOrder); 518 509 … … 522 513 // Set the Gaussian kernel parameters 523 514 int fibIndex = 1, fibIndexMinus1 = 0; // Fibonnacci parameters 524 int radiusLast = 0; // Last radius 525 for (int i = 0, index = 0; i < numRings + 1; i++) { 526 515 int radiusLast = 1; // Last radius 516 for (int i = 1, index = 0; i < numRings + 1; i++) { 527 517 float lower2; // Lower limit of radius^2 528 518 float upper2; // Upper limit of radius^2 529 if (i == 0) { 530 lower2 = 0; 531 upper2 = PS_SQR(0.5); 532 } else if (i <= numInner) { 519 if (i <= inner) { 533 520 // A ring every pixel width 534 521 float radius = i; … … 572 559 for (int v = -size; v <= size; v++) { 573 560 int v2 = PS_SQR(v); // Square of v 574 // float vPoly = power(v, vOrder); // Value of v^vOrder575 561 float vPoly = powf(v/(float)size, vOrder); // Value of v^vOrder 576 562 … … 579 565 int distance2 = u2 + v2; // Distance from the centre 580 566 if (distance2 > lower2 && distance2 < upper2) { 581 // float uPoly = power(u, uOrder); // Value of u^uOrder582 567 float uPoly = powf(u/(float)size, uOrder); // Value of u^uOrder 583 568 … … 627 612 } 628 613 629 kernels->subIndex = 0;630 631 614 return kernels; 632 615 } … … 634 617 pmSubtractionKernels *pmSubtractionKernelsGenerate(pmSubtractionKernelsType type, int size, int spatialOrder, 635 618 const psVector *fwhms, const psVector *orders, int inner, 636 int binning, int ringsOrder )619 int binning, int ringsOrder, pmSubtractionMode mode) 637 620 { 638 621 switch (type) { 639 622 case PM_SUBTRACTION_KERNEL_POIS: 640 return pmSubtractionKernelsPOIS(size, spatialOrder );623 return pmSubtractionKernelsPOIS(size, spatialOrder, mode); 641 624 case PM_SUBTRACTION_KERNEL_ISIS: 642 return pmSubtractionKernelsISIS(size, spatialOrder, fwhms, orders );625 return pmSubtractionKernelsISIS(size, spatialOrder, fwhms, orders, mode); 643 626 case PM_SUBTRACTION_KERNEL_SPAM: 644 return pmSubtractionKernelsSPAM(size, spatialOrder, inner, binning );627 return pmSubtractionKernelsSPAM(size, spatialOrder, inner, binning, mode); 645 628 case PM_SUBTRACTION_KERNEL_FRIES: 646 return pmSubtractionKernelsFRIES(size, spatialOrder, inner );629 return pmSubtractionKernelsFRIES(size, spatialOrder, inner, mode); 647 630 case PM_SUBTRACTION_KERNEL_GUNK: 648 return pmSubtractionKernelsGUNK(size, spatialOrder, fwhms, orders, inner );631 return pmSubtractionKernelsGUNK(size, spatialOrder, fwhms, orders, inner, mode); 649 632 case PM_SUBTRACTION_KERNEL_RINGS: 650 return pmSubtractionKernelsRINGS(size, spatialOrder, inner, ringsOrder );633 return pmSubtractionKernelsRINGS(size, spatialOrder, inner, ringsOrder, mode); 651 634 default: 652 635 psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Unknown kernel type: %x", type); -
trunk/psModules/src/imcombine/pmSubtractionKernels.h
r15443 r15756 31 31 long num; ///< Number of kernel components (not including the spatial ones) 32 32 psVector *u, *v; ///< Offset (for POIS) or polynomial order (for ISIS) 33 psVector *widths; ///< Gaussian FWHMs (ISIS) or ring radius (RINGS)33 psVector *widths; ///< Gaussian FWHMs (ISIS) 34 34 psVector *uStop, *vStop; ///< Width of kernel element (SPAM,FRIES only) 35 int subIndex; ///< Index of kernel to be subtracted (to maintain flux conservation)36 35 psArray *preCalc; ///< Array of images containing pre-calculated kernel (for ISIS) 37 36 int size; ///< The half-size of the kernel … … 39 38 int spatialOrder; ///< The spatial order of the kernels 40 39 int bgOrder; ///< The order for the background fitting 40 pmSubtractionMode mode; ///< Mode for subtraction 41 psVector *solution1, *solution2; ///< Solution for the PSF matching 41 42 } pmSubtractionKernels; 43 44 // Assertion to check pmSubtractionKernels 45 #define PM_ASSERT_SUBTRACTION_KERNELS_NON_NULL(KERNELS, RETURNVALUE) { \ 46 PS_ASSERT_PTR_NON_NULL(KERNELS, RETURNVALUE); \ 47 PS_ASSERT_STRING_NON_EMPTY((KERNELS)->description, RETURNVALUE); \ 48 PS_ASSERT_INT_POSITIVE((KERNELS)->num, RETURNVALUE); \ 49 PS_ASSERT_VECTOR_NON_NULL((KERNELS)->u, RETURNVALUE); \ 50 PS_ASSERT_VECTOR_NON_NULL((KERNELS)->v, RETURNVALUE); \ 51 PS_ASSERT_VECTOR_TYPE((KERNELS)->u, PS_TYPE_S32, RETURNVALUE); \ 52 PS_ASSERT_VECTOR_TYPE((KERNELS)->v, PS_TYPE_S32, RETURNVALUE); \ 53 PS_ASSERT_VECTOR_SIZE((KERNELS)->u, (KERNELS)->num, RETURNVALUE); \ 54 PS_ASSERT_VECTOR_SIZE((KERNELS)->v, (KERNELS)->num, RETURNVALUE); \ 55 if ((KERNELS)->type == PM_SUBTRACTION_KERNEL_ISIS) { \ 56 PS_ASSERT_VECTOR_NON_NULL((KERNELS)->widths, RETURNVALUE); \ 57 PS_ASSERT_VECTOR_TYPE((KERNELS)->widths, PS_TYPE_F32, RETURNVALUE); \ 58 PS_ASSERT_VECTOR_SIZE((KERNELS)->widths, (KERNELS)->num, RETURNVALUE); \ 59 } \ 60 if ((KERNELS)->uStop || (KERNELS)->vStop) { \ 61 PS_ASSERT_VECTOR_NON_NULL((KERNELS)->uStop, RETURNVALUE); \ 62 PS_ASSERT_VECTOR_NON_NULL((KERNELS)->vStop, RETURNVALUE); \ 63 PS_ASSERT_VECTOR_TYPE((KERNELS)->uStop, PS_TYPE_S32, RETURNVALUE); \ 64 PS_ASSERT_VECTOR_TYPE((KERNELS)->vStop, PS_TYPE_S32, RETURNVALUE); \ 65 PS_ASSERT_VECTOR_SIZE((KERNELS)->uStop, (KERNELS)->num, RETURNVALUE); \ 66 PS_ASSERT_VECTOR_SIZE((KERNELS)->vStop, (KERNELS)->num, RETURNVALUE); \ 67 } \ 68 if ((KERNELS)->preCalc) { \ 69 PS_ASSERT_ARRAY_NON_NULL((KERNELS)->preCalc, RETURNVALUE); \ 70 PS_ASSERT_ARRAY_SIZE((KERNELS)->preCalc, (KERNELS)->num, RETURNVALUE); \ 71 } \ 72 PS_ASSERT_INT_NONNEGATIVE((KERNELS)->size, RETURNVALUE); \ 73 PS_ASSERT_INT_NONNEGATIVE((KERNELS)->inner, RETURNVALUE); \ 74 PS_ASSERT_INT_NONNEGATIVE((KERNELS)->spatialOrder, RETURNVALUE); \ 75 PS_ASSERT_INT_NONNEGATIVE((KERNELS)->bgOrder, RETURNVALUE); \ 76 } 77 78 // Assertion to check that the solution is attached 79 #define PM_ASSERT_SUBTRACTION_KERNELS_SOLUTION(KERNELS, RETURNVALUE) { \ 80 PS_ASSERT_VECTOR_NON_NULL((KERNELS)->solution1, RETURNVALUE); \ 81 PS_ASSERT_VECTOR_TYPE((KERNELS)->solution1, PS_TYPE_F64, RETURNVALUE); \ 82 PS_ASSERT_VECTOR_SIZE((KERNELS)->solution1, \ 83 (KERNELS)->num * PM_SUBTRACTION_POLYTERMS((KERNELS)->spatialOrder) + 1 + \ 84 PM_SUBTRACTION_POLYTERMS((KERNELS)->bgOrder), \ 85 RETURNVALUE); \ 86 if (kernels->mode == PM_SUBTRACTION_MODE_DUAL) { \ 87 PS_ASSERT_VECTOR_NON_NULL(kernels->solution2, RETURNVALUE); \ 88 PS_ASSERT_VECTOR_TYPE((KERNELS)->solution2, PS_TYPE_F64, RETURNVALUE); \ 89 PS_ASSERT_VECTOR_SIZE((KERNELS)->solution2, \ 90 (KERNELS)->num * PM_SUBTRACTION_POLYTERMS((KERNELS)->spatialOrder), \ 91 RETURNVALUE); \ 92 } \ 93 } 42 94 43 95 /// Generate a delta-function grid for subtraction kernels (like the POIS kernel) … … 54 106 pmSubtractionKernelsType type, ///< Kernel type 55 107 int size, ///< Half-size of kernel 56 int spatialOrder ///< Order of spatial variations 108 int spatialOrder, ///< Order of spatial variations 109 pmSubtractionMode mode ///< Mode for subtraction 57 110 ); 58 111 59 112 /// Generate POIS kernels 60 113 pmSubtractionKernels *pmSubtractionKernelsPOIS(int size, ///< Half-size of the kernel (in both dims) 61 int spatialOrder ///< Order of spatial variations 114 int spatialOrder, ///< Order of spatial variations 115 pmSubtractionMode mode ///< Mode for subtraction 62 116 ); 63 117 … … 66 120 int spatialOrder, ///< Order of spatial variations 67 121 const psVector *fwhms, ///< Gaussian FWHMs 68 const psVector *orders ///< Polynomial order of gaussians 122 const psVector *orders, ///< Polynomial order of gaussians 123 pmSubtractionMode mode ///< Mode for subtraction 69 124 ); 70 125 … … 73 128 int spatialOrder, ///< Order of spatial variations 74 129 const psVector *fwhms, ///< Gaussian FWHMs 75 const psVector *orders ///< Polynomial order of gaussians 130 const psVector *orders, ///< Polynomial order of gaussians 131 pmSubtractionMode mode ///< Mode for subtraction 76 132 ); 77 133 … … 80 136 int spatialOrder, ///< Order of spatial variations 81 137 int inner, ///< Inner radius to preserve unbinned 82 int binning ///< Kernel binning factor 138 int binning, ///< Kernel binning factor 139 pmSubtractionMode mode ///< Mode for subtraction 83 140 ); 84 141 … … 86 143 pmSubtractionKernels *pmSubtractionKernelsFRIES(int size, ///< Half-size of the kernel 87 144 int spatialOrder, ///< Order of spatial variations 88 int inner ///< Inner radius to preserve unbinned 145 int inner, ///< Inner radius to preserve unbinned 146 pmSubtractionMode mode ///< Mode for subtraction 89 147 ); 90 148 … … 94 152 const psVector *fwhms, ///< Gaussian FWHMs 95 153 const psVector *orders, ///< Polynomial order of gaussians 96 int inner ///< Inner radius containing grid of delta functions 154 int inner, ///< Inner radius containing grid of delta functions 155 pmSubtractionMode mode ///< Mode for subtraction 97 156 ); 98 157 … … 101 160 int spatialOrder, ///< Order of spatial variations 102 161 int inner, ///< Inner radius to preserve unbinned 103 int ringsOrder ///< Polynomial order 162 int ringsOrder, ///< Polynomial order 163 pmSubtractionMode mode ///< Mode for subtraction 104 164 ); 105 165 … … 113 173 int inner, ///< Inner radius to preserve unbinned 114 174 int binning, ///< Kernel binning factor 115 int ringsOrder ///< Polynomial order for RINGS 175 int ringsOrder, ///< Polynomial order for RINGS 176 pmSubtractionMode mode ///< Mode for subtraction 116 177 ); 117 178 -
trunk/psModules/src/imcombine/pmSubtractionMatch.c
r15447 r15756 13 13 #include "pmSubtractionKernels.h" 14 14 #include "pmSubtractionStamps.h" 15 #include "pmSubtractionEquation.h" 15 16 #include "pmSubtraction.h" 17 #include "pmSubtractionMask.h" 16 18 #include "pmSubtractionMatch.h" 17 19 20 #define TOL 1.0e-3 // Tolerance for subtraction solution 21 #define KERNEL_MOSAIC 2 // Half-number of kernel instances in the mosaic image 18 22 19 23 static bool useFFT = true; // Do convolutions using FFT … … 63 67 { 64 68 psTrace("psModules.imcombine", 3, "Finding stamps...\n"); 65 *stamps = pmSubtractionStampsFind(*stamps, ro1->image, subMask, region, threshold, stampSpacing, mode); 69 *stamps = pmSubtractionStampsFind(*stamps, ro1->image, subMask, region, threshold, footprint, 70 stampSpacing, mode); 66 71 if (!*stamps) { 67 72 psError(PS_ERR_UNKNOWN, false, "Unable to find stamps."); … … 72 77 73 78 psTrace("psModules.imcombine", 3, "Extracting stamps...\n"); 74 if (!pmSubtractionStampsExtract(*stamps, ro1->image, ro2 ? ro2->image : NULL, weight, footprint,size)) {79 if (!pmSubtractionStampsExtract(*stamps, ro1->image, ro2 ? ro2->image : NULL, weight, size)) { 75 80 psError(PS_ERR_UNKNOWN, false, "Unable to extract stamps."); 76 81 return false; … … 86 91 87 92 88 bool pmSubtractionMatch(pmReadout *conv olved, const pmReadout *ro1, const pmReadout *ro2,93 bool pmSubtractionMatch(pmReadout *conv1, pmReadout *conv2, const pmReadout *ro1, const pmReadout *ro2, 89 94 int footprint, float regionSize, float stampSpacing, float threshold, 90 95 const psArray *sources, const char *stampsName, … … 95 100 psMaskType maskBlank, float badFrac, pmSubtractionMode mode) 96 101 { 97 PS_ASSERT_PTR_NON_NULL(convolved, false); 102 PS_ASSERT_PTR_NON_NULL(conv1, false); 103 if (mode == PM_SUBTRACTION_MODE_DUAL) { 104 PS_ASSERT_PTR_NON_NULL(conv2, false); 105 } 98 106 PS_ASSERT_PTR_NON_NULL(ro1, false); 99 107 PS_ASSERT_IMAGE_NON_NULL(ro1->image, false); … … 174 182 175 183 // Reset the output readout, just in case 176 if (conv olved->image) {177 psFree(conv olved->image);178 conv olved->image = NULL;179 } 180 if (conv olved->mask) {181 psFree(conv olved->mask);182 conv olved->mask = NULL;183 } 184 if (conv olved->weight) {185 psFree(conv olved->weight);186 conv olved->weight = NULL;184 if (conv1->image) { 185 psFree(conv1->image); 186 conv1->image = NULL; 187 } 188 if (conv1->mask) { 189 psFree(conv1->mask); 190 conv1->mask = NULL; 191 } 192 if (conv1->weight) { 193 psFree(conv1->weight); 194 conv1->weight = NULL; 187 195 } 188 196 … … 250 258 251 259 if (sources) { 252 stamps = pmSubtractionStampsSetFromSources(sources, subMask, region, stampSpacing, mode); 260 stamps = pmSubtractionStampsSetFromSources(sources, subMask, region, footprint, 261 stampSpacing, mode); 253 262 } else if (stampsName && strlen(stampsName) > 0) { 254 stamps = pmSubtractionStampsSetFromFile(stampsName, subMask, region, stampSpacing, mode); 263 stamps = pmSubtractionStampsSetFromFile(stampsName, subMask, region, footprint, 264 stampSpacing, mode); 255 265 } 256 266 … … 295 305 // Not an ISIS/GUNK kernel, or the optimum kernel search failed 296 306 kernels = pmSubtractionKernelsGenerate(type, size, spatialOrder, isisWidths, isisOrders, 297 inner, binning, ringsOrder );298 } 299 psMetadataAddPtr(conv olved->analysis, PS_LIST_TAIL, "SUBTRACTION.KERNEL",307 inner, binning, ringsOrder, mode); 308 } 309 psMetadataAddPtr(conv1->analysis, PS_LIST_TAIL, "SUBTRACTION.KERNEL", 300 310 PS_DATA_UNKNOWN | PS_META_DUPLICATE_OK, "Subtraction kernels", kernels); 301 311 … … 312 322 313 323 psTrace("psModules.imcombine", 3, "Calculating equation...\n"); 314 if (!pmSubtractionCalculateEquation(stamps, kernels , footprint, mode)) {324 if (!pmSubtractionCalculateEquation(stamps, kernels)) { 315 325 psError(PS_ERR_UNKNOWN, false, "Unable to calculate least-squares equation."); 316 326 goto MATCH_ERROR; … … 320 330 321 331 psTrace("psModules.imcombine", 3, "Solving equation...\n"); 322 solution = pmSubtractionSolveEquation(solution, stamps); 323 if (! solution) {332 333 if (!pmSubtractionSolveEquation(kernels, stamps, TOL)) { 324 334 psError(PS_ERR_UNKNOWN, false, "Unable to calculate least-squares equation."); 325 335 goto MATCH_ERROR; … … 328 338 memCheck(" solve equation"); 329 339 330 psVector *deviations = pmSubtractionCalculateDeviations(stamps, solution, footprint, kernels, 331 mode); // Deviations for each stamp 340 psVector *deviations = pmSubtractionCalculateDeviations(stamps, kernels); // Stamp deviations 332 341 if (!deviations) { 333 342 psError(PS_ERR_UNKNOWN, false, "Unable to calculate deviations."); … … 351 360 if (numRejected > 0) { 352 361 psTrace("psModules.imcombine", 3, "Solving equation...\n"); 353 solution = pmSubtractionSolveEquation(solution, stamps); 354 if (!solution) { 362 if (!pmSubtractionSolveEquation(kernels, stamps, TOL)) { 355 363 psError(PS_ERR_UNKNOWN, false, "Unable to calculate least-squares equation."); 356 364 goto MATCH_ERROR; 357 365 } 358 psVector *deviations = pmSubtractionCalculateDeviations(stamps, solution, footprint, kernels, 359 mode); // Deviations for each stamp 366 psVector *deviations = pmSubtractionCalculateDeviations(stamps, kernels); // Stamp deviations 360 367 if (!deviations) { 361 368 psError(PS_ERR_UNKNOWN, false, "Unable to calculate deviations."); … … 376 383 psImage *convKernels = psImageAlloc(5 * fullSize - 1, 5 * fullSize - 1, PS_TYPE_F32); 377 384 psImageInit(convKernels, NAN); 378 for (int j = -2; j <= 2; j++) { 379 for (int i = -2; i <= 2; i++) { 380 psImage *kernel = pmSubtractionKernelImage(solution, kernels, (float)i / 2.0, 381 (float)j / 2.0); // Image of the kernel 385 for (int j = -KERNEL_MOSAIC; j <= KERNEL_MOSAIC; j++) { 386 for (int i = -KERNEL_MOSAIC; i <= KERNEL_MOSAIC; i++) { 387 psImage *kernel = pmSubtractionKernelImage(kernels, (float)i / (float)KERNEL_MOSAIC, 388 (float)j / (float)KERNEL_MOSAIC, 389 false); // Image of the kernel 382 390 if (!kernel) { 383 391 psError(PS_ERR_UNKNOWN, false, "Unable to generate kernel image."); … … 386 394 } 387 395 388 if (psImageOverlaySection(convKernels, kernel, (i + 2) * fullSize,389 (j + 2) * fullSize, "=") == 0) {396 if (psImageOverlaySection(convKernels, kernel, (i + KERNEL_MOSAIC) * fullSize, 397 (j + KERNEL_MOSAIC) * fullSize, "=") == 0) { 390 398 psError(PS_ERR_UNKNOWN, false, "Unable to overlay kernel image."); 391 399 psFree(kernel); … … 399 407 psString comment = NULL; // Comment for metadata 400 408 psStringAppend(&comment, "Subtraction kernel for region %s", regionString); 401 psMetadataAddImage(conv olved->analysis, PS_LIST_TAIL, "SUBTRACTION.KERNEL.IMAGE",409 psMetadataAddImage(conv1->analysis, PS_LIST_TAIL, "SUBTRACTION.KERNEL.IMAGE", 402 410 PS_META_DUPLICATE_OK, comment, convKernels); 403 411 psFree(comment); … … 427 435 428 436 psTrace("psModules.imcombine", 2, "Convolving...\n"); 429 if (!pmSubtractionConvolve(convolved, ro1, ro2, subMask, maskBlank, region, 430 solution, kernels, mode, useFFT)) { 437 if (!pmSubtractionConvolve(conv1, conv2, ro1, ro2, subMask, maskBlank, region, kernels, useFFT)) { 431 438 psError(PS_ERR_UNKNOWN, false, "Unable to convolve image."); 432 439 goto MATCH_ERROR; … … 439 446 psString comment = NULL; // Comment for metadata 440 447 psStringAppend(&comment, "Subtraction solution for region %s", regionString); 441 psMetadataAddVector(conv olved->analysis, PS_LIST_TAIL, "SUBTRACTION.SOLUTION",448 psMetadataAddVector(conv1->analysis, PS_LIST_TAIL, "SUBTRACTION.SOLUTION", 442 449 PS_META_DUPLICATE_OK, comment, solution); 443 450 psFree(comment); 444 451 if (region) { 445 psMetadataAddPtr(conv olved->analysis, PS_LIST_TAIL, "SUBTRACTION.REGION",452 psMetadataAddPtr(conv1->analysis, PS_LIST_TAIL, "SUBTRACTION.REGION", 446 453 PS_META_DUPLICATE_OK | PS_DATA_REGION, comment, region); 447 454 } else { 448 455 region = psRegionAlloc(0, numCols, 0, numRows); 449 psMetadataAddPtr(conv olved->analysis, PS_LIST_TAIL, "SUBTRACTION.REGION",456 psMetadataAddPtr(conv1->analysis, PS_LIST_TAIL, "SUBTRACTION.REGION", 450 457 PS_META_DUPLICATE_OK | PS_DATA_REGION, comment, region); 451 458 psFree(region); … … 458 465 459 466 // There is data in the readout now 460 convolved->data_exists = true; 461 if (convolved->parent) { 462 convolved->parent->data_exists = true; 463 convolved->parent->parent->data_exists = true; 467 conv1->data_exists = true; 468 if (conv1->parent) { 469 conv1->parent->data_exists = true; 470 conv1->parent->parent->data_exists = true; 471 } 472 if (mode == PM_SUBTRACTION_MODE_DUAL) { 473 conv2->data_exists = true; 474 if (conv2->parent) { 475 conv2->parent->data_exists = true; 476 conv2->parent->parent->data_exists = true; 477 } 464 478 } 465 479 } … … 474 488 weight = NULL; 475 489 476 if (!pmSubtractionBorder(conv olved->image, convolved->weight, convolved->mask, size, maskBlank)) {490 if (!pmSubtractionBorder(conv1->image, conv1->weight, conv1->mask, size, maskBlank)) { 477 491 psError(PS_ERR_UNKNOWN, false, "Unable to set border of convolved image."); 478 492 goto MATCH_ERROR; -
trunk/psModules/src/imcombine/pmSubtractionMatch.h
r15443 r15756 10 10 11 11 /// Match two images 12 bool pmSubtractionMatch(pmReadout *convolved, ///< Output convolved data 12 bool pmSubtractionMatch(pmReadout *conv1, ///< Output convolved data for image 1 13 pmReadout *conv2, ///< Output convolved data for image 2 13 14 const pmReadout *ro1, ///< Image 1 14 15 const pmReadout *ro2, ///< Image 2 -
trunk/psModules/src/imcombine/pmSubtractionParams.c
r15443 r15756 232 232 psVectorInit(orders, maxOrder); 233 233 pmSubtractionKernels *kernels = p_pmSubtractionKernelsRawISIS(size, spatialOrder, 234 fwhms, orders ); // Kernels234 fwhms, orders, mode); // Kernels 235 235 psFree(orders); 236 236 psFree(kernels->description); … … 279 279 continue; 280 280 } 281 if (!pmSubtractionConvolveStamp(stamp, kernels, footprint , mode)) {281 if (!pmSubtractionConvolveStamp(stamp, kernels, footprint)) { 282 282 psError(PS_ERR_UNKNOWN, false, "Unable to convolve stamp %d.", i); 283 283 psFree(targets); … … 505 505 506 506 kernels->type = PM_SUBTRACTION_KERNEL_GUNK; 507 508 kernels->subIndex = PS_SQR(2 * inner + 1) / 2 + numGaussians;509 assert(kernels->u->data.S32[kernels->subIndex] == 0 &&510 kernels->v->data.S32[kernels->subIndex] == 0);511 507 } 512 508 -
trunk/psModules/src/imcombine/pmSubtractionStamps.c
r15745 r15756 44 44 ) 45 45 { 46 psFree(stamp->matrix);47 psFree(stamp->vector);48 46 psFree(stamp->image1); 49 47 psFree(stamp->image2); … … 51 49 psFree(stamp->convolutions1); 52 50 psFree(stamp->convolutions2); 51 52 psFree(stamp->matrix1); 53 psFree(stamp->matrix2); 54 psFree(stamp->matrixX); 55 psFree(stamp->vector); 56 53 57 } 54 58 … … 103 107 104 108 pmSubtractionStampList *pmSubtractionStampListAlloc(int numCols, int numRows, const psRegion *region, 105 float spacing)109 int footprint, float spacing) 106 110 { 107 111 pmSubtractionStampList *list = psAlloc(sizeof(pmSubtractionStampList)); // Stamp list to return … … 124 128 125 129 for (int y = 0, index = 0; y < yStamps; y++) { 126 int yStart = yMin + y * ySize / (yStamps + 1); // Subregion starts here127 int yStop = yMin + (y + 1) * ySize / (yStamps + 1) - 1; // Subregion stops here130 int yStart = yMin + y * ((float)ySize / (float)(yStamps + 1)); // Subregion starts here 131 int yStop = yMin + (y + 1) * ((float)ySize / (float)(yStamps + 1)) - 1; // Subregion stops here 128 132 assert(yStart >= yMin && yStop < yMax); 129 133 130 134 for (int x = 0; x < xStamps; x++, index++) { 131 int xStart = xMin + x * xSize / (xStamps + 1); // Subregion starts here132 int xStop = xMin + (x + 1) * xSize / (xStamps + 1) - 1; // Subregion stops here135 int xStart = xMin + x * ((float)xSize / (float)(xStamps + 1)); // Subregion starts here 136 int xStop = xMin + (x + 1) * ((float)xSize / (float)(xStamps + 1)) - 1; // Subregion stops here 133 137 assert(xStart >= xMin && xStop < xMax); 134 138 135 139 list->stamps->data[index] = pmSubtractionStampAlloc(); 140 psTrace("psModules.imcombine", 6, "Stamp region %d: [%d:%d,%d:%d]\n", 141 index, xStart, xStop, yStart, yStop); 136 142 list->regions->data[index] = psRegionAlloc(xStart, xStop, yStart, yStop); 137 143 } … … 141 147 list->y = NULL; 142 148 list->flux = NULL; 149 list->footprint = footprint; 143 150 144 151 return list; … … 155 162 stamp->xNorm = NAN; 156 163 stamp->yNorm = NAN; 157 stamp->matrix = NULL;158 stamp->vector = NULL;159 164 stamp->status = PM_SUBTRACTION_STAMP_INIT; 160 165 … … 165 170 stamp->convolutions2 = NULL; 166 171 172 stamp->matrix1 = NULL; 173 stamp->matrix2 = NULL; 174 stamp->matrixX = NULL; 175 stamp->vector = NULL; 176 167 177 return stamp; 168 178 } … … 171 181 pmSubtractionStampList *pmSubtractionStampsFind(pmSubtractionStampList *stamps, const psImage *image, 172 182 const psImage *subMask, const psRegion *region, 173 float threshold, float spacing, pmSubtractionMode mode) 183 float threshold, int footprint, float spacing, 184 pmSubtractionMode mode) 174 185 { 175 186 PS_ASSERT_IMAGE_NON_NULL(image, NULL); … … 180 191 PS_ASSERT_IMAGE_TYPE(subMask, PS_TYPE_MASK, NULL); 181 192 } 193 PS_ASSERT_INT_NONNEGATIVE(footprint, NULL); 182 194 PS_ASSERT_FLOAT_LARGER_THAN(spacing, 0.0, NULL); 183 195 if (region) { … … 201 213 202 214 if (!stamps) { 203 stamps = pmSubtractionStampListAlloc(numCols, numRows, region, spacing);215 stamps = pmSubtractionStampListAlloc(numCols, numRows, region, footprint, spacing); 204 216 } 205 217 … … 244 256 fluxStamp = threshold; 245 257 psRegion *subRegion = stamps->regions->data[i]; // Sub-region of interest 246 for (int y = subRegion->y0; y <= subRegion->y1 ; y++) {247 for (int x = subRegion->x0; x <= subRegion->x1 ; x++) {258 for (int y = subRegion->y0; y <= subRegion->y1; y++) { 259 for (int x = subRegion->x0; x <= subRegion->x1; x++) { 248 260 if (checkStampMask(x, y, subMask, mode) && image->data.F32[y][x] > fluxStamp) { 249 261 fluxStamp = image->data.F32[y][x]; … … 289 301 pmSubtractionStampList *pmSubtractionStampsSet(const psVector *x, const psVector *y, const psVector *flux, 290 302 const psImage *image, const psImage *subMask, 291 const psRegion *region, float spacing, pmSubtractionMode mode) 303 const psRegion *region, int footprint, float spacing, 304 pmSubtractionMode mode) 292 305 293 306 { … … 316 329 int numStars = x->n; // Number of stars 317 330 pmSubtractionStampList *stamps = pmSubtractionStampListAlloc(subMask->numCols, subMask->numRows, 318 region, spacing); // Stamp list331 region, footprint, spacing); // Stamp list 319 332 int numStamps = stamps->num; // Number of stamps 320 333 … … 401 414 402 415 bool pmSubtractionStampsExtract(pmSubtractionStampList *stamps, psImage *image1, psImage *image2, 403 psImage *weight, int footprint, intkernelSize)416 psImage *weight, int kernelSize) 404 417 { 405 418 PM_ASSERT_SUBTRACTION_STAMP_LIST_NON_NULL(stamps, false); … … 414 427 PS_ASSERT_IMAGES_SIZE_EQUAL(weight, image1, false); 415 428 PS_ASSERT_IMAGE_TYPE(weight, PS_TYPE_F32, false); 416 PS_ASSERT_INT_NONNEGATIVE(footprint, false);417 429 PS_ASSERT_INT_NONNEGATIVE(kernelSize, false); 418 430 419 431 int numCols = image1->numCols, numRows = image1->numRows; // Size of images 420 int size = kernelSize + footprint; // Size of postage stamps432 int size = kernelSize + stamps->footprint; // Size of postage stamps 421 433 422 434 for (int i = 0; i < stamps->num; i++) { … … 467 479 468 480 #if 0 469 bool pmSubtractionStampsGenerate(pmSubtractionStampList *stamps, float fwhm, int footprint, intkernelSize)481 bool pmSubtractionStampsGenerate(pmSubtractionStampList *stamps, float fwhm, int kernelSize) 470 482 { 471 483 PM_ASSERT_SUBTRACTION_STAMP_LIST_NON_NULL(stamps, false); 472 484 PS_ASSERT_FLOAT_LARGER_THAN(fwhm, 0.0, false); 473 PS_ASSERT_INT_NONNEGATIVE(footprint, false);474 485 PS_ASSERT_INT_NONNEGATIVE(kernelSize, false); 475 486 476 int size = kernelSize + footprint; // Size of postage stamps487 int size = kernelSize + stamps->footprint; // Size of postage stamps 477 488 int num = stamps->num; // Number of stamps 478 489 float sigma = fwhm / (2.0 * sqrtf(2.0 * log(2.0))); // Gaussian sigma … … 514 525 515 526 pmSubtractionStampList *pmSubtractionStampsSetFromSources(const psArray *sources, const psImage *subMask, 516 const psRegion *region, float spacing,517 pmSubtractionMode mode)527 const psRegion *region, int footprint, 528 float spacing, pmSubtractionMode mode) 518 529 { 519 530 PS_ASSERT_ARRAY_NON_NULL(sources, NULL); … … 539 550 540 551 pmSubtractionStampList *stamps = pmSubtractionStampsSet(x, y, flux, NULL, subMask, region, 541 spacing, mode); // Stamps to return552 footprint, spacing, mode); // Stamps to return 542 553 psFree(x); 543 554 psFree(y); … … 553 564 554 565 pmSubtractionStampList *pmSubtractionStampsSetFromFile(const char *filename, const psImage *subMask, 555 const psRegion *region, float spacing,566 const psRegion *region, int footprint, float spacing, 556 567 pmSubtractionMode mode) 557 568 { … … 572 583 psBinaryOp(y, y, "-", psScalarAlloc(1.0, PS_TYPE_F32)); 573 584 574 pmSubtractionStampList *stamps = pmSubtractionStampsSet(x, y, flux, NULL, subMask, region, spacing,575 mode);585 pmSubtractionStampList *stamps = pmSubtractionStampsSet(x, y, flux, NULL, subMask, region, footprint, 586 spacing, mode); 576 587 psFree(data); 577 588 -
trunk/psModules/src/imcombine/pmSubtractionStamps.h
r15443 r15756 23 23 psArray *x, *y; ///< Coordinates for possible stamps (or NULL) 24 24 psArray *flux; ///< Fluxes for possible stamps (or NULL) 25 int footprint; ///< Half-size of stamps 25 26 } pmSubtractionStampList; 26 27 … … 29 30 int numRows, // Number of rows in image 30 31 const psRegion *region, // Region for stamps, or NULL 32 int footprint, // Half-size of stamps 31 33 float spacing // Rough average spacing between stamps 32 34 ); … … 40 42 PS_ASSERT_ARRAY_SIZE((LIST)->stamps, (LIST)->num, RETURNVALUE); \ 41 43 PS_ASSERT_ARRAY_SIZE((LIST)->regions, (LIST)->num, RETURNVALUE); \ 44 PS_ASSERT_INT_NONNEGATIVE((LIST)->footprint, RETURNVALUE); \ 42 45 if ((LIST)->x || (LIST)->y || (LIST)->flux) { \ 43 46 PS_ASSERT_ARRAY_NON_NULL((LIST)->x, RETURNVALUE); \ … … 57 60 psKernel *image1; ///< Reference image postage stamp 58 61 psKernel *image2; ///< Input image postage stamp 59 psKernel *weight; ///< Weight image postage stamp 60 psArray *convolutions1; ///< Convolutions of image 1 for each kernel component 61 psArray *convolutions2; ///< Convolutions of image 2 for each kernel component 62 psImage *matrix; ///< Associated matrix 63 psVector *vector; ///< Assoicated vector 62 psKernel *weight; ///< Weight image postage stamp, or NULL 63 psArray *convolutions1; ///< Convolutions of image 1 for each kernel component, or NULL 64 psArray *convolutions2; ///< Convolutions of image 2 for each kernel component, or NULL 65 psImage *matrix1, *matrix2; ///< Matrices for each image, or NULL 66 psImage *matrixX; ///< Cross-matrix (for mode DUAL), or NULL 67 psVector *vector; ///< Associated vector (when mode not DUAL), or NULL 64 68 pmSubtractionStampStatus status; ///< Status of stamp 65 69 } pmSubtractionStamp; … … 74 78 const psRegion *region, ///< Region to search, or NULL 75 79 float threshold, ///< Threshold for stamps in the image 80 int footprint, ///< Half-size for stamps 76 81 float spacing, ///< Rough spacing for stamps 77 82 pmSubtractionMode mode ///< Mode for subtraction … … 85 90 const psImage *mask, ///< Mask, or NULL 86 91 const psRegion *region, ///< Region to search, or NULL 92 int footprint, ///< Half-size for stamps 87 93 float spacing, ///< Rough spacing for stamps 88 94 pmSubtractionMode mode ///< Mode for subtraction … … 94 100 const psImage *subMask, ///< Mask, or NULL 95 101 const psRegion *region, ///< Region to search, or NULL 102 int footprint, ///< Half-size for stamps 96 103 float spacing, ///< Rough spacing for stamps 97 104 pmSubtractionMode mode ///< Mode for subtraction … … 103 110 const psImage *subMask, ///< Mask, or NULL 104 111 const psRegion *region, ///< Region to search, or NULL 112 int footprint, ///< Half-size for stamps 105 113 float spacing, ///< Rough spacing for stamps 106 114 pmSubtractionMode mode ///< Mode for subtraction … … 109 117 /// Extract stamps from the images 110 118 bool pmSubtractionStampsExtract(pmSubtractionStampList *stamps, ///< Stamps 111 psImage * reference, ///< Reference image112 psImage *i nput, ///< Input image (or NULL)119 psImage *image1, ///< Reference image 120 psImage *image2, ///< Input image (or NULL) 113 121 psImage *weight, ///< Weight (variance) map 114 int footprint, ///< Stamp footprint size115 122 int kernelSize ///< Kernel half-size 116 123 ); -
trunk/psModules/src/psmodules.h
r15362 r15756 82 82 #include <pmSubtractionMatch.h> 83 83 #include <pmSubtractionParams.h> 84 #include <pmSubtractionMask.h> 85 #include <pmSubtractionEquation.h> 84 86 #include <pmReadoutCombine.h> 85 87
Note:
See TracChangeset
for help on using the changeset viewer.
