Changeset 25999 for trunk/psModules/src/imcombine
- Timestamp:
- Nov 2, 2009, 10:38:23 AM (17 years ago)
- Location:
- trunk/psModules/src/imcombine
- Files:
-
- 5 edited
-
. (modified) (1 prop)
-
pmSubtraction.c (modified) (24 diffs)
-
pmSubtractionAnalysis.c (modified) (3 diffs)
-
pmSubtractionEquation.c (modified) (9 diffs)
-
pmSubtractionKernels.c (modified) (8 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psModules/src/imcombine
-
Property svn:mergeinfo
set to (toggle deleted branches)
/branches/czw_branch/cleanup/psModules/src/imcombine merged eligible /branches/eam_branches/20090522/psModules/src/imcombine merged eligible /branches/eam_branches/20090715/psModules/src/imcombine merged eligible /branches/eam_branches/20090820/psModules/src/imcombine merged eligible /branches/pap/psModules/src/imcombine merged eligible /branches/pap_mops/psModules/src/imcombine 25137-25255
-
Property svn:mergeinfo
set to (toggle deleted branches)
-
trunk/psModules/src/imcombine/pmSubtraction.c
r25279 r25999 29 29 #define PIXEL_LIST_BUFFER 100 // Number of entries to add to pixel list at a time 30 30 #define MIN_SAMPLE_STATS 7 // Minimum number to use sample statistics; otherwise use quartiles 31 #define USE_SYS_ERR // Use systematic error image? 31 32 32 33 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// … … 36 37 // Generate the kernel to apply to the variance from the normal kernel 37 38 static psKernel *varianceKernel(psKernel *out, // Output kernel 38 psKernel *normalKernel // Normal kernel39 const psKernel *normalKernel // Normal kernel 39 40 ) 40 41 { … … 48 49 49 50 // Take the square of the normal kernel 50 double sum Normal = 0.0, sumVariance = 0.0; // Sum of the normal andvariance kernels51 double sumVariance = 0.0; // Sum of the variance kernels 51 52 for (int v = yMin; v <= yMax; v++) { 52 53 for (int u = xMin; u <= xMax; u++) { 53 float value = normalKernel->kernel[v][u]; // Value of interest 54 float value2 = PS_SQR(value); // Value squared 55 sumNormal += value; 56 sumVariance += value2; 57 out->kernel[v][u] = value2; 54 sumVariance += out->kernel[v][u] = PS_SQR(normalKernel->kernel[v][u]); 58 55 } 59 56 } … … 65 62 return out; 66 63 } 64 65 // Contribute to an image of the solved kernel component for ISIS 66 static void solvedKernelISIS(psKernel *kernel, // Kernel, updated 67 const pmSubtractionKernels *kernels, // Kernel basis functions 68 float value, // Normalisation value for basis function 69 int index // Index of basis function of interest 70 ) 71 { 72 int size = kernels->size; // Kernel half-size 73 psArray *preCalc = kernels->preCalc->data[index]; // Precalculated values 74 #if 0 75 psVector *xKernel = preCalc->data[0]; // Kernel in x 76 psVector *yKernel = preCalc->data[1]; // Kernel in y 77 // Iterating over the kernel 78 for (int y = 0, v = -size; v <= size; y++, v++) { 79 float yValue = value * yKernel->data.F32[y]; 80 for (int x = 0, u = -size; u <= size; x++, u++) { 81 kernel->kernel[v][u] += yValue * xKernel->data.F32[x]; 82 } 83 } 84 // Photometric scaling for even kernels only 85 if (kernels->u->data.S32[i] % 2 == 0 && kernels->v->data.S32[i] % 2 == 0) { 86 kernel->kernel[0][0] -= value; 87 } 88 #else 89 psKernel *k = preCalc->data[2]; // Kernel image 90 for (int v = -size; v <= size; v++) { 91 for (int u = -size; u <= size; u++) { 92 kernel->kernel[v][u] += value * k->kernel[v][u]; 93 } 94 } 95 #endif 96 97 return; 98 } 99 67 100 68 101 // Generate an image of the solved kernel … … 70 103 const pmSubtractionKernels *kernels, // Kernel basis functions 71 104 const psImage *polyValues, // Spatial polynomial values 105 bool normalise, // Add normalisation? 72 106 bool wantDual // Want the dual (second) kernel? 73 107 ) … … 115 149 case PM_SUBTRACTION_KERNEL_GUNK: { 116 150 if (i < kernels->inner) { 117 // Using pre-calculated function 118 psKernel *preCalc = kernels->preCalc->data[i]; // Precalculated values 119 // Iterating over the kernel 120 for (int v = -size; v <= size; v++) { 121 for (int u = -size; u <= size; u++) { 122 kernel->kernel[v][u] += preCalc->kernel[v][u] * value; 123 // Photometric scaling is built into the preCalc kernel --- no subtraction! 124 } 125 } 151 solvedKernelISIS(kernel, kernels, value, i); 126 152 } else { 127 153 // Using delta function … … 134 160 } 135 161 case PM_SUBTRACTION_KERNEL_ISIS: { 136 psArray *preCalc = kernels->preCalc->data[i]; // Precalculated values 137 psVector *xKernel = preCalc->data[0]; // Kernel in x 138 psVector *yKernel = preCalc->data[1]; // Kernel in y 139 // Iterating over the kernel 140 for (int y = 0, v = -size; v <= size; y++, v++) { 141 for (int x = 0, u = -size; u <= size; x++, u++) { 142 kernel->kernel[v][u] += value * xKernel->data.F32[x] * yKernel->data.F32[y]; 143 } 144 } 145 // Photometric scaling for even kernels only 146 if (kernels->u->data.S32[i] % 2 == 0 && kernels->v->data.S32[i] % 2 == 0) { 147 kernel->kernel[0][0] -= value; 148 } 162 solvedKernelISIS(kernel, kernels, value, i); 149 163 break; 150 164 } … … 168 182 } 169 183 170 // Put in the normalisation component 171 kernel->kernel[0][0] += (wantDual ? 1.0 : p_pmSubtractionSolutionNorm(kernels)); 184 if (normalise) { 185 // Put in the normalisation component 186 kernel->kernel[0][0] += (wantDual ? 1.0 : p_pmSubtractionSolutionNorm(kernels)); 187 } 172 188 173 189 return kernel; … … 339 355 ) 340 356 { 341 *kernelImage = solvedKernel(*kernelImage, kernels, polyValues, wantDual);357 *kernelImage = solvedKernel(*kernelImage, kernels, polyValues, true, wantDual); 342 358 if (variance || subMask) { 343 359 *kernelVariance = varianceKernel(*kernelVariance, *kernelImage); … … 413 429 } 414 430 431 #ifdef USE_SYS_ERR 415 432 // Generate an image that can be used to track systematic errors 416 433 static psImage *subtractionSysErrImage(const psImage *image, // Image from which to make sys err image … … 433 450 434 451 return sys; 452 } 453 #endif 454 455 // Convolve a stamp using an ISIS kernel basis function 456 static psKernel *convolveStampISIS(const psKernel *image, // Image to convolve 457 const pmSubtractionKernels *kernels, // Kernel basis functions 458 int index, // Index of basis function of interest 459 int footprint // Half-size of stamp 460 ) 461 { 462 psArray *preCalc = kernels->preCalc->data[index]; // Precalculated data 463 #if 1 464 // Convolving using separable convolution 465 psVector *xKernel = preCalc->data[0]; // Kernel in x 466 psVector *yKernel = preCalc->data[1]; // Kernel in y 467 int size = kernels->size; // Size of kernel 468 469 // Convolve in x 470 // Need to convolve a bit more than the footprint, for the y convolution 471 int yMin = -size - footprint, yMax = size + footprint; // Range for y 472 psKernel *temp = psKernelAlloc(yMin, yMax, 473 -footprint, footprint); // Temporary convolution; NOTE: wrong way! 474 for (int y = yMin; y <= yMax; y++) { 475 for (int x = -footprint; x <= footprint; x++) { 476 float value = 0.0; // Value of convolved pixel 477 int uMin = x - size, uMax = x + size; // Range for u 478 psF32 *xKernelData = &xKernel->data.F32[xKernel->n - 1]; // Kernel values 479 psF32 *imageData = &image->kernel[y][uMin]; // Image values 480 for (int u = uMin; u <= uMax; u++, xKernelData--, imageData++) { 481 value += *xKernelData * *imageData; 482 } 483 temp->kernel[x][y] = value; // NOTE: putting in wrong way! 484 } 485 } 486 487 // Convolve in y 488 psKernel *convolved = psKernelAlloc(-footprint, footprint, -footprint, footprint);// Convolved image 489 for (int x = -footprint; x <= footprint; x++) { 490 for (int y = -footprint; y <= footprint; y++) { 491 float value = 0.0; // Value of convolved pixel 492 int vMin = y - size, vMax = y + size; // Range for v 493 psF32 *yKernelData = &yKernel->data.F32[yKernel->n - 1]; // Kernel values 494 psF32 *imageData = &temp->kernel[x][vMin]; // Image values; NOTE: wrong way! 495 for (int v = vMin; v <= vMax; v++, yKernelData--, imageData++) { 496 value += *yKernelData * *imageData; 497 } 498 convolved->kernel[y][x] = value; 499 } 500 } 501 psFree(temp); 502 503 // Photometric scaling for even kernels only 504 if (kernels->u->data.S32[index] % 2 == 0 && kernels->v->data.S32[index] % 2 == 0) { 505 convolveSub(convolved, image, footprint); 506 } 507 return convolved; 508 #else 509 // Convolving using precalculated kernel 510 return p_pmSubtractionConvolveStampPrecalc(image, preCalc->data[2]); 511 #endif 435 512 } 436 513 … … 456 533 psKernel *kernel; // Kernel to use 457 534 if (!preKernel) { 458 kernel = solvedKernel(NULL, kernels, polyValues, wantDual);535 kernel = solvedKernel(NULL, kernels, polyValues, true, wantDual); 459 536 } else { 460 537 kernel = psMemIncrRefCounter(preKernel); … … 586 663 if (index < kernels->inner) { 587 664 // Photometric scaling is already built in to the precalculated kernel 588 return p_pmSubtractionConvolveStampPrecalc(image, kernels->preCalc->data[index]);665 return convolveStampISIS(image, kernels, index, footprint); 589 666 } 590 667 // Using delta function … … 596 673 } 597 674 case PM_SUBTRACTION_KERNEL_ISIS: { 598 psArray *preCalc = kernels->preCalc->data[index]; // Precalculated values 599 psVector *xKernel = preCalc->data[0]; // Kernel in x 600 psVector *yKernel = preCalc->data[1]; // Kernel in y 601 int size = kernels->size; // Size of kernel 602 603 // Convolve in x 604 // Need to convolve a bit more than the footprint, for the y convolution 605 int yMin = -size - footprint, yMax = size + footprint; // Range for y 606 psKernel *temp = psKernelAlloc(yMin, yMax, 607 -footprint, footprint); // Temporary convolution; NOTE: wrong way! 608 for (int y = yMin; y <= yMax; y++) { 609 for (int x = -footprint; x <= footprint; x++) { 610 float value = 0.0; // Value of convolved pixel 611 int uMin = x - size, uMax = x + size; // Range for u 612 psF32 *xKernelData = &xKernel->data.F32[xKernel->n - 1]; // Kernel values 613 psF32 *imageData = &image->kernel[y][uMin]; // Image values 614 for (int u = uMin; u <= uMax; u++, xKernelData--, imageData++) { 615 value += *xKernelData * *imageData; 616 } 617 temp->kernel[x][y] = value; // NOTE: putting in wrong way! 618 } 619 } 620 621 // Convolve in y 622 psKernel *convolved = psKernelAlloc(-footprint, footprint, -footprint, footprint);// Convolved image 623 for (int x = -footprint; x <= footprint; x++) { 624 for (int y = -footprint; y <= footprint; y++) { 625 float value = 0.0; // Value of convolved pixel 626 int vMin = y - size, vMax = y + size; // Range for v 627 psF32 *yKernelData = &yKernel->data.F32[yKernel->n - 1]; // Kernel values 628 psF32 *imageData = &temp->kernel[x][vMin]; // Image values; NOTE: wrong way! 629 for (int v = vMin; v <= vMax; v++, yKernelData--, imageData++) { 630 value += *yKernelData * *imageData; 631 } 632 convolved->kernel[y][x] = value; 633 } 634 } 635 psFree(temp); 636 637 // Photometric scaling for even kernels only 638 if (kernels->u->data.S32[index] % 2 == 0 && kernels->v->data.S32[index] % 2 == 0) { 639 convolveSub(convolved, image, footprint); 640 } 641 return convolved; 675 return convolveStampISIS(image, kernels, index, footprint); 642 676 } 643 677 case PM_SUBTRACTION_KERNEL_RINGS: { … … 901 935 902 936 psImage *polyValues = p_pmSubtractionPolynomial(NULL, kernels->spatialOrder, x, y); // Solved polynomial 903 psKernel *kernel = solvedKernel(NULL, kernels, polyValues, wantDual); // The appropriate kernel937 psKernel *kernel = solvedKernel(NULL, kernels, polyValues, true, wantDual); // The appropriate kernel 904 938 psFree(polyValues); 905 939 … … 932 966 psImage *polyValues = p_pmSubtractionPolynomial(NULL, kernels->spatialOrder, x, y); 933 967 934 psKernel *kernel = solvedKernel(NULL, kernels, polyValues, wantDual); // The appropriate kernel968 psKernel *kernel = solvedKernel(NULL, kernels, polyValues, true, wantDual); // The appropriate kernel 935 969 psFree(polyValues); 936 970 … … 949 983 } 950 984 951 #if 0985 #if 1 952 986 psArray *pmSubtractionKernelSolutions(const pmSubtractionKernels *kernels, float x, float y, bool wantDual) 953 987 { … … 957 991 PS_ASSERT_FLOAT_WITHIN_RANGE(y, -1.0, 1.0, NULL); 958 992 959 psArray *images = psArrayAlloc(kernels->solution1->n - 1); // Images of each kernel to return 960 psVector *fakeSolution = psVectorAlloc(kernels->solution1->n, PS_TYPE_F64); // Fake solution vector 961 psVectorInit(fakeSolution, 0.0); 962 963 for (int i = 0; i < kernels->solution1->n - 1; i++) { 964 fakeSolution->data.F64[i] = kernels->solution1->data.F64[i]; 965 images->data[i] = pmSubtractionKernelImage(kernels, x, y, wantDual); 966 fakeSolution->data.F64[i] = 0.0; 967 } 968 969 psFree(fakeSolution); 993 psVector *solution = wantDual ? kernels->solution2 : kernels->solution1; // Solution of interest 994 psVector *backup = psVectorCopy(NULL, solution, PS_TYPE_F64); // Backup version 995 996 int num = wantDual ? solution->n - 1 : solution->n; // Number of kernel basis functions 997 998 psImage *polyValues = p_pmSubtractionPolynomial(NULL, kernels->spatialOrder, x, y); // Solved polynomial 999 psArray *images = psArrayAlloc(num + 1); // Images of each kernel to return 1000 1001 // The whole kernel 1002 { 1003 psKernel *kernel = solvedKernel(NULL, kernels, polyValues, true, wantDual); // The appropriate kernel 1004 images->data[0] = psMemIncrRefCounter(kernel->image); 1005 psFree(kernel); 1006 } 1007 1008 // The parts 1009 psVectorInit(solution, 0.0); 1010 for (int i = 0; i < num; i++) { 1011 solution->data.F64[i] = backup->data.F64[i]; 1012 psKernel *kernel = solvedKernel(NULL, kernels, polyValues, false, wantDual); // The appropriate kernel 1013 #if 0 1014 int size = kernels->size; 1015 double sum = 0.0; 1016 for (int v = -size; v <= size; v++) { 1017 for (int u = -size; u <= size; u++) { 1018 sum += kernel->kernel[v][u]; 1019 } 1020 } 1021 fprintf(stderr, "Kernel %d: %lf\n", i, sum); 1022 #endif 1023 images->data[i + 1] = psMemIncrRefCounter(kernel->image); 1024 psFree(kernel); 1025 solution->data.F64[i] = 0.0; 1026 } 1027 psFree(polyValues); 1028 psVectorCopy(solution, backup, PS_TYPE_F64); 1029 psFree(backup); 970 1030 971 1031 return images; … … 1129 1189 if (!out1->image) { 1130 1190 out1->image = psImageAlloc(numCols, numRows, PS_TYPE_F32); 1131 // XXX if (threaded) {1132 // XXX psMutexInit(out1->image);1133 // XXX }1134 1191 } 1135 1192 if (ro1->variance) { 1136 1193 if (!out1->variance) { 1137 1194 out1->variance = psImageAlloc(numCols, numRows, PS_TYPE_F32); 1138 // XXX if (threaded) {1139 // XXX psMutexInit(out1->variance);1140 // XXX }1141 1195 } 1142 1196 psImageInit(out1->variance, 0.0); … … 1146 1200 if (!out2->image) { 1147 1201 out2->image = psImageAlloc(numCols, numRows, PS_TYPE_F32); 1148 // XXX if (threaded) {1149 // XXX psMutexInit(out2->image);1150 // XXX }1151 1202 } 1152 1203 if (ro2->variance) { 1153 1204 if (!out2->variance) { 1154 1205 out2->variance = psImageAlloc(numCols, numRows, PS_TYPE_F32); 1155 // XXX if (threaded) {1156 // XXX psMutexInit(out2->variance);1157 // XXX }1158 1206 } 1159 1207 psImageInit(out2->variance, 0.0); … … 1162 1210 psImage *convMask = NULL; // Convolved mask image (common to inputs 1 and 2) 1163 1211 if (subMask) { 1164 // XXX if (threaded) {1165 // XXX psMutexInit(subMask);1166 // XXX }1167 1212 if (kernels->mode == PM_SUBTRACTION_MODE_1 || kernels->mode == PM_SUBTRACTION_MODE_DUAL) { 1168 1213 if (!out1->mask) { … … 1188 1233 1189 1234 psImage *sys1 = NULL, *sys2 = NULL; // Systematic error images 1235 #ifdef USE_SYS_ERR 1190 1236 if (kernels->mode == PM_SUBTRACTION_MODE_1 || kernels->mode == PM_SUBTRACTION_MODE_DUAL) { 1191 1237 sys1 = subtractionSysErrImage(ro1->image, sysError); 1192 // XXX if (threaded && sys1) {1193 // XXX psMutexInit(sys1);1194 // XXX }1195 1238 } 1196 1239 if (kernels->mode == PM_SUBTRACTION_MODE_2 || kernels->mode == PM_SUBTRACTION_MODE_DUAL) { 1197 1240 sys2 = subtractionSysErrImage(ro2->image, sysError); 1198 // XXX if (threaded && sys2) { 1199 // XXX psMutexInit(sys2); 1200 // XXX } 1201 } 1241 } 1242 #endif 1202 1243 1203 1244 int size = kernels->size; // Half-size of kernel … … 1248 1289 psArrayAdd(args, 1, (pmReadout*)ro1); // Casting away const 1249 1290 psArrayAdd(args, 1, (pmReadout*)ro2); // Casting away const 1250 // Since adding to the array can impact the reference count, we need to lock1251 // XXX if (sys1) {1252 // XXX psMutexLock(sys1);1253 // XXX }1254 1291 psArrayAdd(args, 1, sys1); 1255 // XXX if (sys1) {1256 // XXX psMutexUnlock(sys1);1257 // XXX }1258 // XXX if (sys2) {1259 // XXX psMutexLock(sys2);1260 // XXX }1261 1292 psArrayAdd(args, 1, sys2); 1262 // XXX if (sys2) {1263 // XXX psMutexUnlock(sys2);1264 // XXX }1265 // XXX if (subMask) {1266 // XXX psMutexLock(subMask);1267 // XXX }1268 1293 psArrayAdd(args, 1, subMask); 1269 // XXX if (subMask) {1270 // XXX psMutexUnlock(subMask);1271 // XXX }1272 1294 PS_ARRAY_ADD_SCALAR(args, maskBad, PS_TYPE_IMAGE_MASK); 1273 1295 PS_ARRAY_ADD_SCALAR(args, maskPoor, PS_TYPE_IMAGE_MASK); … … 1308 1330 psFree(job); 1309 1331 } 1310 1311 // XXX if (subMask) {1312 // XXX psMutexDestroy(subMask);1313 // XXX }1314 // XXX if (sys1) {1315 // XXX psMutexDestroy(sys1);1316 // XXX }1317 // XXX if (sys2) {1318 // XXX psMutexDestroy(sys2);1319 // XXX }1320 1332 } 1321 1333 psImageConvolveSetThreads(oldThreads); -
trunk/psModules/src/imcombine/pmSubtractionAnalysis.c
r25279 r25999 16 16 #define KERNEL_MOSAIC 2 // Half-number of kernel instances in the mosaic image 17 17 18 //#define TESTING 18 19 19 20 bool pmSubtractionAnalysis(psMetadata *analysis, psMetadata *header, … … 117 118 118 119 119 #if 0120 #ifdef TESTING 120 121 // Generate images of the kernel components 121 122 { … … 128 129 } 129 130 psArray *kernelImages = pmSubtractionKernelSolutions(kernels, 0.0, 0.0, false); 130 psFits *kernelFile = psFitsOpen("kernels.fits", "w"); 131 psFits *kernelFile = psFitsOpen("kernels1.fits", "w"); 132 (void)psFitsWriteImageCube(kernelFile, header, kernelImages, NULL); 133 psFitsClose(kernelFile); 134 psFree(kernelImages); 135 psFree(header); 136 } 137 if (kernels->solution2) { 138 psMetadata *header = psMetadataAlloc(); // Header 139 for (int i = 0; i < kernels->solution2->n; i++) { 140 psString name = NULL; // Header keyword 141 psStringAppend(&name, "SOLN%04d", i); 142 psMetadataAddF64(header, PS_LIST_TAIL, name, 0, NULL, kernels->solution2->data.F64[i]); 143 psFree(name); 144 } 145 psArray *kernelImages = pmSubtractionKernelSolutions(kernels, 0.0, 0.0, true); 146 psFits *kernelFile = psFitsOpen("kernels2.fits", "w"); 131 147 (void)psFitsWriteImageCube(kernelFile, header, kernelImages, NULL); 132 148 psFitsClose(kernelFile); -
trunk/psModules/src/imcombine/pmSubtractionEquation.c
r24844 r25999 15 15 #include "pmSubtractionVisual.h" 16 16 17 // #define TESTING // TESTING output for debugging; may not work with threads!17 //#define TESTING // TESTING output for debugging; may not work with threads! 18 18 19 19 #define USE_VARIANCE // Include variance in equation? 20 20 21 21 22 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// … … 23 24 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// 24 25 25 // Calculate the sum over a stamp product 26 static inline double calculateSumProduct(const psKernel *image1, // First image in multiplication 27 const psKernel *image2, // Second image in multiplication 28 const psKernel *variance, // Variance image 29 int footprint // (Half-)Size of stamp 30 ) 26 // Calculate the least-squares matrix and vector 27 static bool calculateMatrixVector(psImage *matrix, // Least-squares matrix, updated 28 psVector *vector, // Least-squares vector, updated 29 const psKernel *input, // Input image (target) 30 const psKernel *reference, // Reference image (convolution source) 31 const psKernel *variance, // Variance image 32 const psArray *convolutions, // Convolutions for each kernel 33 const pmSubtractionKernels *kernels, // Kernels 34 const psImage *polyValues, // Spatial polynomial values 35 int footprint // (Half-)Size of stamp 36 ) 31 37 { 32 double sum = 0.0; // Sum of the image products 38 // (I - R * sum_i a_i k_i - g) (R * k_j) = 0 39 // I C_j = sum_i C_i C_j 40 41 // Background: C_i = 1.0 42 // Normalisation: C_i = R 43 44 int numKernels = kernels->num; // Number of kernels 45 int normIndex = PM_SUBTRACTION_INDEX_NORM(kernels); // Index for normalisation 46 int bgIndex = PM_SUBTRACTION_INDEX_BG(kernels); // Index in matrix for background 47 int spatialOrder = kernels->spatialOrder; // Order of spatial variation 48 int numPoly = PM_SUBTRACTION_POLYTERMS(spatialOrder); // Number of polynomial terms 49 double poly[numPoly]; // Polynomial terms 50 double poly2[numPoly][numPoly]; // Polynomial-polynomial values 51 52 // Evaluate polynomial-polynomial terms 53 for (int iyOrder = 0, iIndex = 0; iyOrder <= spatialOrder; iyOrder++) { 54 for (int ixOrder = 0; ixOrder <= spatialOrder - iyOrder; ixOrder++, iIndex++) { 55 double iPoly = polyValues->data.F64[iyOrder][ixOrder]; // Value of polynomial 56 poly[iIndex] = iPoly; 57 for (int jyOrder = 0, jIndex = 0; jyOrder <= spatialOrder; jyOrder++) { 58 for (int jxOrder = 0; jxOrder <= spatialOrder - jyOrder; jxOrder++, jIndex++) { 59 double jPoly = polyValues->data.F64[jyOrder][jxOrder]; 60 poly2[iIndex][jIndex] = iPoly * jPoly; 61 } 62 } 63 } 64 } 65 66 67 for (int i = 0; i < numKernels; i++) { 68 psKernel *iConv = convolutions->data[i]; // Convolution for index i 69 for (int j = i; j < numKernels; j++) { 70 psKernel *jConv = convolutions->data[j]; // Convolution for index j 71 72 double sumCC = 0.0; // Sum of convolution products 73 for (int y = - footprint; y <= footprint; y++) { 74 for (int x = - footprint; x <= footprint; x++) { 75 double cc = iConv->kernel[y][x] * jConv->kernel[y][x]; 76 #ifdef USE_VARIANCE 77 cc /= variance->kernel[y][x]; 78 #endif 79 sumCC += cc; 80 } 81 } 82 83 // Spatial variation 84 for (int iTerm = 0, iIndex = i; iTerm < numPoly; iTerm++, iIndex += numKernels) { 85 for (int jTerm = 0, jIndex = j; jTerm < numPoly; jTerm++, jIndex += numKernels) { 86 double value = sumCC * poly2[iTerm][jTerm]; 87 matrix->data.F64[iIndex][jIndex] = value; 88 matrix->data.F64[jIndex][iIndex] = value; 89 } 90 } 91 } 92 93 double sumRC = 0.0; // Sum of the reference-convolution products 94 double sumIC = 0.0; // Sum of the input-convolution products 95 double sumC = 0.0; // Sum of the convolution 96 for (int y = - footprint; y <= footprint; y++) { 97 for (int x = - footprint; x <= footprint; x++) { 98 float conv = iConv->kernel[y][x]; 99 float in = input->kernel[y][x]; 100 float ref = reference->kernel[y][x]; 101 double ic = in * conv; 102 double rc = ref * conv; 103 double c = conv; 104 #ifdef USE_VARIANCE 105 float varVal = 1.0 / variance->kernel[y][x]; 106 ic *= varVal; 107 rc *= varVal; 108 c *= varVal; 109 #endif 110 sumIC += ic; 111 sumRC += rc; 112 sumC += c; 113 } 114 } 115 // Spatial variation 116 for (int iTerm = 0, iIndex = i; iTerm < numPoly; iTerm++, iIndex += numKernels) { 117 double normTerm = sumRC * poly[iTerm]; 118 double bgTerm = sumC * poly[iTerm]; 119 matrix->data.F64[iIndex][normIndex] = normTerm; 120 matrix->data.F64[normIndex][iIndex] = normTerm; 121 matrix->data.F64[iIndex][bgIndex] = bgTerm; 122 matrix->data.F64[bgIndex][iIndex] = bgTerm; 123 vector->data.F64[iIndex] = sumIC * poly[iTerm]; 124 } 125 } 126 127 double sumRR = 0.0; // Sum of the reference product 128 double sumIR = 0.0; // Sum of the input-reference product 129 double sum1 = 0.0; // Sum of the background 130 double sumR = 0.0; // Sum of the reference 131 double sumI = 0.0; // Sum of the input 33 132 for (int y = - footprint; y <= footprint; y++) { 34 133 for (int x = - footprint; x <= footprint; x++) { 35 double value = image1->kernel[y][x] * image2->kernel[y][x]; 134 double in = input->kernel[y][x]; 135 double ref = reference->kernel[y][x]; 136 double ir = in * ref; 137 double rr = PS_SQR(ref); 138 double one = 1.0; 36 139 #ifdef USE_VARIANCE 37 value /= variance->kernel[y][x]; 38 #endif 39 sum += value; 40 } 41 } 42 return sum; 43 } 44 45 // Calculate a single element of the least-squares matrix, with the polynomial expansions in one direction 46 static inline bool calculateMatrixElement1(psImage *matrix, // Matrix to calculate 47 int i, int j, // Coordinates of element 48 const psKernel *image1, // First image in multiplication 49 const psKernel *image2, // Second image in multiplication 50 const psKernel *variance, // Variance image 51 const psImage *polyValues, // Spatial polynomial values 52 int numKernels, // Number of kernel basis functions 53 int footprint, // (Half-)Size of stamp 54 int spatialOrder, // Maximum order of spatial variation 55 bool symmetric // Is the matrix symmetric? 56 ) 57 { 58 double sum = calculateSumProduct(image1, image2, variance, footprint); // Sum of the image products 59 if (!isfinite(sum)) { 60 return false; 61 } 62 63 // Generate the pseudo-convolutions from the spatial polynomial terms 64 for (int iyOrder = 0, iIndex = i; iyOrder <= spatialOrder; iyOrder++) { 65 for (int ixOrder = 0; ixOrder <= spatialOrder - iyOrder; ixOrder++, iIndex += numKernels) { 66 double convPoly = sum * polyValues->data.F64[iyOrder][ixOrder]; 67 68 assert(iIndex < matrix->numRows && j < matrix->numCols); 69 70 matrix->data.F64[iIndex][j] = convPoly; 71 if (symmetric) { 72 73 assert(iIndex < matrix->numCols && j < matrix->numRows); 74 75 matrix->data.F64[j][iIndex] = convPoly; 76 } 77 } 78 } 140 float varVal = 1.0 / variance->kernel[y][x]; 141 rr *= varVal; 142 ir *= varVal; 143 in *= varVal; 144 ref *= varVal; 145 one *= varVal; 146 #endif 147 sumRR += rr; 148 sumIR += ir; 149 sumR += ref; 150 sumI += in; 151 sum1 += one; 152 } 153 } 154 matrix->data.F64[normIndex][normIndex] = sumRR; 155 matrix->data.F64[bgIndex][bgIndex] = sum1; 156 matrix->data.F64[normIndex][bgIndex] = matrix->data.F64[bgIndex][normIndex] = sumR; 157 vector->data.F64[normIndex] = sumIR; 158 vector->data.F64[bgIndex] = sumI; 159 79 160 return true; 80 161 } 81 162 82 // Calculate a single element of the least-squares matrix, with the polynomial expansions in both directions 83 static inline bool calculateMatrixElement2(psImage *matrix, // Matrix to calculate 84 int i, int j, // Coordinates of element 85 const psKernel *image1, // First image in multiplication 86 const psKernel *image2, // Second image in multiplication 87 const psKernel *variance, // Variance image 88 const psImage *polyValues, // Spatial polynomial values 89 int numKernels, // Number of kernel basis functions 90 int footprint, // (Half-)Size of stamp 91 int spatialOrder, // Maximum order of spatial variation 92 bool symmetric // Is the matrix symmetric? 93 ) 163 // Calculate the least-squares matrix and vector for dual convolution 164 static bool calculateDualMatrixVector(psImage *matrix1, // Least-squares matrix, updated 165 psVector *vector1, // Least-squares vector, updated 166 psImage *matrix2, // Least-squares matrix, updated 167 psVector *vector2, // Least-squares vector, updated 168 psImage *matrixX, // Cross-matrix 169 const psKernel *image1, // Image 1 170 const psKernel *image2, // Image 2 171 const psKernel *variance, // Variance image 172 const psArray *convolutions1, // Convolutions of image 1 for each kernel 173 const psArray *convolutions2, // Convolutions of image 2 for each kernel 174 const pmSubtractionKernels *kernels, // Kernels 175 const psImage *polyValues, // Spatial polynomial values 176 int footprint // (Half-)Size of stamp 177 ) 94 178 { 95 double sum = calculateSumProduct(image1, image2, variance, footprint); // Sum of the image products 96 if (!isfinite(sum)) { 97 return false; 98 } 99 100 // Generate the pseudo-convolutions from the spatial polynomial terms 101 for (int iyOrder = 0, iIndex = i; iyOrder <= spatialOrder; iyOrder++) { 102 for (int ixOrder = 0; ixOrder <= spatialOrder - iyOrder; ixOrder++, iIndex += numKernels) { 179 // A_ij = A_i A_j 180 // B_ij = B_i B_j 181 // C_ij = A_i B_j 182 // d_i = A_i I_2 183 // e_i = B_i I_2 184 185 // A_i = I_1 * k_i 186 // B_i = I_2 * k_i 187 188 // Background: A_i = 1.0 189 // Normalisation: A_i = I_1 190 191 int numKernels = kernels->num; // Number of kernels 192 int normIndex = PM_SUBTRACTION_INDEX_NORM(kernels); // Index for normalisation 193 int bgIndex = PM_SUBTRACTION_INDEX_BG(kernels); // Index in matrix for background 194 int spatialOrder = kernels->spatialOrder; // Order of spatial variation 195 int numPoly = PM_SUBTRACTION_POLYTERMS(spatialOrder); // Number of polynomial terms 196 double poly[numPoly]; // Polynomial terms 197 double poly2[numPoly][numPoly]; // Polynomial-polynomial values 198 199 // Evaluate polynomial-polynomial terms 200 for (int iyOrder = 0, iIndex = 0; iyOrder <= spatialOrder; iyOrder++) { 201 for (int ixOrder = 0; ixOrder <= spatialOrder - iyOrder; ixOrder++, iIndex++) { 103 202 double iPoly = polyValues->data.F64[iyOrder][ixOrder]; // Value of polynomial 104 for (int jyOrder = 0, jIndex = j; jyOrder <= spatialOrder; jyOrder++) { 105 for (int jxOrder = 0; jxOrder <= spatialOrder - jyOrder; jxOrder++, jIndex += numKernels) { 106 double convPoly = sum * iPoly * polyValues->data.F64[jyOrder][jxOrder]; 107 108 assert(iIndex < matrix->numRows && jIndex < matrix->numCols); 109 110 matrix->data.F64[iIndex][jIndex] = convPoly; 111 if (symmetric) { 112 113 assert(iIndex < matrix->numCols && jIndex < matrix->numRows); 114 115 matrix->data.F64[jIndex][iIndex] = convPoly; 116 } 117 } 118 } 119 } 120 } 203 poly[iIndex] = iPoly; 204 for (int jyOrder = 0, jIndex = 0; jyOrder <= spatialOrder; jyOrder++) { 205 for (int jxOrder = 0; jxOrder <= spatialOrder - jyOrder; jxOrder++, jIndex++) { 206 double jPoly = polyValues->data.F64[jyOrder][jxOrder]; 207 poly2[iIndex][jIndex] = iPoly * jPoly; 208 } 209 } 210 } 211 } 212 213 214 for (int i = 0; i < numKernels; i++) { 215 psKernel *iConv1 = convolutions1->data[i]; // Convolution 1 for index i 216 psKernel *iConv2 = convolutions2->data[i]; // Convolution 2 for index i 217 for (int j = i; j < numKernels; j++) { 218 psKernel *jConv1 = convolutions1->data[j]; // Convolution 1 for index j 219 psKernel *jConv2 = convolutions2->data[j]; // Convolution 2 for index j 220 221 double sumAA = 0.0; // Sum of convolution products for matrix A 222 double sumBB = 0.0; // Sum of convolution products for matrix B 223 double sumAB = 0.0; // Sum of convolution products for matrix C 224 for (int y = - footprint; y <= footprint; y++) { 225 for (int x = - footprint; x <= footprint; x++) { 226 double aa = iConv1->kernel[y][x] * jConv1->kernel[y][x]; 227 double bb = iConv2->kernel[y][x] * jConv2->kernel[y][x]; 228 double ab = iConv1->kernel[y][x] * jConv2->kernel[y][x]; 229 #ifdef USE_VARIANCE 230 aa /= variance->kernel[y][x]; 231 bb /= variance->kernel[y][x]; 232 ab /= variance->kernel[y][x]; 233 #endif 234 sumAA += aa; 235 sumBB += bb; 236 sumAB += ab; 237 } 238 } 239 240 // Spatial variation 241 for (int iTerm = 0, iIndex = i; iTerm < numPoly; iTerm++, iIndex += numKernels) { 242 for (int jTerm = 0, jIndex = j; jTerm < numPoly; jTerm++, jIndex += numKernels) { 243 double aa = sumAA * poly2[iTerm][jTerm]; 244 double bb = sumBB * poly2[iTerm][jTerm]; 245 double ab = sumAB * poly2[iTerm][jTerm]; 246 matrix1->data.F64[iIndex][jIndex] = aa; 247 matrix1->data.F64[jIndex][iIndex] = aa; 248 matrix2->data.F64[iIndex][jIndex] = bb; 249 matrix2->data.F64[jIndex][iIndex] = bb; 250 matrixX->data.F64[iIndex][jIndex] = ab; 251 } 252 } 253 } 254 for (int j = 0; j < i; j++) { 255 psKernel *jConv2 = convolutions2->data[j]; // Convolution 2 for index j 256 double sumAB = 0.0; // Sum of convolution products for matrix C 257 for (int y = - footprint; y <= footprint; y++) { 258 for (int x = - footprint; x <= footprint; x++) { 259 double ab = iConv1->kernel[y][x] * jConv2->kernel[y][x]; 260 #ifdef USE_VARIANCE 261 ab /= variance->kernel[y][x]; 262 #endif 263 sumAB += ab; 264 } 265 } 266 267 // Spatial variation 268 for (int iTerm = 0, iIndex = i; iTerm < numPoly; iTerm++, iIndex += numKernels) { 269 for (int jTerm = 0, jIndex = j; jTerm < numPoly; jTerm++, jIndex += numKernels) { 270 double ab = sumAB * poly2[iTerm][jTerm]; 271 matrixX->data.F64[iIndex][jIndex] = ab; 272 } 273 } 274 } 275 276 double sumAI2 = 0.0; // Sum of A.I_2 products (for vector 1) 277 double sumBI2 = 0.0; // Sum of B.I_2 products (for vector 2) 278 double sumAI1 = 0.0; // Sum of A.I_1 products (for matrix 1, normalisation) 279 double sumA = 0.0; // Sum of A (for matrix 1, background) 280 double sumBI1 = 0.0; // Sum of B.I_1 products (for matrix X, normalisation) 281 double sumB = 0.0; // Sum of B products (for matrix X, background) 282 double sumI2 = 0.0; // Sum of I_2 (for vector 1, background) 283 double sumI1I2 = 0.0; // Sum of I_1.I_2 (for vector 1, normalisation) 284 for (int y = - footprint; y <= footprint; y++) { 285 for (int x = - footprint; x <= footprint; x++) { 286 float a = iConv1->kernel[y][x]; 287 float b = iConv2->kernel[y][x]; 288 float i1 = image1->kernel[y][x]; 289 float i2 = image2->kernel[y][x]; 290 291 double ai2 = a * i2; 292 double bi2 = b * i2; 293 double ai1 = a * i1; 294 double bi1 = b * i1; 295 double i1i2 = i1 * i2; 296 297 #ifdef USE_VARIANCE 298 float varVal = 1.0 / variance->kernel[y][x]; 299 ai2 *= varVal; 300 bi2 *= varVal; 301 ai1 *= varVal; 302 bi1 *= varVal; 303 i1i2 *= varVal; 304 a *= varVal; 305 b *= varVal; 306 i2 *= varVal; 307 #endif 308 309 sumAI2 += ai2; 310 sumBI2 += bi2; 311 sumAI1 += ai1; 312 sumA += a; 313 sumBI1 += bi1; 314 sumB += b; 315 sumI2 += i2; 316 sumI1I2 += i1i2; 317 } 318 } 319 // Spatial variation 320 for (int iTerm = 0, iIndex = i; iTerm < numPoly; iTerm++, iIndex += numKernels) { 321 double ai2 = sumAI2 * poly[iTerm]; 322 double bi2 = sumBI2 * poly[iTerm]; 323 double ai1 = sumAI1 * poly[iTerm]; 324 double a = sumA * poly[iTerm]; 325 double bi1 = sumBI1 * poly[iTerm]; 326 double b = sumB * poly[iTerm]; 327 328 matrix1->data.F64[iIndex][normIndex] = ai1; 329 matrix1->data.F64[normIndex][iIndex] = ai1; 330 matrix1->data.F64[iIndex][bgIndex] = a; 331 matrix1->data.F64[bgIndex][iIndex] = a; 332 vector1->data.F64[iIndex] = ai2; 333 vector2->data.F64[iIndex] = bi2; 334 matrixX->data.F64[iIndex][normIndex] = bi1; 335 matrixX->data.F64[iIndex][bgIndex] = b; 336 } 337 } 338 339 double sumI1 = 0.0; // Sum of I_1 (for matrix 1, background-normalisation) 340 double sumI1I1 = 0.0; // Sum of I_1^2 (for matrix 1, normalisation-normalisation) 341 double sum1 = 0.0; // Sum of 1 (for matrix 1, background-background) 342 double sumI2 = 0.0; // Sum of I_2 (for vector 1, background) 343 double sumI1I2 = 0.0; // Sum of I_1.I_2 (for vector 1, normalisation) 344 for (int y = - footprint; y <= footprint; y++) { 345 for (int x = - footprint; x <= footprint; x++) { 346 float i1 = image1->kernel[y][x]; 347 float i2 = image2->kernel[y][x]; 348 349 double i1i1 = i1 * i1; 350 double one = 1.0; 351 double i1i2 = i1 * i2; 352 353 #ifdef USE_VARIANCE 354 float varVal = 1.0 / variance->kernel[y][x]; 355 i1 *= varVal; 356 i1i1 *= varVal; 357 one *= varVal; 358 i2 *= varVal; 359 i1i2 *= varVal; 360 #endif 361 362 sumI1 += i1; 363 sumI1I1 += i1i1; 364 sum1 += one; 365 sumI2 += i2; 366 sumI1I2 += i1i2; 367 } 368 } 369 matrix1->data.F64[bgIndex][normIndex] = sumI1; 370 matrix1->data.F64[normIndex][bgIndex] = sumI1; 371 matrix1->data.F64[normIndex][normIndex] = sumI1I1; 372 matrix1->data.F64[bgIndex][bgIndex] = sum1; 373 vector1->data.F64[bgIndex] = sumI2; 374 vector1->data.F64[normIndex] = sumI1I2; 375 121 376 return true; 122 377 } 123 378 124 // Calculate the square part of the matrix derived from multiplying convolutions 125 static bool calculateMatrixSquare(psImage *matrix, // Matrix to calculate 126 const psArray *convolutions1, // Convolutions for element 1 127 const psArray *convolutions2, // Convolutions for element 2 128 const psKernel *variance, // Variance image 129 const psImage *polyValues, // Polynomial values 130 int numKernels, // Number of kernel basis functions 131 int spatialOrder, // Order of spatial variation 132 int footprint // Half-size of stamp 379 // Merge dual matrices and vectors into single matrix equation 380 // Have: Aa = Ct.b + d 381 // Have: Ca = Bb + e 382 // Set: F = ( A -Ct ; C -B ) 383 // Set: g = ( a ; b ) 384 // Set: h = ( d ; e ) 385 // So that we combine the above two equations: Fg = h 386 static bool calculateEquationDual(psImage **outMatrix, 387 psVector **outVector, 388 const psImage *sumMatrix1, 389 const psImage *sumMatrix2, 390 const psImage *sumMatrixX, 391 const psVector *sumVector1, 392 const psVector *sumVector2 133 393 ) 134 394 { 135 bool symmetric = (convolutions1 == convolutions2 ? true : false); // Is matrix symmetric? 136 137 for (int i = 0; i < numKernels; i++) { 138 psKernel *iConv = convolutions1->data[i]; // Convolution for i-th element 139 140 for (int j = (symmetric ? i : 0); j < numKernels; j++) { 141 psKernel *jConv = convolutions2->data[j]; // Convolution for j-th element 142 143 if (!calculateMatrixElement2(matrix, i, j, iConv, jConv, variance, polyValues, numKernels, 144 footprint, spatialOrder, symmetric)) { 145 psTrace("psModules.imcombine", 2, "Bad sumCC at %d, %d", i, j); 146 return false; 147 } 395 psAssert(sumMatrix1 && sumMatrix2 && sumMatrixX, "Require input matrices"); 396 psAssert(sumVector1 && sumVector2, "Require input vectors"); 397 int num1 = sumVector1->n; // Number of parameters in first set 398 int num2 = sumVector2->n; // Number of parameters in second set 399 int num = num1 + num2; // Number of parameters in new set 400 401 psAssert(sumMatrix1->type.type == PS_TYPE_F64 && 402 sumMatrix2->type.type == PS_TYPE_F64 && 403 sumMatrixX->type.type == PS_TYPE_F64 && 404 sumVector1->type.type == PS_TYPE_F64 && 405 sumVector2->type.type == PS_TYPE_F64, 406 "Require input type is F64"); 407 408 psAssert(outMatrix, "Require output matrix"); 409 psAssert(outVector, "Require output vector"); 410 if (!*outMatrix) { 411 *outMatrix = psImageAlloc(num, num, PS_TYPE_F64); 412 } 413 if (!*outVector) { 414 *outVector = psVectorAlloc(num, PS_TYPE_F64); 415 } 416 psImage *matrix = *outMatrix; 417 psVector *vector = *outVector; 418 419 psAssert(sumMatrix1->numCols == num1 && sumMatrix1->numRows == num1, "Require size NxN"); 420 psAssert(sumMatrix2->numCols == num2 && sumMatrix2->numRows == num2, "Require size MxM"); 421 psAssert(sumMatrixX->numCols == num1 && sumMatrixX->numRows == num2, "Require size MxN"); 422 423 memcpy(vector->data.F64, sumVector1->data.F64, num1 * PSELEMTYPE_SIZEOF(PS_TYPE_F64)); 424 memcpy(&vector->data.F64[num1], sumVector2->data.F64, num2 * PSELEMTYPE_SIZEOF(PS_TYPE_F64)); 425 426 for (int i = 0; i < num1; i++) { 427 memcpy(matrix->data.F64[i], sumMatrix1->data.F64[i], num1 * PSELEMTYPE_SIZEOF(PS_TYPE_F64)); 428 for (int j = 0, k = num1; j < num2; j++, k++) { 429 matrix->data.F64[i][k] = - sumMatrixX->data.F64[j][i]; 430 } 431 } 432 for (int i1 = 0, i2 = num1; i1 < num2; i1++, i2++) { 433 memcpy(matrix->data.F64[i2], sumMatrixX->data.F64[i1], num1 * PSELEMTYPE_SIZEOF(PS_TYPE_F64)); 434 for (int j = 0, k = num1; j < num2; j++, k++) { 435 matrix->data.F64[i2][k] = - sumMatrix2->data.F64[i1][j]; 148 436 } 149 437 } … … 152 440 } 153 441 154 // Calculate least-squares matrix and vector155 static bool calculateMatrix(psImage *matrix, // Matrix to calculate156 const pmSubtractionKernels *kernels, // Kernel components157 const psArray *convolutions, // Convolutions of source with kernels158 const psKernel *input, // Input stamp, or NULL159 const psKernel *variance, // Variance stamp160 const psImage *polyValues, // Spatial polynomial values161 int footprint, // (Half-)Size of stamp162 bool normAndBG // Calculate normalisation and background terms?163 )164 {165 int numKernels = kernels->num; // Number of kernel components166 int spatialOrder = kernels->spatialOrder; // Maximum order of spatial variation167 int numSpatial = PM_SUBTRACTION_POLYTERMS(spatialOrder); // Number of spatial variation terms168 int bgOrder = kernels->bgOrder; // Maximum order of background fit169 int numBackground = normAndBG ? PM_SUBTRACTION_POLYTERMS(bgOrder) : 0; // Number of background terms170 int numTerms = numKernels * numSpatial + (normAndBG ? 1 + numBackground : 0); // Total number of terms171 assert(matrix);172 assert(matrix->numCols == matrix->numRows);173 assert(matrix->numCols == numTerms);174 assert(convolutions && convolutions->n == numKernels);175 assert(polyValues);176 assert(!normAndBG || input); // If we want the normalisation and BG, then we need the input image177 178 // Square part of the matrix (convolution-convolution products)179 if (!calculateMatrixSquare(matrix, convolutions, convolutions, variance, polyValues, numKernels,180 spatialOrder, footprint)) {181 return false;182 }183 184 // XXX To support higher-order background model than simply constant, the below code needs to be updated.185 if (normAndBG) {186 int normIndex = PM_SUBTRACTION_INDEX_NORM(kernels); // Index for normalisation187 int bgIndex = PM_SUBTRACTION_INDEX_BG(kernels); // Index in matrix for background188 189 for (int i = 0; i < numKernels; i++) {190 psKernel *conv = convolutions->data[i]; // Convolution for i-th element191 192 // Normalisation-convolution terms193 if (!calculateMatrixElement1(matrix, i, normIndex, conv, input, variance, polyValues, numKernels,194 footprint, spatialOrder, true)) {195 psTrace("psModules.imcombine", 2, "Bad sumIC at %d", i);196 return false;197 }198 199 // Background-convolution terms200 double sumC = 0.0; // Sum of the convolution201 for (int y = - footprint; y <= footprint; y++) {202 for (int x = - footprint; x <= footprint; x++) {203 double value = conv->kernel[y][x];204 #ifdef USE_VARIANCE205 value /= variance->kernel[y][x];206 #endif207 sumC += value;208 }209 }210 if (!isfinite(sumC)) {211 psTrace("psModules.imcombine", 2, "Bad sumC at %d", i);212 return false;213 }214 215 for (int yOrder = 0, index = i; yOrder <= spatialOrder; yOrder++) {216 for (int xOrder = 0; xOrder <= spatialOrder - yOrder; xOrder++, index += numKernels) {217 double value = sumC * polyValues->data.F64[yOrder][xOrder];218 matrix->data.F64[index][bgIndex] = value;219 matrix->data.F64[bgIndex][index] = value;220 }221 }222 }223 224 // Background only, normalisation only, and background-normalisation terms225 double sum1 = 0.0; // Sum of the weighting226 double sumI = 0.0; // Sum of the input227 double sumII = 0.0; // Sum of the input squared228 for (int y = - footprint; y <= footprint; y++) {229 for (int x = - footprint; x <= footprint; x++) {230 double invNoise2 = 1.0;231 #ifdef USE_VARIANCE232 invNoise2 /= variance->kernel[y][x];233 #endif234 double value = input->kernel[y][x] * invNoise2;235 sumI += value;236 sumII += value * input->kernel[y][x];237 sum1 += invNoise2;238 }239 }240 if (!isfinite(sumI)) {241 psTrace("psModules.imcombine", 2, "Bad sumI detected");242 return false;243 }244 if (!isfinite(sumII)) {245 psTrace("psModules.imcombine", 2, "Bad sumII detected");246 return false;247 }248 if (!isfinite(sum1)) {249 psTrace("psModules.imcombine", 2, "Bad sum1 detected");250 return false;251 }252 matrix->data.F64[normIndex][normIndex] = sumII;253 matrix->data.F64[bgIndex][bgIndex] = sum1;254 matrix->data.F64[normIndex][bgIndex] = sumI;255 matrix->data.F64[bgIndex][normIndex] = sumI;256 }257 258 return true;259 }260 261 262 // Calculate least-squares matrix and vector263 static bool calculateVector(psVector *vector, // Vector to calculate, or NULL264 const pmSubtractionKernels *kernels, // Kernel components265 const psArray *convolutions, // Convolutions of source with kernels266 const psKernel *input, // Input stamp, or NULL if !normAndBG267 const psKernel *target, // Target stamp268 const psKernel *variance, // Variance stamp269 const psImage *polyValues, // Spatial polynomial values270 int footprint, // (Half-)Size of stamp271 bool normAndBG // Calculate normalisation and background terms?272 )273 {274 int numKernels = kernels->num; // Number of kernel components275 int spatialOrder = kernels->spatialOrder; // Maximum order of spatial variation276 int numSpatial = PM_SUBTRACTION_POLYTERMS(spatialOrder); // Number of spatial variation terms277 int bgOrder = kernels->bgOrder; // Maximum order of background fit278 int numBackground = normAndBG ? PM_SUBTRACTION_POLYTERMS(bgOrder) : 0; // Number of background terms279 int numTerms = numKernels * numSpatial + (normAndBG ? 1 + numBackground : 0); // Total number of terms280 assert(vector && vector->n == numTerms);281 assert(convolutions && convolutions->n == numKernels);282 assert(target);283 assert(polyValues);284 assert(!normAndBG || input); // If we want the normalisation and BG, then we need the input image285 286 // Convolution terms287 for (int i = 0; i < numKernels; i++) {288 psKernel *conv = convolutions->data[i]; // Convolution for i-th element289 double sumTC = 0.0; // Sum of the target and convolution290 for (int y = - footprint; y <= footprint; y++) {291 for (int x = - footprint; x <= footprint; x++) {292 double value = target->kernel[y][x] * conv->kernel[y][x];293 #ifdef USE_VARIANCE294 value /= variance->kernel[y][x];295 #endif296 sumTC += value;297 }298 }299 if (!isfinite(sumTC)) {300 psTrace("psModules.imcombine", 2, "Bad sumTC at %d", i);301 return false;302 }303 for (int yOrder = 0, index = i; yOrder <= spatialOrder; yOrder++) {304 for (int xOrder = 0; xOrder <= spatialOrder - yOrder; xOrder++, index += numKernels) {305 vector->data.F64[index] = sumTC * polyValues->data.F64[yOrder][xOrder];306 }307 }308 }309 310 if (normAndBG) {311 // Background terms312 double sumT = 0.0; // Sum of the target313 double sumIT = 0.0; // Sum of the input-target product314 for (int y = - footprint; y <= footprint; y++) {315 for (int x = - footprint; x <= footprint; x++) {316 double value = target->kernel[y][x];317 #ifdef USE_VARIANCE318 value /= variance->kernel[y][x];319 #endif320 sumIT += value * input->kernel[y][x];321 sumT += value;322 }323 }324 if (!isfinite(sumT)) {325 psTrace("psModules.imcombine", 2, "Bad sumI detected");326 return false;327 }328 if (!isfinite(sumIT)) {329 psTrace("psModules.imcombine", 2, "Bad sumIT detected");330 return false;331 }332 333 int normIndex = PM_SUBTRACTION_INDEX_NORM(kernels); // Index for normalisation term334 vector->data.F64[normIndex] = sumIT;335 int bgIndex = PM_SUBTRACTION_INDEX_BG(kernels); // Index for background term336 vector->data.F64[bgIndex] = sumT;337 }338 339 return true;340 }341 342 343 344 // Calculate the cross-matrix, composed of convolutions of each image345 // Note that the cross-matrix is NOT square346 static bool calculateMatrixCross(psImage *matrix, // Matrix to calculate347 const pmSubtractionKernels *kernels, // Kernel components348 const psArray *convolutions1, // Convolutions of image 1349 const psArray *convolutions2, // Convolutions of image 2350 const psKernel *image1, // Image 1 stamp351 const psKernel *variance, // Variance stamp352 const psImage *polyValues, // Spatial polynomial values353 int footprint // (Half-)Size of stamp354 )355 {356 assert(matrix);357 int numKernels = kernels->num; // Number of kernel components358 int spatialOrder = kernels->spatialOrder; // Maximum order of spatial variation359 int numSpatial = PM_SUBTRACTION_POLYTERMS(spatialOrder); // Number of spatial polynomial terms360 int numBackground = PM_SUBTRACTION_POLYTERMS(kernels->bgOrder); // Number of background terms361 int numCols = numKernels * numSpatial + 1 + numBackground; // Number of columns362 int numRows = numKernels * numSpatial; // Number of rows363 assert(matrix->numCols == numCols && matrix->numRows == numRows);364 assert(convolutions1 && convolutions1->n == numKernels);365 assert(convolutions2 && convolutions2->n == numKernels);366 367 int normIndex, bgIndex; // Indices in matrix for normalisation and background terms368 PM_SUBTRACTION_INDICES(normIndex, bgIndex, kernels);369 370 if (!calculateMatrixSquare(matrix, convolutions1, convolutions2, variance, polyValues, numKernels,371 spatialOrder, footprint)) {372 return false;373 }374 375 for (int i = 0; i < numKernels; i++) {376 // Normalisation377 psKernel *conv = convolutions2->data[i]; // Convolution378 if (!calculateMatrixElement1(matrix, i, normIndex, conv, image1, variance, polyValues, numKernels,379 footprint, spatialOrder, false)) {380 psTrace("psModules.imcombine", 2, "Bad sumIC at %d", i);381 return false;382 }383 384 // Background385 double sumC = 0.0; // Sum of the weighting386 for (int y = - footprint; y <= footprint; y++) {387 for (int x = - footprint; x <= footprint; x++) {388 double value = conv->kernel[y][x];389 #ifdef USE_VARIANCE390 value /= variance->kernel[y][x];391 #endif392 sumC += value;393 }394 }395 if (!isfinite(sumC)) {396 psTrace("psModules.imcombine", 2, "Bad sumC detected at %d", i);397 return false;398 }399 for (int yOrder = 0, index = i; yOrder <= spatialOrder; yOrder++) {400 for (int xOrder = 0; xOrder <= spatialOrder - yOrder; xOrder++, index += numKernels) {401 matrix->data.F64[index][bgIndex] = sumC * polyValues->data.F64[yOrder][xOrder];402 }403 }404 }405 406 return true;407 }408 409 442 410 443 // Add in penalty term to least-squares vector 411 static bool calculatePenalty(psVector *vector, // Vector to which to add in penalty term 412 const pmSubtractionKernels *kernels // Kernel parameters 444 static bool calculatePenalty(psImage *matrix, // Matrix to which to add in penalty term 445 psVector *vector, // Vector to which to add in penalty term 446 const pmSubtractionKernels *kernels, // Kernel parameters 447 float norm // Normalisation 413 448 ) 414 449 { … … 423 458 for (int yOrder = 0, index = i; yOrder <= spatialOrder; yOrder++) { 424 459 for (int xOrder = 0; xOrder <= spatialOrder - yOrder; xOrder++, index += numKernels) { 425 vector->data.F64[index] -= penalties->data.F32[i]; 460 // Contribution to chi^2: a_i^2 P_i 461 matrix->data.F64[index][index] -= norm * penalties->data.F32[i]; 426 462 } 427 463 } … … 582 618 switch (kernels->mode) { 583 619 case PM_SUBTRACTION_MODE_1: 584 status = calculateMatrix(stamp->matrix1, kernels, stamp->convolutions1, stamp->image1, 585 stamp->variance, polyValues, footprint, true); 586 status &= calculateVector(stamp->vector1, kernels, stamp->convolutions1, stamp->image1, 587 stamp->image2, stamp->variance, polyValues, footprint, true); 620 status = calculateMatrixVector(stamp->matrix1, stamp->vector1, stamp->image2, stamp->image1, 621 stamp->variance, stamp->convolutions1, kernels, polyValues, 622 footprint); 588 623 break; 589 624 case PM_SUBTRACTION_MODE_2: 590 status = calculateMatrix(stamp->matrix1, kernels, stamp->convolutions2, stamp->image2, 591 stamp->variance, polyValues, footprint, true); 592 status &= calculateVector(stamp->vector1, kernels, stamp->convolutions2, stamp->image2, 593 stamp->image1, stamp->variance, polyValues, footprint, true); 625 status = calculateMatrixVector(stamp->matrix1, stamp->vector1, stamp->image1, stamp->image2, 626 stamp->variance, stamp->convolutions2, kernels, polyValues, 627 footprint); 594 628 break; 595 629 case PM_SUBTRACTION_MODE_DUAL: … … 604 638 psVectorInit(stamp->vector2, NAN); 605 639 #endif 606 status = calculateMatrix(stamp->matrix1, kernels, stamp->convolutions1, stamp->image1, 607 stamp->variance, polyValues, footprint, true); 608 status &= calculateMatrix(stamp->matrix2, kernels, stamp->convolutions2, NULL, 609 stamp->variance, polyValues, footprint, false); 610 status &= calculateMatrixCross(stamp->matrixX, kernels, stamp->convolutions1, 611 stamp->convolutions2, stamp->image1, stamp->variance, polyValues, 612 footprint); 613 status &= calculateVector(stamp->vector1, kernels, stamp->convolutions1, stamp->image1, 614 stamp->image2, stamp->variance, polyValues, footprint, true); 615 status &= calculateVector(stamp->vector2, kernels, stamp->convolutions2, NULL, 616 stamp->image2, stamp->variance, polyValues, footprint, false); 640 status = calculateDualMatrixVector(stamp->matrix1, stamp->vector1, stamp->matrix2, stamp->vector2, 641 stamp->matrixX, stamp->image1, stamp->image2, stamp->variance, 642 stamp->convolutions1, stamp->convolutions2, kernels, polyValues, 643 footprint); 617 644 break; 618 645 default: … … 629 656 630 657 #ifdef TESTING 631 if (psTraceGetLevel("psModules.imcombine.equation") >= 10){658 { 632 659 psString matrixName = NULL; 633 660 psStringAppend(&matrixName, "matrix1_%d.fits", index); … … 825 852 #endif 826 853 827 calculatePenalty(sumVector, kernels); 854 #if 0 855 int bgIndex = PM_SUBTRACTION_INDEX_BG(kernels); // Index for background 856 calculatePenalty(sumMatrix, sumVector, kernels, sumMatrix->data.F64[bgIndex][bgIndex]); 857 #endif 828 858 829 859 #ifdef TESTING … … 909 939 } 910 940 } 911 calculatePenalty(sumVector1, kernels); 912 calculatePenalty(sumVector2, kernels); 913 914 // Pure matrix operations 915 916 // A * a = Ct * b + d 917 // C * a = B * b + e 918 // 919 // a = (Ct * Bi * C - A)i (Ct * Bi * e - d) 920 // b = Bi * (C * a - e) 921 psVector *a = psVectorRecycle(kernels->solution1, numParams, PS_TYPE_F64); 922 psVector *b = psVectorRecycle(kernels->solution2, numParams2, PS_TYPE_F64); 923 #ifdef TESTING 924 psVectorInit(a, NAN); 925 psVectorInit(b, NAN); 926 #endif 927 psImage *A = sumMatrix1; 928 psImage *B = sumMatrix2; 929 psImage *C = sumMatrixX; 930 psVector *d = sumVector1; 931 psVector *e = sumVector2; 932 933 assert(a->n == numParams); 934 assert(b->n == numParams2); 935 assert(A->numRows == numParams && A->numCols == numParams); 936 assert(B->numRows == numParams2 && B->numCols == numParams2); 937 assert(C->numRows == numParams2 && C->numCols == numParams); 938 assert(d->n == numParams); 939 assert(e->n == numParams2); 940 941 psImage *Bi = psMatrixInvert(NULL, B, NULL); 942 assert(Bi->numRows == numParams2 && Bi->numCols == numParams2); 943 psImage *Ct = psMatrixTranspose(NULL, C); 944 assert(Ct->numRows == numParams && Ct->numCols == numParams2); 945 946 psImage *BiC = psMatrixMultiply(NULL, Bi, C); 947 assert(BiC->numRows == numParams2 && BiC->numCols == numParams); 948 psImage *CtBi = psMatrixMultiply(NULL, Ct, Bi); 949 assert(CtBi->numRows == numParams && CtBi->numCols == numParams2); 950 951 psImage *CtBiC = psMatrixMultiply(NULL, Ct, BiC); 952 assert(CtBiC->numRows == numParams && CtBiC->numCols == numParams); 953 954 psImage *F = (psImage*)psBinaryOp(NULL, CtBiC, "-", A); 955 assert(F->numRows == numParams && F->numCols == numParams); 956 float det = 0.0; 957 psImage *Fi = psMatrixInvert(NULL, F, &det); 958 assert(Fi->numRows == numParams && Fi->numCols == numParams); 959 psTrace("psModules.imcombine", 4, "Determinant of F: %f\n", det); 960 961 psVector *g = psVectorAlloc(numParams, PS_TYPE_F64); 962 #ifdef TESTING 963 psVectorInit(g, NAN); 964 #endif 965 assert(CtBi->numRows == numParams && CtBi->numCols == numParams2); 966 assert(e->n == numParams2); 967 assert(d->n == numParams); 968 for (int i = 0; i < numParams; i++) { 969 double value = 0.0; 970 for (int j = 0; j < numParams2; j++) { 971 value += CtBi->data.F64[i][j] * e->data.F64[j]; 972 } 973 g->data.F64[i] = value - d->data.F64[i]; 974 } 975 976 assert(Fi->numRows == numParams && Fi->numCols == numParams); 977 assert(g->n == numParams); 978 for (int i = 0; i < numParams; i++) { 979 double value = 0.0; 980 for (int j = 0; j < numParams; j++) { 981 value += Fi->data.F64[i][j] * g->data.F64[j]; 982 } 983 a->data.F64[i] = value; 984 } 985 986 psVector *h = psVectorAlloc(numParams2, PS_TYPE_F64); 987 #ifdef TESTING 988 psVectorInit(h, NAN); 989 #endif 990 assert(C->numRows == numParams2 && C->numCols == numParams); 991 assert(a->n == numParams); 992 assert(e->n == numParams2); 993 for (int i = 0; i < numParams2; i++) { 994 double value = 0.0; 995 for (int j = 0; j < numParams; j++) { 996 value += C->data.F64[i][j] * a->data.F64[j]; 997 } 998 h->data.F64[i] = value - e->data.F64[i]; 999 } 1000 1001 assert(Bi->numRows == numParams2 && Bi->numCols == numParams2); 1002 assert(h->n == numParams2); 1003 for (int i = 0; i < numParams2; i++) { 1004 double value = 0.0; 1005 for (int j = 0; j < numParams2; j++) { 1006 value += Bi->data.F64[i][j] * h->data.F64[j]; 1007 } 1008 b->data.F64[i] = value; 1009 } 1010 1011 1012 #if 0 1013 for (int i = 0; i < numParams; i++) { 1014 double aVal1 = 0.0, bVal1 = 0.0; 1015 for (int j = 0; j < numParams2; j++) { 1016 aVal1 += A->data.F64[i][j] * a->data.F64[j]; 1017 bVal1 += Ct->data.F64[i][j] * b->data.F64[j]; 1018 } 1019 bVal1 += d->data.F64[i]; 1020 for (int j = numParams2; j < numParams; j++) { 1021 aVal1 += A->data.F64[i][j] * a->data.F64[j]; 1022 } 1023 printf("%d: %lf\n", i, aVal1 - bVal1); 1024 } 1025 1026 for (int i = 0; i < numParams2; i++) { 1027 double aVal2 = 0.0, bVal2 = 0.0; 1028 for (int j = 0; j < numParams2; j++) { 1029 aVal2 += C->data.F64[i][j] * a->data.F64[j]; 1030 bVal2 += B->data.F64[i][j] * b->data.F64[j]; 1031 } 1032 bVal2 += e->data.F64[i]; 1033 for (int j = numParams2; j < numParams; j++) { 1034 aVal2 += C->data.F64[i][j] * a->data.F64[j]; 1035 } 1036 printf("%d: %lf\n", i, aVal2 - bVal2); 1037 } 1038 #endif 941 942 int bgIndex = PM_SUBTRACTION_INDEX_BG(kernels); // Index for background 943 calculatePenalty(sumMatrix1, sumVector1, kernels, sumMatrix1->data.F64[bgIndex][bgIndex]); 944 calculatePenalty(sumMatrix2, sumVector2, kernels, -sumMatrix1->data.F64[bgIndex][bgIndex]); 945 946 psImage *sumMatrix = NULL; // Combined matrix 947 psVector *sumVector = NULL; // Combined vector 948 calculateEquationDual(&sumMatrix, &sumVector, sumMatrix1, sumMatrix2, 949 sumMatrixX, sumVector1, sumVector2); 1039 950 1040 951 #ifdef TESTING 1041 952 { 1042 psFits *fits = psFitsOpen("sumMatrix 1.fits", "w");1043 psFitsWriteImage(fits, NULL, sumMatrix 1, 0, NULL);953 psFits *fits = psFitsOpen("sumMatrix.fits", "w"); 954 psFitsWriteImage(fits, NULL, sumMatrix, 0, NULL); 1044 955 psFitsClose(fits); 1045 956 } 1046 957 { 1047 psFits *fits = psFitsOpen("sumMatrix2.fits", "w"); 1048 psFitsWriteImage(fits, NULL, sumMatrix2, 0, NULL); 958 psImage *image = psImageAlloc(1, numParams + numParams2, PS_TYPE_F64); 959 psFits *fits = psFitsOpen("sumVector.fits", "w"); 960 for (int i = 0; i < numParams + numParams2; i++) { 961 image->data.F64[0][i] = sumVector->data.F64[i]; 962 } 963 psFitsWriteImage(fits, NULL, image, 0, NULL); 964 psFree(image); 1049 965 psFitsClose(fits); 1050 966 } 967 #endif 968 969 psVector *solution = NULL; // Solution to equation! 1051 970 { 1052 psFits *fits = psFitsOpen("sumMatrixX.fits", "w"); 1053 psFitsWriteImage(fits, NULL, sumMatrixX, 0, NULL); 971 solution = psMatrixSolveSVD(solution, sumMatrix, sumVector); 972 if (!solution) { 973 psError(PS_ERR_UNKNOWN, false, "SVD solution of least-squares equation failed.\n"); 974 psFree(sumMatrix); 975 psFree(sumVector); 976 return NULL; 977 } 978 979 int numSpatial = PM_SUBTRACTION_POLYTERMS(kernels->spatialOrder); // Number of spatial variations 980 int numKernels = kernels->num; // Number of kernel basis functions 981 982 // Remove a kernel basis for image 1 from the equation 983 #define MASK_BASIS_1(INDEX) \ 984 { \ 985 for (int j = 0, index = INDEX; j < numSpatial; j++, index += numKernels) { \ 986 for (int k = 0; k < numParams2; k++) { \ 987 sumMatrix1->data.F64[k][index] = 0.0; \ 988 sumMatrix1->data.F64[index][k] = 0.0; \ 989 sumMatrixX->data.F64[k][index] = 0.0; \ 990 } \ 991 sumMatrix1->data.F64[bgIndex][index] = 0.0; \ 992 sumMatrix1->data.F64[index][bgIndex] = 0.0; \ 993 sumMatrix1->data.F64[normIndex][index] = 0.0; \ 994 sumMatrix1->data.F64[index][normIndex] = 0.0; \ 995 sumMatrix1->data.F64[index][index] = 1.0; \ 996 sumVector1->data.F64[index] = 0.0; \ 997 } \ 998 } 999 1000 // Remove a kernel basis for image 2 from the equation 1001 #define MASK_BASIS_2(INDEX) \ 1002 { \ 1003 for (int j = 0, index = INDEX; j < numSpatial; j++, index += numKernels) { \ 1004 for (int k = 0; k < numParams2; k++) { \ 1005 sumMatrix2->data.F64[k][index] = 0.0; \ 1006 sumMatrix2->data.F64[index][k] = 0.0; \ 1007 sumMatrixX->data.F64[index][k] = 0.0; \ 1008 } \ 1009 sumMatrix2->data.F64[index][index] = 1.0; \ 1010 sumMatrixX->data.F64[index][normIndex] = 0.0; \ 1011 sumMatrixX->data.F64[index][bgIndex] = 0.0; \ 1012 sumVector2->data.F64[index] = 0.0; \ 1013 } \ 1014 } 1015 1016 #define TOL 1.0e-5 1017 int normIndex = PM_SUBTRACTION_INDEX_NORM(kernels); // Index for normalisation 1018 double norm = solution->data.F64[normIndex]; // Normalisation 1019 double thresh = norm * TOL; // Threshold for low parameters 1020 for (int i = 0; i < numKernels; i++) { 1021 // Getting 0th order parameter value. In the presence of spatial variation, the actual value 1022 // of the parameter will vary over the image. We are in effect getting the value in the 1023 // centre of the image. If we use different polynomial functions (e.g., Chebyshev), we may 1024 // have to change this to properly determine the value of the parameter at the centre. 1025 double param1 = solution->data.F64[i], 1026 param2 = solution->data.F64[numParams + i]; // Parameters of interest 1027 bool mask1 = false, mask2 = false; // Masked the parameter? 1028 if (fabs(param1) < thresh) { 1029 psTrace("psModules.imcombine", 7, "Parameter %d: 1 below threshold\n", i); 1030 MASK_BASIS_1(i); 1031 mask1 = true; 1032 } 1033 if (fabs(param2) < thresh) { 1034 psTrace("psModules.imcombine", 7, "Parameter %d: 2 below threshold\n", i); 1035 MASK_BASIS_2(i); 1036 mask2 = true; 1037 } 1038 1039 if (!mask1 && !mask2) { 1040 if (fabs(param1) < fabs(param2)) { 1041 psTrace("psModules.imcombine", 7, "Parameter %d: 1 < 2\n", i); 1042 MASK_BASIS_1(i); 1043 } else { 1044 psTrace("psModules.imcombine", 7, "Parameter %d: 2 < 1\n", i); 1045 MASK_BASIS_2(i); 1046 } 1047 } 1048 } 1049 } 1050 1051 calculateEquationDual(&sumMatrix, &sumVector, sumMatrix1, sumMatrix2, 1052 sumMatrixX, sumVector1, sumVector2); 1053 1054 #ifdef TESTING 1055 { 1056 psFits *fits = psFitsOpen("sumMatrixFix.fits", "w"); 1057 psFitsWriteImage(fits, NULL, sumMatrix, 0, NULL); 1054 1058 psFitsClose(fits); 1055 1059 } 1056 1060 { 1057 psFits *fits = psFitsOpen("sumFinverse.fits", "w"); 1058 psFitsWriteImage(fits, NULL, Fi, 0, NULL); 1061 psImage *image = psImageAlloc(1, numParams + numParams2, PS_TYPE_F64); 1062 psFits *fits = psFitsOpen("sumVectorFix.fits", "w"); 1063 for (int i = 0; i < numParams + numParams2; i++) { 1064 image->data.F64[0][i] = sumVector->data.F64[i]; 1065 } 1066 psFitsWriteImage(fits, NULL, image, 0, NULL); 1067 psFree(image); 1059 1068 psFitsClose(fits); 1060 1069 } 1061 1070 #endif 1062 1071 1063 kernels->solution1 = a; 1064 kernels->solution2 = b; 1065 1066 // XXXXX Free temporary matrices and vectors 1072 solution = psMatrixSolveSVD(solution, sumMatrix, sumVector); 1073 if (!solution) { 1074 psError(PS_ERR_UNKNOWN, false, "SVD solution of least-squares equation failed.\n"); 1075 psFree(sumMatrix); 1076 psFree(sumVector); 1077 return NULL; 1078 } 1079 1080 psFree(sumMatrix1); 1081 psFree(sumMatrix2); 1082 psFree(sumMatrixX); 1083 psFree(sumVector1); 1084 psFree(sumVector2); 1085 1086 psFree(sumMatrix); 1087 psFree(sumVector); 1088 1089 #ifdef TESTING 1090 { 1091 psImage *image = psImageAlloc(1, numParams + numParams2, PS_TYPE_F64); 1092 psFits *fits = psFitsOpen("solnVector.fits", "w"); 1093 for (int i = 0; i < numParams + numParams2; i++) { 1094 image->data.F64[0][i] = solution->data.F64[i]; 1095 } 1096 psFitsWriteImage(fits, NULL, image, 0, NULL); 1097 psFree(image); 1098 psFitsClose(fits); 1099 } 1100 #endif 1101 1102 if (!kernels->solution1) { 1103 kernels->solution1 = psVectorAlloc(numParams, PS_TYPE_F64); 1104 } 1105 if (!kernels->solution2) { 1106 kernels->solution2 = psVectorAlloc(numParams2, PS_TYPE_F64); 1107 } 1108 1109 memcpy(kernels->solution1->data.F64, solution->data.F64, numParams * PSELEMTYPE_SIZEOF(PS_TYPE_F64)); 1110 memcpy(kernels->solution2->data.F64, &solution->data.F64[numParams], 1111 numParams2 * PSELEMTYPE_SIZEOF(PS_TYPE_F64)); 1112 1113 psFree(solution); 1067 1114 1068 1115 } -
trunk/psModules/src/imcombine/pmSubtractionKernels.c
r25120 r25999 81 81 kernels->penalties = psVectorRealloc(kernels->penalties, start + numNew); 82 82 kernels->inner = start; 83 kernels->num += numNew; 83 84 84 85 // Generate a set of kernels for each (u,v) … … 94 95 kernels->v->data.S32[index] = v; 95 96 kernels->preCalc->data[index] = NULL; 96 kernels->penalties->data.F32[index] = kernels->penalty * (PS_SQR(u) + PS_SQR(v));97 kernels->penalties->data.F32[index] = kernels->penalty * PS_SQR(PS_SQR(u) + PS_SQR(v)); 97 98 98 99 psTrace("psModules.imcombine", 7, "Kernel %d: %d %d\n", index, u, v); 99 100 } 100 101 } 102 103 kernels->widths->n = start + numNew; 104 kernels->u->n = start + numNew; 105 kernels->v->n = start + numNew; 106 kernels->preCalc->n = start + numNew; 107 kernels->penalties->n = start + numNew; 101 108 102 109 return true; … … 140 147 for (int uOrder = 0; uOrder <= orders->data.S32[i]; uOrder++) { 141 148 for (int vOrder = 0; vOrder <= orders->data.S32[i] - uOrder; vOrder++, index++) { 142 psArray *preCalc = psArrayAlloc( 2); // Array to hold precalculated values149 psArray *preCalc = psArrayAlloc(3); // Array to hold precalculated values 143 150 psVector *xKernel = preCalc->data[0] = subtractionKernelISIS(sigma, uOrder, size); // x Kernel 144 151 psVector *yKernel = preCalc->data[1] = subtractionKernelISIS(sigma, vOrder, size); // y Kernel 152 psKernel *kernel = preCalc->data[2] = psKernelAlloc(-size, size, -size, size); // Kernel 145 153 146 154 // Calculate moments … … 149 157 for (int u = -size, x = 0; u <= size; u++, x++) { 150 158 double value = xKernel->data.F32[x] * yKernel->data.F32[y]; // Value of kernel 151 moment += value * (PS_SQR(u) + PS_SQR(v)); 159 kernel->kernel[v][u] = value; 160 moment += value * PS_SQR((PS_SQR(u) + PS_SQR(v))); 152 161 } 153 162 } … … 164 173 psBinaryOp(xKernel, xKernel, "*", psScalarAlloc(sum, PS_TYPE_F32)); 165 174 psBinaryOp(yKernel, yKernel, "*", psScalarAlloc(sum, PS_TYPE_F32)); 175 psBinaryOp(kernel->image, kernel->image, "*", psScalarAlloc(PS_SQR(sum), PS_TYPE_F32)); 176 kernel->kernel[0][0] -= 1.0; 166 177 moment *= PS_SQR(sum); 167 178 } 179 180 181 #if 0 182 double sum = 0.0; // Sum of kernel component 183 for (int v = -size; v <= size; v++) { 184 for (int u = -size; u <= size; u++) { 185 sum += kernel->kernel[v][u]; 186 } 187 } 188 fprintf(stderr, "%d sum: %lf\n", index, sum); 189 #endif 168 190 169 191 kernels->widths->data.F32[index] = fwhms->data.F32[i]; … … 456 478 PS_ASSERT_INT_LESS_THAN(inner, size, NULL); 457 479 458 // XXX GUNK doesn't seem to work --- doesn't add the POIS components, or at least, they're not noticed459 460 480 pmSubtractionKernels *kernels = p_pmSubtractionKernelsRawISIS(size, spatialOrder, fwhms, orders, 461 481 penalty, mode); // Kernels 482 kernels->type = PM_SUBTRACTION_KERNEL_GUNK; 462 483 psStringPrepend(&kernels->description, "GUNK="); 463 484 psStringAppend(&kernels->description, "+POIS(%d,%d)", inner, spatialOrder); … … 577 598 poly->data.F32[j] = polyVal; 578 599 norm += polyVal; 579 moment += polyVal * (PS_SQR(u) + PS_SQR(v));600 moment += polyVal * PS_SQR(PS_SQR(u) + PS_SQR(v)); 580 601 581 602 psVectorExtend(uCoords, RINGS_BUFFER, 1); … … 603 624 psBinaryOp(poly, poly, "*", psScalarAlloc(1.0 / norm, PS_TYPE_F32)); 604 625 } 605 //moment /= norm;626 moment /= norm; 606 627 } 607 628
Note:
See TracChangeset
for help on using the changeset viewer.
