IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 28667


Ignore:
Timestamp:
Jul 13, 2010, 2:34:04 PM (16 years ago)
Author:
Paul Price
Message:

It's bothered me for a while that the noise model that we have been using is only kind of spatially variable. The variance map is intended to track the change in the noise properties as a function of position, and while it does keep track of different noise levels due to, e.g., different detectors, vignetting, etc., it has not tracked the different noise that comes from convolution kernels changing over an image. This had been an intentional oversight --- the prescription we were using for calculating the variance and covariance removed the spatial variation (by prescribing that the variance level under a convolution remain unchanged) and we were sweeping it under the carpet so we could calculate the covariance pseudo-matrix and use that for setting the absolute level of the noise.

I've now figured out how to have our cake and eat it too. By changing where the scalings are applied, the variance map can track the changing noise introduced by a varying convolution kernel, while the covariance pseudo-matrix tracks an absolute change. This fix is purely algorithmic --- it does not affect any of the variances/covariances stored on disk, nor is it affected by them. I hope that this means that any Magic recertification required is either minimal or completely unnecessary.

Again, all that has changed is where the scalings are applied.

Location:
trunk
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/archive/noise_model/simulate.c

    r28173 r28667  
    66#define DET_SIZE 2000
    77#define SKY_SIZE 1000
    8 #define SIZE 1024
    98#define OUTPUT_ROOT "test"
    10 #define SCALE 0.654321
     9#define SCALE 0.7654321
    1110#define ROT M_PI_2
    12 #define INTERPOLATION PS_INTERPOLATE_LANCZOS4
     11#define INTERPOLATION PS_INTERPOLATE_LANCZOS3
    1312#define OFFSET 16
    1413#define SMOOTH_SIGMA 6.54321
     
    1615#define DUAL_KERNEL "sub.subkernel"
    1716#define WARP_NUM 10000
     17#define CONV_NUM 1000
    1818
    1919static const float variances[] = { 3.0, 10.0, 30.0, 100.0, 300.0, 1000.0, 3000.0, 10000.0 };
     
    2121static const char *rootNames[] = { "o5298g0209o.fake.warp", "o5298g0210o.fake.warp", "o5298g0211o.fake.warp",
    2222                                   "o5298g0212o.fake.warp", "o5298g0213o.fake.warp", "o5298g0214o.fake.warp",
     23
    2324                                   "o5298g0215o.fake.warp", "o5298g0216o.fake.warp" };
     25#if 1
    2426static const char *kernels[] = { "test.5.kernel", "test.11.kernel", "test.17.kernel", "test.23.kernel",
    2527                                 "test.29.kernel", "test.35.kernel", "test.41.kernel", "test.47.kernel" };
    26 
     28#else
     29static const char *kernels[] = { "test.11.kernel", "test.11.kernel", "test.11.kernel", "test.11.kernel",
     30                                 "test.11.kernel", "test.11.kernel", "test.11.kernel", "test.11.kernel" };
     31#endif
    2732
    2833void writeImage(const psImage *image, const char *suffix)
     
    7681float meanVar(const psImage *var, const psImage *mask, const psKernel *covar)
    7782{
    78     psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS);
    7983    psStats *stats = psStatsAlloc(PS_STAT_SAMPLE_MEDIAN);
    80     psImageBackground(stats, NULL, var, mask, 0xFF, rng);
     84    psImageStats(stats, var, mask, 0xFF);
    8185    float variance = stats->sampleMedian * psImageCovarianceFactor(covar);
    8286    psFree(stats);
    83     psFree(rng);
    8487    return variance;
    8588}
     
    9396        for (int x = 0; x < image->numCols; x++) {
    9497            sn->data.F32[y][x] = image->data.F32[y][x] / sqrtf(var->data.F32[y][x] * varFactor);
     98            if (!isfinite(sn->data.F32[y][x])) {
     99                mask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] = 0xFF;
     100            }
    95101        }
    96102    }
     
    100106    float offset = stats->sampleMean;
    101107    psFree(stats);
     108
     109    static int number = 0;
     110
     111    psString snName = NULL;
     112    psStringAppend(&snName, "sn.%d.fits", number);
     113    writeImage(sn, snName);
     114    fprintf(stderr, "Writing S/N image %d\n", number);
    102115
    103116    psHistogram *hist = psHistogramAlloc(-5, +5, 101);
     
    121134    psFree(sn);
    122135
    123     static int number = 0;
    124136    psString name = NULL;
    125137    fprintf(stderr, "Writing histogram %d\n", number);
    126     psStringAppend(&name, "hist_%d.dat", number++);
     138    psStringAppend(&name, "hist_%d.dat", number);
    127139    FILE *file = fopen(name, "w");
    128140    psFree(name);
     
    136148    psFree(hist);
    137149
     150    number++;
     151
    138152    return noise;
    139153}
     
    144158{
    145159    psKernel *kernel2 = psKernelAlloc(kernel->xMin, kernel->xMax, kernel->yMin, kernel->yMax);
    146     double sum = 0.0, sum2 = 0.0;
    147160    for (int y = kernel->yMin; y <= kernel->yMax; y++) {
    148161        for (int x = kernel->xMin; x <= kernel->xMax; x++) {
    149             sum += kernel->kernel[y][x];
    150             sum2 += kernel2->kernel[y][x] = PS_SQR(kernel->kernel[y][x]);
    151         }
    152     }
    153     for (int y = kernel->yMin; y <= kernel->yMax; y++) {
    154         for (int x = kernel->xMin; x <= kernel->xMax; x++) {
    155             kernel2->kernel[y][x] /= sum2;
     162            kernel2->kernel[y][x] = PS_SQR(kernel->kernel[y][x]);
    156163        }
    157164    }
     
    176183
    177184    psKernel *kernel = psImageSmoothKernel(SMOOTH_SIGMA, SMOOTH_N_SIGMA); // Kernel used for smoothing
     185    double sum2 = 0.0;                                               // Sum of kernel squared
     186    for (int y = kernel->yMin; y <= kernel->yMax; y++) {
     187        for (int x = kernel->xMin; x <= kernel->xMax; x++) {
     188            sum2 += PS_SQR(kernel->kernel[y][x]);
     189        }
     190    }
     191    float factor = 1.0 / sum2;
    178192    psKernel *smoothCovar = psImageCovarianceCalculate(kernel, covar);
    179193    psFree(kernel);
    180     psImageCovarianceTransfer(smoothVariance, smoothCovar);
     194
     195    // Apply square root of significance image scaling factor to image
     196    psBinaryOp(smoothImage, smoothImage, "*", psScalarAlloc(sqrtf(factor), PS_TYPE_F32));
     197
    181198#else
    182199    psKernel *kernel = psImageSmoothKernel(SMOOTH_SIGMA, SMOOTH_N_SIGMA); // Kernel used for smoothing
    183200    psKernel *kernel2 = psKernelAlloc(kernel->xMin, kernel->xMax, kernel->yMin, kernel->yMax);
    184     double sum = 0.0, sum2 = 0.0;
    185201    for (int y = kernel->yMin; y <= kernel->yMax; y++) {
    186202        for (int x = kernel->xMin; x <= kernel->xMax; x++) {
    187             sum += kernel->kernel[y][x];
    188             sum2 += kernel2->kernel[y][x] = PS_SQR(kernel->kernel[y][x]);
    189         }
    190     }
    191     fprintf(stderr, "Kernel sum: %f %f\n", sum, sum2);
    192     for (int y = kernel->yMin; y <= kernel->yMax; y++) {
    193         for (int x = kernel->xMin; x <= kernel->xMax; x++) {
    194             kernel2->kernel[y][x] /= sum2;
     203            kernel2->kernel[y][x] = PS_SQR(kernel->kernel[y][x]);
    195204        }
    196205    }
     
    332341}
    333342
     343float covarianceSum(const psKernel *covar)
     344{
     345    if (!covar) {
     346        return 1.0;
     347    }
     348    double sum = 0.0;
     349    for (int y = covar->yMin; y <= covar->yMax; y++) {
     350        for (int x = covar->xMin; x <= covar->xMax; x++) {
     351            sum += covar->kernel[y][x];
     352        }
     353    }
     354    return sum;
     355}
     356
     357
    334358int main(int argc, char *argv[])
    335359{
     
    383407        }
    384408
    385         fprintf(stderr, "Input image %d: S/N: %f Covar: %f Var: %f\n",
     409        fprintf(stderr, "Input image %d: S/N: %f Covar: %f Var: %f CovarSum: %f\n",
    386410                i,
    387411                signoise(inImage, inMask, inVariance, inCovar),
    388412                psImageCovarianceFactor(inCovar),
    389                 meanVar(inVariance, inMask, inCovar));
     413                meanVar(inVariance, inMask, inCovar),
     414                covarianceSum(inCovar));
    390415
    391416        phot(inImage, inMask, inVariance, inCovar);
     
    417442        }
    418443
    419         fprintf(stderr, "Warp image %d: S/N: %f Covar: %f Var: %f\n",
     444        fprintf(stderr, "Warp image %d: S/N: %f Covar: %f Var: %f CovarSum: %f\n",
    420445                i,
    421446                signoise(warpImage, warpMask, warpVariance, warpCovar),
    422447                psImageCovarianceFactor(warpCovar),
    423                 meanVar(warpVariance, warpMask, warpCovar));
     448                meanVar(warpVariance, warpMask, warpCovar),
     449                covarianceSum(warpCovar));
    424450
    425451        phot(warpImage, warpMask, warpVariance, warpCovar);
     
    434460        pmReadoutReadSubtractionKernels(ro, fits);
    435461        pmSubtractionKernels *kernels = psMetadataLookupPtr(NULL, ro->analysis, PM_SUBTRACTION_ANALYSIS_KERNEL);
     462        int normIndex = PM_SUBTRACTION_INDEX_NORM(kernels);
     463        int bgIndex = PM_SUBTRACTION_INDEX_BG(kernels);
     464#if 1
     465//        kernels->solution1->data.F64[normIndex] += 1.0;
     466        kernels->solution1->data.F64[bgIndex] = 0.0;
     467#endif
     468        fprintf(stderr, "Norm: %f BG: %f\n", kernels->solution1->data.F64[normIndex], kernels->solution1->data.F64[bgIndex]);
    436469#if 0
    437470        for (int i = 0; i < kernels->num; i++) {
     
    455488        psFitsClose(fits);
    456489
     490#if 0
     491        {
     492            psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS);
     493            psArray *covariances = psArrayAlloc(CONV_NUM);
     494            psVector *factors = psVectorAlloc(CONV_NUM, PS_TYPE_F32);
     495            double mean = 0.0;
     496            for (int i = 0; i < CONV_NUM; i++) {
     497                float x, y;
     498                p_pmSubtractionPolynomialNormCoords(&x, &y, psRandomUniform(rng) * SKY_SIZE,
     499                                                    psRandomUniform(rng) * SKY_SIZE,
     500                                                    kernels->xMin, kernels->xMax,
     501                                                    kernels->yMin, kernels->yMax);
     502                psKernel *kernel = pmSubtractionKernel(kernels, x, y, false);
     503                psKernel *covar = covariances->data[i] = psImageCovarianceCalculate(kernel, inCovar);
     504                psFree(kernel);
     505                mean += factors->data.F32[i] = psImageCovarianceFactor(covar);
     506            }
     507            psFree(rng);
     508            psFree(covariances);
     509
     510            mean /= WARP_NUM;
     511
     512            double stdev = 0.0;
     513            for (int i = 0; i < CONV_NUM; i++) {
     514                stdev += PS_SQR(factors->data.F32[i] - mean);
     515            }
     516            stdev = sqrt(stdev/(CONV_NUM-1));
     517            fprintf(stderr, "Conv covariance mean: %f stdev: %f\n", mean, stdev);
     518            psFree(factors);
     519        }
     520#endif
     521
    457522        pmReadout *conv = pmReadoutAlloc(NULL);
    458523#if 1
     
    460525        conv->mask = psImageAlloc(SKY_SIZE, SKY_SIZE, PS_TYPE_IMAGE_MASK);
    461526        conv->variance = psImageAlloc(SKY_SIZE, SKY_SIZE, PS_TYPE_F32);
    462         if (!pmSubtractionMatchPrecalc(NULL, conv, NULL, ro, ro->analysis, 32, 0.0, 0.01,
     527        if (!pmSubtractionMatchPrecalc(NULL, conv, NULL, ro, ro->analysis, 2 * kernels->size + 1, 0.0, 0.01,
    463528                                       0xFF, 0xF0, 0x0F, 0.1, 1.0)) {
    464529            psErrorStackPrint(stderr, "Error:");
     
    494559        }
    495560
    496         fprintf(stderr, "Conv Image %d: S/N: %f Covar: %f Var: %f\n",
     561        fprintf(stderr, "Conv Image %d: S/N: %f Covar: %f Var: %f CovarSum: %f\n",
    497562                i,
    498563                signoise(conv->image, conv->mask, conv->variance, conv->covariance),
    499564                psImageCovarianceFactor(conv->covariance),
    500                 meanVar(conv->variance, conv->mask, conv->covariance));
     565                meanVar(conv->variance, conv->mask, conv->covariance),
     566                covarianceSum(conv->covariance));
    501567
    502568        phot(conv->image, conv->mask, conv->variance, conv->covariance);
    503569        readouts->data[i] = conv;
    504570
     571        //        exit(1);
    505572    }
    506573
     
    624691                meanVar(diffVariance, diffMask, diffCovar));
    625692
    626         phot(diffImage, diffMask, diffVariance, diffCovar);
    627 
    628693        writeImage(diffImage, "ssdiff.image.fits");
    629694        writeImage(diffMask, "ssdiff.mask.fits");
  • trunk/psLib/src/imageops/psImageCovariance.c

    r28405 r28667  
    3434static float imageCovarianceCalculate(const psKernel *covar, // Original covariance matrix
    3535                                      const psKernel *kernel, // Convolution kernel
    36                                       int x, int y            // Coordinates in output covariance matrix
     36                                      int x, int y,           // Coordinates in output covariance matrix
     37                                      float scale             // Scale to apply
    3738                                      )
    3839{
     
    8384    }
    8485
    85     return sum;
     86    return scale * sum;
    8687}
    8788
     
    9192    PS_ASSERT_THREAD_JOB_NON_NULL(job, false);
    9293    psAssert(job->args, "No job arguments");
    93     psAssert(job->args->n == 5, "Wrong number of job arguments: %ld", job->args->n);
     94    psAssert(job->args->n == 6, "Wrong number of job arguments: %ld", job->args->n);
    9495
    9596    psKernel *out = job->args->data[0]; // Output covariance matrix
     
    9899    int x = PS_SCALAR_VALUE(job->args->data[3], S32); // x coordinate in output covariance matrix
    99100    int y = PS_SCALAR_VALUE(job->args->data[4], S32); // y coordinate in output covariance matrix
    100 
    101     out->kernel[y][x] = imageCovarianceCalculate(covar, kernel, x, y);
     101    float scale = PS_SCALAR_VALUE(job->args->data[5], F32); // Scaling to apply
     102
     103    out->kernel[y][x] = imageCovarianceCalculate(covar, kernel, x, y, scale);
    102104
    103105    return true;
     
    127129
    128130    // Check for non-finite elements
     131    double sumKernel = 0.0, sumKernel2 = 0.0; // Sum of the kernel
    129132    for (int y = kernel->yMin; y <= kernel->yMax; y++) {
    130133        for (int x = kernel->xMin; x <= kernel->xMax; x++) {
     
    135138                return NULL;
    136139            }
     140            sumKernel += kernel->kernel[y][x];
     141            sumKernel2 += PS_SQR(kernel->kernel[y][x]);
    137142        }
    138143    }
     
    155160    int yMin = kernel->yMin - kernel->yMax + covar->yMin, yMax = kernel->yMax - kernel->yMin + covar->yMax;
    156161    psKernel *out = psKernelAlloc(xMin, xMax, yMin, yMax); // Covariance matrix for output
     162    float scale = 1.0 / sumKernel2;          // Scaling to apply
    157163
    158164    for (int y = yMin; y <= yMax; y++) {
     
    165171                PS_ARRAY_ADD_SCALAR(job->args, x, PS_TYPE_S32);
    166172                PS_ARRAY_ADD_SCALAR(job->args, y, PS_TYPE_S32);
     173                PS_ARRAY_ADD_SCALAR(job->args, scale, PS_TYPE_F32);
    167174                if (!psThreadJobAddPending(job)) {
    168175                    psFree(covar);
     
    170177                }
    171178            } else {
    172                 out->kernel[y][x] = imageCovarianceCalculate(covar, kernel, x, y);
    173             }
    174         }
    175     }
    176     psFree(covar);
     179                out->kernel[y][x] = imageCovarianceCalculate(covar, kernel, x, y, scale);
     180            }
     181        }
     182    }
    177183
    178184    if (threaded && !psThreadPoolWait(true)) {
     
    180186        return false;
    181187    }
     188
     189    psFree(covar);
    182190
    183191    return out;
     
    194202
    195203    // Check for non-finite elements
     204    double sumKernel2 = 0.0; // Sum of the squared kernel
    196205    for (int y = kernel->yMin; y <= kernel->yMax; y++) {
    197206        for (int x = kernel->xMin; x <= kernel->xMax; x++) {
     
    202211                return NAN;
    203212            }
     213            sumKernel2 += PS_SQR(kernel->kernel[y][x]);
    204214        }
    205215    }
     
    215225    }
    216226
    217     float factor = imageCovarianceCalculate(covar, kernel, 0, 0); // Covariance factor
     227    float scale = 1.0 / sumKernel2;     // Scale to apply
     228    float factor = imageCovarianceCalculate(covar, kernel, 0, 0, scale); // Covariance factor
    218229    psFree(covar);
    219230    return factor;
     
    338349        }
    339350    }
    340     psFree(covar);
    341 
    342351    if (threaded && !psThreadPoolWait(true)) {
    343352        psError(PS_ERR_UNKNOWN, false, "Error waiting for threads.");
    344353        return false;
    345354    }
     355    psFree(covar);
    346356
    347357    return out;
     
    616626    if (set && !threaded) {
    617627        {
    618             psThreadTask *task = psThreadTaskAlloc("PSLIB_IMAGE_COVARIANCE_CALCULATE", 5);
     628            psThreadTask *task = psThreadTaskAlloc("PSLIB_IMAGE_COVARIANCE_CALCULATE", 6);
    619629            task->function = &imageCovarianceCalculateThread;
    620630            psThreadTaskAdd(task);
  • trunk/psLib/src/imageops/psImageInterpolate.c

    r26892 r28667  
    427427
    428428// Determine the result of the interpolation after all the math has been done
    429 #define INTERPOLATE_RESULT() \
    430     psImageInterpolateStatus status = PS_INTERPOLATE_STATUS_ERROR; /* Status of interpolation */ \
    431     *imageValue = sumKernel > 0 ? sumImage / sumKernel : interp->badImage; \
    432     if (wantVariance) { \
    433         *varianceValue = sumVariance / (sumKernel2 - sumBad); \
    434     } \
    435     if (sumKernel == 0.0) { \
    436         /* No kernel contributions */ \
    437         if (haveMask && maskValue) { \
    438             *maskValue |= interp->badMask; \
    439         } \
    440         status = PS_INTERPOLATE_STATUS_BAD; \
    441     } else if (sumBad == 0) { \
    442         /* Completely good pixel */ \
    443         status = PS_INTERPOLATE_STATUS_GOOD; \
    444     } else if (sumBad < PS_SQR(interp->poorFrac) * sumKernel2) { \
    445         /* Some pixels masked: poor pixel */ \
    446         if (haveMask && maskValue) { \
    447             *maskValue |= interp->poorMask; \
    448         } \
    449         status = PS_INTERPOLATE_STATUS_POOR; \
    450     } else { \
    451         /* Many pixels (or a few important pixels) masked: bad pixel */ \
    452         if (haveMask && maskValue) { \
    453             *maskValue |= interp->badMask; \
    454         } \
    455         status = PS_INTERPOLATE_STATUS_BAD; \
    456     }
     429static psImageInterpolateStatus interpolateResult(const psImageInterpolation *interp,
     430                                                  double *imageValue, double *varianceValue,
     431                                                  psImageMaskType *maskValue,
     432                                                  double sumImage, double sumVariance, double sumBad,
     433                                                  double sumKernel, double sumKernel2,
     434                                                  bool wantVariance, bool haveMask)
     435{
     436    *imageValue = sumKernel > 0 ? sumImage / sumKernel : interp->badImage;
     437    if (wantVariance) {
     438        if (sumBad > 0) {
     439            sumVariance *= sumKernel2 / (sumKernel2 - sumBad);
     440        }
     441        *varianceValue = sumVariance / PS_SQR(sumKernel);
     442    }
     443    if (sumKernel == 0.0) {
     444        // No kernel contributions at all
     445        if (haveMask && maskValue) {
     446            *maskValue |= interp->badMask;
     447        }
     448        return PS_INTERPOLATE_STATUS_BAD;
     449    }
     450    if (sumBad == 0) {
     451        // Completely good pixel
     452        return PS_INTERPOLATE_STATUS_GOOD;
     453    }
     454    if (sumBad < PS_SQR(interp->poorFrac) * sumKernel2) {
     455        // Some pixels masked: poor pixel
     456        if (haveMask && maskValue) {
     457            *maskValue |= interp->poorMask;
     458        }
     459        return PS_INTERPOLATE_STATUS_POOR;
     460    }
     461    // Many pixels (or a few important pixels) masked: bad pixel
     462    if (haveMask && maskValue) {
     463        *maskValue |= interp->badMask;
     464    }
     465    return PS_INTERPOLATE_STATUS_BAD;
     466}
    457467
    458468// Interpolation engine for separable interpolation kernels
     
    703713    }
    704714
    705     INTERPOLATE_RESULT();
    706 
    707715    psFree(xKernelNew);
    708716    psFree(yKernelNew);
     
    710718    psFree(yKernel2New);
    711719
    712     return status;
     720    return interpolateResult(interp, imageValue, varianceValue, maskValue, sumImage, sumVariance, sumBad,
     721                             sumKernel, sumKernel2, wantVariance, haveMask);
    713722}
    714723
     
    861870    }
    862871
    863     INTERPOLATE_RESULT();
    864 
    865     return status;
     872    return interpolateResult(interp, imageValue, varianceValue, maskValue, sumImage, sumVariance, sumBad,
     873                             sumKernel, sumKernel2, wantVariance, haveMask);
    866874}
    867875
  • trunk/psModules/src/imcombine/pmSubtraction.c

    r28405 r28667  
    5252
    5353    // Take the square of the normal kernel
    54     double sumVariance = 0.0; // Sum of the variance kernels
    5554    for (int v = yMin; v <= yMax; v++) {
    5655        for (int u = xMin; u <= xMax; u++) {
    57             sumVariance += out->kernel[v][u] = PS_SQR(normalKernel->kernel[v][u]);
    58         }
    59     }
    60 
    61     // Normalise so that the sum of the variance kernel is the square of the sum of the normal kernel
    62     // This is required to keep the relative scaling between the image and the variance map
    63     psBinaryOp(out->image, out->image, "*", psScalarAlloc(1.0 / sumVariance, PS_TYPE_F32));
    64 
     56            out->kernel[v][u] = PS_SQR(normalKernel->kernel[v][u]);
     57        }
     58    }
    6559    return out;
    6660}
     
    271265// Convolve an image using FFT
    272266static void convolveVarianceFFT(psImage *target,// Place the result in here
    273                               psImage *variance, // Variance map to convolve
    274                               psImage *kernelErr, // Kernel error image
    275                               psImage *mask, // Mask image
    276                               psImageMaskType maskVal, // Value to mask
    277                               const psKernel *kernel, // Kernel by which to convolve
    278                               psRegion region,// Region of interest
    279                               int size        // Size of (square) kernel
    280                               )
     267                                psImage *variance, // Variance map to convolve
     268                                psImage *kernelErr, // Kernel error image
     269                                psImage *mask, // Mask image
     270                                psImageMaskType maskVal, // Value to mask
     271                                const psKernel *kernel, // Kernel by which to convolve
     272                                psRegion region,// Region of interest
     273                                int size        // Size of (square) kernel
     274                                )
    281275{
    282276    psRegion border = psRegionSet(region.x0 - size, region.x1 + size,
     
    348342                                  psImage *image, // Image to convolve
    349343                                  psImage *variance, // Variance map to convolve, or NULL
     344                                  const psKernel *covar,               // Covariance, or NULL
    350345                                  psImage *kernelErr, // Kernel error image, or NULL
    351346                                  psImage *subMask, // Subtraction mask
     
    393388        if (variance) {
    394389            convolveDirect(convVariance, variance, *kernelVariance, region, 0.0, kernels->size);
     390        }
     391    }
     392
     393    if (variance && covar) {
     394        // Apply covariance factor to variance map, to allow for spatial variation
     395        float factor = psImageCovarianceCalculateFactor(*kernelImage, covar); // Factor to apply
     396        for (int y = region.y0; y < region.y1; y++) {
     397            for (int x = region.x0; x < region.x1; x++) {
     398                convVariance->data.F32[y][x] *= factor;
     399            }
    395400        }
    396401    }
     
    10851090    if (kernels->mode == PM_SUBTRACTION_MODE_1 || kernels->mode == PM_SUBTRACTION_MODE_DUAL) {
    10861091        convolveRegion(out1->image, out1->variance, out1->mask, &kernelImage, &kernelVariance,
    1087                        ro1->image, ro1->variance, kernelErr1, subMask, kernels, polyValues, background,
    1088                        *region, maskBad, maskPoor, poorFrac, useFFT, false);
     1092                       ro1->image, ro1->variance, ro1->covariance, kernelErr1, subMask, kernels,
     1093                       polyValues, background, *region, maskBad, maskPoor, poorFrac, useFFT, false);
    10891094    }
    10901095    if (kernels->mode == PM_SUBTRACTION_MODE_2 || kernels->mode == PM_SUBTRACTION_MODE_DUAL) {
    10911096        convolveRegion(out2->image, out2->variance, out2->mask, &kernelImage, &kernelVariance,
    1092                        ro2->image, ro2->variance, kernelErr2, subMask, kernels, polyValues, background,
    1093                        *region, maskBad, maskPoor, poorFrac, useFFT,
     1097                       ro2->image, ro2->variance, ro2->covariance, kernelErr2, subMask, kernels,
     1098                       polyValues, background, *region, maskBad, maskPoor, poorFrac, useFFT,
    10941099                       kernels->mode == PM_SUBTRACTION_MODE_DUAL);
    10951100    }
     
    13251330
    13261331    // Calculate covariances
    1327     // This can be fairly involved, so we only do it for a single instance
    1328     // Enable threads for covariance calculation, since we're not threading on top of it.
     1332    // This can be fairly involved, so we only do it for a small number of instances
    13291333    float position[NUM_COVAR_POS] = { -1.0, -0.5, 0.0, +0.5, +1.0 }; // Positions for covariance calculations
     1334    // Enable threads for covariance calculation, since we're not threading on top of it
    13301335    oldThreads = psImageCovarianceSetThreads(true);
    13311336    if (kernels->mode == PM_SUBTRACTION_MODE_1 || kernels->mode == PM_SUBTRACTION_MODE_DUAL) {
     
    13421347        out1->covariance = psImageCovarianceAverage(covars);
    13431348        psFree(covars);
     1349        // Remove covariance factor from covariance, since we've put it in the variance map already
     1350        float factor = psImageCovarianceFactor(out1->covariance);
     1351        psBinaryOp(out1->covariance->image, out1->covariance->image, "/", psScalarAlloc(factor, PS_TYPE_F32));
    13441352    }
    13451353    if (kernels->mode == PM_SUBTRACTION_MODE_2 || kernels->mode == PM_SUBTRACTION_MODE_DUAL) {
     
    13561364        out2->covariance = psImageCovarianceAverage(covars);
    13571365        psFree(covars);
     1366        // Remove covariance factor from covariance, since we've put it in the variance map already
     1367        float factor = psImageCovarianceFactor(out2->covariance);
     1368        psBinaryOp(out2->covariance->image, out2->covariance->image, "/", psScalarAlloc(factor, PS_TYPE_F32));
    13581369    }
    13591370    psImageCovarianceSetThreads(oldThreads);
  • trunk/psphot/src/psphotSignificanceImage.c

    r26894 r28667  
    7676    // Calculate correction factor for the covariance produced by the (potentially multiple) smoothing
    7777    psKernel *kernel = psImageSmoothKernel(SIGMA_SMTH, NSIGMA_SMTH); // Kernel used for smoothing
    78     float factor = 1.0 / psImageCovarianceCalculateFactor(kernel, readout->covariance);
     78    double sum2 = 0.0;                                               // Sum of kernel squared
     79    for (int y = kernel->yMin; y <= kernel->yMax; y++) {
     80        for (int x = kernel->xMin; x <= kernel->xMax; x++) {
     81            sum2 += PS_SQR(kernel->kernel[y][x]);
     82        }
     83    }
     84    float factor = 1.0 / (sum2 * psImageCovarianceCalculateFactor(kernel, readout->covariance));
    7985    psFree(kernel);
    8086
Note: See TracChangeset for help on using the changeset viewer.