Changeset 26586
- Timestamp:
- Jan 13, 2010, 2:37:39 PM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/eam_branches/20091201/psModules/src/imcombine/pmSubtractionEquation.c
r26583 r26586 17 17 // #define TESTING // TESTING output for debugging; may not work with threads! 18 18 19 #define USE_WEIGHT // Include weight (1/variance) in equation?20 #define USE_WINDOW // Include weight (1/variance) in equation?19 //#define USE_WEIGHT // Include weight (1/variance) in equation? 20 //#define USE_WINDOW // Include weight (1/variance) in equation? 21 21 22 22 … … 36 36 const psImage *polyValues, // Spatial polynomial values 37 37 int footprint, // (Half-)Size of stamp 38 const pmSubtractionEquationCalculationMode mode38 const pmSubtractionEquationCalculationMode mode 39 39 ) 40 40 { … … 68 68 } 69 69 70 // initialize the matrix and vector for NOP on all coeffs. we only fill in the coeffs we 70 // initialize the matrix and vector for NOP on all coeffs. we only fill in the coeffs we 71 71 // choose to calculate 72 72 psImageInit(matrix, 0.0); 73 73 psVectorInit(vector, 1.0); 74 74 for (int i = 0; i < matrix->numCols; i++) { 75 matrix->data.F64[i][i] = 1.0;75 matrix->data.F64[i][i] = 1.0; 76 76 } 77 77 … … 84 84 85 85 for (int i = 0; i < numKernels; i++) { 86 psKernel *iConv = convolutions->data[i]; // Convolution for index i87 for (int j = i; j < numKernels; j++) {88 psKernel *jConv = convolutions->data[j]; // Convolution for index j89 90 double sumCC = 0.0; // Sum of convolution products91 for (int y = - footprint; y <= footprint; y++) {92 for (int x = - footprint; x <= footprint; x++) {93 double cc = iConv->kernel[y][x] * jConv->kernel[y][x];94 if (weight) {95 cc *= weight->kernel[y][x];96 }97 if (window) {98 cc *= window->kernel[y][x];99 }100 sumCC += cc;101 }102 }103 104 // Spatial variation of kernel coeffs105 if (mode & PM_SUBTRACTION_EQUATION_KERNELS) {106 for (int iTerm = 0, iIndex = i; iTerm < numPoly; iTerm++, iIndex += numKernels) {107 for (int jTerm = 0, jIndex = j; jTerm < numPoly; jTerm++, jIndex += numKernels) {108 double value = sumCC * poly2[iTerm][jTerm];109 matrix->data.F64[iIndex][jIndex] = value;110 matrix->data.F64[jIndex][iIndex] = value;111 }112 }113 }114 }115 116 double sumRC = 0.0; // Sum of the reference-convolution products117 double sumIC = 0.0; // Sum of the input-convolution products118 double sumC = 0.0; // Sum of the convolution119 for (int y = - footprint; y <= footprint; y++) {120 for (int x = - footprint; x <= footprint; x++) {121 float conv = iConv->kernel[y][x];122 float in = input->kernel[y][x];123 float ref = reference->kernel[y][x];124 double ic = in * conv;125 double rc = ref * conv;126 double c = conv;127 if (weight) {128 float wtVal = weight->kernel[y][x];129 ic *= wtVal;130 rc *= wtVal;131 c *= wtVal;132 }133 if (window) {134 float winVal = window->kernel[y][x];135 ic *= winVal;136 rc *= winVal;137 c *= winVal;138 }139 sumIC += ic;140 sumRC += rc;141 sumC += c;142 }143 }144 // Spatial variation145 for (int iTerm = 0, iIndex = i; iTerm < numPoly; iTerm++, iIndex += numKernels) {146 double normTerm = sumRC * poly[iTerm];147 double bgTerm = sumC * poly[iTerm];148 if ((mode & PM_SUBTRACTION_EQUATION_NORM) && (mode & PM_SUBTRACTION_EQUATION_KERNELS)) {149 matrix->data.F64[iIndex][normIndex] = normTerm;150 matrix->data.F64[normIndex][iIndex] = normTerm;151 }152 if ((mode & PM_SUBTRACTION_EQUATION_BG) && (mode & PM_SUBTRACTION_EQUATION_KERNELS)) {153 matrix->data.F64[iIndex][bgIndex] = bgTerm;154 matrix->data.F64[bgIndex][iIndex] = bgTerm;155 }156 if (mode & PM_SUBTRACTION_EQUATION_KERNELS) {157 vector->data.F64[iIndex] = sumIC * poly[iTerm];158 // XXX TEST for Hermitians: do not calculate A - norm*B - \sum(k x B),159 // instead, calculate A - \sum(k x B), with full hermitians160 if (0 && !(mode & PM_SUBTRACTION_EQUATION_NORM)) {161 // subtract norm * sumRC * poly[iTerm]162 psAssert (kernels->solution1, "programming error: define solution first!");163 int normIndex = PM_SUBTRACTION_INDEX_NORM(kernels); // Index for normalisation164 double norm = fabs(kernels->solution1->data.F64[normIndex]); // Normalisation165 vector->data.F64[iIndex] -= norm * normTerm;166 }167 }168 }86 psKernel *iConv = convolutions->data[i]; // Convolution for index i 87 for (int j = i; j < numKernels; j++) { 88 psKernel *jConv = convolutions->data[j]; // Convolution for index j 89 90 double sumCC = 0.0; // Sum of convolution products 91 for (int y = - footprint; y <= footprint; y++) { 92 for (int x = - footprint; x <= footprint; x++) { 93 double cc = iConv->kernel[y][x] * jConv->kernel[y][x]; 94 if (weight) { 95 cc *= weight->kernel[y][x]; 96 } 97 if (window) { 98 cc *= window->kernel[y][x]; 99 } 100 sumCC += cc; 101 } 102 } 103 104 // Spatial variation of kernel coeffs 105 if (mode & PM_SUBTRACTION_EQUATION_KERNELS) { 106 for (int iTerm = 0, iIndex = i; iTerm < numPoly; iTerm++, iIndex += numKernels) { 107 for (int jTerm = 0, jIndex = j; jTerm < numPoly; jTerm++, jIndex += numKernels) { 108 double value = sumCC * poly2[iTerm][jTerm]; 109 matrix->data.F64[iIndex][jIndex] = value; 110 matrix->data.F64[jIndex][iIndex] = value; 111 } 112 } 113 } 114 } 115 116 double sumRC = 0.0; // Sum of the reference-convolution products 117 double sumIC = 0.0; // Sum of the input-convolution products 118 double sumC = 0.0; // Sum of the convolution 119 for (int y = - footprint; y <= footprint; y++) { 120 for (int x = - footprint; x <= footprint; x++) { 121 float conv = iConv->kernel[y][x]; 122 float in = input->kernel[y][x]; 123 float ref = reference->kernel[y][x]; 124 double ic = in * conv; 125 double rc = ref * conv; 126 double c = conv; 127 if (weight) { 128 float wtVal = weight->kernel[y][x]; 129 ic *= wtVal; 130 rc *= wtVal; 131 c *= wtVal; 132 } 133 if (window) { 134 float winVal = window->kernel[y][x]; 135 ic *= winVal; 136 rc *= winVal; 137 c *= winVal; 138 } 139 sumIC += ic; 140 sumRC += rc; 141 sumC += c; 142 } 143 } 144 // Spatial variation 145 for (int iTerm = 0, iIndex = i; iTerm < numPoly; iTerm++, iIndex += numKernels) { 146 double normTerm = sumRC * poly[iTerm]; 147 double bgTerm = sumC * poly[iTerm]; 148 if ((mode & PM_SUBTRACTION_EQUATION_NORM) && (mode & PM_SUBTRACTION_EQUATION_KERNELS)) { 149 matrix->data.F64[iIndex][normIndex] = normTerm; 150 matrix->data.F64[normIndex][iIndex] = normTerm; 151 } 152 if ((mode & PM_SUBTRACTION_EQUATION_BG) && (mode & PM_SUBTRACTION_EQUATION_KERNELS)) { 153 matrix->data.F64[iIndex][bgIndex] = bgTerm; 154 matrix->data.F64[bgIndex][iIndex] = bgTerm; 155 } 156 if (mode & PM_SUBTRACTION_EQUATION_KERNELS) { 157 vector->data.F64[iIndex] = sumIC * poly[iTerm]; 158 // XXX TEST for Hermitians: do not calculate A - norm*B - \sum(k x B), 159 // instead, calculate A - \sum(k x B), with full hermitians 160 if (0 && !(mode & PM_SUBTRACTION_EQUATION_NORM)) { 161 // subtract norm * sumRC * poly[iTerm] 162 psAssert (kernels->solution1, "programming error: define solution first!"); 163 int normIndex = PM_SUBTRACTION_INDEX_NORM(kernels); // Index for normalisation 164 double norm = fabs(kernels->solution1->data.F64[normIndex]); // Normalisation 165 vector->data.F64[iIndex] -= norm * normTerm; 166 } 167 } 168 } 169 169 } 170 170 … … 181 181 double rr = PS_SQR(ref); 182 182 double one = 1.0; 183 if (weight) {184 float wtVal = weight->kernel[y][x];185 rr *= wtVal;186 ir *= wtVal;187 in *= wtVal;188 ref *= wtVal;189 one *= wtVal;190 }191 if (window) {192 float winVal = window->kernel[y][x];193 rr*= winVal;194 ir*= winVal;195 in*= winVal;196 ref *= winVal;197 one *= winVal;198 }183 if (weight) { 184 float wtVal = weight->kernel[y][x]; 185 rr *= wtVal; 186 ir *= wtVal; 187 in *= wtVal; 188 ref *= wtVal; 189 one *= wtVal; 190 } 191 if (window) { 192 float winVal = window->kernel[y][x]; 193 rr *= winVal; 194 ir *= winVal; 195 in *= winVal; 196 ref *= winVal; 197 one *= winVal; 198 } 199 199 sumRR += rr; 200 200 sumIR += ir; … … 205 205 } 206 206 if (mode & PM_SUBTRACTION_EQUATION_NORM) { 207 matrix->data.F64[normIndex][normIndex] = sumRR;208 vector->data.F64[normIndex] = sumIR;209 // subtract sum over kernels * kernel solution207 matrix->data.F64[normIndex][normIndex] = sumRR; 208 vector->data.F64[normIndex] = sumIR; 209 // subtract sum over kernels * kernel solution 210 210 } 211 211 if (mode & PM_SUBTRACTION_EQUATION_BG) { 212 matrix->data.F64[bgIndex][bgIndex] = sum1;213 vector->data.F64[bgIndex] = sumI;212 matrix->data.F64[bgIndex][bgIndex] = sum1; 213 vector->data.F64[bgIndex] = sumI; 214 214 } 215 215 if ((mode & PM_SUBTRACTION_EQUATION_NORM) && (mode & PM_SUBTRACTION_EQUATION_BG)) { 216 matrix->data.F64[normIndex][bgIndex] = sumR;217 matrix->data.F64[bgIndex][normIndex] = sumR;216 matrix->data.F64[normIndex][bgIndex] = sumR; 217 matrix->data.F64[bgIndex][normIndex] = sumR; 218 218 } 219 219 return true; … … 288 288 double bb = iConv2->kernel[y][x] * jConv2->kernel[y][x]; 289 289 double ab = iConv1->kernel[y][x] * jConv2->kernel[y][x]; 290 if (weight) {291 float wtVal = weight->kernel[y][x];292 aa *= wtVal;293 bb *= wtVal;294 ab *= wtVal;295 }296 if (window) {297 float wtVal = window->kernel[y][x];298 aa *= wtVal;299 bb *= wtVal;300 ab *= wtVal;301 }290 if (weight) { 291 float wtVal = weight->kernel[y][x]; 292 aa *= wtVal; 293 bb *= wtVal; 294 ab *= wtVal; 295 } 296 if (window) { 297 float wtVal = window->kernel[y][x]; 298 aa *= wtVal; 299 bb *= wtVal; 300 ab *= wtVal; 301 } 302 302 sumAA += aa; 303 303 sumBB += bb; … … 330 330 for (int x = - footprint; x <= footprint; x++) { 331 331 double ab = iConv1->kernel[y][x] * jConv2->kernel[y][x]; 332 if (weight) {333 ab *= weight->kernel[y][x];334 }335 if (window) {336 ab *= window->kernel[y][x];337 }332 if (weight) { 333 ab *= weight->kernel[y][x]; 334 } 335 if (window) { 336 ab *= window->kernel[y][x]; 337 } 338 338 sumAB += ab; 339 339 } … … 369 369 double bi1 = b * i1; 370 370 371 if (weight) {372 float wtVal = weight->kernel[y][x];373 ai2 *= wtVal;374 bi2 *= wtVal;375 ai1 *= wtVal;376 bi1 *= wtVal;377 a *= wtVal;378 b *= wtVal;379 i2 *= wtVal;380 }381 if (window) {382 float wtVal = window->kernel[y][x];383 ai2 *= wtVal;384 bi2 *= wtVal;385 ai1 *= wtVal;386 bi1 *= wtVal;387 a *= wtVal;388 b *= wtVal;389 i2 *= wtVal;390 }371 if (weight) { 372 float wtVal = weight->kernel[y][x]; 373 ai2 *= wtVal; 374 bi2 *= wtVal; 375 ai1 *= wtVal; 376 bi1 *= wtVal; 377 a *= wtVal; 378 b *= wtVal; 379 i2 *= wtVal; 380 } 381 if (window) { 382 float wtVal = window->kernel[y][x]; 383 ai2 *= wtVal; 384 bi2 *= wtVal; 385 ai1 *= wtVal; 386 bi1 *= wtVal; 387 a *= wtVal; 388 b *= wtVal; 389 i2 *= wtVal; 390 } 391 391 sumAI2 += ai2; 392 392 sumBI2 += bi2; … … 434 434 double i1i2 = i1 * i2; 435 435 436 if (weight) {437 float wtVal = weight->kernel[y][x];438 i1 *= wtVal;439 i1i1 *= wtVal;440 one *= wtVal;441 i2 *= wtVal;442 i1i2 *= wtVal;443 }444 if (window) {445 float wtVal = window->kernel[y][x];446 i1 *= wtVal;447 i1i1 *= wtVal;448 one *= wtVal;449 i2 *= wtVal;450 i1i2 *= wtVal;451 }436 if (weight) { 437 float wtVal = weight->kernel[y][x]; 438 i1 *= wtVal; 439 i1i1 *= wtVal; 440 one *= wtVal; 441 i2 *= wtVal; 442 i1i2 *= wtVal; 443 } 444 if (window) { 445 float wtVal = window->kernel[y][x]; 446 i1 *= wtVal; 447 i1i1 *= wtVal; 448 one *= wtVal; 449 i2 *= wtVal; 450 i1i2 *= wtVal; 451 } 452 452 sumI1 += i1; 453 453 sumI1I1 += i1i1; … … 486 486 for (int xOrder = 0; xOrder <= spatialOrder - yOrder; xOrder++, index += numKernels) { 487 487 // Contribution to chi^2: a_i^2 P_i 488 psAssert(isfinite(penalties->data.F32[i]), "Invalid penalty");488 psAssert(isfinite(penalties->data.F32[i]), "Invalid penalty"); 489 489 matrix->data.F64[index][index] -= norm * penalties->data.F32[i]; 490 490 } … … 595 595 int numBackground = PM_SUBTRACTION_POLYTERMS(kernels->bgOrder); // Number of background terms 596 596 597 // numKernels is the number of unique kernel images (one for each Gaussian modified by a specific polynomial). 597 // numKernels is the number of unique kernel images (one for each Gaussian modified by a specific polynomial). 598 598 // = \sum_i^N_Gaussians [(order + 1) * (order + 2) / 2], eg for 1 Gauss and 1st order, numKernels = 3 599 599 … … 670 670 status = calculateMatrixVector(stamp->matrix, stamp->vector, stamp->image2, stamp->image1, 671 671 weight, window, stamp->convolutions1, kernels, 672 polyValues, footprint, mode);672 polyValues, footprint, mode); 673 673 break; 674 674 case PM_SUBTRACTION_MODE_2: 675 675 status = calculateMatrixVector(stamp->matrix, stamp->vector, stamp->image1, stamp->image2, 676 676 weight, window, stamp->convolutions2, kernels, 677 polyValues, footprint, mode);677 polyValues, footprint, mode); 678 678 break; 679 679 case PM_SUBTRACTION_MODE_DUAL: … … 736 736 } 737 737 738 if ((stamp->x <= 0.0) && (stamp->y <= 0.0)) {739 psAbort ("bad stamp");740 }741 if (!isfinite(stamp->x) && !isfinite(stamp->y)) {742 psAbort ("bad stamp");743 }738 if ((stamp->x <= 0.0) && (stamp->y <= 0.0)) { 739 psAbort ("bad stamp"); 740 } 741 if (!isfinite(stamp->x) && !isfinite(stamp->y)) { 742 psAbort ("bad stamp"); 743 } 744 744 745 745 if (pmSubtractionThreaded()) { … … 796 796 double p_pmSubSolve_ChiSquare (pmSubtractionKernels *kernels, const pmSubtractionStampList *stamps); 797 797 798 bool pmSubtractionSolveEquation(pmSubtractionKernels *kernels, 799 const pmSubtractionStampList *stamps, 800 const pmSubtractionEquationCalculationMode mode)798 bool pmSubtractionSolveEquation(pmSubtractionKernels *kernels, 799 const pmSubtractionStampList *stamps, 800 const pmSubtractionEquationCalculationMode mode) 801 801 { 802 802 PM_ASSERT_SUBTRACTION_KERNELS_NON_NULL(kernels, false); … … 913 913 # define SVD_TOL 0.0 914 914 915 psVector *solution = NULL;916 psVector *solutionErr = NULL;915 psVector *solution = NULL; 916 psVector *solutionErr = NULL; 917 917 918 918 #ifdef TESTING 919 psFitsWriteImageSimple("A.fits", sumMatrix, NULL);920 psVectorWriteFile ("B.dat", sumVector);921 #endif 922 923 // Use SVD to determine the kernel coeffs (and validate)924 if (SVD_ANALYSIS) {925 926 // We have sumVector and sumMatrix. we are trying to solve the following equation:927 // sumMatrix * x = sumVector.928 929 // we can use any standard matrix inversion to solve this. However, the basis930 // functions in general have substantial correlation, so that the solution may be931 // somewhat poorly determined or unstable. If not numerically ill-conditioned, the932 // system of equations may be statistically ill-conditioned. Noise in the image933 // will drive insignificant, but correlated, terms in the solution. To avoid these934 // problems, we can use SVD to identify numerically unconstrained values and to935 // avoid statistically badly determined value.936 937 // A = sumMatrix, B = sumVector938 // SVD: A = U w V^T -> A^{-1} = V (1/w) U^T939 // x = V (1/w) (U^T B)940 // \sigma_x = sqrt(diag(A^{-1}))941 // solve for x and A^{-1} to get x & dx942 // identify the elements of (1/w) that are nan (1/0.0) -> set to 0.0943 // identify the elements of x that are insignificant (x / dx < 1.0? < 0.5?) -> set to 0.0944 945 // If I use the SVD trick to re-condition the matrix, I need to break out the946 // kernel and normalization terms from the background term.947 // XXX is this true? or was this due to an error in the analysis?948 949 int bgIndex = PM_SUBTRACTION_INDEX_BG(kernels); // Index in matrix for background950 951 // now pull out the kernel elements into their own square matrix952 psImage *kernelMatrix = psImageAlloc (sumMatrix->numCols - 1, sumMatrix->numRows - 1, PS_TYPE_F64);953 psVector *kernelVector = psVectorAlloc (sumMatrix->numCols - 1, PS_TYPE_F64);954 955 for (int ix = 0, kx = 0; ix < sumMatrix->numCols; ix++) {956 if (ix == bgIndex) continue;957 for (int iy = 0, ky = 0; iy < sumMatrix->numRows; iy++) {958 if (iy == bgIndex) continue;959 kernelMatrix->data.F64[ky][kx] = sumMatrix->data.F64[iy][ix];960 ky++;961 }962 kernelVector->data.F64[kx] = sumVector->data.F64[ix];963 kx++;964 }965 966 psImage *U = NULL;967 psImage *V = NULL;968 psVector *w = NULL;969 if (!psMatrixSVD (&U, &w, &V, kernelMatrix)) {970 psError(PS_ERR_UNKNOWN, false, "failed to perform SVD on sumMatrix\n");971 return NULL;972 }973 974 // calculate A_inverse:975 // Ainv = V * w * U^T976 psImage *wUt = p_pmSubSolve_wUt (w, U);977 psImage *Ainv = p_pmSubSolve_VwUt (V, wUt);978 psImage *Xvar = NULL;979 psFree (wUt);919 psFitsWriteImageSimple("A.fits", sumMatrix, NULL); 920 psVectorWriteFile ("B.dat", sumVector); 921 #endif 922 923 // Use SVD to determine the kernel coeffs (and validate) 924 if (SVD_ANALYSIS) { 925 926 // We have sumVector and sumMatrix. we are trying to solve the following equation: 927 // sumMatrix * x = sumVector. 928 929 // we can use any standard matrix inversion to solve this. However, the basis 930 // functions in general have substantial correlation, so that the solution may be 931 // somewhat poorly determined or unstable. If not numerically ill-conditioned, the 932 // system of equations may be statistically ill-conditioned. Noise in the image 933 // will drive insignificant, but correlated, terms in the solution. To avoid these 934 // problems, we can use SVD to identify numerically unconstrained values and to 935 // avoid statistically badly determined value. 936 937 // A = sumMatrix, B = sumVector 938 // SVD: A = U w V^T -> A^{-1} = V (1/w) U^T 939 // x = V (1/w) (U^T B) 940 // \sigma_x = sqrt(diag(A^{-1})) 941 // solve for x and A^{-1} to get x & dx 942 // identify the elements of (1/w) that are nan (1/0.0) -> set to 0.0 943 // identify the elements of x that are insignificant (x / dx < 1.0? < 0.5?) -> set to 0.0 944 945 // If I use the SVD trick to re-condition the matrix, I need to break out the 946 // kernel and normalization terms from the background term. 947 // XXX is this true? or was this due to an error in the analysis? 948 949 int bgIndex = PM_SUBTRACTION_INDEX_BG(kernels); // Index in matrix for background 950 951 // now pull out the kernel elements into their own square matrix 952 psImage *kernelMatrix = psImageAlloc (sumMatrix->numCols - 1, sumMatrix->numRows - 1, PS_TYPE_F64); 953 psVector *kernelVector = psVectorAlloc (sumMatrix->numCols - 1, PS_TYPE_F64); 954 955 for (int ix = 0, kx = 0; ix < sumMatrix->numCols; ix++) { 956 if (ix == bgIndex) continue; 957 for (int iy = 0, ky = 0; iy < sumMatrix->numRows; iy++) { 958 if (iy == bgIndex) continue; 959 kernelMatrix->data.F64[ky][kx] = sumMatrix->data.F64[iy][ix]; 960 ky++; 961 } 962 kernelVector->data.F64[kx] = sumVector->data.F64[ix]; 963 kx++; 964 } 965 966 psImage *U = NULL; 967 psImage *V = NULL; 968 psVector *w = NULL; 969 if (!psMatrixSVD (&U, &w, &V, kernelMatrix)) { 970 psError(PS_ERR_UNKNOWN, false, "failed to perform SVD on sumMatrix\n"); 971 return NULL; 972 } 973 974 // calculate A_inverse: 975 // Ainv = V * w * U^T 976 psImage *wUt = p_pmSubSolve_wUt (w, U); 977 psImage *Ainv = p_pmSubSolve_VwUt (V, wUt); 978 psImage *Xvar = NULL; 979 psFree (wUt); 980 980 981 981 # ifdef TESTING 982 // kernel terms:983 for (int i = 0; i < w->n; i++) {984 fprintf (stderr, "w: %f\n", w->data.F64[i]);985 }982 // kernel terms: 983 for (int i = 0; i < w->n; i++) { 984 fprintf (stderr, "w: %f\n", w->data.F64[i]); 985 } 986 986 # endif 987 // loop over w adding in more and more of the values until chisquare is no longer988 // dropping significantly.989 // XXX this does not seem to work very well: we seem to need all terms even for990 // simple cases...991 992 psVector *Xsvd = NULL;993 { 994 psVector *Ax = NULL;995 psVector *UtB = NULL;996 psVector *wUtB = NULL;997 998 psVector *wApply = psVectorAlloc(w->n, PS_TYPE_F64);999 psVector *wMask = psVectorAlloc(w->n, PS_TYPE_U8);1000 psVectorInit (wMask, 1); // start by masking everything1001 1002 double chiSquareLast = NAN;1003 int maxWeight = 0;1004 1005 double Axx, Bx, y2;1006 1007 // XXX this is an attempt to exclude insignificant modes.1008 // it was not successful with the ISIS kernel set: removing even 1009 // the least significant mode leaves additional ringing / noise1010 // because the terms are so coupled.1011 for (int k = 0; false && (k < w->n); k++) {1012 1013 // unmask the k-th weight1014 wMask->data.U8[k] = 0;1015 p_pmSubSolve_SetWeights(wApply, w, wMask);1016 1017 // solve for x:1018 // x = V * w * (U^T * B)1019 p_pmSubSolve_UtB (&UtB, U, kernelVector);1020 p_pmSubSolve_wUtB (&wUtB, wApply, UtB);1021 p_pmSubSolve_VwUtB (&Xsvd, V, wUtB);1022 1023 // chi-square for this system of equations:1024 // chi-square = sum over terms of: (Ax - B)*x - b*x - y^21025 // y^2 = \sum_stamps \sum_pixels input->kernel[y][x]^21026 p_pmSubSolve_Ax (&Ax, kernelMatrix, Xsvd);1027 p_pmSubSolve_VdV (&Axx, Ax, Xsvd);1028 p_pmSubSolve_VdV (&Bx, kernelVector, Xsvd);1029 p_pmSubSolve_y2 (&y2, kernels, stamps);1030 1031 // apparently, this works (compare with the brute force value below1032 double chiSquare = Axx - 2.0*Bx + y2;1033 double deltaChi = (k == 0) ? chiSquare : chiSquareLast - chiSquare;1034 chiSquareLast = chiSquare;1035 1036 // fprintf (stderr, "chi square = %f, delta: %f\n", chiSquare, deltaChi);1037 if (k && !maxWeight && (deltaChi < 1.0)) {1038 maxWeight = k;1039 }1040 }1041 1042 // keep all terms or we get extra ringing1043 maxWeight = w->n;1044 psVectorInit (wMask, 1);1045 for (int k = 0; k < maxWeight; k++) {1046 wMask->data.U8[k] = 0;1047 }1048 p_pmSubSolve_SetWeights(wApply, w, wMask);1049 1050 // solve for x:1051 // x = V * w * (U^T * B)1052 p_pmSubSolve_UtB (&UtB, U, kernelVector);1053 p_pmSubSolve_wUtB (&wUtB, wApply, UtB);1054 p_pmSubSolve_VwUtB (&Xsvd, V, wUtB);1055 1056 // chi-square for this system of equations:1057 // chi-square = sum over terms of: (Ax - B)*x - b*x - y^21058 // y^2 = \sum_stamps \sum_pixels input->kernel[y][x]^21059 p_pmSubSolve_Ax (&Ax, kernelMatrix, Xsvd);1060 p_pmSubSolve_VdV (&Axx, Ax, Xsvd);1061 p_pmSubSolve_VdV (&Bx, kernelVector, Xsvd);1062 p_pmSubSolve_y2 (&y2, kernels, stamps);1063 1064 // apparently, this works (compare with the brute force value below1065 double chiSquare = Axx - 2.0*Bx + y2;1066 psLogMsg ("psModules.imcombine", PS_LOG_INFO, "model kernel with %d terms; chi square = %f\n", maxWeight, chiSquare);1067 1068 // re-calculate A^{-1} to get new variances:1069 // Ainv = V * w * U^T1070 // XXX since we keep all terms, this is identical to Ainv1071 psImage *wUt = p_pmSubSolve_wUt (wApply, U);1072 Xvar = p_pmSubSolve_VwUt (V, wUt);1073 psFree (wUt);1074 1075 psFree (Ax);1076 psFree (UtB);1077 psFree (wUtB);1078 psFree (wApply);1079 psFree (wMask);1080 }1081 1082 // copy the kernel solutions to the full solution vector:1083 solution = psVectorAlloc(sumVector->n, PS_TYPE_F64);1084 solutionErr = psVectorAlloc(sumVector->n, PS_TYPE_F64);1085 1086 for (int ix = 0, kx = 0; ix < sumVector->n; ix++) {1087 if (ix == bgIndex) {1088 solution->data.F64[ix] = 0;1089 solutionErr->data.F64[ix] = 0.001;1090 continue;1091 }1092 solutionErr->data.F64[ix] = sqrt(Ainv->data.F64[kx][kx]);1093 solution->data.F64[ix] = Xsvd->data.F64[kx];1094 kx++;1095 }1096 1097 psFree (kernelMatrix);1098 psFree (kernelVector);1099 1100 psFree (U);1101 psFree (V);1102 psFree (w);1103 1104 psFree (Ainv);1105 psFree (Xsvd);1106 } else {1107 psVector *permutation = NULL; // Permutation vector, required for LU decomposition1108 psImage *luMatrix = psMatrixLUDecomposition(NULL, &permutation, sumMatrix);1109 if (!luMatrix) {1110 psError(PS_ERR_UNKNOWN, true, "LU Decomposition of least-squares matrix failed.\n");1111 psFree(solution);1112 psFree(sumVector);1113 psFree(sumMatrix);1114 psFree(luMatrix);1115 psFree(permutation);1116 return NULL;1117 }1118 1119 solution = psMatrixLUSolution(NULL, luMatrix, sumVector, permutation);1120 psFree(luMatrix);1121 psFree(permutation);1122 if (!solution) {1123 psError(PS_ERR_UNKNOWN, true, "Failed to solve the least-squares system.\n");1124 psFree(solution);1125 psFree(sumVector);1126 psFree(sumMatrix);1127 return NULL;1128 }1129 1130 // XXX LUD does not provide A^{-1}? fake the error for now 1131 solutionErr = psVectorAlloc(sumVector->n, PS_TYPE_F64);1132 for (int ix = 0; ix < sumVector->n; ix++) {1133 solutionErr->data.F64[ix] = 0.1*solution->data.F64[ix];1134 }1135 }1136 1137 if (!kernels->solution1) {1138 kernels->solution1 = psVectorAlloc (sumVector->n, PS_TYPE_F64);1139 psVectorInit (kernels->solution1, 0.0);1140 }1141 1142 // only update the solutions that we chose to calculate:1143 if (mode & PM_SUBTRACTION_EQUATION_NORM) {1144 int normIndex = PM_SUBTRACTION_INDEX_NORM(kernels); // Index for normalisation1145 kernels->solution1->data.F64[normIndex] = solution->data.F64[normIndex];1146 }1147 if (mode & PM_SUBTRACTION_EQUATION_BG) {1148 int bgIndex = PM_SUBTRACTION_INDEX_BG(kernels); // Index in matrix for background1149 kernels->solution1->data.F64[bgIndex] = solution->data.F64[bgIndex];1150 }1151 if (mode & PM_SUBTRACTION_EQUATION_KERNELS) {1152 int numKernels = kernels->num;1153 int spatialOrder = kernels->spatialOrder; // Order of spatial variation1154 int numPoly = PM_SUBTRACTION_POLYTERMS(spatialOrder); // Number of polynomial terms1155 for (int i = 0; i < numKernels * numPoly; i++) {1156 // XXX fprintf (stderr, "%f +/- %f (%f) -> ", solution->data.F64[i], solutionErr->data.F64[i], fabs(solution->data.F64[i]/solutionErr->data.F64[i]));1157 if (fabs(solution->data.F64[i] / solutionErr->data.F64[i]) < COEFF_SIG) {1158 // XXX fprintf (stderr, "drop\n");1159 kernels->solution1->data.F64[i] = 0.0;1160 } else {1161 // XXX fprintf (stderr, "keep\n");1162 kernels->solution1->data.F64[i] = solution->data.F64[i];1163 }1164 }1165 }1166 // double chiSquare = p_pmSubSolve_ChiSquare (kernels, stamps);1167 // fprintf (stderr, "chi square Brute = %f\n", chiSquare);1168 1169 psFree(solution);1170 psFree(sumVector);1171 psFree(sumMatrix);987 // loop over w adding in more and more of the values until chisquare is no longer 988 // dropping significantly. 989 // XXX this does not seem to work very well: we seem to need all terms even for 990 // simple cases... 991 992 psVector *Xsvd = NULL; 993 { 994 psVector *Ax = NULL; 995 psVector *UtB = NULL; 996 psVector *wUtB = NULL; 997 998 psVector *wApply = psVectorAlloc(w->n, PS_TYPE_F64); 999 psVector *wMask = psVectorAlloc(w->n, PS_TYPE_U8); 1000 psVectorInit (wMask, 1); // start by masking everything 1001 1002 double chiSquareLast = NAN; 1003 int maxWeight = 0; 1004 1005 double Axx, Bx, y2; 1006 1007 // XXX this is an attempt to exclude insignificant modes. 1008 // it was not successful with the ISIS kernel set: removing even 1009 // the least significant mode leaves additional ringing / noise 1010 // because the terms are so coupled. 1011 for (int k = 0; false && (k < w->n); k++) { 1012 1013 // unmask the k-th weight 1014 wMask->data.U8[k] = 0; 1015 p_pmSubSolve_SetWeights(wApply, w, wMask); 1016 1017 // solve for x: 1018 // x = V * w * (U^T * B) 1019 p_pmSubSolve_UtB (&UtB, U, kernelVector); 1020 p_pmSubSolve_wUtB (&wUtB, wApply, UtB); 1021 p_pmSubSolve_VwUtB (&Xsvd, V, wUtB); 1022 1023 // chi-square for this system of equations: 1024 // chi-square = sum over terms of: (Ax - B)*x - b*x - y^2 1025 // y^2 = \sum_stamps \sum_pixels input->kernel[y][x]^2 1026 p_pmSubSolve_Ax (&Ax, kernelMatrix, Xsvd); 1027 p_pmSubSolve_VdV (&Axx, Ax, Xsvd); 1028 p_pmSubSolve_VdV (&Bx, kernelVector, Xsvd); 1029 p_pmSubSolve_y2 (&y2, kernels, stamps); 1030 1031 // apparently, this works (compare with the brute force value below 1032 double chiSquare = Axx - 2.0*Bx + y2; 1033 double deltaChi = (k == 0) ? chiSquare : chiSquareLast - chiSquare; 1034 chiSquareLast = chiSquare; 1035 1036 // fprintf (stderr, "chi square = %f, delta: %f\n", chiSquare, deltaChi); 1037 if (k && !maxWeight && (deltaChi < 1.0)) { 1038 maxWeight = k; 1039 } 1040 } 1041 1042 // keep all terms or we get extra ringing 1043 maxWeight = w->n; 1044 psVectorInit (wMask, 1); 1045 for (int k = 0; k < maxWeight; k++) { 1046 wMask->data.U8[k] = 0; 1047 } 1048 p_pmSubSolve_SetWeights(wApply, w, wMask); 1049 1050 // solve for x: 1051 // x = V * w * (U^T * B) 1052 p_pmSubSolve_UtB (&UtB, U, kernelVector); 1053 p_pmSubSolve_wUtB (&wUtB, wApply, UtB); 1054 p_pmSubSolve_VwUtB (&Xsvd, V, wUtB); 1055 1056 // chi-square for this system of equations: 1057 // chi-square = sum over terms of: (Ax - B)*x - b*x - y^2 1058 // y^2 = \sum_stamps \sum_pixels input->kernel[y][x]^2 1059 p_pmSubSolve_Ax (&Ax, kernelMatrix, Xsvd); 1060 p_pmSubSolve_VdV (&Axx, Ax, Xsvd); 1061 p_pmSubSolve_VdV (&Bx, kernelVector, Xsvd); 1062 p_pmSubSolve_y2 (&y2, kernels, stamps); 1063 1064 // apparently, this works (compare with the brute force value below 1065 double chiSquare = Axx - 2.0*Bx + y2; 1066 psLogMsg ("psModules.imcombine", PS_LOG_INFO, "model kernel with %d terms; chi square = %f\n", maxWeight, chiSquare); 1067 1068 // re-calculate A^{-1} to get new variances: 1069 // Ainv = V * w * U^T 1070 // XXX since we keep all terms, this is identical to Ainv 1071 psImage *wUt = p_pmSubSolve_wUt (wApply, U); 1072 Xvar = p_pmSubSolve_VwUt (V, wUt); 1073 psFree (wUt); 1074 1075 psFree (Ax); 1076 psFree (UtB); 1077 psFree (wUtB); 1078 psFree (wApply); 1079 psFree (wMask); 1080 } 1081 1082 // copy the kernel solutions to the full solution vector: 1083 solution = psVectorAlloc(sumVector->n, PS_TYPE_F64); 1084 solutionErr = psVectorAlloc(sumVector->n, PS_TYPE_F64); 1085 1086 for (int ix = 0, kx = 0; ix < sumVector->n; ix++) { 1087 if (ix == bgIndex) { 1088 solution->data.F64[ix] = 0; 1089 solutionErr->data.F64[ix] = 0.001; 1090 continue; 1091 } 1092 solutionErr->data.F64[ix] = sqrt(Ainv->data.F64[kx][kx]); 1093 solution->data.F64[ix] = Xsvd->data.F64[kx]; 1094 kx++; 1095 } 1096 1097 psFree (kernelMatrix); 1098 psFree (kernelVector); 1099 1100 psFree (U); 1101 psFree (V); 1102 psFree (w); 1103 1104 psFree (Ainv); 1105 psFree (Xsvd); 1106 } else { 1107 psVector *permutation = NULL; // Permutation vector, required for LU decomposition 1108 psImage *luMatrix = psMatrixLUDecomposition(NULL, &permutation, sumMatrix); 1109 if (!luMatrix) { 1110 psError(PS_ERR_UNKNOWN, true, "LU Decomposition of least-squares matrix failed.\n"); 1111 psFree(solution); 1112 psFree(sumVector); 1113 psFree(sumMatrix); 1114 psFree(luMatrix); 1115 psFree(permutation); 1116 return NULL; 1117 } 1118 1119 solution = psMatrixLUSolution(NULL, luMatrix, sumVector, permutation); 1120 psFree(luMatrix); 1121 psFree(permutation); 1122 if (!solution) { 1123 psError(PS_ERR_UNKNOWN, true, "Failed to solve the least-squares system.\n"); 1124 psFree(solution); 1125 psFree(sumVector); 1126 psFree(sumMatrix); 1127 return NULL; 1128 } 1129 1130 // XXX LUD does not provide A^{-1}? fake the error for now 1131 solutionErr = psVectorAlloc(sumVector->n, PS_TYPE_F64); 1132 for (int ix = 0; ix < sumVector->n; ix++) { 1133 solutionErr->data.F64[ix] = 0.1*solution->data.F64[ix]; 1134 } 1135 } 1136 1137 if (!kernels->solution1) { 1138 kernels->solution1 = psVectorAlloc (sumVector->n, PS_TYPE_F64); 1139 psVectorInit (kernels->solution1, 0.0); 1140 } 1141 1142 // only update the solutions that we chose to calculate: 1143 if (mode & PM_SUBTRACTION_EQUATION_NORM) { 1144 int normIndex = PM_SUBTRACTION_INDEX_NORM(kernels); // Index for normalisation 1145 kernels->solution1->data.F64[normIndex] = solution->data.F64[normIndex]; 1146 } 1147 if (mode & PM_SUBTRACTION_EQUATION_BG) { 1148 int bgIndex = PM_SUBTRACTION_INDEX_BG(kernels); // Index in matrix for background 1149 kernels->solution1->data.F64[bgIndex] = solution->data.F64[bgIndex]; 1150 } 1151 if (mode & PM_SUBTRACTION_EQUATION_KERNELS) { 1152 int numKernels = kernels->num; 1153 int spatialOrder = kernels->spatialOrder; // Order of spatial variation 1154 int numPoly = PM_SUBTRACTION_POLYTERMS(spatialOrder); // Number of polynomial terms 1155 for (int i = 0; i < numKernels * numPoly; i++) { 1156 // XXX fprintf (stderr, "%f +/- %f (%f) -> ", solution->data.F64[i], solutionErr->data.F64[i], fabs(solution->data.F64[i]/solutionErr->data.F64[i])); 1157 if (fabs(solution->data.F64[i] / solutionErr->data.F64[i]) < COEFF_SIG) { 1158 // XXX fprintf (stderr, "drop\n"); 1159 kernels->solution1->data.F64[i] = 0.0; 1160 } else { 1161 // XXX fprintf (stderr, "keep\n"); 1162 kernels->solution1->data.F64[i] = solution->data.F64[i]; 1163 } 1164 } 1165 } 1166 // double chiSquare = p_pmSubSolve_ChiSquare (kernels, stamps); 1167 // fprintf (stderr, "chi square Brute = %f\n", chiSquare); 1168 1169 psFree(solution); 1170 psFree(sumVector); 1171 psFree(sumMatrix); 1172 1172 1173 1173 #ifdef TESTING … … 1242 1242 sumMatrix->data.F64[index][index] = 1.0; \ 1243 1243 sumVector->data.F64[index] = 0.0; \ 1244 } \1245 }1246 1247 // Remove a kernel basis for image 1 from the equation1248 #define MASK_BASIS_1(INDEX) \1249 { \1250 for (int j = 0, index = INDEX; j < numSpatial; j++, index += numKernels) { \1251 for (int k = 0; k < numParams2; k++) { \1252 sumMatrix1->data.F64[k][index] = 0.0; \1253 sumMatrix1->data.F64[index][k] = 0.0; \1254 sumMatrixX->data.F64[k][index] = 0.0; \1255 } \1256 sumMatrix1->data.F64[bgIndex][index] = 0.0; \1257 sumMatrix1->data.F64[index][bgIndex] = 0.0; \1258 sumMatrix1->data.F64[normIndex][index] = 0.0; \1259 sumMatrix1->data.F64[index][normIndex] = 0.0; \1260 sumMatrix1->data.F64[index][index] = 1.0; \1261 sumVector1->data.F64[index] = 0.0; \1262 } \1263 }1264 1265 // Remove a kernel basis for image 2 from the equation1266 #define MASK_BASIS_2(INDEX) \1267 { \1268 for (int j = 0, index = INDEX; j < numSpatial; j++, index += numKernels) { \1269 for (int k = 0; k < numParams2; k++) { \1270 sumMatrix2->data.F64[k][index] = 0.0; \1271 sumMatrix2->data.F64[index][k] = 0.0; \1272 sumMatrixX->data.F64[index][k] = 0.0; \1273 } \1274 sumMatrix2->data.F64[index][index] = 1.0; \1275 sumMatrixX->data.F64[index][normIndex] = 0.0; \1276 sumMatrixX->data.F64[index][bgIndex] = 0.0; \1277 sumVector2->data.F64[index] = 0.0; \1278 1244 } \ 1279 1245 } … … 1317 1283 psVectorWriteFile("sumVectorFix.dat", sumVector); 1318 1284 #endif 1319 }1285 } 1320 1286 #endif /*** kernel-masking block ***/ 1321 1287 solution = psMatrixSolveSVD(solution, sumMatrix, sumVector, NAN); 1322 1288 1323 1289 #ifdef TESTING 1324 1290 for (int i = 0; i < solution->n; i++) { 1325 1291 fprintf(stderr, "Dual solution %d: %lf\n", i, solution->data.F64[i]); 1326 1292 } 1293 #endif 1327 1294 1328 1295 psFree(sumMatrix); … … 1383 1350 pmSubtractionVisualShowFitInit (stamps); 1384 1351 1385 psVector *fSigRes = psVectorAllocEmpty(stamps->num, PS_TYPE_F32); 1386 psVector *fMinRes = psVectorAllocEmpty(stamps->num, PS_TYPE_F32); 1387 psVector *fMaxRes = psVectorAllocEmpty(stamps->num, PS_TYPE_F32); 1352 psVector *fSigRes = psVectorAllocEmpty(stamps->num, PS_TYPE_F32); 1353 psVector *fMinRes = psVectorAllocEmpty(stamps->num, PS_TYPE_F32); 1354 psVector *fMaxRes = psVectorAllocEmpty(stamps->num, PS_TYPE_F32); 1388 1355 1389 1356 for (int i = 0; i < stamps->num; i++) { 1390 pmSubtractionStamp *stamp = stamps->stamps->data[i]; // The stamp of interest1391 if (stamp->status != PM_SUBTRACTION_STAMP_USED) {1392 deviations->data.F32[i] = NAN;1393 continue;1394 }1395 1396 // Calculate coefficients of the kernel basis functions1397 polyValues = p_pmSubtractionPolynomial(polyValues, kernels->spatialOrder, stamp->xNorm, stamp->yNorm);1398 double norm = p_pmSubtractionSolutionNorm(kernels); // Normalisation1399 double background = p_pmSubtractionSolutionBackground(kernels, polyValues);// Difference in background1400 1401 // Calculate residuals1402 psKernel *weight = stamp->weight; // Weight postage stamp1403 psImageInit(residual->image, 0.0);1404 if (kernels->mode != PM_SUBTRACTION_MODE_DUAL) {1405 psKernel *target; // Target postage stamp1406 psKernel *source; // Source postage stamp1407 psArray *convolutions; // Convolution postage stamps for each kernel basis function1408 switch (kernels->mode) {1409 case PM_SUBTRACTION_MODE_1:1410 target = stamp->image2;1411 source = stamp->image1;1412 convolutions = stamp->convolutions1;1413 1414 // Having convolved image1 and changed its normalisation, we need to renormalise the residual1415 // so that it is on the scale of image1.1416 psImage *image = pmSubtractionKernelImage(kernels, stamp->xNorm, stamp->yNorm,1417 false); // Kernel image1418 if (!image) {1419 psError(PS_ERR_UNKNOWN, false, "Unable to generate image of kernel.");1420 return false;1421 }1422 double sumKernel = 0; // Sum of kernel, for normalising residual1423 int size = kernels->size; // Half-size of kernel1424 int fullSize = 2 * size + 1; // Full size of kernel1425 for (int y = 0; y < fullSize; y++) {1426 for (int x = 0; x < fullSize; x++) {1427 sumKernel += image->data.F32[y][x];1428 }1429 }1430 psFree(image);1431 devNorm = 1.0 / sumKernel / numPixels;1432 break;1433 case PM_SUBTRACTION_MODE_2:1434 target = stamp->image1;1435 source = stamp->image2;1436 convolutions = stamp->convolutions2;1437 break;1438 default:1439 psAbort("Unsupported subtraction mode: %x", kernels->mode);1440 }1441 1442 for (int j = 0; j < numKernels; j++) {1443 psKernel *convolution = convolutions->data[j]; // Convolution1444 double coefficient = p_pmSubtractionSolutionCoeff(kernels, polyValues, j,1445 false); // Coefficient1446 for (int y = - footprint; y <= footprint; y++) {1447 for (int x = - footprint; x <= footprint; x++) {1448 residual->kernel[y][x] += convolution->kernel[y][x] * coefficient;1449 }1450 }1451 }1452 1453 // XXX visualize the target, source, convolution and residual1454 pmSubtractionVisualShowFitAddStamp (target, source, residual, background, norm, i);1455 1456 for (int y = - footprint; y <= footprint; y++) {1457 for (int x = - footprint; x <= footprint; x++) {1458 residual->kernel[y][x] += background + source->kernel[y][x] * norm - target->kernel[y][x];1459 }1460 }1461 1462 // XXX measure some useful stats on the residuals1463 float sum = 0.0;1464 float peak = 0.0;1465 for (int y = - footprint; y <= footprint; y++) {1466 for (int x = - footprint; x <= footprint; x++) {1467 sum += 0.5*(target->kernel[y][x] + source->kernel[y][x] * norm);1468 peak = PS_MAX(peak, 0.5*(target->kernel[y][x] + source->kernel[y][x] * norm));1469 }1470 }1471 1472 // only count pixels with more than X% of the source flux1473 // calculate stdev(dflux)1474 float dflux1 = 0.0;1475 float dflux2 = 0.0;1476 int npix = 0;1477 1478 float dmax = 0.0;1479 float dmin = 0.0;1480 1481 for (int y = - footprint; y <= footprint; y++) {1482 for (int x = - footprint; x <= footprint; x++) {1483 float dflux = 0.5*(target->kernel[y][x] + source->kernel[y][x] * norm);1484 if (dflux < 0.02*sum) continue;1485 dflux1 += residual->kernel[y][x];1486 dflux2 += PS_SQR(residual->kernel[y][x]);1487 dmax = PS_MAX(residual->kernel[y][x], dmax);1488 dmin = PS_MIN(residual->kernel[y][x], dmin);1489 npix ++;1490 }1491 }1492 float sigma = sqrt(dflux2 / npix - PS_SQR(dflux1/npix));1493 // fprintf (stderr, "sum: %f, peak: %f, sigma: %f, fsigma: %f, fmax: %f, fmin: %f\n", sum, peak, sigma, sigma/sum, dmax/peak, dmin/peak);1494 psVectorAppend(fSigRes, sigma/sum);1495 psVectorAppend(fMaxRes, dmax/peak);1496 psVectorAppend(fMinRes, dmin/peak);1497 } else {1498 // Dual convolution1499 psArray *convolutions1 = stamp->convolutions1; // Convolutions of the first image1500 psArray *convolutions2 = stamp->convolutions2; // Convolutions of the second image1501 psKernel *image1 = stamp->image1; // The first image1502 psKernel *image2 = stamp->image2; // The second image1503 1504 for (int j = 0; j < numKernels; j++) {1505 psKernel *conv1 = convolutions1->data[j]; // Convolution of first image1506 psKernel *conv2 = convolutions2->data[j]; // Convolution of second image1507 double coeff1 = p_pmSubtractionSolutionCoeff(kernels, polyValues, j, false); // Coefficient 11508 double coeff2 = p_pmSubtractionSolutionCoeff(kernels, polyValues, j, true); // Coefficient 21509 1510 for (int y = - footprint; y <= footprint; y++) {1511 for (int x = - footprint; x <= footprint; x++) {1512 residual->kernel[y][x] += conv2->kernel[y][x] * coeff2 + conv1->kernel[y][x] * coeff1;1513 }1514 }1515 }1516 1517 // XXX visualize the target, source, convolution and residual1518 pmSubtractionVisualShowFitAddStamp (image2, image1, residual, background, norm, i);1519 1520 for (int y = - footprint; y <= footprint; y++) {1521 for (int x = - footprint; x <= footprint; x++) {1522 residual->kernel[y][x] += background + image1->kernel[y][x] * norm - image2->kernel[y][x];1523 }1524 }1525 }1526 1527 double deviation = 0.0; // Sum of differences1528 for (int y = - footprint; y <= footprint; y++) {1529 for (int x = - footprint; x <= footprint; x++) {1530 double dev = PS_SQR(residual->kernel[y][x]) * weight->kernel[y][x];1531 deviation += dev;1357 pmSubtractionStamp *stamp = stamps->stamps->data[i]; // The stamp of interest 1358 if (stamp->status != PM_SUBTRACTION_STAMP_USED) { 1359 deviations->data.F32[i] = NAN; 1360 continue; 1361 } 1362 1363 // Calculate coefficients of the kernel basis functions 1364 polyValues = p_pmSubtractionPolynomial(polyValues, kernels->spatialOrder, stamp->xNorm, stamp->yNorm); 1365 double norm = p_pmSubtractionSolutionNorm(kernels); // Normalisation 1366 double background = p_pmSubtractionSolutionBackground(kernels, polyValues);// Difference in background 1367 1368 // Calculate residuals 1369 psKernel *weight = stamp->weight; // Weight postage stamp 1370 psImageInit(residual->image, 0.0); 1371 if (kernels->mode != PM_SUBTRACTION_MODE_DUAL) { 1372 psKernel *target; // Target postage stamp 1373 psKernel *source; // Source postage stamp 1374 psArray *convolutions; // Convolution postage stamps for each kernel basis function 1375 switch (kernels->mode) { 1376 case PM_SUBTRACTION_MODE_1: 1377 target = stamp->image2; 1378 source = stamp->image1; 1379 convolutions = stamp->convolutions1; 1380 1381 // Having convolved image1 and changed its normalisation, we need to renormalise the residual 1382 // so that it is on the scale of image1. 1383 psImage *image = pmSubtractionKernelImage(kernels, stamp->xNorm, stamp->yNorm, 1384 false); // Kernel image 1385 if (!image) { 1386 psError(PS_ERR_UNKNOWN, false, "Unable to generate image of kernel."); 1387 return false; 1388 } 1389 double sumKernel = 0; // Sum of kernel, for normalising residual 1390 int size = kernels->size; // Half-size of kernel 1391 int fullSize = 2 * size + 1; // Full size of kernel 1392 for (int y = 0; y < fullSize; y++) { 1393 for (int x = 0; x < fullSize; x++) { 1394 sumKernel += image->data.F32[y][x]; 1395 } 1396 } 1397 psFree(image); 1398 devNorm = 1.0 / sumKernel / numPixels; 1399 break; 1400 case PM_SUBTRACTION_MODE_2: 1401 target = stamp->image1; 1402 source = stamp->image2; 1403 convolutions = stamp->convolutions2; 1404 break; 1405 default: 1406 psAbort("Unsupported subtraction mode: %x", kernels->mode); 1407 } 1408 1409 for (int j = 0; j < numKernels; j++) { 1410 psKernel *convolution = convolutions->data[j]; // Convolution 1411 double coefficient = p_pmSubtractionSolutionCoeff(kernels, polyValues, j, 1412 false); // Coefficient 1413 for (int y = - footprint; y <= footprint; y++) { 1414 for (int x = - footprint; x <= footprint; x++) { 1415 residual->kernel[y][x] += convolution->kernel[y][x] * coefficient; 1416 } 1417 } 1418 } 1419 1420 // XXX visualize the target, source, convolution and residual 1421 pmSubtractionVisualShowFitAddStamp (target, source, residual, background, norm, i); 1422 1423 for (int y = - footprint; y <= footprint; y++) { 1424 for (int x = - footprint; x <= footprint; x++) { 1425 residual->kernel[y][x] += background + source->kernel[y][x] * norm - target->kernel[y][x]; 1426 } 1427 } 1428 1429 // XXX measure some useful stats on the residuals 1430 float sum = 0.0; 1431 float peak = 0.0; 1432 for (int y = - footprint; y <= footprint; y++) { 1433 for (int x = - footprint; x <= footprint; x++) { 1434 sum += 0.5*(target->kernel[y][x] + source->kernel[y][x] * norm); 1435 peak = PS_MAX(peak, 0.5*(target->kernel[y][x] + source->kernel[y][x] * norm)); 1436 } 1437 } 1438 1439 // only count pixels with more than X% of the source flux 1440 // calculate stdev(dflux) 1441 float dflux1 = 0.0; 1442 float dflux2 = 0.0; 1443 int npix = 0; 1444 1445 float dmax = 0.0; 1446 float dmin = 0.0; 1447 1448 for (int y = - footprint; y <= footprint; y++) { 1449 for (int x = - footprint; x <= footprint; x++) { 1450 float dflux = 0.5*(target->kernel[y][x] + source->kernel[y][x] * norm); 1451 if (dflux < 0.02*sum) continue; 1452 dflux1 += residual->kernel[y][x]; 1453 dflux2 += PS_SQR(residual->kernel[y][x]); 1454 dmax = PS_MAX(residual->kernel[y][x], dmax); 1455 dmin = PS_MIN(residual->kernel[y][x], dmin); 1456 npix ++; 1457 } 1458 } 1459 float sigma = sqrt(dflux2 / npix - PS_SQR(dflux1/npix)); 1460 // fprintf (stderr, "sum: %f, peak: %f, sigma: %f, fsigma: %f, fmax: %f, fmin: %f\n", sum, peak, sigma, sigma/sum, dmax/peak, dmin/peak); 1461 psVectorAppend(fSigRes, sigma/sum); 1462 psVectorAppend(fMaxRes, dmax/peak); 1463 psVectorAppend(fMinRes, dmin/peak); 1464 } else { 1465 // Dual convolution 1466 psArray *convolutions1 = stamp->convolutions1; // Convolutions of the first image 1467 psArray *convolutions2 = stamp->convolutions2; // Convolutions of the second image 1468 psKernel *image1 = stamp->image1; // The first image 1469 psKernel *image2 = stamp->image2; // The second image 1470 1471 for (int j = 0; j < numKernels; j++) { 1472 psKernel *conv1 = convolutions1->data[j]; // Convolution of first image 1473 psKernel *conv2 = convolutions2->data[j]; // Convolution of second image 1474 double coeff1 = p_pmSubtractionSolutionCoeff(kernels, polyValues, j, false); // Coefficient 1 1475 double coeff2 = p_pmSubtractionSolutionCoeff(kernels, polyValues, j, true); // Coefficient 2 1476 1477 for (int y = - footprint; y <= footprint; y++) { 1478 for (int x = - footprint; x <= footprint; x++) { 1479 residual->kernel[y][x] += conv2->kernel[y][x] * coeff2 + conv1->kernel[y][x] * coeff1; 1480 } 1481 } 1482 } 1483 1484 // XXX visualize the target, source, convolution and residual 1485 pmSubtractionVisualShowFitAddStamp (image2, image1, residual, background, norm, i); 1486 1487 for (int y = - footprint; y <= footprint; y++) { 1488 for (int x = - footprint; x <= footprint; x++) { 1489 residual->kernel[y][x] += background + image1->kernel[y][x] * norm - image2->kernel[y][x]; 1490 } 1491 } 1492 } 1493 1494 double deviation = 0.0; // Sum of differences 1495 for (int y = - footprint; y <= footprint; y++) { 1496 for (int x = - footprint; x <= footprint; x++) { 1497 double dev = PS_SQR(residual->kernel[y][x]) * weight->kernel[y][x]; 1498 deviation += dev; 1532 1499 #ifdef TESTING 1533 residual->kernel[y][x] = dev;1534 #endif 1535 }1536 }1537 deviations->data.F32[i] = devNorm * deviation;1538 psTrace("psModules.imcombine", 5, "Deviation for stamp %d (%d,%d): %f\n",1539 i, (int)(stamp->x + 0.5), (int)(stamp->y + 0.5), deviations->data.F32[i]);1540 if (!isfinite(deviations->data.F32[i])) {1541 stamp->status = PM_SUBTRACTION_STAMP_REJECTED;1542 psTrace("psModules.imcombine", 5,1543 "Rejecting stamp %d (%d,%d) because of non-finite deviation\n",1544 i, (int)(stamp->x + 0.5), (int)(stamp->y + 0.5));1545 continue;1546 }1500 residual->kernel[y][x] = dev; 1501 #endif 1502 } 1503 } 1504 deviations->data.F32[i] = devNorm * deviation; 1505 psTrace("psModules.imcombine", 5, "Deviation for stamp %d (%d,%d): %f\n", 1506 i, (int)(stamp->x + 0.5), (int)(stamp->y + 0.5), deviations->data.F32[i]); 1507 if (!isfinite(deviations->data.F32[i])) { 1508 stamp->status = PM_SUBTRACTION_STAMP_REJECTED; 1509 psTrace("psModules.imcombine", 5, 1510 "Rejecting stamp %d (%d,%d) because of non-finite deviation\n", 1511 i, (int)(stamp->x + 0.5), (int)(stamp->y + 0.5)); 1512 continue; 1513 } 1547 1514 1548 1515 #ifdef TESTING 1549 {1550 psString filename = NULL;1551 psStringAppend(&filename, "resid_%03d.fits", i);1552 psFits *fits = psFitsOpen(filename, "w");1553 psFree(filename);1554 psFitsWriteImage(fits, NULL, residual->image, 0, NULL);1555 psFitsClose(fits);1556 }1557 if (stamp->image1) {1558 psString filename = NULL;1559 psStringAppend(&filename, "stamp_image1_%03d.fits", i);1560 psFits *fits = psFitsOpen(filename, "w");1561 psFree(filename);1562 psFitsWriteImage(fits, NULL, stamp->image1->image, 0, NULL);1563 psFitsClose(fits);1564 }1565 if (stamp->image2) {1566 psString filename = NULL;1567 psStringAppend(&filename, "stamp_image2_%03d.fits", i);1568 psFits *fits = psFitsOpen(filename, "w");1569 psFree(filename);1570 psFitsWriteImage(fits, NULL, stamp->image2->image, 0, NULL);1571 psFitsClose(fits);1572 }1573 if (stamp->weight) {1574 psString filename = NULL;1575 psStringAppend(&filename, "stamp_weight_%03d.fits", i);1576 psFits *fits = psFitsOpen(filename, "w");1577 psFree(filename);1578 psFitsWriteImage(fits, NULL, stamp->weight->image, 0, NULL);1579 psFitsClose(fits);1580 }1581 #endif 1582 1516 { 1517 psString filename = NULL; 1518 psStringAppend(&filename, "resid_%03d.fits", i); 1519 psFits *fits = psFitsOpen(filename, "w"); 1520 psFree(filename); 1521 psFitsWriteImage(fits, NULL, residual->image, 0, NULL); 1522 psFitsClose(fits); 1523 } 1524 if (stamp->image1) { 1525 psString filename = NULL; 1526 psStringAppend(&filename, "stamp_image1_%03d.fits", i); 1527 psFits *fits = psFitsOpen(filename, "w"); 1528 psFree(filename); 1529 psFitsWriteImage(fits, NULL, stamp->image1->image, 0, NULL); 1530 psFitsClose(fits); 1531 } 1532 if (stamp->image2) { 1533 psString filename = NULL; 1534 psStringAppend(&filename, "stamp_image2_%03d.fits", i); 1535 psFits *fits = psFitsOpen(filename, "w"); 1536 psFree(filename); 1537 psFitsWriteImage(fits, NULL, stamp->image2->image, 0, NULL); 1538 psFitsClose(fits); 1539 } 1540 if (stamp->weight) { 1541 psString filename = NULL; 1542 psStringAppend(&filename, "stamp_weight_%03d.fits", i); 1543 psFits *fits = psFitsOpen(filename, "w"); 1544 psFree(filename); 1545 psFitsWriteImage(fits, NULL, stamp->weight->image, 0, NULL); 1546 psFitsClose(fits); 1547 } 1548 #endif 1549 1583 1550 } 1584 1551 1585 1552 // calculate and report the normalization and background for the image center 1586 { 1587 polyValues = p_pmSubtractionPolynomial(polyValues, kernels->spatialOrder, 0.0, 0.0);1588 double norm = p_pmSubtractionSolutionNorm(kernels); // Normalisation1589 double background = p_pmSubtractionSolutionBackground(kernels, polyValues);// Difference in background1590 psLogMsg("psModules.imcombine", PS_LOG_INFO, "normalization: %f, background: %f", norm, background);1591 1592 pmSubtractionVisualShowFit(norm);1593 pmSubtractionVisualPlotFit(kernels);1594 1595 psStats *stats = psStatsAlloc(PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV);1596 psVectorStats (stats, fSigRes, NULL, NULL, 0);1597 kernels->fSigResMean = stats->robustMedian;1598 kernels->fSigResStdev = stats->robustStdev;1599 1600 psStatsInit (stats);1601 psVectorStats (stats, fMaxRes, NULL, NULL, 0);1602 kernels->fMaxResMean = stats->robustMedian;1603 kernels->fMaxResStdev = stats->robustStdev;1604 1605 psStatsInit (stats);1606 psVectorStats (stats, fMinRes, NULL, NULL, 0);1607 kernels->fMinResMean = stats->robustMedian;1608 kernels->fMinResStdev = stats->robustStdev;1609 1610 // XXX save these values somewhere1611 psLogMsg("psModules.imcombine", PS_LOG_INFO, "fSigma: %f +/- %f, fMaxRes: %f +/- %f, fMinRes: %f +/- %f", 1612 kernels->fSigResMean, kernels->fSigResStdev, 1613 kernels->fMaxResMean, kernels->fMaxResStdev, 1614 kernels->fMinResMean, kernels->fMinResStdev);1615 1616 psFree (fSigRes);1617 psFree (fMaxRes);1618 psFree (fMinRes);1619 psFree (stats);1553 { 1554 polyValues = p_pmSubtractionPolynomial(polyValues, kernels->spatialOrder, 0.0, 0.0); 1555 double norm = p_pmSubtractionSolutionNorm(kernels); // Normalisation 1556 double background = p_pmSubtractionSolutionBackground(kernels, polyValues);// Difference in background 1557 psLogMsg("psModules.imcombine", PS_LOG_INFO, "normalization: %f, background: %f", norm, background); 1558 1559 pmSubtractionVisualShowFit(norm); 1560 pmSubtractionVisualPlotFit(kernels); 1561 1562 psStats *stats = psStatsAlloc(PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV); 1563 psVectorStats (stats, fSigRes, NULL, NULL, 0); 1564 kernels->fSigResMean = stats->robustMedian; 1565 kernels->fSigResStdev = stats->robustStdev; 1566 1567 psStatsInit (stats); 1568 psVectorStats (stats, fMaxRes, NULL, NULL, 0); 1569 kernels->fMaxResMean = stats->robustMedian; 1570 kernels->fMaxResStdev = stats->robustStdev; 1571 1572 psStatsInit (stats); 1573 psVectorStats (stats, fMinRes, NULL, NULL, 0); 1574 kernels->fMinResMean = stats->robustMedian; 1575 kernels->fMinResStdev = stats->robustStdev; 1576 1577 // XXX save these values somewhere 1578 psLogMsg("psModules.imcombine", PS_LOG_INFO, "fSigma: %f +/- %f, fMaxRes: %f +/- %f, fMinRes: %f +/- %f", 1579 kernels->fSigResMean, kernels->fSigResStdev, 1580 kernels->fMaxResMean, kernels->fMaxResStdev, 1581 kernels->fMinResMean, kernels->fMinResStdev); 1582 1583 psFree (fSigRes); 1584 psFree (fMaxRes); 1585 psFree (fMinRes); 1586 psFree (stats); 1620 1587 } 1621 1588 … … 1637 1604 1638 1605 for (int i = 0; i < wUt->numCols; i++) { 1639 for (int j = 0; j < wUt->numRows; j++) {1640 if (!isfinite(w->data.F64[j])) continue;1641 if (w->data.F64[j] == 0.0) continue;1642 wUt->data.F64[j][i] = U->data.F64[i][j] / w->data.F64[j];1643 }1606 for (int j = 0; j < wUt->numRows; j++) { 1607 if (!isfinite(w->data.F64[j])) continue; 1608 if (w->data.F64[j] == 0.0) continue; 1609 wUt->data.F64[j][i] = U->data.F64[i][j] / w->data.F64[j]; 1610 } 1644 1611 } 1645 1612 return wUt; … … 1654 1621 1655 1622 for (int i = 0; i < Ainv->numCols; i++) { 1656 for (int j = 0; j < Ainv->numRows; j++) {1657 double sum = 0.0;1658 for (int k = 0; k < V->numCols; k++) {1659 sum += V->data.F64[j][k] * wUt->data.F64[k][i];1660 }1661 Ainv->data.F64[j][i] = sum;1662 }1623 for (int j = 0; j < Ainv->numRows; j++) { 1624 double sum = 0.0; 1625 for (int k = 0; k < V->numCols; k++) { 1626 sum += V->data.F64[j][k] * wUt->data.F64[k][i]; 1627 } 1628 Ainv->data.F64[j][i] = sum; 1629 } 1663 1630 } 1664 1631 return Ainv; … … 1673 1640 1674 1641 for (int i = 0; i < U->numCols; i++) { 1675 double sum = 0.0;1676 for (int j = 0; j < U->numRows; j++) {1677 sum += B->data.F64[j] * U->data.F64[j][i];1678 }1679 UtB[0]->data.F64[i] = sum;1642 double sum = 0.0; 1643 for (int j = 0; j < U->numRows; j++) { 1644 sum += B->data.F64[j] * U->data.F64[j][i]; 1645 } 1646 UtB[0]->data.F64[i] = sum; 1680 1647 } 1681 1648 return true; … … 1692 1659 1693 1660 for (int i = 0; i < w->n; i++) { 1694 if (!isfinite(w->data.F64[i])) continue;1695 if (w->data.F64[i] == 0.0) continue;1696 wUtB[0]->data.F64[i] = UtB->data.F64[i] / w->data.F64[i];1661 if (!isfinite(w->data.F64[i])) continue; 1662 if (w->data.F64[i] == 0.0) continue; 1663 wUtB[0]->data.F64[i] = UtB->data.F64[i] / w->data.F64[i]; 1697 1664 } 1698 1665 return true; … … 1707 1674 1708 1675 for (int j = 0; j < V->numRows; j++) { 1709 double sum = 0.0;1710 for (int i = 0; i < V->numCols; i++) {1711 sum += V->data.F64[j][i] * wUtB->data.F64[i];1712 }1713 VwUtB[0]->data.F64[j] = sum;1676 double sum = 0.0; 1677 for (int i = 0; i < V->numCols; i++) { 1678 sum += V->data.F64[j][i] * wUtB->data.F64[i]; 1679 } 1680 VwUtB[0]->data.F64[j] = sum; 1714 1681 } 1715 1682 return true; … … 1724 1691 1725 1692 for (int j = 0; j < A->numRows; j++) { 1726 double sum = 0.0;1727 for (int i = 0; i < A->numCols; i++) {1728 sum += A->data.F64[j][i] * x->data.F64[i];1729 }1730 B[0]->data.F64[j] = sum;1693 double sum = 0.0; 1694 for (int i = 0; i < A->numCols; i++) { 1695 sum += A->data.F64[j][i] * x->data.F64[i]; 1696 } 1697 B[0]->data.F64[j] = sum; 1731 1698 } 1732 1699 return true; … … 1740 1707 double sum = 0.0; 1741 1708 for (int i = 0; i < x->n; i++) { 1742 sum += x->data.F64[i] * y->data.F64[i];1709 sum += x->data.F64[i] * y->data.F64[i]; 1743 1710 } 1744 1711 *value = sum; … … 1753 1720 for (int i = 0; i < stamps->num; i++) { 1754 1721 1755 pmSubtractionStamp *stamp = stamps->stamps->data[i];1756 if (stamp->status != PM_SUBTRACTION_STAMP_USED) continue;1757 1758 psKernel *weight = NULL;1759 psKernel *window = NULL;1760 psKernel *input = NULL;1722 pmSubtractionStamp *stamp = stamps->stamps->data[i]; 1723 if (stamp->status != PM_SUBTRACTION_STAMP_USED) continue; 1724 1725 psKernel *weight = NULL; 1726 psKernel *window = NULL; 1727 psKernel *input = NULL; 1761 1728 1762 1729 #ifdef USE_WEIGHT 1763 weight = stamp->weight;1730 weight = stamp->weight; 1764 1731 #endif 1765 1732 #ifdef USE_WINDOW 1766 window = stamps->window;1767 #endif 1768 1769 switch (kernels->mode) {1770 // MODE_1 : convolve image 1 to match image 2 (and vice versa)1771 case PM_SUBTRACTION_MODE_1:1772 input = stamp->image2;1773 break;1774 case PM_SUBTRACTION_MODE_2:1775 input = stamp->image1;1776 break;1777 default:1778 psAbort ("programming error");1779 }1780 1781 for (int y = - footprint; y <= footprint; y++) {1782 for (int x = - footprint; x <= footprint; x++) {1783 double in = input->kernel[y][x];1784 double value = in*in;1785 if (weight) {1786 float wtVal = weight->kernel[y][x];1787 value *= wtVal;1788 }1789 if (window) {1790 float winVal = window->kernel[y][x];1791 value *= winVal;1792 }1793 sum += value;1794 }1795 }1733 window = stamps->window; 1734 #endif 1735 1736 switch (kernels->mode) { 1737 // MODE_1 : convolve image 1 to match image 2 (and vice versa) 1738 case PM_SUBTRACTION_MODE_1: 1739 input = stamp->image2; 1740 break; 1741 case PM_SUBTRACTION_MODE_2: 1742 input = stamp->image1; 1743 break; 1744 default: 1745 psAbort ("programming error"); 1746 } 1747 1748 for (int y = - footprint; y <= footprint; y++) { 1749 for (int x = - footprint; x <= footprint; x++) { 1750 double in = input->kernel[y][x]; 1751 double value = in*in; 1752 if (weight) { 1753 float wtVal = weight->kernel[y][x]; 1754 value *= wtVal; 1755 } 1756 if (window) { 1757 float winVal = window->kernel[y][x]; 1758 value *= winVal; 1759 } 1760 sum += value; 1761 } 1762 } 1796 1763 } 1797 1764 *y2 = sum; … … 1813 1780 for (int i = 0; i < stamps->num; i++) { 1814 1781 1815 pmSubtractionStamp *stamp = stamps->stamps->data[i];1816 if (stamp->status != PM_SUBTRACTION_STAMP_USED) continue;1817 1818 psKernel *weight = NULL;1819 psKernel *window = NULL;1820 psKernel *target = NULL;1821 psKernel *source = NULL;1822 1823 psArray *convolutions = NULL;1782 pmSubtractionStamp *stamp = stamps->stamps->data[i]; 1783 if (stamp->status != PM_SUBTRACTION_STAMP_USED) continue; 1784 1785 psKernel *weight = NULL; 1786 psKernel *window = NULL; 1787 psKernel *target = NULL; 1788 psKernel *source = NULL; 1789 1790 psArray *convolutions = NULL; 1824 1791 1825 1792 #ifdef USE_WEIGHT 1826 weight = stamp->weight;1793 weight = stamp->weight; 1827 1794 #endif 1828 1795 #ifdef USE_WINDOW 1829 window = stamps->window;1830 #endif 1831 1832 switch (kernels->mode) {1833 // MODE_1 : convolve image 1 to match image 2 (and vice versa)1834 case PM_SUBTRACTION_MODE_1:1835 target = stamp->image2;1836 source = stamp->image1;1837 convolutions = stamp->convolutions1;1838 break;1839 case PM_SUBTRACTION_MODE_2:1840 target = stamp->image1;1841 source = stamp->image2;1842 convolutions = stamp->convolutions2;1843 break;1844 default:1845 psAbort ("programming error");1846 }1847 1848 // Calculate coefficients of the kernel basis functions1849 polyValues = p_pmSubtractionPolynomial(polyValues, kernels->spatialOrder, stamp->xNorm, stamp->yNorm);1850 double norm = p_pmSubtractionSolutionNorm(kernels); // Normalisation1851 double background = p_pmSubtractionSolutionBackground(kernels, polyValues);// Difference in background1852 1853 psImageInit(residual->image, 0.0);1854 for (int j = 0; j < numKernels; j++) {1855 psKernel *convolution = convolutions->data[j]; // Convolution1856 double coefficient = p_pmSubtractionSolutionCoeff(kernels, polyValues, j, false); // Coefficient1857 for (int y = - footprint; y <= footprint; y++) {1858 for (int x = - footprint; x <= footprint; x++) {1859 residual->kernel[y][x] -= convolution->kernel[y][x] * coefficient;1860 }1861 }1862 }1863 1864 for (int y = - footprint; y <= footprint; y++) {1865 for (int x = - footprint; x <= footprint; x++) {1866 double resid = target->kernel[y][x] - background - source->kernel[y][x] * norm + residual->kernel[y][x];1867 double value = PS_SQR(resid);1868 if (weight) {1869 float wtVal = weight->kernel[y][x];1870 value *= wtVal;1871 }1872 if (window) {1873 float winVal = window->kernel[y][x];1874 value *= winVal;1875 }1876 sum += value;1877 }1878 }1796 window = stamps->window; 1797 #endif 1798 1799 switch (kernels->mode) { 1800 // MODE_1 : convolve image 1 to match image 2 (and vice versa) 1801 case PM_SUBTRACTION_MODE_1: 1802 target = stamp->image2; 1803 source = stamp->image1; 1804 convolutions = stamp->convolutions1; 1805 break; 1806 case PM_SUBTRACTION_MODE_2: 1807 target = stamp->image1; 1808 source = stamp->image2; 1809 convolutions = stamp->convolutions2; 1810 break; 1811 default: 1812 psAbort ("programming error"); 1813 } 1814 1815 // Calculate coefficients of the kernel basis functions 1816 polyValues = p_pmSubtractionPolynomial(polyValues, kernels->spatialOrder, stamp->xNorm, stamp->yNorm); 1817 double norm = p_pmSubtractionSolutionNorm(kernels); // Normalisation 1818 double background = p_pmSubtractionSolutionBackground(kernels, polyValues);// Difference in background 1819 1820 psImageInit(residual->image, 0.0); 1821 for (int j = 0; j < numKernels; j++) { 1822 psKernel *convolution = convolutions->data[j]; // Convolution 1823 double coefficient = p_pmSubtractionSolutionCoeff(kernels, polyValues, j, false); // Coefficient 1824 for (int y = - footprint; y <= footprint; y++) { 1825 for (int x = - footprint; x <= footprint; x++) { 1826 residual->kernel[y][x] -= convolution->kernel[y][x] * coefficient; 1827 } 1828 } 1829 } 1830 1831 for (int y = - footprint; y <= footprint; y++) { 1832 for (int x = - footprint; x <= footprint; x++) { 1833 double resid = target->kernel[y][x] - background - source->kernel[y][x] * norm + residual->kernel[y][x]; 1834 double value = PS_SQR(resid); 1835 if (weight) { 1836 float wtVal = weight->kernel[y][x]; 1837 value *= wtVal; 1838 } 1839 if (window) { 1840 float winVal = window->kernel[y][x]; 1841 value *= winVal; 1842 } 1843 sum += value; 1844 } 1845 } 1879 1846 } 1880 1847 psFree (polyValues); … … 1887 1854 1888 1855 for (int i = 0; i < w->n; i++) { 1889 wApply->data.F64[i] = wMask->data.U8[i] ? 0.0 : w->data.F64[i];1856 wApply->data.F64[i] = wMask->data.U8[i] ? 0.0 : w->data.F64[i]; 1890 1857 } 1891 1858 return true; … … 1902 1869 // generate Vn = V * w^{-1} 1903 1870 for (int j = 0; j < Vn->numRows; j++) { 1904 for (int i = 0; i < Vn->numCols; i++) {1905 if (!isfinite(w->data.F64[i])) continue;1906 if (w->data.F64[i] == 0.0) continue;1907 Vn->data.F64[j][i] = V->data.F64[j][i] / w->data.F64[i];1908 }1871 for (int i = 0; i < Vn->numCols; i++) { 1872 if (!isfinite(w->data.F64[i])) continue; 1873 if (w->data.F64[i] == 0.0) continue; 1874 Vn->data.F64[j][i] = V->data.F64[j][i] / w->data.F64[i]; 1875 } 1909 1876 } 1910 1877 … … 1914 1881 // generate Xvar = Vn * Vn^T 1915 1882 for (int j = 0; j < Vn->numRows; j++) { 1916 for (int i = 0; i < Vn->numCols; i++) {1917 double sum = 0.0;1918 for (int k = 0; k < Vn->numCols; k++) {1919 sum += Vn->data.F64[k][i]*Vn->data.F64[k][j];1920 }1921 Xvar->data.F64[j][i] = sum;1922 }1883 for (int i = 0; i < Vn->numCols; i++) { 1884 double sum = 0.0; 1885 for (int k = 0; k < Vn->numCols; k++) { 1886 sum += Vn->data.F64[k][i]*Vn->data.F64[k][j]; 1887 } 1888 Xvar->data.F64[j][i] = sum; 1889 } 1923 1890 } 1924 1891 return Xvar; … … 1935 1902 psFitsWriteImage(fits, header, image, 0, NULL); 1936 1903 psFitsClose(fits); 1937 1904 1938 1905 return true; 1939 1906 }
Note:
See TracChangeset
for help on using the changeset viewer.
