IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Oct 29, 2021, 5:17:26 AM (5 years ago)
Author:
eugene
Message:

combine-by-percent must select a symmetric subset

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/eam_branches/psModules.20211028/src/imcombine/pmStack.c

    r41852 r41872  
    15141514
    15151515# define MIN_GOOD_PERCENTILE 2
     1516# define SUSPECT_FRACTION 0.65
     1517
     1518// Comparison and swap functions for sorting values directly
     1519#define SORT_VV_COMPARE(A,B) (pixelData->data.F32[A] < pixelData->data.F32[B])
     1520#define SORT_VV_SWAP(TYPE,A,B) {                                        \
     1521    if (A != B) {                                                       \
     1522      psF32 tempVal = pixelData->data.F32[A];                           \
     1523      pixelData->data.F32[A] = pixelData->data.F32[B];                  \
     1524      pixelData->data.F32[B] = tempVal;                                 \
     1525      psF32 tempVar = pixelVariances->data.F32[A];                      \
     1526      pixelVariances->data.F32[A] = pixelVariances->data.F32[B];                \
     1527      pixelVariances->data.F32[B] = tempVar;                            \
     1528    }                                                                   \
     1529}
     1530
     1531#define SORT_VALUE_AND_VAR(A,B) { PSSORT(A->n, SORT_VV_COMPARE, SORT_VV_SWAP, F32); }
     1532 
     1533
    15161534bool pmStackCombineByPercentile(
    15171535    pmReadout *combined,
    15181536    psArray *stackData,
    1519     psF64 minRange,
     1537    psF64 rejectFraction,
    15201538    psF64 maxRange,
    15211539    psImageMaskType badMaskBits,        // treat these bits as 'bad'
     
    15411559    psFree(stackReadouts);
    15421560
    1543     psVector *pixelData = psVectorAlloc(stackData->n, PS_TYPE_F32);
    1544     psVector *pixelMask = psVectorAlloc(stackData->n, PS_TYPE_VECTOR_MASK);
     1561    // make sure the output readout matches the inputs, and set to blank by default
     1562    pmReadoutUpdateSize(combined, minInputCols, minInputRows, xSize, ySize, true, true, blankMaskBits);
     1563
     1564    psVector *pixelData      = psVectorAlloc(stackData->n, PS_TYPE_F32);
     1565    psVector *pixelVariances = psVectorAlloc(stackData->n, PS_TYPE_F32);
     1566    psVector *pixelMask      = psVectorAlloc(stackData->n, PS_TYPE_VECTOR_MASK);
     1567
     1568    int nGoodBits[16]; // accumulate the good pixel bits here for fuzzy logic
     1569    psAssert (sizeof(psImageMaskType) == 2, "psImageMaskType is not the expected size");
     1570    memset (nGoodBits, 0, 16*sizeof(int));
    15451571
    15461572    for (int y = minInputRows; y < maxInputRows; y++) {
     
    15521578                pmStackData *data = stackData->data[i]; // Stack data for this input
    15531579                pmReadout *ro = data->readout;  // Readout of interest
    1554                 psImage *image = ro->image;
    1555                 psImage *mask = ro->mask;
     1580
     1581                psImage *image    = ro->image;
     1582                psImage *variance = ro->variance;
     1583                psImage *mask     = ro->mask;
    15561584
    15571585                int xIn = x - data->readout->col0;
    15581586                int yIn = y - data->readout->row0; // Coordinates on input readout
    15591587
     1588                // skip obviously bad input data
    15601589                if (!isfinite(image->data.F32[yIn][xIn])) continue;
    1561                 if (fabs(image->data.F32[yIn][xIn]) > 1e5) continue;
    1562                 // XXX need to test the input mask as well here
    1563                 if (mask->data.PS_TYPE_IMAGE_MASK_DATA[yIn][xIn] & badMaskBits);
    1564 
    1565                 // XXX save the count of suspect bits
    1566 
    1567 # if (0)
     1590                if (fabs(image->data.F32[yIn][xIn]) > 1e5) continue; // XXX this cut is a bit arbitrary..
     1591                if (mask->data.PS_TYPE_IMAGE_MASK_DATA[yIn][xIn] & badMaskBits) continue;
     1592
    15681593                // count the number of times a given mask bit is set in the input pixels.
    15691594                // NOTE: since we have explicitly skipped the pixels with any bad bits, these are only
    15701595                // the suspect bits (nGoodBits is a bit of a misnomer: it is more like 'nSuspectBitsForGoodInputs'
    1571                 if (1) {
    1572                   psImageMaskType value = 0x0001;
    1573                   for (int nbit = 0; nbit < 16; nbit ++) {
    1574                     if (mask->data.PS_TYPE_IMAGE_MASK_DATA[yIn][xIn] & value) {
    1575                       // XXX nGoodBits[nbit] ++;
    1576                     }
    1577                     value <<= 1;
     1596                psImageMaskType value = 0x0001;
     1597                for (int nbit = 0; nbit < 16; nbit ++) {
     1598                  if (mask->data.PS_TYPE_IMAGE_MASK_DATA[yIn][xIn] & value) {
     1599                    nGoodBits[nbit] ++;
    15781600                  }
     1601                  value <<= 1;
    15791602                }
    1580 # endif
     1603
     1604                // pixelWeights->data.F32[nGood] = data->weight;
     1605                // pixelExps->data.F32[nGood] = data->exp;
     1606                // pixelSources->data.U16[nGood] = i;
    15811607
    15821608                pixelData->data.F32[nGood] = image->data.F32[yIn][xIn];
     1609                if (variance) {
     1610                  // pixelVariances->data.F32[numGood] = variance->data.F32[yIn][xIn] * addVariance->data.F32[i];
     1611                  pixelVariances->data.F32[nGood] = variance->data.F32[yIn][xIn];
     1612                }
     1613
    15831614                nGood ++;
    15841615            }
    15851616            pixelData->n = nGood;
    1586             psVectorSortInPlace (pixelData);
    1587 
    1588             if (nGood < MIN_GOOD_PERCENTILE) {
     1617
     1618
     1619            // rather than define a min and max value,
     1620            // what we really want is a symmetric selection about the middle,
     1621            // or the output is biased.  If N % 2 = 1, then
     1622           
     1623            // we are going to exclude rejectFraction*nGood measurements.  But the
     1624            // rejection needs to be symmetric
     1625
     1626# define AT_LEAST 0
     1627# if (AT_LEAST)
     1628            int Ns = MIN(MAX(1, 0.5*rejectFraction * nGood), nGood);
     1629            int Ne = nGood - Ns;
     1630            int Npt = Ne - Ns;
     1631# else
     1632            int Ns = MIN(MAX(0, 0.5*rejectFraction * nGood), nGood);
     1633            int Ne = nGood - Ns;
     1634            int Npt = Ne - Ns;
     1635# endif
     1636            if ((Npt < 1) || (nGood < MIN_GOOD_PERCENTILE)) {
    15891637                combined->image->data.F32[y][x] = NAN;
    15901638                combined->variance->data.F32[y][x] = NAN;
    1591                 combined->mask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] = 1;
     1639                combined->mask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] = blankMaskBits; // probably not needed since it was set above.
    15921640                continue;
    15931641            }
    15941642
    1595 # if (0)
    1596 # define SUSPECT_FRACTION 0.65
    1597             // set the mask bits if nGoodBits[i] > f*numGood
    1598             if (0) {
    1599               psImageMaskType value = 0x0001;
    1600               for (int nbit = 0; nbit < 16; nbit ++) {
    1601                 if (nGoodBits[nbit] > SUSPECT_FRACTION*numGood) {
    1602                   *goodMask |= value;
    1603                 }
    1604                 value <<= 1;
     1643            // sort both pixelData and pixelVariance
     1644            SORT_VALUE_AND_VAR (pixelData, pixelVariances);
     1645
     1646            // set the given (suspect) mask bit if nGoodBits[i] > f*nGood
     1647            // in other words if more than 65% of the good inputs had one of
     1648            // these bits set, then we should set that bit in the output mask
     1649            psImageMaskType value = 0x0001;
     1650            psImageMaskType outputMask = 0x0000;
     1651            for (int nbit = 0; nbit < 16; nbit ++) {
     1652              if (nGoodBits[nbit] > SUSPECT_FRACTION*nGood) {
     1653                outputMask |= value;
    16051654              }
     1655              value <<= 1;
    16061656            }
    1607 # endif
    1608 
    1609             int Ns = MIN(MAX(0, minRange * nGood),nGood); // e.g., 0.1 * 50 = 5
    1610             int Ne = MIN(MAX(0, maxRange * nGood),nGood); // e.g., 0.9 * 50 = 45
    1611             int Npt = Ne - Ns;
    16121657
    16131658            float sum = 0.0;
     1659            float varSum = 0.0;
    16141660            for (int n = Ns; n < Ne; n++) {
    16151661                sum += pixelData->data.F32[n];
     1662                varSum += pixelVariances->data.F32[n];
    16161663            }
    16171664            float mean = sum / (float) Npt;
    16181665
    1619             float varSum = 0.0;
    1620             for (int n = Ns; n < Ne; n++) {
    1621                 varSum += SQ(pixelData->data.F32[n] - mean);
    1622             }
     1666            // alternative: calculate the stdev of the pixel values
     1667            // float varSum = 0.0;
     1668            // for (int n = Ns; n < Ne; n++) {
     1669            //  varSum += SQ(pixelData->data.F32[n] - mean);
     1670            // }
    16231671            // variance on the mean (stdev / sqrt(N))^2
    1624             float varValue = varSum / (Npt - 1) / Npt;
    1625 
    1626             // XXX this is probably not the correct variance to save
    1627             // the predicted variance should be the 1 / sum (1/var)
     1672            float varValue = varSum / (Npt*Npt);
    16281673
    16291674            combined->image->data.F32[y][x] = mean;
    16301675            combined->variance->data.F32[y][x] = varValue;
    1631             combined->mask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] = 0;
     1676            combined->mask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] = outputMask;
    16321677        }
    16331678    }
Note: See TracChangeset for help on using the changeset viewer.