IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Sep 27, 2021, 11:11:33 AM (5 years ago)
Author:
eugene
Message:

added binned vs unbinned version of pattern fitting; stricter cuts on thresholding

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/eam_branches/ipp-dev-20210817/psModules/src/detrend/pmPattern.c

    r41811 r41817  
    137137
    138138// Comparison and swap functions for sorting values directly
    139 #define SORT_COMPARE(A,B) (value[A] < value[B])
    140 #define SORT_SWAP(A,B) { \
     139#define SORT_COMPARE(A,B) (sampleArray[A] < sampleArray[B])
     140#define SORT_SWAP(TYPE,A,B) {                   \
    141141    if (A != B) { \
    142         float temp = value[A]; \
    143         value[A] = value[B]; \
    144         value[B] = temp; \
     142        TYPE temp = sampleArray[A];                     \
     143        sampleArray[A] = sampleArray[B]; \
     144        sampleArray[B] = temp; \
    145145    } \
    146146}
     
    150150//////////////////////////////////////////////////////////////////////////////////////////////////////////////
    151151
     152bool pmPatternRowUnbinned(pmReadout *ro, int order, int iter, float rej, float thresh,
     153                          psStatsOptions clipMean, psStatsOptions clipStdev,
     154                          psImageMaskType maskVal, psImageMaskType maskBad);
     155
     156
     157bool pmPatternRowBinned(pmReadout *ro, int order, int iter, float rej, float thresh,
     158                        psStatsOptions clipMean, psStatsOptions clipStdev,
     159                        psImageMaskType maskVal, psImageMaskType maskBad);
     160
     161
     162bool pmPatternRow(pmReadout *ro, int order, int iter, float rej, float thresh,
     163                  psStatsOptions clipMean, psStatsOptions clipStdev,
     164                  psImageMaskType maskVal, psImageMaskType maskBad) {
     165
     166//  bool status = pmPatternRowBinned(ro, order, iter, rej, thresh, clipMean, clipStdev, maskVal, maskBad);
     167    bool status = pmPatternRowUnbinned(ro, order, iter, rej, thresh, clipMean, clipStdev, maskVal, maskBad);
     168    return status;
     169}
     170
    152171// USE_BACKGROUND_STDEV: if true, the analysis will use the measured robust stdev to clip the out-of-range pixles
    153172// if false, the stdev will be estimated based on the Poisson statistics of the median (sky level).
    154173# define USE_BACKGROUND_STDEV 0
    155174
    156 bool pmPatternRow(pmReadout *ro, int order, int iter, float rej, float thresh,
     175bool pmPatternRowUnbinned(pmReadout *ro, int order, int iter, float rej, float thresh,
    157176                  psStatsOptions clipMean, psStatsOptions clipStdev,
    158177                  psImageMaskType maskVal, psImageMaskType maskBad)
     
    233252
    234253    psStats *clip = psStatsAlloc(clipMean | clipStdev); // Clipping statistics
    235     // XXX clip->clipIter = iter;
    236     clip->clipIter = 1; // XXX skip iteration for a test
     254    clip->clipIter = iter;
    237255    clip->clipSigma = rej;
    238256    psVector *clipMask = psVectorAlloc(numCols, PS_TYPE_VECTOR_MASK); // Mask for clipping
     
    440458}
    441459
    442 // bin by Npix in the x-direction to reduce the number of calculations needed to measure
     460# define NPIX 31   
     461
     462// bin by NPIX in the x-direction to reduce the number of calculations needed to measure
    443463// the pattern
    444464bool pmPatternRowBinned(pmReadout *ro, int order, int iter, float rej, float thresh,
     
    474494    }
    475495
     496    // if USE_BACKGROUND_STDEV is TRUE, the observed standard deviation is used to set the
     497    // thresholds.  this is going to be an overestimate if there is any structure in the
     498    // image.  If FALSE, the thresholds are set based on poisson stats for the background
     499    // level.  We assume the gain is 1, so this is an overestimate if the gain is > 1
     500
    476501# if (USE_BACKGROUND_STDEV)
    477502    float lower = stats->robustMedian - thresh * stats->robustStdev; // Lower bound for data
     
    497522    # define READNOISE 10
    498523    float sigma = sqrt(stats->robustMedian + PS_SQR(READNOISE));
    499     float lower = stats->robustMedian - thresh * sigma; // Lower bound for data
    500     float upper = stats->robustMedian + thresh * sigma; // Upper bound for data
     524    float delta = PS_MIN (thresh * sigma, 40);
     525    float lower = stats->robustMedian - delta; // Lower bound for data
     526    float upper = stats->robustMedian + delta; // Upper bound for data
    501527    float background = stats->robustMedian;
    502528# endif   
     
    513539    psFree(rng);
    514540
    515 # define NPIX 15   
    516 
    517     // Indices are distributed [-1:1] [-1 = 0, +1 = numCols = indices[nSamples]
     541    // the vector 'indices' maps the x-coordinate to a range [-1:1].  the element number (i) of indices
     542    // related to the x-coordinate (column number) by x = (i + 0.5) * NPIX
     543
    518544    int nSamples = numCols / NPIX;
    519     psVector *indices = psVectorAlloc(nSamples, PS_TYPE_F32); // Indices for fitting
    520     psVector *fitData = psVectorAlloc(nSAmples, PS_TYPE_F32); // Data to fit
    521 
    522     // indices elements run from 0 - nSamples, element 'sample' corresponds to the middle of the bin sample*NPIX + 0.5*NPIX
     545
     546    psVector *indices = psVectorAlloc(numCols, PS_TYPE_F32); // Indices for fit solutions
     547    psVector *xFit = psVectorAlloc(nSamples, PS_TYPE_F32); // x-coordinate for fitting
     548    psVector *yFit = psVectorAlloc(nSamples, PS_TYPE_F32); // flux values for fitting
     549
     550    // xFit elements run from 0 - nSamples, element 'sample' corresponds to the middle of the bin sample*NPIX + 0.5*NPIX
    523551
    524552    float norm = 2.0 / (float)numCols;  // Normalisation for indices
    525553    for (int sample = 0; sample < nSamples; sample ++) {
    526554        int x = (sample + 0.5)*NPIX;
    527         indices->data.F32[sample] = x * norm - 1.0;
     555        xFit->data.F32[sample] = x * norm - 1.0;
     556    }
     557    for (int x = 0; x < numCols; x ++) {
     558        indices->data.F32[x] = x * norm - 1.0;
    528559    }
    529560
    530561    psStats *clip = psStatsAlloc(clipMean | clipStdev); // Clipping statistics
    531     // XXX clip->clipIter = iter;
    532     clip->clipIter = 1; // XXX skip iteration for a test
     562    clip->clipIter = iter;
    533563    clip->clipSigma = rej;
    534     psVector *clipMask = psVectorAlloc(numCols, PS_TYPE_VECTOR_MASK); // Mask for clipping
     564    psVector *clipMask = psVectorAlloc(nSamples, PS_TYPE_VECTOR_MASK); // Mask for clipping
    535565    psPolynomial1D *poly = psPolynomial1DAlloc(PS_POLYNOMIAL_ORD, order); // Polynomial to fit
    536566    psVector *data = psVectorAlloc(numCols, PS_TYPE_F32); // Data to fit
     
    539569    psImageInit(corr, NAN);
    540570
    541 #ifdef PATTERN_ROW_BKG_FIX
    542571    // CZW: 2011-11-30
    543572    // Define the vectors to hold the "x" and "y" slope trends.
     
    556585    psVector *xaxisData = psVectorAlloc(numRows, PS_TYPE_F32); // Data to fit to the linear term
    557586    psVectorInit(yaxisMask, 0);
    558 #endif
    559 
    560     // we really need more than order + 1 points (= 4).
     587
     588    // validNmin is the minimum number of samples needed to measure the trend.
    561589    // this should be tunable, but let's try 5 - 10%
    562     int validNmin = numCols * 0.1;
     590    int validNmin = PS_MAX (nSamples * 0.1, order + 2);
    563591
    564592    for (int y = 0; y < numRows; y++) {
     
    572600        float validXmax = -1;
    573601
    574         // XXX bookkeeping might be easier if this loop is over elements of 'indices'
    575         // XXX can we do just as well fitting 1/3 of the pixels? (NOT REALLY)
    576         // (x % 3) ||
    577602        for (int sample = 0; sample < nSamples; sample ++) {
    578603
    579             // store valid samples in the array
     604            // store valid samples in the array to be sorted
    580605            float sampleArray[NPIX];
    581606            int seq = 0;
    582607            for (int j = 0; j < NPIX; j++) {
    583                 int pix = sample  * NPIX + j;
     608                int pix = sample  * NPIX + j; // real pixel elements in x-dir
    584609                if ((mask && mask->data.PS_TYPE_IMAGE_MASK_DATA[y][pix] & maskVal)) continue;
    585610                if (data->data.F32[pix] < lower || data->data.F32[pix] > upper) continue;
    586                 sampleArray[seq] = data->data.F32[pix];
     611                sampleArray[seq] = data->data.F32[pix]; // store the value to be sorted
    587612                seq ++;
    588613            }
    589614            if (seq < 1) {
    590615                clipMask->data.PS_TYPE_VECTOR_MASK_DATA[sample] = 0xFF;
    591             } else {
    592                 clipMask->data.PS_TYPE_VECTOR_MASK_DATA[sample] = 0;
    593                 num++;
    594                 validXmin = PS_MIN(indices->data.F32[sample], validXmin);
    595                 validXmax = PS_MAX(indices->data.F32[sample], validXmax);
    596             }
    597 
    598             PSSORT (seq, sampleArray
    599 
    600         }
    601 
    602         // XXX how much time is spent in the fitting
     616                yFit->data.F32[sample] = NAN;
     617                continue;
     618            }
     619            // note that we are treating the x-coordinate as the center
     620            // of the binned pixel group, even if some or most pixels have
     621            // been masked.  compared to the amplitude of the slope, this
     622            // error is small
     623            clipMask->data.PS_TYPE_VECTOR_MASK_DATA[sample] = 0;
     624            validXmin = PS_MIN(xFit->data.F32[sample], validXmin);
     625            validXmax = PS_MAX(xFit->data.F32[sample], validXmax);
     626            num++;
     627
     628            // PSSORT operates on sampleArray (see define of macro SORT_SWAP above)
     629            PSSORT (seq, SORT_COMPARE, SORT_SWAP, float);
     630
     631            int midPt = 0.5 * seq;
     632            float medValue = (seq % 2) ? sampleArray[midPt] : 0.5*(sampleArray[midPt] + sampleArray[midPt-1]);
     633            yFit->data.F32[sample] = medValue;
     634        }
     635
     636        // XXX how much time is spent in the fitting? to test: make this always true
    603637        if (num < validNmin) {
    604638            // Not enough points to fit
     
    609643        }
    610644        // XXX does this need to be a clipped fit if we are clipping based on the median poisson noise?
    611         if (!psVectorClipFitPolynomial1D(poly, clip, clipMask, 0xFF, data, NULL, indices)) {
     645        if (!psVectorClipFitPolynomial1D(poly, clip, clipMask, 0xFF, yFit, NULL, xFit)) {
    612646            psWarning("Unable to fit polynomial to row %d", y);
    613647            psErrorClear();
     
    628662            psErrorClear();
    629663            patternMaskRow(ro, y, maskBad);
    630 #ifdef PATTERN_ROW_BKG_FIX
    631664            yaxisMask->data.PS_TYPE_VECTOR_MASK_DATA[y] = 0xFF;
    632 #endif
    633665            continue;
    634666        }
     
    641673    }
    642674
    643 #ifdef PATTERN_ROW_BKG_FIX
    644675    // Put the global trends back that were removed by the PATTERN.ROW correction.
    645676    // Set up the indices for the polynomial
     
    665696        corr->data.F64[y][0]  -= background;
    666697      }
    667     }
    668     else {
     698    } else {
    669699      psVector *solution = psPolynomial1DEvalVector(yaxisPoly,yaxisIndices);
    670700      if (!solution) {
     
    679709          corr->data.F64[y][0]  -= background;
    680710        }
    681       }
    682       else {
     711      } else {
    683712        for (int y = 0; y < numRows; y++) {
    684713          for (int x = 0; x < numCols; x++) {
     
    699728      psWarning("Unable to fit polynomial to x-axis trend");
    700729      psErrorClear();
    701     }
    702     else {
     730    } else {
    703731      psVector *solution = psPolynomial1DEvalVector(xaxisPoly,yaxisIndices);
    704732      if (!solution) {
    705733        psWarning("Unable to evaluate polynomial");
    706734        psErrorClear();
    707       }
    708       else {
     735      } else {
    709736        for (int y = 0; y < numRows; y++) {
    710737          for (int x = 0; x < numCols; x++) {
     
    723750    psFree(yaxisData);
    724751    psFree(xaxisData);
    725     // End PATTERN_ROW_BKG_FIX global trend replacement
    726 #endif
    727752   
    728753    psMetadataAddImage(ro->analysis, PS_LIST_TAIL, PM_PATTERN_ROW_CORRECTION, PS_META_REPLACE,
     
    731756
    732757    psFree(indices);
     758    psFree(xFit);
     759    psFree(yFit);
    733760    psFree(clip);
    734761    psFree(clipMask);
Note: See TracChangeset for help on using the changeset viewer.