IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 30289


Ignore:
Timestamp:
Jan 17, 2011, 5:18:09 PM (15 years ago)
Author:
eugene
Message:

apply window only to the moments portions of the calculation; apply weights only to the chisq portion of the calculation; do not renormalize the chisq portion by the flux (keeps SINGLE and DUAL on same scale); move stamp convolution out of CalculateEquation; explicit tests if the convolutions are needed; remove the old unused matrix solution functions; calculate the coefficient errors; add function to calculate chisq and moments statistics, and to generate a subtraction quality statistic; pull model visualization out of CalculateDeviations; adjust the size of the normalization window (if too small, we likely miss some of the flux); exclude excessively faint sources from model fit

Location:
branches/eam_branches/ipp-20101205/psModules/src/imcombine
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • branches/eam_branches/ipp-20101205/psModules/src/imcombine/pmSubtractionEquation.c

    r30266 r30289  
    2020//# define USE_WEIGHT                      // Include weight (1/variance) in equation?
    2121# define USE_WINDOW                      // window to avoid neighbor contamination
    22 // XXX if we want to have a weight and window, we'll need to pass through to the chisq function
     22
     23/* I believe we want to apply the WEIGHT to the chisq portions of the calculation (but not the WINDOW),
     24 * and the WINDOW to the moments portiosn of the calculations (but not the WEIGHT)
     25 *
     26 */
    2327
    2428# define PENALTY false
     
    106110                        cc *= weight->kernel[y][x];
    107111                    }
    108                     if (window) {
     112                    // XXX NOTE: do NOT apply the window to the chisq portions of the calculation
     113                    if (false && window) {
    109114                        cc *= window->kernel[y][x];
    110115                    }
     
    137142                    rc *= wtVal;
    138143                }
    139                 if (window) {
     144                // XXX NOTE: do NOT apply the window to the chisq portions of the calculation
     145                if (false && window) {
    140146                    float winVal = window->kernel[y][x];
    141147                    ic *= winVal;
     
    172178}
    173179
     180# define RENORM_BY_FLUX 0
    174181
    175182// Calculate the least-squares matrix and vector for dual convolution
     
    267274            for (int y = - footprint; y <= footprint; y++) {
    268275                for (int x = - footprint; x <= footprint; x++) {
     276
     277                    // XXX NOTE: clipping low S/N pixels does not seem to work very well
     278                    if (false && weight) {
     279                        float i1 = image1->kernel[y][x];
     280                        float i2 = image2->kernel[y][x];
     281                        float sn = (i1 + i2) / sqrt (weight->kernel[y][x]);
     282                        if (sn < 0.5) continue;
     283                    }
     284
    269285                    double aa = iConv1->kernel[y][x] * jConv1->kernel[y][x] * PS_SQR(normValue);
    270286                    double bb = iConv2->kernel[y][x] * jConv2->kernel[y][x];
    271287                    double ab = iConv1->kernel[y][x] * jConv2->kernel[y][x] * normValue;
    272                     if (weight) {
    273                         float wtVal = weight->kernel[y][x];
    274                         aa *= wtVal;
    275                         bb *= wtVal;
    276                         ab *= wtVal;
    277                     }
    278                     if (window) {
    279                         float wtVal = window->kernel[y][x];
    280                         aa *= wtVal;
    281                         bb *= wtVal;
    282                         ab *= wtVal;
    283                     }
    284                     sumAA += aa;
    285                     sumBB += bb;
    286                     sumAB += ab;
     288
     289                    float wtVal = (weight) ? weight->kernel[y][x] : 1.0;
     290                    sumAA += wtVal*aa;
     291                    sumBB += wtVal*bb;
     292                    sumAB += wtVal*ab;
    287293
    288294                    if (MOMENTS) {
    289                         MxxAA += x*x*aa;
    290                         MyyAA += y*y*aa;
    291                         MxxBB += x*x*bb;
    292                         MyyBB += y*y*bb;
     295                        float winVal = (window) ? window->kernel[y][x] : 1.0;
     296                        MxxAA += winVal*x*x*aa;
     297                        MyyAA += winVal*y*y*aa;
     298                        MxxBB += winVal*x*x*bb;
     299                        MyyBB += winVal*y*y*bb;
    293300                    }
    294301                }
    295302            }
    296303
     304            // XXX does normSquare1,2 mess up the relative scaling?
     305            // XXX no: normSquare1,2 is the sum of the flux^2 for the source
    297306            if (MOMENTS) {
    298307                MxxAA /= stamp->normSquare1 * PS_SQR(normValue);
     
    304313            // XXX this makes the Chisq portion independent of the normalization and star flux
    305314            // but may be mis-scaling between stars of different fluxes
     315# if (RENORM_BY_FLUX)       
    306316            sumAA /= PS_SQR(stamp->normI2);
    307317            sumAB /= PS_SQR(stamp->normI2);
    308318            sumBB /= PS_SQR(stamp->normI2);
     319# endif
    309320
    310321            // fprintf (stderr, "i,j : %d %d : M(xx,yy)(AA,BB) : %f %f %f %f\n", i, j, MxxAA, MyyAA, MxxBB, MyyBB);
     
    327338                        matrix->data.F64[iIndex][jIndex] += kernels->penalty * MxxAA * MOMENTS_PENALTY_SCALE;
    328339                        matrix->data.F64[iIndex][jIndex] += kernels->penalty * MyyAA * MOMENTS_PENALTY_SCALE;
    329 
    330340                        matrix->data.F64[jIndex][iIndex] += kernels->penalty * MxxAA * MOMENTS_PENALTY_SCALE;
    331341                        matrix->data.F64[jIndex][iIndex] += kernels->penalty * MyyAA * MOMENTS_PENALTY_SCALE;
     
    333343                        matrix->data.F64[iIndex + numParams][jIndex + numParams] += kernels->penalty * MxxBB * MOMENTS_PENALTY_SCALE;
    334344                        matrix->data.F64[iIndex + numParams][jIndex + numParams] += kernels->penalty * MyyBB * MOMENTS_PENALTY_SCALE;
    335 
    336345                        matrix->data.F64[jIndex + numParams][iIndex + numParams] += kernels->penalty * MxxBB * MOMENTS_PENALTY_SCALE;
    337346                        matrix->data.F64[jIndex + numParams][iIndex + numParams] += kernels->penalty * MyyBB * MOMENTS_PENALTY_SCALE;
     
    353362                        ab *= weight->kernel[y][x];
    354363                    }
    355                     if (window) {
     364                    // XXX NOTE: do NOT apply the window to the chisq portions of the calculation
     365                    if (false && window) {
    356366                        ab *= window->kernel[y][x];
    357367                    }
     
    362372            // XXX this makes the Chisq portion independent of the normalization and star flux
    363373            // but may be mis-scaling between stars of different fluxes
     374# if (RENORM_BY_FLUX)
    364375            sumAB /= PS_SQR(stamp->normI2);
     376# endif
    365377
    366378            // Spatial variation of kernel coeffs
     
    390402                float i2 = image2->kernel[y][x];
    391403
     404                // XXX NOTE: clipping low S/N pixels does not seem to work very well
     405                if (false && weight) {
     406                    float sn = (i1 + i2) / sqrt (weight->kernel[y][x]);
     407                    if (sn < 0.5) continue;
     408                }
     409
    392410                double ai2 = a * i2 * normValue;
    393411                double bi2 = b * i2;
     
    395413                double bi1 = b * i1 * normValue;
    396414
    397                 if (weight) {
    398                     float wtVal = weight->kernel[y][x];
    399                     ai2 *= wtVal;
    400                     bi2 *= wtVal;
    401                     ai1 *= wtVal;
    402                     bi1 *= wtVal;
    403                 }
    404                 if (window) {
    405                     float wtVal = window->kernel[y][x];
    406                     ai2 *= wtVal;
    407                     bi2 *= wtVal;
    408                     ai1 *= wtVal;
    409                     bi1 *= wtVal;
    410                 }
    411                 sumAI2 += ai2;
    412                 sumBI2 += bi2;
    413                 sumAI1 += ai1;
    414                 sumBI1 += bi1;
     415                float wtVal = (weight) ? weight->kernel[y][x] : 1.0;
     416                sumAI2 += wtVal*ai2;
     417                sumBI2 += wtVal*bi2;
     418                sumAI1 += wtVal*ai1;
     419                sumBI1 += wtVal*bi1;
    415420
    416421                if (MOMENTS) {
    417                     MxxAI1 += x*x*ai1;
    418                     MyyAI1 += y*y*ai1;
    419                     MxxBI2 += x*x*bi2;
    420                     MyyBI2 += y*y*bi2;
     422                    float winVal = (window) ? window->kernel[y][x] : 1.0;
     423                    MxxAI1 += winVal*x*x*ai1;
     424                    MyyAI1 += winVal*y*y*ai1;
     425                    MxxBI2 += winVal*x*x*bi2;
     426                    MyyBI2 += winVal*y*y*bi2;
    421427                }
    422428            }
     
    434440        // XXX this makes the Chisq portion independent of the normalization and star flux
    435441        // but may be mis-scaling between stars of different fluxes
     442# if (RENORM_BY_FLUX)
    436443        sumAI1 /= PS_SQR(stamp->normI2);
    437444        sumBI1 /= PS_SQR(stamp->normI2);
    438445        sumAI2 /= PS_SQR(stamp->normI2);
    439446        sumBI2 /= PS_SQR(stamp->normI2);
     447# endif
    440448
    441449        // Spatial variation
     
    799807    pmSubtractionKernels *kernels = job->args->data[1]; // Kernels
    800808    int index = PS_SCALAR_VALUE(job->args->data[2], S32); // Stamp index
    801     pmSubtractionEquationCalculationMode mode  = PS_SCALAR_VALUE(job->args->data[3], S32); // calculation model
    802 
    803     return pmSubtractionCalculateEquationStamp(stamps, kernels, index, mode);
    804 }
    805 
    806 bool pmSubtractionCalculateEquationStamp(pmSubtractionStampList *stamps, pmSubtractionKernels *kernels,
    807                                          int index, const pmSubtractionEquationCalculationMode mode)
     809
     810    return pmSubtractionCalculateEquationStamp(stamps, kernels, index);
     811}
     812
     813bool pmSubtractionCalculateEquationStamp(pmSubtractionStampList *stamps, pmSubtractionKernels *kernels, int index)
    808814{
    809815    PM_ASSERT_SUBTRACTION_STAMP_LIST_NON_NULL(stamps, false);
     
    832838    psAssert(stamp->status == PM_SUBTRACTION_STAMP_CALCULATE, "We only operate on stamps with this state.");
    833839
    834     // Generate convolutions: these are generated once and saved
    835     if (!pmSubtractionConvolveStamp(stamp, kernels, footprint)) {
    836         psError(psErrorCodeLast(), false, "Unable to convolve stamp %d.", index);
    837         return NULL;
    838     }
    839 
    840 #ifdef TESTING
    841     for (int j = 0; j < numKernels; j++) {
    842         if (stamp->convolutions1) {
    843             psString convName = NULL;
    844             psStringAppend(&convName, "conv1_%03d_%03d.fits", index, j);
    845             psFits *fits = psFitsOpen(convName, "w");
    846             psFree(convName);
    847             psKernel *conv = stamp->convolutions1->data[j];
    848             psFitsWriteImage(fits, NULL, conv->image, 0, NULL);
    849             psFitsClose(fits);
    850         }
    851 
    852         if (stamp->convolutions2) {
    853             psString convName = NULL;
    854             psStringAppend(&convName, "conv2_%03d_%03d.fits", index, j);
    855             psFits *fits = psFitsOpen(convName, "w");
    856             psFree(convName);
    857             psKernel *conv = stamp->convolutions2->data[j];
    858             psFitsWriteImage(fits, NULL, conv->image, 0, NULL);
    859             psFitsClose(fits);
    860         }
    861     }
    862 #endif
    863 
    864     // XXX visualize the set of convolved stamps
    865 
    866     psImage *polyValues = p_pmSubtractionPolynomial(NULL, spatialOrder,
    867                                                     stamp->xNorm, stamp->yNorm); // Polynomial terms
    868 
    869     bool new = stamp->vector ? false : true; // Is this a new run?
     840    psImage *polyValues = p_pmSubtractionPolynomial(NULL, spatialOrder, stamp->xNorm, stamp->yNorm); // Polynomial terms
     841
     842    // Is this a new run? Have we allocated the correct sized vector/matrix?
     843    bool new = stamp->vector ? false : true;
     844    if (!new && (stamp->vector->n != numParams)) {
     845        psFree (stamp->vector);
     846        psFree (stamp->matrix);
     847        new = true;
     848    }
     849
    870850    if (new) {
    871851        stamp->matrix = psImageAlloc(numParams, numParams, PS_TYPE_F64);
     
    940920}
    941921
    942 bool pmSubtractionCalculateEquation(pmSubtractionStampList *stamps, pmSubtractionKernels *kernels,
    943                                     const pmSubtractionEquationCalculationMode mode)
     922bool pmSubtractionCalculateEquation(pmSubtractionStampList *stamps, pmSubtractionKernels *kernels)
    944923{
    945924    PM_ASSERT_SUBTRACTION_STAMP_LIST_NON_NULL(stamps, false);
     
    952931    for (int i = 0; i < stamps->num; i++) {
    953932        pmSubtractionStamp *stamp = stamps->stamps->data[i]; // Stamp of interest
     933
    954934        if (stamp->status != PM_SUBTRACTION_STAMP_CALCULATE) {
    955935            continue;
     
    968948            psArrayAdd(job->args, 1, (pmSubtractionKernels*)kernels); // Casting away const to put on array
    969949            PS_ARRAY_ADD_SCALAR(job->args, i, PS_TYPE_S32);
    970             PS_ARRAY_ADD_SCALAR(job->args, mode, PS_TYPE_S32);
    971950            if (!psThreadJobAddPending(job)) {
    972951                return false;
    973952            }
    974953        } else {
    975             pmSubtractionCalculateEquationStamp(stamps, kernels, i, mode);
     954            pmSubtractionCalculateEquationStamp(stamps, kernels, i);
    976955        }
    977956    }
     
    986965    pmSubtractionVisualPlotLeastSquares(stamps);
    987966
    988     psLogMsg("psModules.imcombine", PS_LOG_INFO, "Calculate equation: %f sec",
    989              psTimerClear("pmSubtractionCalculateEquation"));
    990 
     967    psLogMsg("psModules.imcombine", PS_LOG_INFO, "Calculate equation: %f sec", psTimerClear("pmSubtractionCalculateEquation"));
    991968
    992969    return true;
     
    997974bool psFitsWriteImageSimple (char *filename, psImage *image, psMetadata *header);
    998975
    999 psImage *p_pmSubSolve_wUt (psVector *w, psImage *U);
    1000 psImage *p_pmSubSolve_VwUt (psImage *V, psImage *wUt);
    1001 
    1002 bool p_pmSubSolve_SetWeights (psVector *wApply, psVector *w, psVector *wMask);
    1003 
    1004 bool p_pmSubSolve_UtB (psVector **UtB, psImage *U, psVector *B);
    1005 bool p_pmSubSolve_wUtB (psVector **wUtB, psVector *w, psVector *UtB);
    1006 bool p_pmSubSolve_VwUtB (psVector **VwUtB, psImage *V, psVector *wUtB);
    1007 
    1008 bool p_pmSubSolve_Ax (psVector **B, psImage *A, psVector *x);
    1009 bool p_pmSubSolve_VdV (double *value, psVector *x, psVector *y);
    1010 bool p_pmSubSolve_y2 (double *y2, pmSubtractionKernels *kernels, const pmSubtractionStampList *stamps);
    1011 
    1012 psImage *p_pmSubSolve_Xvar (psImage *V, psVector *w);
    1013 
    1014 double p_pmSubSolve_ChiSquare (pmSubtractionKernels *kernels, const pmSubtractionStampList *stamps);
    1015 
    1016 bool pmSubtractionSolveEquation(pmSubtractionKernels *kernels,
    1017                                 const pmSubtractionStampList *stamps,
    1018                                 const pmSubtractionEquationCalculationMode mode)
     976bool pmSubtractionSolveEquation(pmSubtractionKernels *kernels, const pmSubtractionStampList *stamps)
    1019977{
    1020978    PM_ASSERT_SUBTRACTION_KERNELS_NON_NULL(kernels, false);
    1021979    PM_ASSERT_SUBTRACTION_STAMP_LIST_NON_NULL(stamps, false);
     980
     981    psTimerStart("pmSubtractionSolveEquation");
    1022982
    1023983    // Check inputs
     
    10411001        }
    10421002
     1003        if (stamp->vector->n != numParams) {
     1004            fprintf (stderr, "mismatch length\n");
     1005        }
    10431006        PS_ASSERT_VECTOR_NON_NULL(stamp->vector, false);
    10441007        PS_ASSERT_VECTOR_SIZE(stamp->vector, (long)numParams, false);
     
    10881051#endif
    10891052
     1053        // XXX TEST : print the matrix & vector
     1054        if (0) {
     1055            for (int iy = 0; iy < sumMatrix->numRows; iy++) {
     1056                for (int ix = 0; ix < sumMatrix->numCols; ix++) {
     1057                    fprintf (stderr, "%e  ", sumMatrix->data.F64[iy][ix]);
     1058                }
     1059                fprintf (stderr, " : %e\n", sumVector->data.F64[iy]);
     1060            }
     1061        }
     1062
    10901063        psImage *invMatrix = NULL;
    10911064        psVector *solution = NULL;                       // Solution to equation!
     
    10961069        // solution = psMatrixSolveSVD(solution, sumMatrix, sumVector, NAN);
    10971070        // SINGLE solution
    1098         if (1) {
    1099             solution = psMatrixSolveSVD(solution, sumMatrix, sumVector, NAN);
    1100             invMatrix = psMatrixInvert(NULL, sumMatrix, NULL);
    1101         } else {
    1102             psVector *PERM = NULL;
    1103             psImage *LU = psMatrixLUDecomposition(NULL, &PERM, sumMatrix);
    1104             solution = psMatrixLUSolution(solution, LU, sumVector, PERM);
    1105             psFree (LU);
    1106             psFree (PERM);
    1107         }
    1108 
    11091071# if (1)
     1072        solution = psMatrixSolveSVD(solution, sumMatrix, sumVector, NAN);
     1073        invMatrix = psMatrixInvert(NULL, sumMatrix, NULL);
     1074# endif
     1075# if (0)
     1076        psMatrixLUSolve(sumMatrixLU, sumVector);
     1077        solution = psMemIncrRefCounter(sumVector);
     1078        invMatrix = psMemIncrRefCounter(sumMatrix);
     1079# endif
     1080# if (0)
     1081        psMatrixGJSolve(sumMatrix, sumVector);
     1082        invMatrix = psMemIncrRefCounter(sumMatrix);
     1083        solution = psMemIncrRefCounter(sumVector);
     1084# endif
     1085
     1086# if (0)
    11101087        for (int i = 0; i < solution->n; i++) {
    1111             psLogMsg("psModules.imcombine", PS_LOG_DETAIL, "Single solution %d: %lf +/- %lf\n", i, solution->data.F64[i], sqrt(invMatrix->data.F64[i][i]));
     1088            psLogMsg("psModules.imcombine", PS_LOG_DETAIL, "Single solution %d: %lf +/- %lf\n", i, solution->data.F64[i], sqrt(fabs(invMatrix->data.F64[i][i])));
    11121089        }
    11131090# endif
    11141091
    1115         if (!kernels->solution1) {
    1116             kernels->solution1 = psVectorAlloc(sumVector->n + 2, PS_TYPE_F64); // 1 for norm, 1 for bg
    1117             psVectorInit(kernels->solution1, 0.0);
    1118             kernels->solution1err = psVectorAlloc(sumVector->n + 2, PS_TYPE_F64); // 1 for norm, 1 for bg
    1119             psVectorInit(kernels->solution1err, 0.0);
    1120         }
     1092        // ensure we have a solution vector of the right size
     1093        kernels->solution1    = psVectorRecycle(kernels->solution1,    sumVector->n + 2, PS_TYPE_F64); // 1 for norm, 1 for bg
     1094        kernels->solution1err = psVectorRecycle(kernels->solution1err, sumVector->n + 2, PS_TYPE_F64); // 1 for norm, 1 for bg
     1095        psVectorInit(kernels->solution1, 0.0);
     1096        psVectorInit(kernels->solution1err, 0.0);
    11211097
    11221098        int numKernels = kernels->num;
    11231099        int spatialOrder = kernels->spatialOrder;       // Order of spatial variation
    11241100        int numPoly = PM_SUBTRACTION_POLYTERMS(spatialOrder); // Number of polynomial terms
     1101
    11251102        for (int i = 0; i < numKernels * numPoly; i++) {
    11261103            kernels->solution1->data.F64[i] = solution->data.F64[i];
     
    11801157        }
    11811158
     1159        // XXX TEST : print the matrix & vector
     1160        if (0) {
     1161            for (int iy = 0; iy < sumMatrix->numRows; iy++) {
     1162                for (int ix = 0; ix < sumMatrix->numCols; ix++) {
     1163                    fprintf (stderr, "%e  ", sumMatrix->data.F64[iy][ix]);
     1164                }
     1165                fprintf (stderr, " : %e\n", sumVector->data.F64[iy]);
     1166            }
     1167        }
     1168
    11821169        psImage *invMatrix = NULL;
    11831170        psVector *solution = NULL;                       // Solution to equation!
     
    11871174        // DUAL solution
    11881175# if (1)
    1189         solution = psMatrixSolveSVD(solution, sumMatrix, sumVector, 1e-7);
     1176        solution = psMatrixSolveSVD(solution, sumMatrix, sumVector, NAN);
    11901177        invMatrix = psMatrixInvert(NULL, sumMatrix, NULL);
    11911178# endif
    11921179# if (0)
    11931180        psMatrixLUSolve(sumMatrix, sumVector);
    1194         solution = sumVector;
    1195         invMatrix = sumMatrix;
     1181        solution = psMemIncrRefCounter(sumVector);
     1182        invMatrix = psMemIncrRefCounter(sumMatrix);
    11961183# endif
    11971184
    1198 #if (1)
     1185#if (0)
    11991186        for (int i = 0; i < solution->n; i++) {
    12001187            fprintf(stderr, "Dual solution %d: %lf +/- %lf\n", i, solution->data.F64[i], sqrt(invMatrix->data.F64[i][i]));
     
    12021189#endif
    12031190
    1204         if (!kernels->solution1) {
    1205             kernels->solution1 = psVectorAlloc(numSolution1 + 2, PS_TYPE_F64);
    1206             psVectorInit (kernels->solution1, 0.0);
    1207             kernels->solution1err = psVectorAlloc(numSolution1 + 2, PS_TYPE_F64); // 1 for norm, 1 for bg
    1208             psVectorInit(kernels->solution1err, 0.0);
    1209         }
    1210         if (!kernels->solution2) {
    1211             kernels->solution2 = psVectorAlloc(numSolution2, PS_TYPE_F64);
    1212             psVectorInit (kernels->solution2, 0.0);
    1213             kernels->solution2err = psVectorAlloc(numSolution2, PS_TYPE_F64);
    1214             psVectorInit(kernels->solution2err, 0.0);
    1215         }
     1191        // XXX TEST: manually set the coeffs to a desired solution
     1192        // solution->data.F64[0] = +1.826;
     1193        // solution->data.F64[1] = -0.115;
     1194        // solution->data.F64[2] =  0.0;
     1195        // solution->data.F64[3] =  0.0;
     1196
     1197        // ensure we have solution vectors of the right size
     1198        kernels->solution1    = psVectorRecycle(kernels->solution1,    numSolution1 + 2, PS_TYPE_F64); // 1 for norm, 1 for bg
     1199        kernels->solution1err = psVectorRecycle(kernels->solution1err, numSolution1 + 2, PS_TYPE_F64); // 1 for norm, 1 for bg
     1200        kernels->solution2    = psVectorRecycle(kernels->solution2,    numSolution2,     PS_TYPE_F64); // 1 for norm, 1 for bg
     1201        kernels->solution2err = psVectorRecycle(kernels->solution2err, numSolution2,     PS_TYPE_F64); // 1 for norm, 1 for bg
     1202
     1203        psVectorInit(kernels->solution1, 0.0);
     1204        psVectorInit(kernels->solution1err, 0.0);
     1205        psVectorInit(kernels->solution2, 0.0);
     1206        psVectorInit(kernels->solution2err, 0.0);
    12161207
    12171208        // for DUAL convolution analysis, we apply the normalization to I1 as follows:
     
    12591250        }
    12601251     }
     1252
     1253    psLogMsg("psModules.imcombine", PS_LOG_INFO, "Solve equation: %f sec", psTimerClear("pmSubtractionSolveEquation"));
    12611254
    12621255    // pmSubtractionVisualPlotLeastSquares((pmSubtractionStampList *) stamps); //casting away const
     
    13111304
    13121305// given the convolved image(s) and the residual image, calculate the second moment(s) and the chisq
    1313 bool pmSubtractionChisqStats(psVector *fluxesVector, psVector *chisqVector, psVector *momentVector, psKernel *convolved1, psKernel *convolved2, psKernel *residual, psKernel *weight, psKernel *window) {
     1306bool pmSubtractionChisqStats(psVector *fluxesVector, psVector *chisqVector, psVector *momentVector, psVector *stampMask, psKernel *convolved1, psKernel *convolved2, psKernel *residual, psKernel *weight, psKernel *window) {
     1307
     1308# ifndef USE_WEIGHT
     1309    psAssert(weight == NULL, "impossible!");
     1310# endif
     1311# ifndef USE_WINDOW
     1312    psAssert(window == NULL, "impossible!");
     1313# endif
    13141314
    13151315    int npix = 0;
     
    13191319    for (int y = residual->yMin; y <= residual->yMax; y++) {
    13201320        for (int x = residual->xMin; x <= residual->xMax; x++) {
    1321             chisq  += PS_SQR(residual->kernel[y][x]);
     1321            float value = PS_SQR(residual->kernel[y][x]);
     1322            if (weight) {
     1323                value *= weight->kernel[y][x];
     1324            }
     1325            // XXX NOTE: do NOT apply the window to the chisq portions of the calculation
     1326            if (false && window) {
     1327                value *= window->kernel[y][x];
     1328            }
     1329            chisq += value;
    13221330            npix ++;
    13231331        }
     
    13451353                value2  = PS_SQR(value1);
    13461354
    1347                 if (weight) {
     1355                if (window) {
     1356                    value1 *= window->kernel[y][x];
     1357                    value2 *= window->kernel[y][x];
     1358                }
     1359
     1360                fluxC1 += value1;
     1361                flux2  += value2;
     1362                fluxX  += x * value2;
     1363                fluxY  += y * value2;
     1364                // fluxX2 += PS_SQR(x) * value2;
     1365                // fluxY2 += PS_SQR(y) * value2;
     1366                fluxX2 += PS_SQR(x) * value1;
     1367                fluxY2 += PS_SQR(y) * value1;
     1368            }
     1369        }
     1370        // float Mx = fluxX / flux2;
     1371        // float My = fluxY / flux2;
     1372        // float Mxx = fluxX2 / flux2;
     1373        // float Myy = fluxY2 / flux2;
     1374        float Mxx = fluxX2 / fluxC1;
     1375        float Myy = fluxY2 / fluxC1;
     1376
     1377        // fprintf (stderr, "conv1, flux2: %f, Mx: %f, My: %f, Mxx: %f, Myy: %f, chisq: %f, npix: %d\n", flux2, Mx, My, Mxx, Myy, chisq, npix);
     1378        moment += Mxx + Myy;
     1379    }
     1380
     1381    // get the moments from convolved1
     1382    if (convolved2) {
     1383        for (int y = residual->yMin; y <= residual->yMax; y++) {
     1384            for (int x = residual->xMin; x <= residual->xMax; x++) {
     1385                value1  = convolved2->kernel[y][x];
     1386                value2  = PS_SQR(value1);
     1387
     1388                // XXX NOTE: do NOT apply the weight to the moments calculation
     1389                if (false && weight) {
    13481390                    value2 *= weight->kernel[y][x];
    13491391                }
     
    13531395                }
    13541396
    1355                 fluxC1 += value1;
     1397                fluxC2 += value1;
    13561398                flux2  += value2;
    13571399                fluxX  += x * value2;
    13581400                fluxY  += y * value2;
    1359                 fluxX2 += PS_SQR(x) * value2;
    1360                 fluxY2 += PS_SQR(y) * value2;
     1401                // fluxX2 += PS_SQR(x) * value2;
     1402                // fluxY2 += PS_SQR(y) * value2;
     1403                fluxX2 += PS_SQR(x) * value1;
     1404                fluxY2 += PS_SQR(y) * value1;
    13611405            }
    13621406        }
    13631407        // float Mx = fluxX / flux2;
    13641408        // float My = fluxY / flux2;
    1365         float Mxx = fluxX2 / flux2;
    1366         float Myy = fluxY2 / flux2;
    1367 
    1368         // fprintf (stderr, "conv1, flux2: %f, Mx: %f, My: %f, Mxx: %f, Myy: %f, chisq: %f, npix: %d\n", flux2, Mx, My, Mxx, Myy, chisq, npix);
    1369         moment += Mxx + Myy;
    1370     }
    1371 
    1372     // get the moments from convolved1
    1373     if (convolved2) {
    1374         for (int y = residual->yMin; y <= residual->yMax; y++) {
    1375             for (int x = residual->xMin; x <= residual->xMax; x++) {
    1376                 value1  = convolved2->kernel[y][x];
    1377                 value2  = PS_SQR(value1);
    1378 
    1379                 if (weight) {
    1380                     value2 *= weight->kernel[y][x];
    1381                 }
    1382                 if (window) {
    1383                     value1 *= window->kernel[y][x];
    1384                     value2 *= window->kernel[y][x];
    1385                 }
    1386 
    1387                 fluxC2 += value1;
    1388                 flux2  += value2;
    1389                 fluxX  += x * value2;
    1390                 fluxY  += y * value2;
    1391                 fluxX2 += PS_SQR(x) * value2;
    1392                 fluxY2 += PS_SQR(y) * value2;
    1393             }
    1394         }
    1395         // float Mx = fluxX / flux2;
    1396         // float My = fluxY / flux2;
    1397         float Mxx = fluxX2 / flux2;
    1398         float Myy = fluxY2 / flux2;
     1409        // float Mxx = fluxX2 / flux2;
     1410        // float Myy = fluxY2 / flux2;
     1411        float Mxx = fluxX2 / fluxC2;
     1412        float Myy = fluxY2 / fluxC2;
    13991413
    14001414        // fprintf (stderr, "conv2, flux2: %f, Mx: %f, My: %f, Mxx: %f, Myy: %f, chisq: %f, npix: %d\n", flux2, Mx, My, Mxx, Myy, chisq, npix);
     
    14101424    psVectorAppend(momentVector, moment);
    14111425    psVectorAppend(fluxesVector, flux);
     1426    psVectorAppend(stampMask, 0);
    14121427    return true;
    14131428}
    14141429
    1415 // typedef struct {
    1416 //     float moment;
    1417 //     float chisq;
    1418 // } diffStat;
    1419 
    1420 bool pmSubtractionCalculateChisqAndMoments(pmSubtractionStampList *stamps,
     1430bool pmSubtractionCalculateChisqAndMoments(pmSubtractionQuality **bestMatch,
     1431                                           pmSubtractionStampList *stamps,
    14211432                                           pmSubtractionKernels *kernels)
    14221433{
     
    14251436    PM_ASSERT_SUBTRACTION_KERNELS_SOLUTION(kernels, NULL);
    14261437
     1438    psTimerStart("pmSubtractionCalculateChisqAndMoments");
     1439
     1440    // XXX need to save these somewhere
    14271441    psVector *fluxes = psVectorAllocEmpty(stamps->num, PS_TYPE_F32);
    14281442    psVector *chisq = psVectorAllocEmpty(stamps->num, PS_TYPE_F32);
    14291443    psVector *moments = psVectorAllocEmpty(stamps->num, PS_TYPE_F32);
     1444    psVector *stampMask = psVectorAllocEmpty(stamps->num, PS_TYPE_VECTOR_MASK);
    14301445
    14311446    int footprint = stamps->footprint; // Half-size of stamps
     
    14341449    psImage *polyValues = NULL;         // Polynomial values
    14351450
     1451    // storage for the image (convolved2 is not used in SINGLE mode)
    14361452    psKernel *residual = psKernelAlloc(-footprint, footprint, -footprint, footprint); // Residual image
    1437 
    1438     // storage for the convolved source image (only convolved1 is used in SINGLE mode)
    14391453    psKernel *convolved1 = psKernelAlloc(-footprint, footprint, -footprint, footprint); // Residual image
    14401454    psKernel *convolved2 = psKernelAlloc(-footprint, footprint, -footprint, footprint); // Residual image
    14411455
     1456    int nGood = 0;
    14421457    for (int i = 0; i < stamps->num; i++) {
    14431458        pmSubtractionStamp *stamp = stamps->stamps->data[i]; // The stamp of interest
    14441459        if (stamp->status != PM_SUBTRACTION_STAMP_USED) {
     1460            // mark this stamp as unused (note that we have to append NANs to the other vectors to keep the lengths in sync)
     1461            psVectorAppend(moments, NAN);
     1462            psVectorAppend(fluxes, NAN);
     1463            psVectorAppend(chisq, NAN);
     1464            psVectorAppend(stampMask, 0x01);
    14451465            continue;
    14461466        }
     1467        nGood ++;
    14471468
    14481469        // Calculate coefficients of the kernel basis functions
     
    14541475        psImageInit(residual->image, 0.0);
    14551476
    1456     psKernel *weight = NULL;
    1457     psKernel *window = NULL;
    1458 
     1477        psKernel *weight = NULL;
     1478        psKernel *window = NULL;
     1479   
    14591480#ifdef USE_WEIGHT
    14601481    weight = stamp->weight;
     
    15111532            }
    15121533            // XXX if we want to have a weight and window, we'll need to pass through to here
    1513             pmSubtractionChisqStats(fluxes, chisq, moments, convolved1, NULL, residual, weight, window);
     1534            pmSubtractionChisqStats(fluxes, chisq, moments, stampMask, convolved1, NULL, residual, weight, window);
    15141535
    15151536        } else {
     
    15551576            }
    15561577
    1557             pmSubtractionChisqStats(fluxes, chisq, moments, convolved1, convolved2, residual, weight, window);
    1558         }
    1559     }
    1560 
    1561     pmSubtractionVisualPlotChisqAndMoments(fluxes, chisq, moments);
     1578            pmSubtractionChisqStats(fluxes, chisq, moments, stampMask, convolved1, convolved2, residual, weight, window);
     1579        }
     1580    }
    15621581
    15631582    // find the mean chisq and mean moment
    15641583    psStats *stats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
    1565     psVectorStats (stats, chisq, NULL, NULL, 0);
     1584    psVectorStats (stats, chisq, NULL, stampMask, 0xff);
    15661585    float chisqValue = stats->sampleMean;
    15671586
    15681587    psStatsInit(stats);
    1569     psVectorStats (stats, moments, NULL, NULL, 0);
     1588    psVectorStats (stats, moments, NULL, stampMask, 0xff);
    15701589    float momentValue = stats->sampleMean;
    15711590
    1572     fprintf (stderr, "chisq: %f, moment: %f\n", chisqValue, momentValue);
     1591    // XXX this is probably wrong : I want to score against higher moments **compared with the raw momements**
     1592    // score : chisq * dMoments * modeFactor
     1593    float modeFactor = kernels->mode == PM_SUBTRACTION_MODE_DUAL ? 2.0 : 1.0;
     1594    float orderFactor = 0.5*(kernels->spatialOrder + 1) * (kernels->spatialOrder + 2);
     1595    float score = chisqValue * momentValue * modeFactor * orderFactor;
     1596
     1597    fprintf (stderr, "chisq: %f, moment: %f, score: %f\n", chisqValue, momentValue, score);
     1598
     1599    // save this result if it is the first or the best (skip if bestMatch is NULL)
     1600    if (bestMatch) {
     1601        pmSubtractionQuality *match = *bestMatch;
     1602        bool keep = false;
     1603        if (match == NULL) {
     1604            *bestMatch = match = pmSubtractionQualityAlloc();
     1605            keep = true;
     1606        } else {
     1607            if (score < match->score) {
     1608                psFree(match->fluxes);
     1609                psFree(match->chisq);
     1610                psFree(match->moments);
     1611                psFree(match->stampMask);
     1612                keep = true;
     1613            }
     1614        }
     1615        if (keep) {
     1616            fprintf (stderr, "keeping order: %d, mode: %d, score: %f\n", kernels->spatialOrder, kernels->mode, score);
     1617            match->score        = score;
     1618            match->spatialOrder = kernels->spatialOrder;
     1619            match->mode         = kernels->mode;
     1620            match->nGood        = nGood;
     1621            match->fluxes       = psMemIncrRefCounter(fluxes);
     1622            match->chisq        = psMemIncrRefCounter(chisq);
     1623            match->moments      = psMemIncrRefCounter(moments);
     1624            match->stampMask    = psMemIncrRefCounter(stampMask);
     1625        }           
     1626    }
     1627
     1628    pmSubtractionVisualPlotChisqAndMoments(fluxes, chisq, moments);
    15731629
    15741630    psFree(stats);
     
    15761632    psFree(fluxes);
    15771633    psFree(moments);
     1634    psFree(stampMask);
    15781635
    15791636    psFree(residual);
     
    15821639    psFree(polyValues);
    15831640
     1641    psLogMsg("psModules.imcombine", PS_LOG_INFO, "Calculate Chisq and Moments: %f sec", psTimerClear("pmSubtractionCalculateChisqAndMoments"));
     1642
    15841643    return true;
    15851644}
    15861645
    1587 psVector *pmSubtractionCalculateDeviations(pmSubtractionStampList *stamps,
    1588                                           pmSubtractionKernels *kernels)
     1646// XXX for now, let's not use this, and let's instead just use values from pmSubtractionCalculateChisqAndMoments
     1647psVector *pmSubtractionCalculateDeviations(pmSubtractionStampList *stamps, pmSubtractionKernels *kernels)
    15891648{
    15901649    PM_ASSERT_SUBTRACTION_STAMP_LIST_NON_NULL(stamps, NULL);
    15911650    PM_ASSERT_SUBTRACTION_KERNELS_NON_NULL(kernels, NULL);
    15921651    PM_ASSERT_SUBTRACTION_KERNELS_SOLUTION(kernels, NULL);
     1652
     1653    psTimerStart("pmSubtractionCalculateDeviations");
    15931654
    15941655    psVector *deviations = psVectorAlloc(stamps->num, PS_TYPE_F32); // Mean deviation for stamps
     
    16001661    psImage *polyValues = NULL;         // Polynomial values
    16011662    psKernel *residual = psKernelAlloc(-footprint, footprint, -footprint, footprint); // Residual image
    1602 
    1603     // set up holding images for the visualization
    1604     pmSubtractionVisualShowFitInit (stamps);
    16051663
    16061664    psVector *fResSigma = psVectorAllocEmpty(stamps->num, PS_TYPE_F32);
     
    17031761            }
    17041762
    1705             // XXX visualize the target, source, convolution and residual
    1706             pmSubtractionVisualShowFitAddStamp (target, source, residual, background, norm, i);
    1707 
    17081763            for (int y = - footprint; y <= footprint; y++) {
    17091764                for (int x = - footprint; x <= footprint; x++) {
     
    17401795            }
    17411796
    1742             // XXX visualize the target, source, convolution and residual
    1743             pmSubtractionVisualShowFitAddStamp (image2, image1, residual, background, norm, i);
    1744 
    17451797            for (int y = - footprint; y <= footprint; y++) {
    17461798                for (int x = - footprint; x <= footprint; x++) {
     
    17571809        }
    17581810
     1811        double flux = 0.0;
    17591812        double deviation = 0.0;         // Sum of differences
    17601813        for (int y = - footprint; y <= footprint; y++) {
     
    17621815                double dev = PS_SQR(residual->kernel[y][x]) * weight->kernel[y][x];
    17631816                deviation += dev;
    1764 #ifdef TESTING
    1765                 residual->kernel[y][x] = dev;
    1766 #endif
     1817                flux += stamp->image1->kernel[y][x] + stamp->image2->kernel[y][x];
    17671818            }
    17681819        }
    17691820        deviations->data.F32[i] = devNorm * deviation;
    1770         psTrace("psModules.imcombine", 5, "Deviation for stamp %d (%d,%d): %f\n",
    1771                 i, (int)(stamp->x - 0.5), (int)(stamp->y - 0.5), deviations->data.F32[i]);
     1821        psTrace("psModules.imcombine", 5, "Deviation and Flux for stamp %d (%d,%d): %f %f\n",
     1822                i, (int)(stamp->x - 0.5), (int)(stamp->y - 0.5), deviations->data.F32[i], flux);
    17721823        psStringAppend(&log, "Stamp %d (%d,%d): %f\n",
    17731824                       i, (int)(stamp->x - 0.5), (int)(stamp->y - 0.5), deviations->data.F32[i]);
    17741825        if (!isfinite(deviations->data.F32[i])) {
    17751826            stamp->status = PM_SUBTRACTION_STAMP_REJECTED;
    1776             psTrace("psModules.imcombine", 5,
    1777                     "Rejecting stamp %d (%d,%d) because of non-finite deviation\n",
    1778                     i, (int)(stamp->x - 0.5), (int)(stamp->y - 0.5));
     1827            psTrace("psModules.imcombine", 5, "Rejecting stamp %d (%d,%d) because of non-finite deviation\n", i, (int)(stamp->x - 0.5), (int)(stamp->y - 0.5));
    17791828            continue;
    17801829        }
    1781 
    1782 #ifdef TESTING
    1783         {
    1784             psString filename = NULL;
    1785             psStringAppend(&filename, "resid_%03d.fits", i);
    1786             psFits *fits = psFitsOpen(filename, "w");
    1787             psFree(filename);
    1788             psFitsWriteImage(fits, NULL, residual->image, 0, NULL);
    1789             psFitsClose(fits);
    1790         }
    1791         if (stamp->image1) {
    1792             psString filename = NULL;
    1793             psStringAppend(&filename, "stamp_image1_%03d.fits", i);
    1794             psFits *fits = psFitsOpen(filename, "w");
    1795             psFree(filename);
    1796             psFitsWriteImage(fits, NULL, stamp->image1->image, 0, NULL);
    1797             psFitsClose(fits);
    1798         }
    1799         if (stamp->image2) {
    1800             psString filename = NULL;
    1801             psStringAppend(&filename, "stamp_image2_%03d.fits", i);
    1802             psFits *fits = psFitsOpen(filename, "w");
    1803             psFree(filename);
    1804             psFitsWriteImage(fits, NULL, stamp->image2->image, 0, NULL);
    1805             psFitsClose(fits);
    1806         }
    1807         if (stamp->weight) {
    1808             psString filename = NULL;
    1809             psStringAppend(&filename, "stamp_weight_%03d.fits", i);
    1810             psFits *fits = psFitsOpen(filename, "w");
    1811             psFree(filename);
    1812             psFitsWriteImage(fits, NULL, stamp->weight->image, 0, NULL);
    1813             psFitsClose(fits);
    1814         }
    1815 #endif
    1816 
    18171830    }
    18181831
     
    18291842        psLogMsg("psModules.imcombine", PS_LOG_INFO, "normalization: %f, background: %f", norm, background);
    18301843
    1831         pmSubtractionVisualShowFit(norm);
    1832         pmSubtractionVisualPlotFit(kernels);
    1833 
    18341844        psStats *stats = psStatsAlloc(PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV);
    18351845        psVectorStats (stats, fResSigma, NULL, NULL, 0);
     
    18621872    psFree(polyValues);
    18631873
     1874    psLogMsg("psModules.imcombine", PS_LOG_INFO, "Calculate Deviations: %f sec", psTimerClear("pmSubtractionCalculateDeviations"));
     1875
    18641876    return deviations;
    1865 }
    1866 
    1867 // we are supplied U, not Ut; w represents a diagonal matrix (also, we apply 1/w instead of w)
    1868 psImage *p_pmSubSolve_wUt (psVector *w, psImage *U) {
    1869 
    1870     psAssert (w->n == U->numCols, "w and U dimensions do not match");
    1871 
    1872     // wUt has dimensions transposed relative to Ut.
    1873     psImage *wUt = psImageAlloc (U->numRows, U->numCols, PS_TYPE_F64);
    1874     psImageInit (wUt, 0.0);
    1875 
    1876     for (int i = 0; i < wUt->numCols; i++) {
    1877         for (int j = 0; j < wUt->numRows; j++) {
    1878             if (!isfinite(w->data.F64[j])) continue;
    1879             if (w->data.F64[j] == 0.0) continue;
    1880             wUt->data.F64[j][i] = U->data.F64[i][j] / w->data.F64[j];
    1881         }
    1882     }
    1883     return wUt;
    1884 }
    1885 
    1886 // XXX this is just standard matrix multiplication: use psMatrixMultiply?
    1887 psImage *p_pmSubSolve_VwUt (psImage *V, psImage *wUt) {
    1888 
    1889     psAssert (V->numCols == wUt->numRows, "matrix dimensions do not match");
    1890 
    1891     psImage *Ainv = psImageAlloc (wUt->numCols, V->numRows, PS_TYPE_F64);
    1892 
    1893     for (int i = 0; i < Ainv->numCols; i++) {
    1894         for (int j = 0; j < Ainv->numRows; j++) {
    1895             double sum = 0.0;
    1896             for (int k = 0; k < V->numCols; k++) {
    1897                 sum += V->data.F64[j][k] * wUt->data.F64[k][i];
    1898             }
    1899             Ainv->data.F64[j][i] = sum;
    1900         }
    1901     }
    1902     return Ainv;
    1903 }
    1904 
    1905 // we are supplied U, not Ut
    1906 bool p_pmSubSolve_UtB (psVector **UtB, psImage *U, psVector *B) {
    1907 
    1908     psAssert (U->numRows == B->n, "U and B dimensions do not match");
    1909 
    1910     UtB[0] = psVectorRecycle (UtB[0], U->numCols, PS_TYPE_F64);
    1911 
    1912     for (int i = 0; i < U->numCols; i++) {
    1913         double sum = 0.0;
    1914         for (int j = 0; j < U->numRows; j++) {
    1915             sum += B->data.F64[j] * U->data.F64[j][i];
    1916         }
    1917         UtB[0]->data.F64[i] = sum;
    1918     }
    1919     return true;
    1920 }
    1921 
    1922 // w is diagonal
    1923 bool p_pmSubSolve_wUtB (psVector **wUtB, psVector *w, psVector *UtB) {
    1924 
    1925     psAssert (w->n == UtB->n, "w and UtB dimensions do not match");
    1926 
    1927     // wUt has dimensions transposed relative to Ut.
    1928     wUtB[0] = psVectorRecycle (wUtB[0], w->n, PS_TYPE_F64);
    1929     psVectorInit (wUtB[0], 0.0);
    1930 
    1931     for (int i = 0; i < w->n; i++) {
    1932         if (!isfinite(w->data.F64[i])) continue;
    1933         if (w->data.F64[i] == 0.0) continue;
    1934         wUtB[0]->data.F64[i] = UtB->data.F64[i] / w->data.F64[i];
    1935     }
    1936     return true;
    1937 }
    1938 
    1939 // this is basically matrix * vector
    1940 bool p_pmSubSolve_VwUtB (psVector **VwUtB, psImage *V, psVector *wUtB) {
    1941 
    1942     psAssert (V->numCols == wUtB->n, "V and wUtB dimensions do not match");
    1943 
    1944     VwUtB[0] = psVectorRecycle (*VwUtB, V->numRows, PS_TYPE_F64);
    1945 
    1946     for (int j = 0; j < V->numRows; j++) {
    1947         double sum = 0.0;
    1948         for (int i = 0; i < V->numCols; i++) {
    1949             sum += V->data.F64[j][i] * wUtB->data.F64[i];
    1950         }
    1951         VwUtB[0]->data.F64[j] = sum;
    1952     }
    1953     return true;
    1954 }
    1955 
    1956 // this is basically matrix * vector
    1957 bool p_pmSubSolve_Ax (psVector **B, psImage *A, psVector *x) {
    1958 
    1959     psAssert (A->numCols == x->n, "A and x dimensions do not match");
    1960 
    1961     B[0] = psVectorRecycle (*B, A->numRows, PS_TYPE_F64);
    1962 
    1963     for (int j = 0; j < A->numRows; j++) {
    1964         double sum = 0.0;
    1965         for (int i = 0; i < A->numCols; i++) {
    1966             sum += A->data.F64[j][i] * x->data.F64[i];
    1967         }
    1968         B[0]->data.F64[j] = sum;
    1969     }
    1970     return true;
    1971 }
    1972 
    1973 // this is basically Vector * vector
    1974 bool p_pmSubSolve_VdV (double *value, psVector *x, psVector *y) {
    1975 
    1976     psAssert (x->n == y->n, "x and y dimensions do not match");
    1977 
    1978     double sum = 0.0;
    1979     for (int i = 0; i < x->n; i++) {
    1980         sum += x->data.F64[i] * y->data.F64[i];
    1981     }
    1982     *value = sum;
    1983     return true;
    1984 }
    1985 
    1986 bool p_pmSubSolve_y2 (double *y2, pmSubtractionKernels *kernels, const pmSubtractionStampList *stamps) {
    1987 
    1988     int footprint = stamps->footprint; // Half-size of stamps
    1989 
    1990     double sum = 0.0;
    1991     for (int i = 0; i < stamps->num; i++) {
    1992 
    1993         pmSubtractionStamp *stamp = stamps->stamps->data[i];
    1994         if (stamp->status != PM_SUBTRACTION_STAMP_USED) continue;
    1995 
    1996         psKernel *weight = NULL;
    1997         psKernel *window = NULL;
    1998         psKernel *input = NULL;
    1999 
    2000 #ifdef USE_WEIGHT
    2001         weight = stamp->weight;
    2002 #endif
    2003 #ifdef USE_WINDOW
    2004         window = stamps->window;
    2005 #endif
    2006 
    2007         switch (kernels->mode) {
    2008             // MODE_1 : convolve image 1 to match image 2 (and vice versa)
    2009           case PM_SUBTRACTION_MODE_1:
    2010             input = stamp->image2;
    2011             break;
    2012           case PM_SUBTRACTION_MODE_2:
    2013             input = stamp->image1;
    2014             break;
    2015           default:
    2016             psAbort ("programming error");
    2017         }
    2018 
    2019         for (int y = - footprint; y <= footprint; y++) {
    2020             for (int x = - footprint; x <= footprint; x++) {
    2021                 double in = input->kernel[y][x];
    2022                 double value = in*in;
    2023                 if (weight) {
    2024                     float wtVal = weight->kernel[y][x];
    2025                     value *= wtVal;
    2026                 }
    2027                 if (window) {
    2028                     float  winVal = window->kernel[y][x];
    2029                     value *= winVal;
    2030                 }
    2031                 sum += value;
    2032             }
    2033         }
    2034     }
    2035     *y2 = sum;
    2036     return true;
    2037 }
    2038 
    2039 double p_pmSubSolve_ChiSquare (pmSubtractionKernels *kernels, const pmSubtractionStampList *stamps) {
    2040 
    2041     int footprint = stamps->footprint; // Half-size of stamps
    2042     int numKernels = kernels->num;      // Number of kernels
    2043 
    2044     double sum = 0.0;
    2045 
    2046     psKernel *residual = psKernelAlloc(-footprint, footprint, -footprint, footprint); // Residual image
    2047     psImageInit(residual->image, 0.0);
    2048 
    2049     psImage *polyValues = NULL;         // Polynomial values
    2050 
    2051     for (int i = 0; i < stamps->num; i++) {
    2052 
    2053         pmSubtractionStamp *stamp = stamps->stamps->data[i];
    2054         if (stamp->status != PM_SUBTRACTION_STAMP_USED) continue;
    2055 
    2056         psKernel *weight = NULL;
    2057         psKernel *window = NULL;
    2058         psKernel *target = NULL;
    2059         psKernel *source = NULL;
    2060 
    2061         psArray *convolutions = NULL;
    2062 
    2063 #ifdef USE_WEIGHT
    2064         weight = stamp->weight;
    2065 #endif
    2066 #ifdef USE_WINDOW
    2067         window = stamps->window;
    2068 #endif
    2069 
    2070         switch (kernels->mode) {
    2071             // MODE_1 : convolve image 1 to match image 2 (and vice versa)
    2072           case PM_SUBTRACTION_MODE_1:
    2073             target = stamp->image2;
    2074             source = stamp->image1;
    2075             convolutions = stamp->convolutions1;
    2076             break;
    2077           case PM_SUBTRACTION_MODE_2:
    2078             target = stamp->image1;
    2079             source = stamp->image2;
    2080             convolutions = stamp->convolutions2;
    2081             break;
    2082           default:
    2083             psAbort ("programming error");
    2084         }
    2085 
    2086         // Calculate coefficients of the kernel basis functions
    2087         polyValues = p_pmSubtractionPolynomial(polyValues, kernels->spatialOrder, stamp->xNorm, stamp->yNorm);
    2088         double norm = p_pmSubtractionSolutionNorm(kernels); // Normalisation
    2089         double background = p_pmSubtractionSolutionBackground(kernels, polyValues);// Difference in background
    2090 
    2091         psImageInit(residual->image, 0.0);
    2092         for (int j = 0; j < numKernels; j++) {
    2093             psKernel *convolution = convolutions->data[j]; // Convolution
    2094             double coefficient = p_pmSubtractionSolutionCoeff(kernels, polyValues, j, false); // Coefficient
    2095             for (int y = - footprint; y <= footprint; y++) {
    2096                 for (int x = - footprint; x <= footprint; x++) {
    2097                     residual->kernel[y][x] -= convolution->kernel[y][x] * coefficient;
    2098                 }
    2099             }
    2100         }
    2101 
    2102         for (int y = - footprint; y <= footprint; y++) {
    2103             for (int x = - footprint; x <= footprint; x++) {
    2104                 double resid = target->kernel[y][x] - background - source->kernel[y][x] * norm + residual->kernel[y][x];
    2105                 double value = PS_SQR(resid);
    2106                 if (weight) {
    2107                     float wtVal = weight->kernel[y][x];
    2108                     value *= wtVal;
    2109                 }
    2110                 if (window) {
    2111                     float  winVal = window->kernel[y][x];
    2112                     value *= winVal;
    2113                 }
    2114                 sum += value;
    2115             }
    2116         }
    2117     }
    2118     psFree (polyValues);
    2119     psFree (residual);
    2120 
    2121     return sum;
    2122 }
    2123 
    2124 bool p_pmSubSolve_SetWeights (psVector *wApply, psVector *w, psVector *wMask) {
    2125 
    2126     for (int i = 0; i < w->n; i++) {
    2127         wApply->data.F64[i] = wMask->data.U8[i] ? 0.0 : w->data.F64[i];
    2128     }
    2129     return true;
    2130 }
    2131 
    2132 // we are supplied V and w; w represents a diagonal matrix (also, we apply 1/w instead of w)
    2133 psImage *p_pmSubSolve_Xvar (psImage *V, psVector *w) {
    2134 
    2135     psAssert (w->n == V->numCols, "w and U dimensions do not match");
    2136 
    2137     psImage *Vn = psImageAlloc (V->numCols, V->numRows, PS_TYPE_F64);
    2138     psImageInit (Vn, 0.0);
    2139 
    2140     // generate Vn = V * w^{-1}
    2141     for (int j = 0; j < Vn->numRows; j++) {
    2142         for (int i = 0; i < Vn->numCols; i++) {
    2143             if (!isfinite(w->data.F64[i])) continue;
    2144             if (w->data.F64[i] == 0.0) continue;
    2145             Vn->data.F64[j][i] = V->data.F64[j][i] / w->data.F64[i];
    2146         }
    2147     }
    2148 
    2149     psImage *Xvar = psImageAlloc (V->numCols, V->numRows, PS_TYPE_F64);
    2150     psImageInit (Xvar, 0.0);
    2151 
    2152     // generate Xvar = Vn * Vn^T
    2153     for (int j = 0; j < Vn->numRows; j++) {
    2154         for (int i = 0; i < Vn->numCols; i++) {
    2155             double sum = 0.0;
    2156             for (int k = 0; k < Vn->numCols; k++) {
    2157                 sum += Vn->data.F64[k][i]*Vn->data.F64[k][j];
    2158             }
    2159             Xvar->data.F64[j][i] = sum;
    2160         }
    2161     }
    2162     return Xvar;
    21631877}
    21641878
     
    21661880// of the elements of an image A(x,y) = A->data.F64[y][x] = A_x,y, a matrix
    21671881// multiplication is: A_k,j * B_i,k = C_i,j
    2168 
    21691882
    21701883bool psFitsWriteImageSimple (char *filename, psImage *image, psMetadata *header) {
  • branches/eam_branches/ipp-20101205/psModules/src/imcombine/pmSubtractionEquation.h

    r30266 r30289  
    44#include "pmSubtractionStamps.h"
    55#include "pmSubtractionKernels.h"
     6#include "pmSubtraction.h"
    67
    7 typedef enum {
    8     PM_SUBTRACTION_EQUATION_NONE    = 0x00,
    9     PM_SUBTRACTION_EQUATION_NORM    = 0x01,
    10     PM_SUBTRACTION_EQUATION_BG      = 0x02,
    11     PM_SUBTRACTION_EQUATION_KERNELS = 0x04,
    12     PM_SUBTRACTION_EQUATION_ALL     = 0x07, // value should be NORM | BG | KERNELS
    13 } pmSubtractionEquationCalculationMode;
     8// typedef enum {
     9//     PM_SUBTRACTION_EQUATION_NONE    = 0x00,
     10//     PM_SUBTRACTION_EQUATION_NORM    = 0x01,
     11//     PM_SUBTRACTION_EQUATION_BG      = 0x02,
     12//     PM_SUBTRACTION_EQUATION_KERNELS = 0x04,
     13//     PM_SUBTRACTION_EQUATION_ALL     = 0x07, // value should be NORM | BG | KERNELS
     14// } pmSubtractionEquationCalculationMode;
    1415
    1516/// Execute a thread job to calculate the least-squares equation for a stamp
     
    2021bool pmSubtractionCalculateEquationStamp(pmSubtractionStampList *stamps, ///< Stamps
    2122                                         pmSubtractionKernels *kernels, ///< Kernel parameters
    22                                          int index, ///< Index of stamp
    23                                          const pmSubtractionEquationCalculationMode mode
     23                                         int index ///< Index of stamp
    2424    );
    2525
    2626/// Calculate the least-squares equation to match the image quality
    2727bool pmSubtractionCalculateEquation(pmSubtractionStampList *stamps, ///< Stamps
    28                                     pmSubtractionKernels *kernels, ///< Kernel parameters
    29                                     const pmSubtractionEquationCalculationMode mode
     28                                    pmSubtractionKernels *kernels ///< Kernel parameters
    3029    );
    3130
    3231/// Solve the least-squares equation to match the image quality
    3332bool pmSubtractionSolveEquation(pmSubtractionKernels *kernels, ///< Kernel parameters
    34                                 const pmSubtractionStampList *stamps, ///< Stamps
    35                                 const pmSubtractionEquationCalculationMode mode
     33                                const pmSubtractionStampList *stamps ///< Stamps
    3634    );
    3735
     
    9290bool pmSubtractionCalculateMomentsKernel(double *Mxx, double *Myy, psKernel *image, int footprint, int window);
    9391
    94 bool pmSubtractionChisqStats(psVector *fluxesVector, psVector *chisqVector, psVector *momentVector, psKernel *convolved1, psKernel *convolved2, psKernel *residual, psKernel *weight, psKernel *window);
     92bool pmSubtractionChisqStats(psVector *fluxesVector, psVector *chisqVector, psVector *momentVector, psVector *stampMask, psKernel *convolved1, psKernel *convolved2, psKernel *residual, psKernel *weight, psKernel *window);
    9593
    96 bool pmSubtractionCalculateChisqAndMoments(pmSubtractionStampList *stamps,
    97                                            pmSubtractionKernels *kernels);
    98 
     94bool pmSubtractionCalculateChisqAndMoments(pmSubtractionQuality **bestMatch, pmSubtractionStampList *stamps, pmSubtractionKernels *kernels);
    9995#endif
  • branches/eam_branches/ipp-20101205/psModules/src/imcombine/pmSubtractionStamps.c

    r30266 r30289  
    122122            if ((image1 && image1->data.F32[y][x] < thresh1) ||
    123123                (image2 && image2->data.F32[y][x] < thresh2)) {
     124                // fprintf (stderr, "%f,%f : thresh\n", xRaw, yRaw);
    124125                continue;
    125126            }
     
    429430        stamps = pmSubtractionStampListAlloc(numCols, numRows, region, footprint, spacing,
    430431                                             normFrac, sysErr, skyErr);
     432    }
     433
     434    // XXX TEST : dump all stars in the stamps here
     435    if (0) {
     436        FILE *f = fopen ("stamp.dat", "w");
     437        for (int i = 0; i < stamps->num; i++) {
     438            psVector *xList = stamps->x->data[i];
     439            psVector *yList = stamps->y->data[i]; // Coordinate lists
     440            psVector *fluxList = stamps->flux->data[i]; // List of stamp fluxes
     441
     442            for (int j = 0; j < xList->n; j++) {
     443                fprintf (f, "%d %d  %f %f  %f\n", i, j, xList->data.F32[j], yList->data.F32[j], fluxList->data.F32[j]);
     444            }
     445        }
     446        fclose (f);
    431447    }
    432448
     
    636652    }
    637653
     654    int nTotal = 0;
     655
    638656    // Sort the list by flux, with the brightest last
    639657    for (int i = 0; i < numStamps; i++) {
     
    662680        stamps->y->data[i] = ySorted;
    663681        stamps->flux->data[i] = fluxSorted;
    664     }
    665 
     682        nTotal += num;
     683    }
     684    // fprintf (stderr, "nTotal %d\n", nTotal);
     685   
    666686    return stamps;
    667687}
     
    809829    float R2 = Sr2 / Sf2;
    810830
    811     stamps->normWindow1 = 2.0*R1;
    812     stamps->normWindow2 = 2.0*R2;
     831    stamps->normWindow1 = 2.75*R1;
     832    stamps->normWindow2 = 2.75*R2;
    813833    psLogMsg ("psModules.imcombine", PS_LOG_DETAIL, "Kron Radii: %f for 1, %f for 2\n", stamps->normWindow1, stamps->normWindow2);
    814834
    815835    // Generate a weighting window based on the kron radii
    816836    {
    817         float radius = 1.5 * PS_MAX(R1, R2);
     837        float radius = 2.0 * PS_MAX(R1, R2);
    818838
    819839        psImageInit(stamps->window->image, 0.0);
     
    826846        }
    827847    }
     848
     849    // complain if normWindow1 or normWindow2 are larger than size
     850    psAssert(stamps->normWindow1 < size, "norm Window 1 too large");
     851    psAssert(stamps->normWindow2 < size, "norm Window 2 too large");
    828852
    829853# else
     
    11421166            continue;
    11431167        }
     1168       
     1169        // XXX TEST
     1170        if (source->errMag > 0.1) continue;
     1171
    11441172        if (source->modelPSF) {
    11451173            x->data.F32[numOut] = source->modelPSF->params->data.F32[PM_PAR_XPOS];
  • branches/eam_branches/ipp-20101205/psModules/src/imcombine/pmSubtractionVisual.c

    r30266 r30289  
    2020#include "pmSubtractionEquation.h"
    2121#include "pmSubtractionKernels.h"
     22#include "pmSubtractionVisual.h"
    2223
    2324#include "pmVisual.h"
     
    423424    }
    424425
    425     // XXX clear the overlay(s) (red at least!)
     426    // clear the overlay (red at least!)
     427    KiiEraseOverlay (kapa2, "red");
    426428
    427429    // get the kernel sizes
     
    456458    int nKernels = 0;
    457459
     460    // paste in the kernel images, scaled by sum2
    458461    if (maxStamp->convolutions1) {
    459462        // output image is a grid of NXsub by NYsub sub-images
     
    478481            int yPix = ySub * (2*footprint + 1 + 3) + footprint;
    479482           
    480             double sum = 0.0;
    481483            double sum2 = 0.0;
    482484            for (int y = -footprint; y <= footprint; y++) {
    483485                for (int x = -footprint; x <= footprint; x++) {
    484                     output->data.F32[y + yPix][x + xPix] = kernel->kernel[y][x];
    485                     sum += kernel->kernel[y][x];
    486486                    sum2 += PS_SQR(kernel->kernel[y][x]);
    487487                }
    488488            }
    489             // fprintf (stderr, "kernel %d, sum %f, sum2: %e\n", i, sum, sum2);
     489            float scale = sqrt(sum2) / PS_SQR(2*footprint + 1);
     490            for (int y = -footprint; y <= footprint; y++) {
     491                for (int x = -footprint; x <= footprint; x++) {
     492                    output->data.F32[y + yPix][x + xPix] = kernel->kernel[y][x] / scale;
     493                }
     494            }
    490495        }               
    491496        pmVisualScaleImage(kapa2, output, "Image", 0, true);
     
    520525            int yPix = ySub * (2*footprint + 1 + 3) + footprint;
    521526           
    522             double sum = 0.0;
    523527            double sum2 = 0.0;
    524528            for (int y = -footprint; y <= footprint; y++) {
    525529                for (int x = -footprint; x <= footprint; x++) {
    526                     output->data.F32[y + yPix][x + xPix] = kernel->kernel[y][x];
    527                     sum += kernel->kernel[y][x];
    528530                    sum2 += PS_SQR(kernel->kernel[y][x]);
    529531                }
    530532            }
    531             // fprintf (stderr, "kernel %d, sum %f, sum2: %e\n", i, sum, sum2);
     533            float scale = sqrt(sum2) / PS_SQR(2*footprint + 1);
     534            for (int y = -footprint; y <= footprint; y++) {
     535                for (int x = -footprint; x <= footprint; x++) {
     536                    output->data.F32[y + yPix][x + xPix] = kernel->kernel[y][x] / scale;
     537                }
     538            }
    532539        }               
    533540        pmVisualScaleImage(kapa2, output, "Image", 1, true);
     
    587594    KiiLoadOverlay (kapa2, overlay, Noverlay, "red");
    588595    FREE (overlay);
    589     return true;
    590 }
    591 
    592 static int footprint = 0;
    593 static int NX = 0;
    594 static int NY = 0;
    595 static psImage *sourceImage      = NULL;
    596 static psImage *targetImage      = NULL;
    597 static psImage *residualImage    = NULL;
    598 static psImage *fresidualImage   = NULL;
    599 static psImage *differenceImage  = NULL;
    600 static psImage *convolutionImage = NULL;
    601 
    602 bool pmSubtractionVisualShowFitInit(pmSubtractionStampList *stamps) {
    603 
    604     if (!pmVisualTestLevel("ppsub.fit", 1)) return true;
    605 
    606     // generate 4 storage images large enough to hold the N stamps:
    607 
    608     footprint = stamps->footprint;
    609 
    610     float NXf = sqrt(stamps->num);
    611     NX = (int) NXf == NXf ? NXf : NXf + 1.0;
    612    
    613     float NYf = stamps->num / NX;
    614     NY = (int) NYf == NY ? NYf : NYf + 1.0;
    615 
    616     int NXpix = (2*footprint + 1) * NX;
    617     NXpix += (NX > 1) ? 3 * NX : 0;
    618 
    619     int NYpix = (2*footprint + 1) * NY;
    620     NYpix += (NY > 1) ? 3 * NY : 0;
    621 
    622     sourceImage      = psImageAlloc (NXpix, NYpix, PS_TYPE_F32);
    623     targetImage      = psImageAlloc (NXpix, NYpix, PS_TYPE_F32);
    624     residualImage    = psImageAlloc (NXpix, NYpix, PS_TYPE_F32);
    625     fresidualImage   = psImageAlloc (NXpix, NYpix, PS_TYPE_F32);
    626     differenceImage  = psImageAlloc (NXpix, NYpix, PS_TYPE_F32);
    627     convolutionImage = psImageAlloc (NXpix, NYpix, PS_TYPE_F32);
    628    
    629     psImageInit (sourceImage,      0.0);
    630     psImageInit (targetImage,      0.0);
    631     psImageInit (residualImage,    0.0);
    632     psImageInit (fresidualImage,   0.0);
    633     psImageInit (differenceImage,  0.0);
    634     psImageInit (convolutionImage, 0.0);
    635 
    636     return true;
    637 }
    638 
    639 bool pmSubtractionVisualShowFitAddStamp(psKernel *target, psKernel *source, psKernel *convolution, double background, double norm, int index) {
    640 
    641     if (!pmVisualTestLevel("ppsub.stamp", 1)) return true;
    642 
    643     double sum;
    644 
    645     int NXoff = index % NX;
    646     int NYoff = index / NX;
    647 
    648     int NXpix = NXoff * (2*footprint + 1 + 3) + footprint;
    649     int NYpix = NYoff * (2*footprint + 1 + 3) + footprint;
    650 
    651     // insert the (target) kernel into the (target) image:
    652     sum = 0.0;
    653     for (int y = -footprint; y <= footprint; y++) {
    654         for (int x = -footprint; x <= footprint; x++) {
    655             targetImage->data.F32[y + NYpix][x + NXpix] = target->kernel[y][x];
    656             sum += targetImage->data.F32[y + NYpix][x + NXpix];
    657         }
    658     }
    659     targetImage->data.F32[footprint + 1 + NYpix][NXpix] = sum;
    660 
    661     // insert the (source) kernel into the (source) image:
    662     sum = 0.0;
    663     for (int y = -footprint; y <= footprint; y++) {
    664         for (int x = -footprint; x <= footprint; x++) {
    665             sourceImage->data.F32[y + NYpix][x + NXpix] = source->kernel[y][x];
    666             sum += sourceImage->data.F32[y + NYpix][x + NXpix];
    667         }
    668     }
    669     sourceImage->data.F32[footprint + 1 + NYpix][NXpix] = sum;
    670 
    671     // insert the (convolution) kernel into the (convolution) image:
    672     sum = 0.0;
    673     for (int y = -footprint; y <= footprint; y++) {
    674         for (int x = -footprint; x <= footprint; x++) {
    675             convolutionImage->data.F32[y + NYpix][x + NXpix] = convolution->kernel[y][x];
    676             sum += convolutionImage->data.F32[y + NYpix][x + NXpix];
    677         }
    678     }
    679     convolutionImage->data.F32[footprint + 1 + NYpix][NXpix] = sum;
    680    
    681     // insert the (difference) kernel into the (difference) image:
    682     sum = 0.0;
    683     for (int y = -footprint; y <= footprint; y++) {
    684         for (int x = -footprint; x <= footprint; x++) {
    685             differenceImage->data.F32[y + NYpix][x + NXpix] = target->kernel[y][x] - background - source->kernel[y][x] * norm;
    686             sum += differenceImage->data.F32[y + NYpix][x + NXpix];
    687         }
    688     }
    689     differenceImage->data.F32[footprint + 1 + NYpix][NXpix] = sum;
    690 
    691     // insert the (residual) kernel into the (residual) image:
    692     sum = 0.0;
    693     for (int y = -footprint; y <= footprint; y++) {
    694         for (int x = -footprint; x <= footprint; x++) {
    695             residualImage->data.F32[y + NYpix][x + NXpix] = target->kernel[y][x] - background - source->kernel[y][x] * norm - convolution->kernel[y][x];
    696             sum += residualImage->data.F32[y + NYpix][x + NXpix];
    697         }
    698     }
    699     residualImage->data.F32[footprint + 1 + NYpix][NXpix] = sum;
    700 
    701     // insert the (fresidual) kernel into the (fresidual) image:
    702     for (int y = -footprint; y <= footprint; y++) {
    703         for (int x = -footprint; x <= footprint; x++) {
    704             fresidualImage->data.F32[y + NYpix][x + NXpix] = residualImage->data.F32[y + NYpix][x + NXpix] / sqrt(PS_MAX(target->kernel[y][x], 100.0));
    705         }
    706     }
    707596    return true;
    708597}
     
    730619}
    731620
    732 bool pmSubtractionVisualShowFit(double norm) {
    733 
    734     // for testing, dump the residual image and exit
    735     if (0) {
    736         psMetadata *header = psMetadataAlloc();
    737         psMetadataAddF32 (header, PS_LIST_TAIL, "NORM", 0, "Normalization", norm);
    738         psFits *fits = psFitsOpen("resid.fits", "w");
    739         psFitsWriteImage(fits, header, residualImage, 0, NULL);
    740         psFitsClose(fits);
    741         // exit (0);
    742     }
     621static int footprint = 0;
     622static int NX = 0;
     623static int NY = 0;
     624static psImage *sourceImage      = NULL;
     625static psImage *targetImage      = NULL;
     626static psImage *residualImage    = NULL;
     627static psImage *fresidualImage   = NULL;
     628static psImage *differenceImage  = NULL;
     629static psImage *convolutionImage = NULL;
     630
     631bool pmSubtractionVisualShowFit(pmSubtractionStampList *stamps, pmSubtractionKernels *kernels) {
    743632
    744633    if (!pmVisualTestLevel("ppsub.fit", 1)) return true;
     
    746635    if (!pmVisualInitWindow(&kapa1, "ppSub:Images")) return false;
    747636    if (!pmVisualInitWindow(&kapa2, "ppSub:Misc")) return false;
     637
     638    // set up holding images for the visualization
     639    pmSubtractionVisualShowFitInit (stamps);
     640
     641    int numKernels = kernels->num;      // Number of kernels
     642
     643    psImage *polyValues = NULL;         // Polynomial values
     644    psKernel *residual = psKernelAlloc(-stamps->footprint, stamps->footprint, -stamps->footprint, stamps->footprint); // Residual image
     645
     646    double norm = p_pmSubtractionSolutionNorm(kernels); // Normalisation
     647
     648    for (int i = 0; i < stamps->num; i++) {
     649        pmSubtractionStamp *stamp = stamps->stamps->data[i]; // The stamp of interest
     650        if (stamp->status != PM_SUBTRACTION_STAMP_USED) { continue; }
     651
     652        // Calculate coefficients of the kernel basis functions
     653        polyValues = p_pmSubtractionPolynomial(polyValues, kernels->spatialOrder, stamp->xNorm, stamp->yNorm);
     654        double background = p_pmSubtractionSolutionBackground(kernels, polyValues); // Difference in background
     655
     656        psImageInit(residual->image, 0.0);
     657
     658        if (kernels->mode != PM_SUBTRACTION_MODE_DUAL) {
     659            psKernel *target;           // Target postage stamp
     660            psKernel *source;           // Source postage stamp
     661            psArray *convolutions;      // Convolution postage stamps for each kernel basis function
     662            switch (kernels->mode) {
     663              case PM_SUBTRACTION_MODE_1:
     664                target = stamp->image2;
     665                source = stamp->image1;
     666                convolutions = stamp->convolutions1;
     667                break;
     668              case PM_SUBTRACTION_MODE_2:
     669                target = stamp->image1;
     670                source = stamp->image2;
     671                convolutions = stamp->convolutions2;
     672                break;
     673              default:
     674                psAbort("Unsupported subtraction mode: %x", kernels->mode);
     675            }
     676
     677            for (int j = 0; j < numKernels; j++) {
     678                psKernel *convolution = convolutions->data[j]; // Convolution
     679                double coefficient = p_pmSubtractionSolutionCoeff(kernels, polyValues, j, false); // Coefficient
     680                for (int y = - footprint; y <= footprint; y++) {
     681                    for (int x = - footprint; x <= footprint; x++) {
     682                        residual->kernel[y][x] += convolution->kernel[y][x] * coefficient;
     683                    }
     684                }
     685            }
     686            // visualize the target, source, convolution and residual
     687            pmSubtractionVisualShowFitAddStamp (target, source, residual, background, norm, i);
     688        } else {
     689            // Dual convolution
     690            psArray *convolutions1 = stamp->convolutions1; // Convolutions of the first image
     691            psArray *convolutions2 = stamp->convolutions2; // Convolutions of the second image
     692            psKernel *image1 = stamp->image1; // The first image
     693            psKernel *image2 = stamp->image2; // The second image
     694
     695            for (int j = 0; j < numKernels; j++) {
     696                psKernel *conv1 = convolutions1->data[j]; // Convolution of first image
     697                psKernel *conv2 = convolutions2->data[j]; // Convolution of second image
     698                double coeff1 = p_pmSubtractionSolutionCoeff(kernels, polyValues, j, false); // Coefficient 1
     699                double coeff2 = p_pmSubtractionSolutionCoeff(kernels, polyValues, j, true); // Coefficient 2
     700
     701                for (int y = - footprint; y <= footprint; y++) {
     702                    for (int x = - footprint; x <= footprint; x++) {
     703                        residual->kernel[y][x] += conv2->kernel[y][x] * coeff2 + conv1->kernel[y][x] * coeff1;
     704                    }
     705                }
     706            }
     707            // visualize the target, source, convolution and residual
     708            pmSubtractionVisualShowFitAddStamp (image2, image1, residual, background, norm, i);
     709        }
     710    }
     711    pmSubtractionVisualShowFitImage(norm);
     712
     713    return true;
     714}
     715
     716// generate 4 storage images large enough to hold the stamps:
     717bool pmSubtractionVisualShowFitInit(pmSubtractionStampList *stamps) {
     718
     719    footprint = stamps->footprint;
     720
     721    float NXf = sqrt(stamps->num);
     722    NX = (int) NXf == NXf ? NXf : NXf + 1.0;
     723   
     724    float NYf = stamps->num / NX;
     725    NY = (int) NYf == NY ? NYf : NYf + 1.0;
     726
     727    int NXpix = (2*footprint + 1) * NX;
     728    NXpix += (NX > 1) ? 3 * NX : 0;
     729
     730    int NYpix = (2*footprint + 1) * NY;
     731    NYpix += (NY > 1) ? 3 * NY : 0;
     732
     733    sourceImage      = psImageAlloc (NXpix, NYpix, PS_TYPE_F32);
     734    targetImage      = psImageAlloc (NXpix, NYpix, PS_TYPE_F32);
     735    residualImage    = psImageAlloc (NXpix, NYpix, PS_TYPE_F32);
     736    fresidualImage   = psImageAlloc (NXpix, NYpix, PS_TYPE_F32);
     737    differenceImage  = psImageAlloc (NXpix, NYpix, PS_TYPE_F32);
     738    convolutionImage = psImageAlloc (NXpix, NYpix, PS_TYPE_F32);
     739   
     740    psImageInit (sourceImage,      0.0);
     741    psImageInit (targetImage,      0.0);
     742    psImageInit (residualImage,    0.0);
     743    psImageInit (fresidualImage,   0.0);
     744    psImageInit (differenceImage,  0.0);
     745    psImageInit (convolutionImage, 0.0);
     746
     747    return true;
     748}
     749
     750bool pmSubtractionVisualShowFitAddStamp(psKernel *target, psKernel *source, psKernel *convolution, double background, double norm, int index) {
     751
     752    double sum;
     753
     754    int NXoff = index % NX;
     755    int NYoff = index / NX;
     756
     757    int NXpix = NXoff * (2*footprint + 1 + 3) + footprint;
     758    int NYpix = NYoff * (2*footprint + 1 + 3) + footprint;
     759
     760    // insert the (target) kernel into the (target) image:
     761    sum = 0.0;
     762    for (int y = -footprint; y <= footprint; y++) {
     763        for (int x = -footprint; x <= footprint; x++) {
     764            targetImage->data.F32[y + NYpix][x + NXpix] = target->kernel[y][x];
     765            sum += targetImage->data.F32[y + NYpix][x + NXpix];
     766        }
     767    }
     768    targetImage->data.F32[footprint + 1 + NYpix][NXpix] = sum;
     769
     770    // insert the (source) kernel into the (source) image:
     771    sum = 0.0;
     772    for (int y = -footprint; y <= footprint; y++) {
     773        for (int x = -footprint; x <= footprint; x++) {
     774            sourceImage->data.F32[y + NYpix][x + NXpix] = source->kernel[y][x];
     775            sum += sourceImage->data.F32[y + NYpix][x + NXpix];
     776        }
     777    }
     778    sourceImage->data.F32[footprint + 1 + NYpix][NXpix] = sum;
     779
     780    // insert the (convolution) kernel into the (convolution) image:
     781    sum = 0.0;
     782    for (int y = -footprint; y <= footprint; y++) {
     783        for (int x = -footprint; x <= footprint; x++) {
     784            convolutionImage->data.F32[y + NYpix][x + NXpix] = convolution->kernel[y][x];
     785            sum += convolutionImage->data.F32[y + NYpix][x + NXpix];
     786        }
     787    }
     788    convolutionImage->data.F32[footprint + 1 + NYpix][NXpix] = sum;
     789   
     790    // insert the (difference) kernel into the (difference) image:
     791    sum = 0.0;
     792    for (int y = -footprint; y <= footprint; y++) {
     793        for (int x = -footprint; x <= footprint; x++) {
     794            differenceImage->data.F32[y + NYpix][x + NXpix] = target->kernel[y][x] - background - source->kernel[y][x] * norm;
     795            sum += differenceImage->data.F32[y + NYpix][x + NXpix];
     796        }
     797    }
     798    differenceImage->data.F32[footprint + 1 + NYpix][NXpix] = sum;
     799
     800    // insert the (residual) kernel into the (residual) image:
     801    sum = 0.0;
     802    for (int y = -footprint; y <= footprint; y++) {
     803        for (int x = -footprint; x <= footprint; x++) {
     804            residualImage->data.F32[y + NYpix][x + NXpix] = target->kernel[y][x] - background - source->kernel[y][x] * norm - convolution->kernel[y][x];
     805            sum += residualImage->data.F32[y + NYpix][x + NXpix];
     806        }
     807    }
     808    residualImage->data.F32[footprint + 1 + NYpix][NXpix] = sum;
     809
     810    // insert the (fresidual) kernel into the (fresidual) image:
     811    for (int y = -footprint; y <= footprint; y++) {
     812        for (int x = -footprint; x <= footprint; x++) {
     813            fresidualImage->data.F32[y + NYpix][x + NXpix] = residualImage->data.F32[y + NYpix][x + NXpix] / sqrt(PS_MAX(target->kernel[y][x], 100.0));
     814        }
     815    }
     816    return true;
     817}
     818
     819bool pmSubtractionVisualShowFitImage(double norm) {
    748820
    749821    KiiEraseOverlay (kapa1, "red");
     
    792864    psVector *x = psVectorAllocEmpty (kernels->num, PS_TYPE_F32);
    793865    psVector *y = psVectorAllocEmpty (kernels->num, PS_TYPE_F32);
     866    psVector *dy = psVectorAllocEmpty (kernels->num, PS_TYPE_F32);
    794867
    795868    graphdata.xmin = -1.0;
     
    804877        x->data.F32[i] = i;
    805878        y->data.F32[i] = p_pmSubtractionSolutionCoeff(kernels, polyValues, i, false);
     879        dy->data.F32[i] = kernels->solution1err->data.F64[i];
    806880        graphdata.ymin = PS_MIN(graphdata.ymin, y->data.F32[i]);
    807881        graphdata.ymax = PS_MAX(graphdata.ymax, y->data.F32[i]);
    808882    }
    809     x->n = y->n = kernels->num;
     883    x->n = y->n = dy->n = kernels->num;
    810884
    811885    float range;
     
    828902    graphdata.size = 0.5;
    829903    graphdata.style = 2;
     904    graphdata.etype |= 0x01;
    830905
    831906    KapaPrepPlot   (kapa3, x->n, &graphdata);
    832907    KapaPlotVector (kapa3, x->n, x->data.F32, "x");
    833908    KapaPlotVector (kapa3, x->n, y->data.F32, "y");
     909    KapaPlotVector (kapa3, x->n, dy->data.F32, "dym");
     910    KapaPlotVector (kapa3, x->n, dy->data.F32, "dyp");
    834911
    835912    psFree (x);
    836913    psFree (y);
     914    psFree (dy);
    837915    psFree (polyValues);
    838916
  • branches/eam_branches/ipp-20101205/psModules/src/imcombine/pmSubtractionVisual.h

    r30266 r30289  
    88bool pmSubtractionVisualPlotLeastSquaresResid (const pmSubtractionStampList *stamps, psImage *matrixIn, int nUsed);
    99bool pmSubtractionVisualShowSubtraction(psImage *image, psImage *ref, psImage *sub);
     10
     11bool pmSubtractionVisualShowFit(pmSubtractionStampList *stamps, pmSubtractionKernels *kernels);
    1012bool pmSubtractionVisualShowFitInit(pmSubtractionStampList *stamps);
    1113bool pmSubtractionVisualShowFitAddStamp(psKernel *target, psKernel *source, psKernel *convolution, double background, double norm, int index);
    12 bool pmSubtractionVisualShowFit(double norm);
     14bool pmSubtractionVisualShowFitImage(double norm);
     15
    1316bool pmSubtractionVisualPlotFit(const pmSubtractionKernels *kernels);
    1417bool pmSubtractionVisualShowKernels(pmSubtractionKernels *kernels);
Note: See TracChangeset for help on using the changeset viewer.