IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Oct 31, 2008, 11:50:16 AM (18 years ago)
Author:
Paul Price
Message:

Adding functions to renormalise the weight maps based on pixels or on (weighted aperture) photometry.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/psModules/src/camera/pmFPAMaskWeight.c

    r20307 r20486  
    1414
    1515#define PIXELS_BUFFER 100               // Size of buffer for allocating pixel lists
     16#define RENORM_NUM_SIGMA 3.0            // Number of standard deviations for Gaussian kernel
     17#define RENORM_PEAK 4.0                 // Number of standard deviations of noise for fake source peak flux
     18
    1619
    1720//////////////////////////////////////////////////////////////////////////////////////////////////////////////
     
    315318
    316319    return success;
     320}
     321
     322
     323bool pmReadoutWeightRenormPixels(const pmReadout *readout, psMaskType maskVal,
     324                                 psStatsOptions meanStat, psStatsOptions stdevStat, psRandom *rng)
     325{
     326    PM_ASSERT_READOUT_NON_NULL(readout, false);
     327    PM_ASSERT_READOUT_IMAGE(readout, false);
     328    PM_ASSERT_READOUT_WEIGHT(readout, false);
     329
     330    psImage *image = readout->image, *mask = readout->mask, *weight = readout->weight; // Readout parts
     331
     332    if (!psMemIncrRefCounter(rng)) {
     333        rng = psRandomAlloc(PS_RANDOM_TAUS, 0);
     334    }
     335
     336    psStats *weightStats = psStatsAlloc(meanStat);// Statistics for mean
     337    if (!psImageBackground(weightStats, NULL, weight, mask, maskVal, rng)) {
     338        psError(PS_ERR_UNKNOWN, false, "Unable to measure mean weight for image");
     339        psFree(weightStats);
     340        psFree(rng);
     341        return false;
     342    }
     343    float meanVariance = weightStats->robustMedian; // Mean variance
     344    psFree(weightStats);
     345
     346    psStats *imageStats = psStatsAlloc(stdevStat);// Statistics for mean
     347    if (!psImageBackground(imageStats, NULL, image, mask, maskVal, rng)) {
     348        psError(PS_ERR_UNKNOWN, false, "Unable to measure stdev of image");
     349        psFree(imageStats);
     350        psFree(rng);
     351        return false;
     352    }
     353    float stdevImage = imageStats->robustStdev; // Standard deviation of image
     354    psFree(imageStats);
     355    psFree(rng);
     356
     357    float correction = PS_SQR(stdevImage) / meanVariance; // Correction to take variance to what it should be
     358    psLogMsg("psModules.camera", PS_LOG_INFO, "Renormalising weight map by %f", correction);
     359    psBinaryOp(weight, weight, "*", psScalarAlloc(correction, PS_TYPE_F32));
     360
     361    return true;
     362}
     363
     364
     365bool pmReadoutWeightRenormPhot(const pmReadout *readout, psMaskType maskVal, int num, float width,
     366                               psStatsOptions meanStat, psStatsOptions stdevStat, psRandom *rng)
     367{
     368    PM_ASSERT_READOUT_NON_NULL(readout, false);
     369    PM_ASSERT_READOUT_IMAGE(readout, false);
     370    PM_ASSERT_READOUT_WEIGHT(readout, false);
     371
     372    if (!psMemIncrRefCounter(rng)) {
     373        rng = psRandomAlloc(PS_RANDOM_TAUS, 0);
     374    }
     375
     376    psImage *image = readout->image, *mask = readout->mask, *weight = readout->weight; // Readout images
     377
     378    // Measure background
     379    psStats *bgStats = psStatsAlloc(PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV);// Statistics for background
     380    if (!psImageBackground(bgStats, NULL, image, mask, maskVal, rng)) {
     381        psError(PS_ERR_UNKNOWN, false, "Unable to measure background for image");
     382        psFree(bgStats);
     383        psFree(rng);
     384        return false;
     385    }
     386    float bgMean = bgStats->robustMedian; // Background level
     387    float bgNoise = bgStats->robustStdev; // Background standard deviation
     388    psFree(bgStats);
     389    psTrace("psModules.camera", 5, "Background is %f +/- %f\n", bgMean, bgNoise);
     390
     391
     392    // Construct kernels for flux measurement
     393    // We use N(0,width) and N(0,width/sqrt(2)) kernels, following psphotSignificanceImage.
     394    float sigFactor = 4.0 * M_PI * PS_SQR(width); // Factor for conversion from im/wt ratio to significance
     395    int size = RENORM_NUM_SIGMA, fullSize = 2 * size + 1; // Half-size and full size of Gaussian
     396    psVector *gauss = psVectorAlloc(fullSize, PS_TYPE_F32); // Gaussian for weighting
     397    psVector *gauss2 = psVectorAlloc(fullSize, PS_TYPE_F32); // Gaussian squared
     398    for (int i = 0, x = -size; i < fullSize; i++, x++) {
     399        gauss->data.F32[i] = expf(-0.5 * PS_SQR(x) / PS_SQR(width));
     400        gauss2->data.F32[i] = expf(-PS_SQR(x) / PS_SQR(width));
     401    }
     402
     403    // Size of image
     404    int numCols = image->numCols, numRows = image->numRows; // Size of images
     405    int xSize = numCols - fullSize, ySize = numRows - fullSize; // Size of consideration
     406    int xOffset = size, yOffset = size;       // Offset to region of consideration
     407
     408    // Measure fluxes
     409    float peakFlux = RENORM_PEAK * bgNoise;     // Peak flux for fake sources
     410    psVector *noise = psVectorAlloc(num, PS_TYPE_F32); // Measurements of the noise
     411    psVector *source = psVectorAlloc(num, PS_TYPE_F32); // Measurements of fake sources
     412    psVector *guess = psVectorAlloc(num, PS_TYPE_F32); // Guess at significance
     413    psVector *photMask = psVectorAlloc(num, PS_TYPE_MASK); // Mask for fluxes
     414    for (int i = 0; i < num; i++) {
     415        // Coordinates of interest
     416        int xPix = psRandomUniform(rng) * xSize + xOffset;
     417        int yPix = psRandomUniform(rng) * ySize + yOffset;
     418        psAssert(xPix - size >= 0 && xPix + size < numCols &&
     419                 yPix - size >= 0 && yPix + size > numRows,
     420                 "Bad pixel position");
     421
     422        // Weighted aperture photometry
     423        // This has the same effect as smoothing the image by the window function
     424        float sumNoise = 0.0;       // Sum for noise measurement
     425        float sumSource = 0.0;      // Sum for source measurement
     426        float sumWeight = 0.0;      // Sum for weight measurement
     427        float sumGauss = 0.0, sumGauss2 = 0.0; // Sums of Gaussian kernels
     428        for (int v = 0, y = yPix - size; v < fullSize; v++, y++) {
     429            float xSumNoise = 0.0;  // Sum for noise measurement in x
     430            float xSumSource = 0.0; // Sum for source measurement in x
     431            float xSumWeight = 0.0; // Sum for weight measurement in x
     432            float xSumGauss = 0.0, xSumGauss2 = 0.0; // Sums of Gaussian kernels in x
     433            float yGauss = peakFlux * gauss->data.F32[v]; // Value of Gaussian in y
     434            for (int u = 0, x = xPix - size; u < fullSize; u++, x++) {
     435                if (mask && mask->data.PS_TYPE_MASK_DATA[y][x] & maskVal) {
     436                    continue;
     437                }
     438                float value = image->data.F32[y][x] - bgMean; // Value of image
     439                float xGauss = gauss->data.F32[u]; // Value of Gaussian in x
     440                float xGauss2 = gauss2->data.F32[u]; // Value of Gaussian^2 in x
     441                xSumNoise += value * xGauss;
     442                xSumSource += (value + xGauss * yGauss) * xGauss;
     443                xSumWeight += weight->data.F32[y][x] * xGauss2;
     444                xSumGauss += xGauss;
     445                xSumGauss2 += xGauss2;
     446            }
     447            float yGauss2 = gauss2->data.F32[v]; // Value of Gaussian^2 in y
     448            sumNoise += xSumNoise * yGauss;
     449            sumSource += xSumSource * yGauss;
     450            sumWeight += xSumWeight * yGauss2;
     451            sumGauss += xSumGauss * yGauss;
     452            sumGauss2 += xSumGauss2 * yGauss2;
     453        }
     454
     455        float weightValue = sumWeight / sumGauss2; // Value of convolved weight
     456        photMask->data.PS_TYPE_MASK_DATA[i] = ((isfinite(sumNoise) && isfinite(sumSource) &&
     457                                                isfinite(weightValue) && sumGauss > 0 && sumGauss2 > 0) ?
     458                                               0 : 0xFF);
     459
     460        noise->data.F32[i] = sumNoise / sumGauss;
     461        source->data.F32[i] = sumSource / sumGauss;
     462        guess->data.F32[i] = (sumSource > 0) ? sigFactor * PS_SQR(sumSource) / sumWeight * sumGauss2 : 0.0;
     463        psTrace("psModules.camera", 10, "Flux %d (%d,%d): %f, %f, %f\n",
     464                i, xPix, yPix, source->data.F32[i], noise->data.F32[i], guess->data.F32[i]);
     465    }
     466    psFree(gauss);
     467    psFree(gauss2);
     468    psFree(rng);
     469
     470    // Standard deviation of fluxes gives us the real significance
     471    psStats *stdevStats = psStatsAlloc(stdevStat); // Statistics
     472    if (!psVectorStats(stdevStats, noise, NULL, photMask, 0xFF)) {
     473        psError(PS_ERR_UNKNOWN, false, "Unable to measure standard deviation of fluxes");
     474        psFree(stdevStats);
     475        psFree(noise);
     476        psFree(source);
     477        psFree(guess);
     478        psFree(photMask);
     479        return false;
     480    }
     481    float stdev = psStatsGetValue(stdevStats, stdevStat); // Stadard deviation of fluxes
     482    psFree(stdevStats);
     483    psFree(noise);
     484    psTrace("psModules.camera", 5, "Standard deviation of fluxes is %f\n", stdev);
     485
     486    // Ratio of measured significance to guessed significance
     487    psVector *ratio = psVectorAlloc(num, PS_TYPE_F32); // Ratio of measured to guess
     488    for (int i = 0; i < num; i++) {
     489        float measuredSig = PS_SQR(source->data.F32[i] / stdev); // Measured significance
     490        if (source->data.F32[i] <= 0.0) {
     491            photMask->data.PS_TYPE_MASK_DATA[i] = 0xFF;
     492        }
     493        ratio->data.F32[i] = measuredSig / guess->data.F32[i];
     494    }
     495    psFree(source);
     496    psFree(guess);
     497
     498    psStats *meanStats = psStatsAlloc(meanStat | stdevStat); // Statistics
     499    if (!psVectorStats(meanStats, ratio, NULL, photMask, 0xFF)) {
     500        psError(PS_ERR_UNKNOWN, false, "Unable to measure mean ratio");
     501        psFree(meanStats);
     502        psFree(ratio);
     503        psFree(photMask);
     504        return false;
     505    }
     506    float meanRatio = psStatsGetValue(meanStats, meanStat); // Mean ratio
     507    psTrace("psModules.camera", 5, "Mean significance ratio is %f +/- %f\n",
     508            meanRatio, psStatsGetValue(meanStats, stdevStat));
     509    psFree(meanStats);
     510    psFree(ratio);
     511    psFree(photMask);
     512
     513    psLogMsg("psModules.camera", PS_LOG_INFO, "Renormalising weight map by %f", meanRatio);
     514    psBinaryOp(weight, weight, "*", psScalarAlloc(meanRatio, PS_TYPE_F32));
     515
     516    return true;
    317517}
    318518
Note: See TracChangeset for help on using the changeset viewer.