Changeset 26576
- Timestamp:
- Jan 12, 2010, 4:30:30 PM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/eam_branches/20091201/psModules/src/imcombine/pmSubtractionEquation.c
r26562 r26576 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 } … … 494 494 return true; 495 495 } 496 #endif 497 496 # endif 498 497 499 498 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// … … 596 595 int numBackground = PM_SUBTRACTION_POLYTERMS(kernels->bgOrder); // Number of background terms 597 596 598 // 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). 599 598 // = \sum_i^N_Gaussians [(order + 1) * (order + 2) / 2], eg for 1 Gauss and 1st order, numKernels = 3 600 599 … … 671 670 status = calculateMatrixVector(stamp->matrix, stamp->vector, stamp->image2, stamp->image1, 672 671 weight, window, stamp->convolutions1, kernels, 673 polyValues, footprint, mode);672 polyValues, footprint, mode); 674 673 break; 675 674 case PM_SUBTRACTION_MODE_2: 676 675 status = calculateMatrixVector(stamp->matrix, stamp->vector, stamp->image1, stamp->image2, 677 676 weight, window, stamp->convolutions2, kernels, 678 polyValues, footprint, mode);677 polyValues, footprint, mode); 679 678 break; 680 679 case PM_SUBTRACTION_MODE_DUAL: … … 737 736 } 738 737 739 if ((stamp->x <= 0.0) && (stamp->y <= 0.0)) {740 psAbort ("bad stamp");741 }742 if (!isfinite(stamp->x) && !isfinite(stamp->y)) {743 psAbort ("bad stamp");744 }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 } 745 744 746 745 if (pmSubtractionThreaded()) { … … 797 796 double p_pmSubSolve_ChiSquare (pmSubtractionKernels *kernels, const pmSubtractionStampList *stamps); 798 797 799 bool pmSubtractionSolveEquation(pmSubtractionKernels *kernels, 800 const pmSubtractionStampList *stamps, 801 const pmSubtractionEquationCalculationMode mode)798 bool pmSubtractionSolveEquation(pmSubtractionKernels *kernels, 799 const pmSubtractionStampList *stamps, 800 const pmSubtractionEquationCalculationMode mode) 802 801 { 803 802 PM_ASSERT_SUBTRACTION_KERNELS_NON_NULL(kernels, false); … … 914 913 # define SVD_TOL 0.0 915 914 916 psVector *solution = NULL;917 psVector *solutionErr = NULL;915 psVector *solution = NULL; 916 psVector *solutionErr = NULL; 918 917 919 918 #ifdef TESTING 920 psFitsWriteImageSimple("A.fits", sumMatrix, NULL);921 psVectorWriteFile("B.dat", sumVector);922 #endif 923 924 // Use SVD to determine the kernel coeffs (and validate)925 if (SVD_ANALYSIS) {926 927 // We have sumVector and sumMatrix. we are trying to solve the following equation:928 // sumMatrix * x = sumVector.929 930 // we can use any standard matrix inversion to solve this. However, the basis931 // functions in general have substantial correlation, so that the solution may be932 // somewhat poorly determined or unstable. If not numerically ill-conditioned, the933 // system of equations may be statistically ill-conditioned. Noise in the image934 // will drive insignificant, but correlated, terms in the solution. To avoid these935 // problems, we can use SVD to identify numerically unconstrained values and to936 // avoid statistically badly determined value.937 938 // A = sumMatrix, B = sumVector939 // SVD: A = U w V^T -> A^{-1} = V (1/w) U^T940 // x = V (1/w) (U^T B)941 // \sigma_x = sqrt(diag(A^{-1}))942 // solve for x and A^{-1} to get x & dx943 // identify the elements of (1/w) that are nan (1/0.0) -> set to 0.0944 // identify the elements of x that are insignificant (x / dx < 1.0? < 0.5?) -> set to 0.0945 946 // If I use the SVD trick to re-condition the matrix, I need to break out the947 // kernel and normalization terms from the background term.948 // XXX is this true? or was this due to an error in the analysis?949 950 int bgIndex = PM_SUBTRACTION_INDEX_BG(kernels); // Index in matrix for background951 952 // now pull out the kernel elements into their own square matrix953 psImage *kernelMatrix = psImageAlloc (sumMatrix->numCols - 1, sumMatrix->numRows - 1, PS_TYPE_F64);954 psVector *kernelVector = psVectorAlloc (sumMatrix->numCols - 1, PS_TYPE_F64);955 956 for (int ix = 0, kx = 0; ix < sumMatrix->numCols; ix++) {957 if (ix == bgIndex) continue;958 for (int iy = 0, ky = 0; iy < sumMatrix->numRows; iy++) {959 if (iy == bgIndex) continue;960 kernelMatrix->data.F64[ky][kx] = sumMatrix->data.F64[iy][ix];961 ky++;962 }963 kernelVector->data.F64[kx] = sumVector->data.F64[ix];964 kx++;965 }966 967 psImage *U = NULL;968 psImage *V = NULL;969 psVector *w = NULL;970 if (!psMatrixSVD (&U, &w, &V, kernelMatrix)) {971 psError(PS_ERR_UNKNOWN, false, "failed to perform SVD on sumMatrix\n");972 return NULL;973 }974 975 // calculate A_inverse:976 // Ainv = V * w * U^T977 psImage *wUt = p_pmSubSolve_wUt (w, U);978 psImage *Ainv = p_pmSubSolve_VwUt (V, wUt);979 psImage *Xvar = NULL;980 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); 981 980 982 981 # ifdef TESTING 983 // kernel terms:984 for (int i = 0; i < w->n; i++) {985 fprintf (stderr, "w: %f\n", w->data.F64[i]);986 }982 // kernel terms: 983 for (int i = 0; i < w->n; i++) { 984 fprintf (stderr, "w: %f\n", w->data.F64[i]); 985 } 987 986 # endif 988 // loop over w adding in more and more of the values until chisquare is no longer989 // dropping significantly.990 // XXX this does not seem to work very well: we seem to need all terms even for991 // simple cases...992 993 psVector *Xsvd = NULL;994 { 995 psVector *Ax = NULL;996 psVector *UtB = NULL;997 psVector *wUtB = NULL;998 999 psVector *wApply = psVectorAlloc(w->n, PS_TYPE_F64);1000 psVector *wMask = psVectorAlloc(w->n, PS_TYPE_U8);1001 psVectorInit (wMask, 1); // start by masking everything1002 1003 double chiSquareLast = NAN;1004 int maxWeight = 0;1005 1006 double Axx, Bx, y2;1007 1008 // XXX this is an attempt to exclude insignificant modes.1009 // it was not successful with the ISIS kernel set: removing even 1010 // the least significant mode leaves additional ringing / noise1011 // because the terms are so coupled.1012 for (int k = 0; false && (k < w->n); k++) {1013 1014 // unmask the k-th weight1015 wMask->data.U8[k] = 0;1016 p_pmSubSolve_SetWeights(wApply, w, wMask);1017 1018 // solve for x:1019 // x = V * w * (U^T * B)1020 p_pmSubSolve_UtB (&UtB, U, kernelVector);1021 p_pmSubSolve_wUtB (&wUtB, wApply, UtB);1022 p_pmSubSolve_VwUtB (&Xsvd, V, wUtB);1023 1024 // chi-square for this system of equations:1025 // chi-square = sum over terms of: (Ax - B)*x - b*x - y^21026 // y^2 = \sum_stamps \sum_pixels input->kernel[y][x]^21027 p_pmSubSolve_Ax (&Ax, kernelMatrix, Xsvd);1028 p_pmSubSolve_VdV (&Axx, Ax, Xsvd);1029 p_pmSubSolve_VdV (&Bx, kernelVector, Xsvd);1030 p_pmSubSolve_y2 (&y2, kernels, stamps);1031 1032 // apparently, this works (compare with the brute force value below1033 double chiSquare = Axx - 2.0*Bx + y2;1034 double deltaChi = (k == 0) ? chiSquare : chiSquareLast - chiSquare;1035 chiSquareLast = chiSquare;1036 1037 // fprintf (stderr, "chi square = %f, delta: %f\n", chiSquare, deltaChi);1038 if (k && !maxWeight && (deltaChi < 1.0)) {1039 maxWeight = k;1040 }1041 }1042 1043 // keep all terms or we get extra ringing1044 maxWeight = w->n;1045 psVectorInit (wMask, 1);1046 for (int k = 0; k < maxWeight; k++) {1047 wMask->data.U8[k] = 0;1048 }1049 p_pmSubSolve_SetWeights(wApply, w, wMask);1050 1051 // solve for x:1052 // x = V * w * (U^T * B)1053 p_pmSubSolve_UtB (&UtB, U, kernelVector);1054 p_pmSubSolve_wUtB (&wUtB, wApply, UtB);1055 p_pmSubSolve_VwUtB (&Xsvd, V, wUtB);1056 1057 // chi-square for this system of equations:1058 // chi-square = sum over terms of: (Ax - B)*x - b*x - y^21059 // y^2 = \sum_stamps \sum_pixels input->kernel[y][x]^21060 p_pmSubSolve_Ax (&Ax, kernelMatrix, Xsvd);1061 p_pmSubSolve_VdV (&Axx, Ax, Xsvd);1062 p_pmSubSolve_VdV (&Bx, kernelVector, Xsvd);1063 p_pmSubSolve_y2 (&y2, kernels, stamps);1064 1065 // apparently, this works (compare with the brute force value below1066 double chiSquare = Axx - 2.0*Bx + y2;1067 psLogMsg ("psModules.imcombine", PS_LOG_INFO, "model kernel with %d terms; chi square = %f\n", maxWeight, chiSquare);1068 1069 // re-calculate A^{-1} to get new variances:1070 // Ainv = V * w * U^T1071 // XXX since we keep all terms, this is identical to Ainv1072 psImage *wUt = p_pmSubSolve_wUt (wApply, U);1073 Xvar = p_pmSubSolve_VwUt (V, wUt);1074 psFree (wUt);1075 1076 psFree (Ax);1077 psFree (UtB);1078 psFree (wUtB);1079 psFree (wApply);1080 psFree (wMask);1081 }1082 1083 // copy the kernel solutions to the full solution vector:1084 solution = psVectorAlloc(sumVector->n, PS_TYPE_F64);1085 solutionErr = psVectorAlloc(sumVector->n, PS_TYPE_F64);1086 1087 for (int ix = 0, kx = 0; ix < sumVector->n; ix++) {1088 if (ix == bgIndex) {1089 solution->data.F64[ix] = 0;1090 solutionErr->data.F64[ix] = 0.001;1091 continue;1092 }1093 solutionErr->data.F64[ix] = sqrt(Ainv->data.F64[kx][kx]);1094 solution->data.F64[ix] = Xsvd->data.F64[kx];1095 kx++;1096 }1097 1098 psFree (kernelMatrix);1099 psFree (kernelVector);1100 1101 psFree (U);1102 psFree (V);1103 psFree (w);1104 1105 psFree (Ainv);1106 psFree (Xsvd);1107 } else {1108 psVector *permutation = NULL; // Permutation vector, required for LU decomposition1109 psImage *luMatrix = psMatrixLUDecomposition(NULL, &permutation, sumMatrix);1110 if (!luMatrix) {1111 psError(PS_ERR_UNKNOWN, true, "LU Decomposition of least-squares matrix failed.\n");1112 psFree(solution);1113 psFree(sumVector);1114 psFree(sumMatrix);1115 psFree(luMatrix);1116 psFree(permutation);1117 return NULL;1118 }1119 1120 solution = psMatrixLUSolution(NULL, luMatrix, sumVector, permutation);1121 psFree(luMatrix);1122 psFree(permutation);1123 if (!solution) {1124 psError(PS_ERR_UNKNOWN, true, "Failed to solve the least-squares system.\n");1125 psFree(solution);1126 psFree(sumVector);1127 psFree(sumMatrix);1128 return NULL;1129 }1130 1131 // XXX LUD does not provide A^{-1}? fake the error for now 1132 solutionErr = psVectorAlloc(sumVector->n, PS_TYPE_F64);1133 for (int ix = 0; ix < sumVector->n; ix++) {1134 solutionErr->data.F64[ix] = 0.1*solution->data.F64[ix];1135 }1136 }1137 1138 if (!kernels->solution1) {1139 kernels->solution1 = psVectorAlloc (sumVector->n, PS_TYPE_F64);1140 psVectorInit (kernels->solution1, 0.0);1141 }1142 1143 // only update the solutions that we chose to calculate:1144 if (mode & PM_SUBTRACTION_EQUATION_NORM) {1145 int normIndex = PM_SUBTRACTION_INDEX_NORM(kernels); // Index for normalisation1146 kernels->solution1->data.F64[normIndex] = solution->data.F64[normIndex];1147 }1148 if (mode & PM_SUBTRACTION_EQUATION_BG) {1149 int bgIndex = PM_SUBTRACTION_INDEX_BG(kernels); // Index in matrix for background1150 kernels->solution1->data.F64[bgIndex] = solution->data.F64[bgIndex];1151 }1152 if (mode & PM_SUBTRACTION_EQUATION_KERNELS) {1153 int numKernels = kernels->num;1154 int spatialOrder = kernels->spatialOrder; // Order of spatial variation1155 int numPoly = PM_SUBTRACTION_POLYTERMS(spatialOrder); // Number of polynomial terms1156 for (int i = 0; i < numKernels * numPoly; i++) {1157 // XXX fprintf (stderr, "%f +/- %f (%f) -> ", solution->data.F64[i], solutionErr->data.F64[i], fabs(solution->data.F64[i]/solutionErr->data.F64[i]));1158 if (fabs(solution->data.F64[i] / solutionErr->data.F64[i]) < COEFF_SIG) {1159 // XXX fprintf (stderr, "drop\n");1160 kernels->solution1->data.F64[i] = 0.0;1161 } else {1162 // XXX fprintf (stderr, "keep\n");1163 kernels->solution1->data.F64[i] = solution->data.F64[i];1164 }1165 }1166 }1167 // double chiSquare = p_pmSubSolve_ChiSquare (kernels, stamps);1168 // fprintf (stderr, "chi square Brute = %f\n", chiSquare);1169 1170 psFree(solution);1171 psFree(sumVector);1172 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); 1173 1172 1174 1173 #ifdef TESTING … … 1201 1200 } 1202 1201 } 1203 1204 1202 1205 1203 #ifdef TESTING … … 1319 1317 psVectorWriteFile("sumVectorFix.dat", sumVector); 1320 1318 #endif 1321 1322 } 1323 #endif 1324 1319 } 1320 #endif 1321 } 1322 #endif 1325 1323 solution = psMatrixSolveSVD(solution, sumMatrix, sumVector, NAN); 1326 1324 … … 1369 1367 1370 1368 psVector *pmSubtractionCalculateDeviations(pmSubtractionStampList *stamps, 1371 constpmSubtractionKernels *kernels)1369 pmSubtractionKernels *kernels) 1372 1370 { 1373 1371 PM_ASSERT_SUBTRACTION_STAMP_LIST_NON_NULL(stamps, NULL); … … 1387 1385 pmSubtractionVisualShowFitInit (stamps); 1388 1386 1387 psVector *fSigRes = psVectorAllocEmpty(stamps->num, PS_TYPE_F32); 1388 psVector *fMinRes = psVectorAllocEmpty(stamps->num, PS_TYPE_F32); 1389 psVector *fMaxRes = psVectorAllocEmpty(stamps->num, PS_TYPE_F32); 1390 1389 1391 for (int i = 0; i < stamps->num; i++) { 1390 pmSubtractionStamp *stamp = stamps->stamps->data[i]; // The stamp of interest 1391 if (stamp->status != PM_SUBTRACTION_STAMP_USED) { 1392 deviations->data.F32[i] = NAN; 1393 continue; 1394 } 1395 1396 // Calculate coefficients of the kernel basis functions 1397 polyValues = p_pmSubtractionPolynomial(polyValues, kernels->spatialOrder, stamp->xNorm, stamp->yNorm); 1398 double norm = p_pmSubtractionSolutionNorm(kernels); // Normalisation 1399 double background = p_pmSubtractionSolutionBackground(kernels, polyValues);// Difference in background 1400 1401 // Calculate residuals 1402 psKernel *weight = stamp->weight; // Weight postage stamp 1403 psImageInit(residual->image, 0.0); 1404 if (kernels->mode != PM_SUBTRACTION_MODE_DUAL) { 1405 psKernel *target; // Target postage stamp 1406 psKernel *source; // Source postage stamp 1407 psArray *convolutions; // Convolution postage stamps for each kernel basis function 1408 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 residual 1415 // so that it is on the scale of image1. 1416 psImage *image = pmSubtractionKernelImage(kernels, stamp->xNorm, stamp->yNorm, 1417 false); // Kernel image 1418 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 residual 1423 int size = kernels->size; // Half-size of kernel 1424 int fullSize = 2 * size + 1; // Full size of kernel 1425 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]; // Convolution 1444 double coefficient = p_pmSubtractionSolutionCoeff(kernels, polyValues, j, 1445 false); // Coefficient 1446 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 residual 1454 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 } else { 1462 // Dual convolution 1463 psArray *convolutions1 = stamp->convolutions1; // Convolutions of the first image 1464 psArray *convolutions2 = stamp->convolutions2; // Convolutions of the second image 1465 psKernel *image1 = stamp->image1; // The first image 1466 psKernel *image2 = stamp->image2; // The second image 1467 1468 for (int j = 0; j < numKernels; j++) { 1469 psKernel *conv1 = convolutions1->data[j]; // Convolution of first image 1470 psKernel *conv2 = convolutions2->data[j]; // Convolution of second image 1471 double coeff1 = p_pmSubtractionSolutionCoeff(kernels, polyValues, j, false); // Coefficient 1 1472 double coeff2 = p_pmSubtractionSolutionCoeff(kernels, polyValues, j, true); // Coefficient 2 1473 1474 for (int y = - footprint; y <= footprint; y++) { 1475 for (int x = - footprint; x <= footprint; x++) { 1476 residual->kernel[y][x] += conv2->kernel[y][x] * coeff2 + conv1->kernel[y][x] * coeff1; 1477 } 1478 } 1479 } 1480 1481 // XXX visualize the target, source, convolution and residual 1482 pmSubtractionVisualShowFitAddStamp (image2, image1, residual, background, norm, i); 1483 1484 for (int y = - footprint; y <= footprint; y++) { 1485 for (int x = - footprint; x <= footprint; x++) { 1486 residual->kernel[y][x] += background + image1->kernel[y][x] * norm - image2->kernel[y][x]; 1487 } 1488 } 1489 } 1490 1491 double deviation = 0.0; // Sum of differences 1492 for (int y = - footprint; y <= footprint; y++) { 1493 for (int x = - footprint; x <= footprint; x++) { 1494 double dev = PS_SQR(residual->kernel[y][x]) * weight->kernel[y][x]; 1495 deviation += dev; 1392 pmSubtractionStamp *stamp = stamps->stamps->data[i]; // The stamp of interest 1393 if (stamp->status != PM_SUBTRACTION_STAMP_USED) { 1394 deviations->data.F32[i] = NAN; 1395 continue; 1396 } 1397 1398 // Calculate coefficients of the kernel basis functions 1399 polyValues = p_pmSubtractionPolynomial(polyValues, kernels->spatialOrder, stamp->xNorm, stamp->yNorm); 1400 double norm = p_pmSubtractionSolutionNorm(kernels); // Normalisation 1401 double background = p_pmSubtractionSolutionBackground(kernels, polyValues);// Difference in background 1402 1403 // Calculate residuals 1404 psKernel *weight = stamp->weight; // Weight postage stamp 1405 psImageInit(residual->image, 0.0); 1406 if (kernels->mode != PM_SUBTRACTION_MODE_DUAL) { 1407 psKernel *target; // Target postage stamp 1408 psKernel *source; // Source postage stamp 1409 psArray *convolutions; // Convolution postage stamps for each kernel basis function 1410 switch (kernels->mode) { 1411 case PM_SUBTRACTION_MODE_1: 1412 target = stamp->image2; 1413 source = stamp->image1; 1414 convolutions = stamp->convolutions1; 1415 1416 // Having convolved image1 and changed its normalisation, we need to renormalise the residual 1417 // so that it is on the scale of image1. 1418 psImage *image = pmSubtractionKernelImage(kernels, stamp->xNorm, stamp->yNorm, 1419 false); // Kernel image 1420 if (!image) { 1421 psError(PS_ERR_UNKNOWN, false, "Unable to generate image of kernel."); 1422 return false; 1423 } 1424 double sumKernel = 0; // Sum of kernel, for normalising residual 1425 int size = kernels->size; // Half-size of kernel 1426 int fullSize = 2 * size + 1; // Full size of kernel 1427 for (int y = 0; y < fullSize; y++) { 1428 for (int x = 0; x < fullSize; x++) { 1429 sumKernel += image->data.F32[y][x]; 1430 } 1431 } 1432 psFree(image); 1433 devNorm = 1.0 / sumKernel / numPixels; 1434 break; 1435 case PM_SUBTRACTION_MODE_2: 1436 target = stamp->image1; 1437 source = stamp->image2; 1438 convolutions = stamp->convolutions2; 1439 break; 1440 default: 1441 psAbort("Unsupported subtraction mode: %x", kernels->mode); 1442 } 1443 1444 for (int j = 0; j < numKernels; j++) { 1445 psKernel *convolution = convolutions->data[j]; // Convolution 1446 double coefficient = p_pmSubtractionSolutionCoeff(kernels, polyValues, j, 1447 false); // Coefficient 1448 for (int y = - footprint; y <= footprint; y++) { 1449 for (int x = - footprint; x <= footprint; x++) { 1450 residual->kernel[y][x] += convolution->kernel[y][x] * coefficient; 1451 } 1452 } 1453 } 1454 1455 // XXX visualize the target, source, convolution and residual 1456 pmSubtractionVisualShowFitAddStamp (target, source, residual, background, norm, i); 1457 1458 for (int y = - footprint; y <= footprint; y++) { 1459 for (int x = - footprint; x <= footprint; x++) { 1460 residual->kernel[y][x] += background + source->kernel[y][x] * norm - target->kernel[y][x]; 1461 } 1462 } 1463 1464 // XXX measure some useful stats on the residuals 1465 float sum = 0.0; 1466 float peak = 0.0; 1467 for (int y = - footprint; y <= footprint; y++) { 1468 for (int x = - footprint; x <= footprint; x++) { 1469 sum += 0.5*(target->kernel[y][x] + source->kernel[y][x] * norm); 1470 peak = PS_MAX(peak, 0.5*(target->kernel[y][x] + source->kernel[y][x] * norm)); 1471 } 1472 } 1473 1474 // only count pixels with more than X% of the source flux 1475 // calculate stdev(dflux) 1476 float dflux1 = 0.0; 1477 float dflux2 = 0.0; 1478 int npix = 0; 1479 1480 float dmax = 0.0; 1481 float dmin = 0.0; 1482 1483 for (int y = - footprint; y <= footprint; y++) { 1484 for (int x = - footprint; x <= footprint; x++) { 1485 float dflux = 0.5*(target->kernel[y][x] + source->kernel[y][x] * norm); 1486 if (dflux < 0.02*sum) continue; 1487 dflux1 += residual->kernel[y][x]; 1488 dflux2 += PS_SQR(residual->kernel[y][x]); 1489 dmax = PS_MAX(residual->kernel[y][x], dmax); 1490 dmin = PS_MIN(residual->kernel[y][x], dmin); 1491 npix ++; 1492 } 1493 } 1494 float sigma = sqrt(dflux2 / npix - PS_SQR(dflux1/npix)); 1495 // fprintf (stderr, "sum: %f, peak: %f, sigma: %f, fsigma: %f, fmax: %f, fmin: %f\n", sum, peak, sigma, sigma/sum, dmax/peak, dmin/peak); 1496 psVectorAppend(fSigRes, sigma/sum); 1497 psVectorAppend(fMaxRes, dmax/peak); 1498 psVectorAppend(fMinRes, dmin/peak); 1499 } else { 1500 // Dual convolution 1501 psArray *convolutions1 = stamp->convolutions1; // Convolutions of the first image 1502 psArray *convolutions2 = stamp->convolutions2; // Convolutions of the second image 1503 psKernel *image1 = stamp->image1; // The first image 1504 psKernel *image2 = stamp->image2; // The second image 1505 1506 for (int j = 0; j < numKernels; j++) { 1507 psKernel *conv1 = convolutions1->data[j]; // Convolution of first image 1508 psKernel *conv2 = convolutions2->data[j]; // Convolution of second image 1509 double coeff1 = p_pmSubtractionSolutionCoeff(kernels, polyValues, j, false); // Coefficient 1 1510 double coeff2 = p_pmSubtractionSolutionCoeff(kernels, polyValues, j, true); // Coefficient 2 1511 1512 for (int y = - footprint; y <= footprint; y++) { 1513 for (int x = - footprint; x <= footprint; x++) { 1514 residual->kernel[y][x] += conv2->kernel[y][x] * coeff2 + conv1->kernel[y][x] * coeff1; 1515 } 1516 } 1517 } 1518 1519 // XXX visualize the target, source, convolution and residual 1520 pmSubtractionVisualShowFitAddStamp (image2, image1, residual, background, norm, i); 1521 1522 for (int y = - footprint; y <= footprint; y++) { 1523 for (int x = - footprint; x <= footprint; x++) { 1524 residual->kernel[y][x] += background + image1->kernel[y][x] * norm - image2->kernel[y][x]; 1525 } 1526 } 1527 } 1528 1529 double deviation = 0.0; // Sum of differences 1530 for (int y = - footprint; y <= footprint; y++) { 1531 for (int x = - footprint; x <= footprint; x++) { 1532 double dev = PS_SQR(residual->kernel[y][x]) * weight->kernel[y][x]; 1533 deviation += dev; 1496 1534 #ifdef TESTING 1497 residual->kernel[y][x] = dev;1498 #endif 1499 }1500 }1501 deviations->data.F32[i] = devNorm * deviation;1502 psTrace("psModules.imcombine", 5, "Deviation for stamp %d (%d,%d): %f\n",1503 i, (int)(stamp->x + 0.5), (int)(stamp->y + 0.5), deviations->data.F32[i]);1504 if (!isfinite(deviations->data.F32[i])) {1505 stamp->status = PM_SUBTRACTION_STAMP_REJECTED;1506 psTrace("psModules.imcombine", 5,1507 "Rejecting stamp %d (%d,%d) because of non-finite deviation\n",1508 i, (int)(stamp->x + 0.5), (int)(stamp->y + 0.5));1509 continue;1510 }1535 residual->kernel[y][x] = dev; 1536 #endif 1537 } 1538 } 1539 deviations->data.F32[i] = devNorm * deviation; 1540 psTrace("psModules.imcombine", 5, "Deviation for stamp %d (%d,%d): %f\n", 1541 i, (int)(stamp->x + 0.5), (int)(stamp->y + 0.5), deviations->data.F32[i]); 1542 if (!isfinite(deviations->data.F32[i])) { 1543 stamp->status = PM_SUBTRACTION_STAMP_REJECTED; 1544 psTrace("psModules.imcombine", 5, 1545 "Rejecting stamp %d (%d,%d) because of non-finite deviation\n", 1546 i, (int)(stamp->x + 0.5), (int)(stamp->y + 0.5)); 1547 continue; 1548 } 1511 1549 1512 1550 #ifdef TESTING 1513 {1514 psString filename = NULL;1515 psStringAppend(&filename, "resid_%03d.fits", i);1516 psFits *fits = psFitsOpen(filename, "w");1517 psFree(filename);1518 psFitsWriteImage(fits, NULL, residual->image, 0, NULL);1519 psFitsClose(fits);1520 }1521 if (stamp->image1) {1522 psString filename = NULL;1523 psStringAppend(&filename, "stamp_image1_%03d.fits", i);1524 psFits *fits = psFitsOpen(filename, "w");1525 psFree(filename);1526 psFitsWriteImage(fits, NULL, stamp->image1->image, 0, NULL);1527 psFitsClose(fits);1528 }1529 if (stamp->image2) {1530 psString filename = NULL;1531 psStringAppend(&filename, "stamp_image2_%03d.fits", i);1532 psFits *fits = psFitsOpen(filename, "w");1533 psFree(filename);1534 psFitsWriteImage(fits, NULL, stamp->image2->image, 0, NULL);1535 psFitsClose(fits);1536 }1537 if (stamp->weight) {1538 psString filename = NULL;1539 psStringAppend(&filename, "stamp_weight_%03d.fits", i);1540 psFits *fits = psFitsOpen(filename, "w");1541 psFree(filename);1542 psFitsWriteImage(fits, NULL, stamp->weight->image, 0, NULL);1543 psFitsClose(fits);1544 }1545 #endif 1546 1551 { 1552 psString filename = NULL; 1553 psStringAppend(&filename, "resid_%03d.fits", i); 1554 psFits *fits = psFitsOpen(filename, "w"); 1555 psFree(filename); 1556 psFitsWriteImage(fits, NULL, residual->image, 0, NULL); 1557 psFitsClose(fits); 1558 } 1559 if (stamp->image1) { 1560 psString filename = NULL; 1561 psStringAppend(&filename, "stamp_image1_%03d.fits", i); 1562 psFits *fits = psFitsOpen(filename, "w"); 1563 psFree(filename); 1564 psFitsWriteImage(fits, NULL, stamp->image1->image, 0, NULL); 1565 psFitsClose(fits); 1566 } 1567 if (stamp->image2) { 1568 psString filename = NULL; 1569 psStringAppend(&filename, "stamp_image2_%03d.fits", i); 1570 psFits *fits = psFitsOpen(filename, "w"); 1571 psFree(filename); 1572 psFitsWriteImage(fits, NULL, stamp->image2->image, 0, NULL); 1573 psFitsClose(fits); 1574 } 1575 if (stamp->weight) { 1576 psString filename = NULL; 1577 psStringAppend(&filename, "stamp_weight_%03d.fits", i); 1578 psFits *fits = psFitsOpen(filename, "w"); 1579 psFree(filename); 1580 psFitsWriteImage(fits, NULL, stamp->weight->image, 0, NULL); 1581 psFitsClose(fits); 1582 } 1583 #endif 1584 1547 1585 } 1548 1586 1549 1587 // calculate and report the normalization and background for the image center 1550 { 1551 polyValues = p_pmSubtractionPolynomial(polyValues, kernels->spatialOrder, 0.0, 0.0); 1552 double norm = p_pmSubtractionSolutionNorm(kernels); // Normalisation 1553 double background = p_pmSubtractionSolutionBackground(kernels, polyValues);// Difference in background 1554 psLogMsg("psModules.imcombine", PS_LOG_INFO, "normalization: %f, background: %f", norm, background); 1555 1556 pmSubtractionVisualShowFit(norm); 1557 pmSubtractionVisualPlotFit(kernels); 1588 { 1589 polyValues = p_pmSubtractionPolynomial(polyValues, kernels->spatialOrder, 0.0, 0.0); 1590 double norm = p_pmSubtractionSolutionNorm(kernels); // Normalisation 1591 double background = p_pmSubtractionSolutionBackground(kernels, polyValues);// Difference in background 1592 psLogMsg("psModules.imcombine", PS_LOG_INFO, "normalization: %f, background: %f", norm, background); 1593 1594 pmSubtractionVisualShowFit(norm); 1595 pmSubtractionVisualPlotFit(kernels); 1596 1597 psStats *stats = psStatsAlloc(PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV); 1598 psVectorStats (stats, fSigRes, NULL, NULL, 0); 1599 kernels->fSigResMean = stats->robustMedian; 1600 kernels->fSigResStdev = stats->robustStdev; 1601 1602 psStatsInit (stats); 1603 psVectorStats (stats, fMaxRes, NULL, NULL, 0); 1604 kernels->fMaxResMean = stats->robustMedian; 1605 kernels->fMaxResStdev = stats->robustStdev; 1606 1607 psStatsInit (stats); 1608 psVectorStats (stats, fMinRes, NULL, NULL, 0); 1609 kernels->fMinResMean = stats->robustMedian; 1610 kernels->fMinResStdev = stats->robustStdev; 1611 1612 // XXX save these values somewhere 1613 psLogMsg("psModules.imcombine", PS_LOG_INFO, "fSigma: %f +/- %f, fMaxRes: %f +/- %f, fMinRes: %f +/- %f", 1614 kernels->fSigResMean, kernels->fSigResStdev, 1615 kernels->fMaxResMean, kernels->fMaxResStdev, 1616 kernels->fMinResMean, kernels->fMinResStdev); 1617 1618 psFree (fSigRes); 1619 psFree (fMaxRes); 1620 psFree (fMinRes); 1621 psFree (stats); 1558 1622 } 1559 1623 1560 1624 psFree(residual); 1561 1625 psFree(polyValues); 1626 1562 1627 1563 1628 return deviations; … … 1574 1639 1575 1640 for (int i = 0; i < wUt->numCols; i++) { 1576 for (int j = 0; j < wUt->numRows; j++) {1577 if (!isfinite(w->data.F64[j])) continue;1578 if (w->data.F64[j] == 0.0) continue;1579 wUt->data.F64[j][i] = U->data.F64[i][j] / w->data.F64[j];1580 }1641 for (int j = 0; j < wUt->numRows; j++) { 1642 if (!isfinite(w->data.F64[j])) continue; 1643 if (w->data.F64[j] == 0.0) continue; 1644 wUt->data.F64[j][i] = U->data.F64[i][j] / w->data.F64[j]; 1645 } 1581 1646 } 1582 1647 return wUt; … … 1591 1656 1592 1657 for (int i = 0; i < Ainv->numCols; i++) { 1593 for (int j = 0; j < Ainv->numRows; j++) {1594 double sum = 0.0;1595 for (int k = 0; k < V->numCols; k++) {1596 sum += V->data.F64[j][k] * wUt->data.F64[k][i];1597 }1598 Ainv->data.F64[j][i] = sum;1599 }1658 for (int j = 0; j < Ainv->numRows; j++) { 1659 double sum = 0.0; 1660 for (int k = 0; k < V->numCols; k++) { 1661 sum += V->data.F64[j][k] * wUt->data.F64[k][i]; 1662 } 1663 Ainv->data.F64[j][i] = sum; 1664 } 1600 1665 } 1601 1666 return Ainv; … … 1610 1675 1611 1676 for (int i = 0; i < U->numCols; i++) { 1612 double sum = 0.0;1613 for (int j = 0; j < U->numRows; j++) {1614 sum += B->data.F64[j] * U->data.F64[j][i];1615 }1616 UtB[0]->data.F64[i] = sum;1677 double sum = 0.0; 1678 for (int j = 0; j < U->numRows; j++) { 1679 sum += B->data.F64[j] * U->data.F64[j][i]; 1680 } 1681 UtB[0]->data.F64[i] = sum; 1617 1682 } 1618 1683 return true; … … 1629 1694 1630 1695 for (int i = 0; i < w->n; i++) { 1631 if (!isfinite(w->data.F64[i])) continue;1632 if (w->data.F64[i] == 0.0) continue;1633 wUtB[0]->data.F64[i] = UtB->data.F64[i] / w->data.F64[i];1696 if (!isfinite(w->data.F64[i])) continue; 1697 if (w->data.F64[i] == 0.0) continue; 1698 wUtB[0]->data.F64[i] = UtB->data.F64[i] / w->data.F64[i]; 1634 1699 } 1635 1700 return true; … … 1644 1709 1645 1710 for (int j = 0; j < V->numRows; j++) { 1646 double sum = 0.0;1647 for (int i = 0; i < V->numCols; i++) {1648 sum += V->data.F64[j][i] * wUtB->data.F64[i];1649 }1650 VwUtB[0]->data.F64[j] = sum;1711 double sum = 0.0; 1712 for (int i = 0; i < V->numCols; i++) { 1713 sum += V->data.F64[j][i] * wUtB->data.F64[i]; 1714 } 1715 VwUtB[0]->data.F64[j] = sum; 1651 1716 } 1652 1717 return true; … … 1661 1726 1662 1727 for (int j = 0; j < A->numRows; j++) { 1663 double sum = 0.0;1664 for (int i = 0; i < A->numCols; i++) {1665 sum += A->data.F64[j][i] * x->data.F64[i];1666 }1667 B[0]->data.F64[j] = sum;1728 double sum = 0.0; 1729 for (int i = 0; i < A->numCols; i++) { 1730 sum += A->data.F64[j][i] * x->data.F64[i]; 1731 } 1732 B[0]->data.F64[j] = sum; 1668 1733 } 1669 1734 return true; … … 1677 1742 double sum = 0.0; 1678 1743 for (int i = 0; i < x->n; i++) { 1679 sum += x->data.F64[i] * y->data.F64[i];1744 sum += x->data.F64[i] * y->data.F64[i]; 1680 1745 } 1681 1746 *value = sum; … … 1690 1755 for (int i = 0; i < stamps->num; i++) { 1691 1756 1692 pmSubtractionStamp *stamp = stamps->stamps->data[i];1693 if (stamp->status != PM_SUBTRACTION_STAMP_USED) continue;1694 1695 psKernel *weight = NULL;1696 psKernel *window = NULL;1697 psKernel *input = NULL;1757 pmSubtractionStamp *stamp = stamps->stamps->data[i]; 1758 if (stamp->status != PM_SUBTRACTION_STAMP_USED) continue; 1759 1760 psKernel *weight = NULL; 1761 psKernel *window = NULL; 1762 psKernel *input = NULL; 1698 1763 1699 1764 #ifdef USE_WEIGHT 1700 weight = stamp->weight;1765 weight = stamp->weight; 1701 1766 #endif 1702 1767 #ifdef USE_WINDOW 1703 window = stamps->window;1704 #endif 1705 1706 switch (kernels->mode) {1707 // MODE_1 : convolve image 1 to match image 2 (and vice versa)1708 case PM_SUBTRACTION_MODE_1:1709 input = stamp->image2;1710 break;1711 case PM_SUBTRACTION_MODE_2:1712 input = stamp->image1;1713 break;1714 default:1715 psAbort ("programming error");1716 }1717 1718 for (int y = - footprint; y <= footprint; y++) {1719 for (int x = - footprint; x <= footprint; x++) {1720 double in = input->kernel[y][x];1721 double value = in*in;1722 if (weight) {1723 float wtVal = weight->kernel[y][x];1724 value *= wtVal;1725 }1726 if (window) {1727 float winVal = window->kernel[y][x];1728 value *= winVal;1729 }1730 sum += value;1731 }1732 }1768 window = stamps->window; 1769 #endif 1770 1771 switch (kernels->mode) { 1772 // MODE_1 : convolve image 1 to match image 2 (and vice versa) 1773 case PM_SUBTRACTION_MODE_1: 1774 input = stamp->image2; 1775 break; 1776 case PM_SUBTRACTION_MODE_2: 1777 input = stamp->image1; 1778 break; 1779 default: 1780 psAbort ("programming error"); 1781 } 1782 1783 for (int y = - footprint; y <= footprint; y++) { 1784 for (int x = - footprint; x <= footprint; x++) { 1785 double in = input->kernel[y][x]; 1786 double value = in*in; 1787 if (weight) { 1788 float wtVal = weight->kernel[y][x]; 1789 value *= wtVal; 1790 } 1791 if (window) { 1792 float winVal = window->kernel[y][x]; 1793 value *= winVal; 1794 } 1795 sum += value; 1796 } 1797 } 1733 1798 } 1734 1799 *y2 = sum; … … 1750 1815 for (int i = 0; i < stamps->num; i++) { 1751 1816 1752 pmSubtractionStamp *stamp = stamps->stamps->data[i];1753 if (stamp->status != PM_SUBTRACTION_STAMP_USED) continue;1754 1755 psKernel *weight = NULL;1756 psKernel *window = NULL;1757 psKernel *target = NULL;1758 psKernel *source = NULL;1759 1760 psArray *convolutions = NULL;1817 pmSubtractionStamp *stamp = stamps->stamps->data[i]; 1818 if (stamp->status != PM_SUBTRACTION_STAMP_USED) continue; 1819 1820 psKernel *weight = NULL; 1821 psKernel *window = NULL; 1822 psKernel *target = NULL; 1823 psKernel *source = NULL; 1824 1825 psArray *convolutions = NULL; 1761 1826 1762 1827 #ifdef USE_WEIGHT 1763 weight = stamp->weight;1828 weight = stamp->weight; 1764 1829 #endif 1765 1830 #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 target = stamp->image2;1773 source = stamp->image1;1774 convolutions = stamp->convolutions1;1775 break;1776 case PM_SUBTRACTION_MODE_2:1777 target = stamp->image1;1778 source = stamp->image2;1779 convolutions = stamp->convolutions2;1780 break;1781 default:1782 psAbort ("programming error");1783 }1784 1785 // Calculate coefficients of the kernel basis functions1786 polyValues = p_pmSubtractionPolynomial(polyValues, kernels->spatialOrder, stamp->xNorm, stamp->yNorm);1787 double norm = p_pmSubtractionSolutionNorm(kernels); // Normalisation1788 double background = p_pmSubtractionSolutionBackground(kernels, polyValues);// Difference in background1789 1790 psImageInit(residual->image, 0.0);1791 for (int j = 0; j < numKernels; j++) {1792 psKernel *convolution = convolutions->data[j]; // Convolution1793 double coefficient = p_pmSubtractionSolutionCoeff(kernels, polyValues, j, false); // Coefficient1794 for (int y = - footprint; y <= footprint; y++) {1795 for (int x = - footprint; x <= footprint; x++) {1796 residual->kernel[y][x] -= convolution->kernel[y][x] * coefficient;1797 }1798 }1799 }1800 1801 for (int y = - footprint; y <= footprint; y++) {1802 for (int x = - footprint; x <= footprint; x++) {1803 double resid = target->kernel[y][x] - background - source->kernel[y][x] * norm + residual->kernel[y][x];1804 double value = PS_SQR(resid);1805 if (weight) {1806 float wtVal = weight->kernel[y][x];1807 value *= wtVal;1808 }1809 if (window) {1810 float winVal = window->kernel[y][x];1811 value *= winVal;1812 }1813 sum += value;1814 }1815 }1831 window = stamps->window; 1832 #endif 1833 1834 switch (kernels->mode) { 1835 // MODE_1 : convolve image 1 to match image 2 (and vice versa) 1836 case PM_SUBTRACTION_MODE_1: 1837 target = stamp->image2; 1838 source = stamp->image1; 1839 convolutions = stamp->convolutions1; 1840 break; 1841 case PM_SUBTRACTION_MODE_2: 1842 target = stamp->image1; 1843 source = stamp->image2; 1844 convolutions = stamp->convolutions2; 1845 break; 1846 default: 1847 psAbort ("programming error"); 1848 } 1849 1850 // Calculate coefficients of the kernel basis functions 1851 polyValues = p_pmSubtractionPolynomial(polyValues, kernels->spatialOrder, stamp->xNorm, stamp->yNorm); 1852 double norm = p_pmSubtractionSolutionNorm(kernels); // Normalisation 1853 double background = p_pmSubtractionSolutionBackground(kernels, polyValues);// Difference in background 1854 1855 psImageInit(residual->image, 0.0); 1856 for (int j = 0; j < numKernels; j++) { 1857 psKernel *convolution = convolutions->data[j]; // Convolution 1858 double coefficient = p_pmSubtractionSolutionCoeff(kernels, polyValues, j, false); // Coefficient 1859 for (int y = - footprint; y <= footprint; y++) { 1860 for (int x = - footprint; x <= footprint; x++) { 1861 residual->kernel[y][x] -= convolution->kernel[y][x] * coefficient; 1862 } 1863 } 1864 } 1865 1866 for (int y = - footprint; y <= footprint; y++) { 1867 for (int x = - footprint; x <= footprint; x++) { 1868 double resid = target->kernel[y][x] - background - source->kernel[y][x] * norm + residual->kernel[y][x]; 1869 double value = PS_SQR(resid); 1870 if (weight) { 1871 float wtVal = weight->kernel[y][x]; 1872 value *= wtVal; 1873 } 1874 if (window) { 1875 float winVal = window->kernel[y][x]; 1876 value *= winVal; 1877 } 1878 sum += value; 1879 } 1880 } 1816 1881 } 1817 1882 psFree (polyValues); … … 1824 1889 1825 1890 for (int i = 0; i < w->n; i++) { 1826 wApply->data.F64[i] = wMask->data.U8[i] ? 0.0 : w->data.F64[i];1891 wApply->data.F64[i] = wMask->data.U8[i] ? 0.0 : w->data.F64[i]; 1827 1892 } 1828 1893 return true; … … 1839 1904 // generate Vn = V * w^{-1} 1840 1905 for (int j = 0; j < Vn->numRows; j++) { 1841 for (int i = 0; i < Vn->numCols; i++) {1842 if (!isfinite(w->data.F64[i])) continue;1843 if (w->data.F64[i] == 0.0) continue;1844 Vn->data.F64[j][i] = V->data.F64[j][i] / w->data.F64[i];1845 }1906 for (int i = 0; i < Vn->numCols; i++) { 1907 if (!isfinite(w->data.F64[i])) continue; 1908 if (w->data.F64[i] == 0.0) continue; 1909 Vn->data.F64[j][i] = V->data.F64[j][i] / w->data.F64[i]; 1910 } 1846 1911 } 1847 1912 … … 1851 1916 // generate Xvar = Vn * Vn^T 1852 1917 for (int j = 0; j < Vn->numRows; j++) { 1853 for (int i = 0; i < Vn->numCols; i++) {1854 double sum = 0.0;1855 for (int k = 0; k < Vn->numCols; k++) {1856 sum += Vn->data.F64[k][i]*Vn->data.F64[k][j];1857 }1858 Xvar->data.F64[j][i] = sum;1859 }1918 for (int i = 0; i < Vn->numCols; i++) { 1919 double sum = 0.0; 1920 for (int k = 0; k < Vn->numCols; k++) { 1921 sum += Vn->data.F64[k][i]*Vn->data.F64[k][j]; 1922 } 1923 Xvar->data.F64[j][i] = sum; 1924 } 1860 1925 } 1861 1926 return Xvar; … … 1872 1937 psFitsWriteImage(fits, header, image, 0, NULL); 1873 1938 psFitsClose(fits); 1874 1939 1875 1940 return true; 1876 1941 }
Note:
See TracChangeset
for help on using the changeset viewer.
