IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
May 3, 2010, 8:45:22 AM (16 years ago)
Author:
eugene
Message:

updates from trunk

Location:
branches/simmosaic_branches
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • branches/simmosaic_branches

  • branches/simmosaic_branches/psModules

  • branches/simmosaic_branches/psModules/src/camera/pmFPAMaskWeight.c

    r24767 r27839  
    111111        // psError(PS_ERR_IO, true, "CELL.SATURATION is not set --- unable to set mask.\n");
    112112        // return false;
    113         psWarning("CELL.SATURATION is not set --- completely masking cell.\n");
    114         saturation = NAN;
     113        psWarning("CELL.SATURATION is not set --- completely masking cell.\n");
     114        saturation = NAN;
    115115    }
    116116    float bad = psMetadataLookupF32(&mdok, cell->concepts, "CELL.BAD"); // Bad level
     
    118118        // psError(PS_ERR_IO, true, "CELL.BAD is not set --- unable to set mask.\n");
    119119        // return false;
    120         psWarning("CELL.BAD is not set --- completely masking cell.\n");
    121         bad = NAN;
     120        psWarning("CELL.BAD is not set --- completely masking cell.\n");
     121        bad = NAN;
    122122    }
    123123    psTrace("psModules.camera", 5, "Saturation: %f, bad: %f\n", saturation, bad);
    124124
    125     // if CELL.GAIN or CELL.READNOISE are not set, then the variance will be set to NAN; 
     125    // if CELL.GAIN or CELL.READNOISE are not set, then the variance will be set to NAN;
    126126    // in this case, we have to set the mask as well
    127127    float gain = psMetadataLookupF32(&mdok, cell->concepts, "CELL.GAIN"); // Cell gain
     
    140140    // completely mask if SATURATION or BAD are invalid
    141141    if (isnan(saturation) || isnan(bad) || isnan(gain) || isnan(readnoise)) {
    142         psImageInit(mask, badMask);
    143         return true;
     142        psImageInit(mask, badMask);
     143        return true;
    144144    }
    145145
     
    230230        // return false;
    231231        psWarning("CELL.GAIN is not set --- setting variance to NAN\n");
    232         gain = NAN;
     232        gain = NAN;
    233233    }
    234234    float readnoise = psMetadataLookupF32(&mdok, cell->concepts, "CELL.READNOISE"); // Cell read noise
     
    237237        // return false;
    238238        psWarning("CELL.READNOISE is not set --- setting variance to NAN\n");
    239         readnoise = NAN;
     239        readnoise = NAN;
    240240    }
    241241    // if we have a non-NAN readnoise, then we need to ensure it has been updated (not necessary if NAN)
     
    248248    if (isnan(gain) || isnan(readnoise)) {
    249249        if (!readout->variance) {
    250             // generate the image if needed
     250            // generate the image if needed
    251251            readout->variance = psImageAlloc(readout->image->numCols, readout->image->numRows, PS_TYPE_F32);
    252252        }
    253         // XXX need to set the mask, if defined
     253        // XXX need to set the mask, if defined
    254254        psImageInit(readout->variance, NAN);
    255         return true;
     255        return true;
    256256    }
    257257
     
    262262
    263263        // a negative variance is non-sensical. if the image value drops below 1, the variance must be 1.
    264         // XXX this calculation is wrong: limit is 1 e-, but this is in DN
     264        // XXX this calculation is wrong: limit is 1 e-, but this is in DN
    265265        readout->variance = (psImage*)psUnaryOp(readout->variance, readout->variance, "abs");
    266266        readout->variance = (psImage*)psBinaryOp(readout->variance, readout->variance, "max",
     
    276276    // apply a supplied readnoise map (NOTE: in DN, not electrons):
    277277    if (noiseMap) {
    278         psImage *rdVar = (psImage*)psBinaryOp(NULL, (const psPtr) noiseMap, "*", (const psPtr) noiseMap);
    279         readout->variance = (psImage*)psBinaryOp(readout->variance, readout->variance, "+", rdVar);
    280         psFree (rdVar);
     278        psImage *rdVar = (psImage*)psBinaryOp(NULL, (const psPtr) noiseMap, "*", (const psPtr) noiseMap);
     279        readout->variance = (psImage*)psBinaryOp(readout->variance, readout->variance, "+", rdVar);
     280        psFree (rdVar);
    281281    } else {
    282         readout->variance = (psImage*)psBinaryOp(readout->variance, readout->variance, "+", psScalarAlloc(readnoise*readnoise/gain/gain, PS_TYPE_F32));
     282        readout->variance = (psImage*)psBinaryOp(readout->variance, readout->variance, "+", psScalarAlloc(readnoise*readnoise/gain/gain, PS_TYPE_F32));
    283283    }
    284284
     
    362362
    363363
    364 bool pmReadoutVarianceRenormPixels(const pmReadout *readout, psImageMaskType maskVal,
    365                                  psStatsOptions meanStat, psStatsOptions stdevStat, psRandom *rng)
     364bool pmReadoutVarianceRenormalise(const pmReadout *readout, psImageMaskType maskVal,
     365                                  int sample, float minValid, float maxValid)
    366366{
    367367    PM_ASSERT_READOUT_NON_NULL(readout, false);
     
    370370
    371371    psImage *image = readout->image, *mask = readout->mask, *variance = readout->variance; // Readout parts
    372 
    373     if (!psMemIncrRefCounter(rng)) {
    374         rng = psRandomAlloc(PS_RANDOM_TAUS);
    375     }
    376 
    377     psStats *varianceStats = psStatsAlloc(meanStat);// Statistics for mean
    378     if (!psImageBackground(varianceStats, NULL, variance, mask, maskVal, rng)) {
    379         psError(PS_ERR_UNKNOWN, false, "Unable to measure mean variance for image");
    380         psFree(varianceStats);
    381         psFree(rng);
    382         return false;
    383     }
    384     float meanVariance = varianceStats->robustMedian; // Mean variance
    385     psFree(varianceStats);
    386 
    387     psStats *imageStats = psStatsAlloc(stdevStat);// Statistics for mean
    388     if (!psImageBackground(imageStats, NULL, image, mask, maskVal, rng)) {
    389         psError(PS_ERR_UNKNOWN, false, "Unable to measure stdev of image");
    390         psFree(imageStats);
    391         psFree(rng);
    392         return false;
    393     }
    394     float stdevImage = imageStats->robustStdev; // Standard deviation of image
    395     psFree(imageStats);
    396     psFree(rng);
    397 
    398     float correction = PS_SQR(stdevImage) / meanVariance; // Correction to take variance to what it should be
    399     psLogMsg("psModules.camera", PS_LOG_INFO, "Renormalising variance map by %f", correction);
    400     psBinaryOp(variance, variance, "*", psScalarAlloc(correction, PS_TYPE_F32));
    401 
    402     return true;
    403 }
    404 
    405 
    406 bool pmReadoutVarianceRenormPhot(const pmReadout *readout, psImageMaskType maskVal, int num, float width,
    407                                psStatsOptions meanStat, psStatsOptions stdevStat, psRandom *rng)
    408 {
    409     PM_ASSERT_READOUT_NON_NULL(readout, false);
    410     PM_ASSERT_READOUT_IMAGE(readout, false);
    411     PM_ASSERT_READOUT_VARIANCE(readout, false);
    412 
    413     if (!psMemIncrRefCounter(rng)) {
    414         rng = psRandomAlloc(PS_RANDOM_TAUS);
    415     }
    416 
    417     psImage *image = readout->image, *mask = readout->mask, *variance = readout->variance; // Readout images
    418 
    419     // Measure background
    420     psStats *bgStats = psStatsAlloc(PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV);// Statistics for background
    421     if (!psImageBackground(bgStats, NULL, image, mask, maskVal, rng)) {
    422         psError(PS_ERR_UNKNOWN, false, "Unable to measure background for image");
    423         psFree(bgStats);
    424         psFree(rng);
    425         return false;
    426     }
    427     float bgMean = bgStats->robustMedian; // Background level
    428     float bgNoise = bgStats->robustStdev; // Background standard deviation
    429     psFree(bgStats);
    430     psTrace("psModules.camera", 5, "Background is %f +/- %f\n", bgMean, bgNoise);
    431 
    432 
    433     // Construct kernels for flux measurement
    434     // We use N(0,width) and N(0,width/sqrt(2)) kernels, following psphotSignificanceImage.
    435     float sigFactor = 4.0 * M_PI * PS_SQR(width); // Factor for conversion from im/wt ratio to significance
    436     int size = RENORM_NUM_SIGMA, fullSize = 2 * size + 1; // Half-size and full size of Gaussian
    437     psVector *gauss = psVectorAlloc(fullSize, PS_TYPE_F32); // Gaussian for weighting
    438     psVector *gauss2 = psVectorAlloc(fullSize, PS_TYPE_F32); // Gaussian squared
    439     for (int i = 0, x = -size; i < fullSize; i++, x++) {
    440         gauss->data.F32[i] = expf(-0.5 * PS_SQR(x) / PS_SQR(width));
    441         gauss2->data.F32[i] = expf(-PS_SQR(x) / PS_SQR(width));
    442     }
    443 
    444     // Size of image
    445     int numCols = image->numCols, numRows = image->numRows; // Size of images
    446     int xSize = numCols - fullSize, ySize = numRows - fullSize; // Size of consideration
    447     int xOffset = size, yOffset = size;       // Offset to region of consideration
    448 
    449     // Measure fluxes
    450     float peakFlux = RENORM_PEAK * bgNoise;     // Peak flux for fake sources
    451     psVector *noise = psVectorAlloc(num, PS_TYPE_F32); // Measurements of the noise
    452     psVector *source = psVectorAlloc(num, PS_TYPE_F32); // Measurements of fake sources
    453     psVector *guess = psVectorAlloc(num, PS_TYPE_F32); // Guess at significance
    454     psVector *photMask = psVectorAlloc(num, PS_TYPE_VECTOR_MASK); // Mask for fluxes
    455     for (int i = 0; i < num; i++) {
    456         // Coordinates of interest
    457         int xPix = psRandomUniform(rng) * xSize + xOffset + 0.5;
    458         int yPix = psRandomUniform(rng) * ySize + yOffset + 0.5;
    459         psAssert(xPix - size >= 0 && xPix + size < numCols &&
    460                  yPix - size >= 0 && yPix + size < numRows,
    461                  "Bad pixel position: %d,%d", xPix, yPix);
    462 
    463         // Weighted aperture photometry
    464         // This has the same effect as smoothing the image by the window function
    465         float sumNoise = 0.0;       // Sum for noise measurement
    466         float sumSource = 0.0;      // Sum for source measurement
    467         float sumVariance = 0.0;      // Sum for variance measurement
    468         float sumGauss = 0.0, sumGauss2 = 0.0; // Sums of Gaussian kernels
    469         for (int v = 0, y = yPix - size; v < fullSize; v++, y++) {
    470             float xSumNoise = 0.0;  // Sum for noise measurement in x
    471             float xSumSource = 0.0; // Sum for source measurement in x
    472             float xSumVariance = 0.0; // Sum for variance measurement in x
    473             float xSumGauss = 0.0, xSumGauss2 = 0.0; // Sums of Gaussian kernels in x
    474             float yGauss = gauss->data.F32[v]; // Value of Gaussian in y
    475             for (int u = 0, x = xPix - size; u < fullSize; u++, x++) {
    476                 if (mask && mask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] & maskVal) {
     372    int numCols = image->numCols, numRows = image->numRows; // Size of image
     373
     374    int xMin, xMax, yMin, yMax;         // Bounds of image
     375    if (mask) {
     376        xMin = numCols;
     377        xMax = 0;
     378        yMin = numRows;
     379        yMax = 0;
     380        for (int y = 0; y < numRows; y++) {
     381            for (int x = 0; x < numCols; x++) {
     382                if (mask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] & maskVal) {
    477383                    continue;
    478384                }
    479                 float value = image->data.F32[y][x] - bgMean; // Value of image
    480                 float xGauss = gauss->data.F32[u]; // Value of Gaussian in x
    481                 float xGauss2 = gauss2->data.F32[u]; // Value of Gaussian^2 in x
    482                 xSumNoise += value * xGauss;
    483                 xSumSource += (value + peakFlux * xGauss * yGauss) * xGauss;
    484                 xSumVariance += variance->data.F32[y][x] * xGauss2;
    485                 xSumGauss += xGauss;
    486                 xSumGauss2 += xGauss2;
    487             }
    488             float yGauss2 = gauss2->data.F32[v]; // Value of Gaussian^2 in y
    489             sumNoise += xSumNoise * yGauss;
    490             sumSource += xSumSource * yGauss;
    491             sumVariance += xSumVariance * yGauss2;
    492             sumGauss += xSumGauss * yGauss;
    493             sumGauss2 += xSumGauss2 * yGauss2;
    494         }
    495 
    496         photMask->data.PS_TYPE_VECTOR_MASK_DATA[i] = ((isfinite(sumNoise) && isfinite(sumSource) &&
    497                                                 isfinite(sumVariance) && sumGauss > 0 && sumGauss2 > 0) ?
    498                                                0 : 0xFF);
    499 
    500         float smoothImageNoise = sumNoise / sumGauss; // Value of smoothed image pixel for noise
    501         float smoothImageSource = sumSource / sumGauss; // Value of smoothed image pixel for source
    502         float smoothVariance = sumVariance / sumGauss2; // Value of smoothed variance pixel
    503 
    504         noise->data.F32[i] = smoothImageNoise;
    505         source->data.F32[i] = smoothImageSource;
    506         guess->data.F32[i] = (sumSource > 0) ? sigFactor * PS_SQR(smoothImageSource) / smoothVariance : 0.0;
    507         psTrace("psModules.camera", 10, "Flux %d (%d,%d): %f, %f, %f\n",
    508                 i, xPix, yPix, smoothImageNoise, smoothImageSource, smoothVariance);
    509     }
    510     psFree(gauss);
    511     psFree(gauss2);
    512     psFree(rng);
    513 
    514     // Standard deviation of fluxes gives us the real significance
    515     psStats *stdevStats = psStatsAlloc(stdevStat); // Statistics
    516     if (!psVectorStats(stdevStats, noise, NULL, photMask, 0xFF)) {
    517         psError(PS_ERR_UNKNOWN, false, "Unable to measure standard deviation of fluxes");
    518         psFree(stdevStats);
    519         psFree(noise);
    520         psFree(source);
    521         psFree(guess);
    522         psFree(photMask);
     385                xMin = PS_MIN(xMin, x);
     386                xMax = PS_MAX(xMax, x);
     387                yMin = PS_MIN(yMin, y);
     388                yMax = PS_MAX(yMax, y);
     389            }
     390        }
     391    } else {
     392        xMin = 0;
     393        xMax = numCols;
     394        yMin = 0;
     395        yMax = numRows;
     396    }
     397
     398    int xNum = xMax - xMin, yNum = yMax - yMin; // Number of pixels
     399
     400    int numPix = xNum * yNum;                                  // Number of pixels
     401    int num = PS_MIN(sample, numPix);                          // Number we care about
     402    psVector *signoise = psVectorAllocEmpty(num, PS_TYPE_F32);   // Signal-to-noise values
     403
     404    if (num >= numPix) {
     405        // We have an image smaller than Nsubset, so just loop over the image pixels
     406        int index = 0;                  // Index for vector
     407        for (int y = yMin; y < yMax; y++) {
     408            for (int x = xMin; x < xMax; x++) {
     409                if ((mask && mask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] & maskVal) ||
     410                    !isfinite(image->data.F32[y][x]) || !isfinite(variance->data.F32[y][x])) {
     411                    continue;
     412                }
     413
     414                signoise->data.F32[index] = image->data.F32[y][x] / sqrtf(variance->data.F32[y][x]);
     415                index++;
     416            }
     417        }
     418        signoise->n = index;
     419    } else {
     420        psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS); // Random number generator
     421        int index = 0;                  // Index for vector
     422        for (long i = 0; i < num; i++) {
     423            // Pixel coordinates
     424            int pixel = numPix * psRandomUniform(rng);
     425            int x = xMin + pixel % xNum;
     426            int y = yMin + pixel / xNum;
     427
     428            if ((mask && mask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] & maskVal) ||
     429                !isfinite(image->data.F32[y][x]) || !isfinite(variance->data.F32[y][x])) {
     430                continue;
     431            }
     432
     433            signoise->data.F32[index] = image->data.F32[y][x] / sqrtf(variance->data.F32[y][x]);
     434            index++;
     435        }
     436        signoise->n = index;
     437        psFree(rng);
     438    }
     439
     440    psStats *stats = psStatsAlloc(PS_STAT_ROBUST_STDEV); // Statistics
     441
     442    if (!psVectorStats(stats, signoise, NULL, NULL, 0)) {
     443        psError(PS_ERR_UNKNOWN, false, "Unable to measure statistics on S/N image");
     444        psFree(signoise);
    523445        return false;
    524446    }
    525     float stdev = psStatsGetValue(stdevStats, stdevStat); // Standard deviation of fluxes
    526     psFree(stdevStats);
    527     psFree(noise);
    528     psTrace("psModules.camera", 5, "Standard deviation of fluxes is %f\n", stdev);
    529 
    530     // Ratio of measured significance to guessed significance
    531     psVector *ratio = psVectorAlloc(num, PS_TYPE_F32); // Ratio of measured to guess
    532     for (int i = 0; i < num; i++) {
    533         float measuredSig = PS_SQR(source->data.F32[i] / stdev); // Measured significance
    534         ratio->data.F32[i] = measuredSig / guess->data.F32[i];
    535         if (guess->data.F32[i] <= 0.0 || source->data.F32[i] <= 0.0 || !isfinite(ratio->data.F32[i])) {
    536             photMask->data.PS_TYPE_VECTOR_MASK_DATA[i] = 0xFF;
    537         }
    538         psTrace("psModules.camera", 9, "Ratio %d: %f, %f, %f\n",
    539                 i, guess->data.F32[i], measuredSig, ratio->data.F32[i]);
    540     }
    541     psFree(source);
    542     psFree(guess);
    543 
    544     psStats *meanStats = psStatsAlloc(meanStat | stdevStat); // Statistics
    545     if (!psVectorStats(meanStats, ratio, NULL, photMask, 0xFF)) {
    546         psError(PS_ERR_UNKNOWN, false, "Unable to measure mean ratio");
    547         psFree(meanStats);
    548         psFree(ratio);
    549         psFree(photMask);
     447    psFree(signoise);
     448
     449    float covar = sqrtf(psImageCovarianceFactor(readout->covariance)); // Covariance factor
     450    float correction = stats->robustStdev / covar; // Correction factor
     451    psFree(stats);
     452    psLogMsg("psModules.camera", PS_LOG_DETAIL, "Variance renormalisation factor is %f", correction);
     453
     454    // Check valid range of correction factor
     455    if ((isfinite(minValid) && correction < minValid) || (isfinite(maxValid) && correction > maxValid)) {
     456        psError(PS_ERR_UNKNOWN, true, "Variance renormalisation is outside valid range: %f vs %f:%f --- no correction made", correction, minValid, maxValid);
     457        psMetadataAddF32(readout->analysis, PS_LIST_TAIL, PM_READOUT_ANALYSIS_RENORM, 0, "Renormalisation of variance", PS_SQR(correction));
    550458        return false;
    551459    }
    552     float meanRatio = psStatsGetValue(meanStats, meanStat); // Mean ratio
    553     psTrace("psModules.camera", 5, "Mean significance ratio is %f +/- %f\n",
    554             meanRatio, psStatsGetValue(meanStats, stdevStat));
    555     psFree(meanStats);
    556     psFree(ratio);
    557     psFree(photMask);
    558 
    559     psLogMsg("psModules.camera", PS_LOG_INFO, "Renormalising variance map by %f", meanRatio);
    560     psBinaryOp(variance, variance, "*", psScalarAlloc(meanRatio, PS_TYPE_F32));
    561 
    562     return true;
    563 }
    564 
    565 
    566 bool pmReadoutVarianceRenorm(const pmReadout *readout, psImageMaskType maskVal, psStatsOptions meanStat,
    567                            psStatsOptions stdevStat, int width, psRandom *rng)
    568 {
    569     PM_ASSERT_READOUT_NON_NULL(readout, false);
    570     PM_ASSERT_READOUT_IMAGE(readout, false);
    571     PM_ASSERT_READOUT_VARIANCE(readout, false);
    572     PS_ASSERT_INT_POSITIVE(width, false);
    573 
    574     if (!psMemIncrRefCounter(rng)) {
    575         rng = psRandomAlloc(PS_RANDOM_TAUS);
    576     }
    577 
    578     psImage *image = readout->image, *mask = readout->mask, *variance = readout->variance; // Readout images
    579     int numCols = image->numCols, numRows = image->numRows; // Size of images
    580     int xNum = numCols / width + 1, yNum = numRows / width + 1; // Number of renormalisation regions
    581     float xSize = numCols / (float)xNum, ySize = numRows / (float)yNum; // Size of renormalisation regions
    582 
    583     psStats *meanStats = psStatsAlloc(meanStat), *stdevStats = psStatsAlloc(stdevStat); // Statistics
    584     psVector *buffer = NULL;
    585 
    586     for (int j = 0; j < yNum; j++) {
    587         // Bounds in y
    588         int yMin = j * ySize;
    589         int yMax = (j + 1) * ySize;
    590         for (int i = 0; i < xNum; i++) {
    591             // Bounds in x
    592             int xMin = i * xSize;
    593             int xMax = (i + 1) * xSize;
    594 
    595             psRegion region = psRegionSet(xMin, xMax, yMin, yMax); // Region of interest
    596             psImage *subImage = psImageSubset(image, region); // Sub-image of the image pixels
    597             psImage *subVariance = psImageSubset(variance, region); // Sub image of the variance pixels
    598             psImage *subMask = mask ? psImageSubset(mask, region) : NULL; // Sub-image of the mask pixels
    599 
    600             if (!psImageBackground(stdevStats, &buffer, subImage, subMask, maskVal, rng) ||
    601                 !psImageBackground(meanStats, &buffer, subVariance, subMask, maskVal, rng)) {
    602                 // Nothing we can do about it, but don't want to keel over and die, so do our best to flag it.
    603                 psString regionStr = psRegionToString(region); // String with region
    604                 psWarning("Unable to measure statistics over %s", regionStr);
    605                 psFree(regionStr);
    606                 psErrorClear();
    607                 psImageInit(subVariance, NAN);
    608                 if (subMask) {
    609                     psImageInit(subMask, maskVal);
    610                 }
    611             } else {
    612                 double meanVar = psStatsGetValue(meanStats, meanStat); // Mean of variance map
    613                 double stdev = psStatsGetValue(stdevStats, stdevStat); // Standard deviation of image
    614                 psTrace("psModules.camera", 3,
    615                         "Region [%d:%d,%d:%d] has variance %lf, but mean of variance map is %lf\n",
    616                         xMin, xMax, yMin, yMax, PS_SQR(stdev), meanVar);
    617                 psBinaryOp(subVariance, subVariance, "*", psScalarAlloc(PS_SQR(stdev) / meanVar, PS_TYPE_F32));
    618             }
    619 
    620             psFree(subImage);
    621             psFree(subVariance);
    622             psFree(subMask);
    623         }
    624     }
    625     psFree(meanStats);
    626     psFree(stdevStats);
    627     psFree(rng);
    628     psFree(buffer);
    629 
    630     return true;
    631 }
     460
     461    psImage *subImage = psImageSubset(variance, psRegionSet(xMin, xMax, yMin, yMax)); // Smaller image
     462    psBinaryOp(subImage, subImage, "*", psScalarAlloc(PS_SQR(correction), PS_TYPE_F32));
     463    psFree(subImage);
     464
     465    pmHDU *hdu = pmHDUFromReadout(readout); // HDU for readout
     466    if (hdu)  {
     467        psString history = NULL;
     468        psStringAppend(&history, "Rescaled variance by %6.4f (stdev by %6.4f)",
     469                       PS_SQR(correction), correction);
     470        psMetadataAddStr(hdu->header, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, NULL, history);
     471        psFree(history);
     472    }
     473
     474    return psMetadataAddF32(readout->analysis, PS_LIST_TAIL, PM_READOUT_ANALYSIS_RENORM, 0,
     475                            "Renormalisation of variance", PS_SQR(correction));
     476}
     477
    632478
    633479
Note: See TracChangeset for help on using the changeset viewer.