IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 41945


Ignore:
Timestamp:
Dec 1, 2021, 9:27:09 AM (5 years ago)
Author:
eugene
Message:

add coarse outlier rejection

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/eam_branches/ipp-20211108/psModules/src/imcombine/pmStack.c

    r41940 r41945  
    15381538#define SORT_VALUES(NVALUES) { PSSORT(NVALUES, SORT_VV_COMPARE, SORT_VV_SWAP, F32); }
    15391539
     1540#define ESCAPE                                                          \
     1541  combined->image->data.F32[y][x] = NAN;                                \
     1542  combined->variance->data.F32[y][x] = NAN;                             \
     1543  combined->mask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] = blankMaskBits;   \
     1544  if (expmaps) {                                                        \
     1545    expmaps->image->data.F32[y][x] = 0.0;                               \
     1546    expmaps->variance->data.F32[y][x] = 0.0;                            \
     1547    expmaps->mask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] = 0;              \
     1548  }                                                                     \
     1549  continue;
     1550
    15401551bool pmStackCombineByPercentile(
    15411552    pmReadout *combined,                // output stacked readout
     
    16311642                nGood ++;
    16321643            }
     1644# define MIN_GOOD_PERCENTILE 3
     1645
     1646            if (nGood < MIN_GOOD_PERCENTILE) ESCAPE;
     1647           
    16331648            pixelData->n = nGood;
     1649
     1650            // sort pixelData, pixelVariance, expTime (if it exists)
     1651            SORT_VALUES (pixelData->n);
     1652
     1653            // we now have a sorted vector of values.  We can make a very coarse outlier
     1654            // cut based on the median and interquartile range.  This will let us reject
     1655            // some extreme outliers that bias the signal otherwise.
     1656
     1657            int Nlo = 0;     
     1658            int Nhi = nGood;
     1659
     1660            if (nGood >= 5) {
     1661              int midPoint = nGood / 2;
     1662              float rawMedian = (nGood % 2) ? pixelData->data.F32[midPoint] : 0.5*(pixelData->data.F32[midPoint] + pixelData->data.F32[midPoint-1]);
     1663             
     1664              // XXX measure interquartile range
     1665              int P25 = 0.25*nGood;
     1666              int P75 = 0.75*nGood;
     1667              float rawSigma = 0.74*(pixelData->data.F32[P75] - pixelData->data.F32[P25]);
     1668              float minThresh = rawMedian - 7.0*rawSigma;
     1669              float maxThresh = rawMedian + 7.0*rawSigma;
     1670
     1671              // find the entries which are in the range
     1672              // these should be safe since minThresh and maxThresh are guaranteed to contain the median
     1673              while (pixelData->data.F32[Nlo    ] < minThresh) { Nlo ++; }
     1674              while (pixelData->data.F32[Nhi - 1] > maxThresh) { Nhi --; }
     1675            }
     1676
     1677            // if we did not clip above (either nGood < 5 or no rejection), Nlo will be 0, Nhi will be nGood
     1678            // In either case, Nlo is the offset of the first unclipped point.
     1679            int nGoodClip = Nhi - Nlo;
    16341680
    16351681            // rather than define a min and max value,
     
    16451691# define MIN_GOOD_PERCENTILE 3
    16461692# if (AT_LEAST)
    1647             int Ns = MIN(MAX(1, 0.5*rejectFraction * nGood), nGood);
    1648             int Ne = nGood - Ns;
     1693            int Ns = MIN(MAX(1, 0.5*rejectFraction * nGoodClip), nGoodClip) + Nlo;
     1694            int Ne = nGood - Ns + Nlo;
    16491695            int Npt = Ne - Ns;
    16501696# else
    1651             int Ns = MIN(MAX(0, 0.5*rejectFraction * nGood), nGood);
    1652             int Ne = nGood - Ns;
     1697            int Ns = MIN(MAX(0, 0.5*rejectFraction * nGood), nGood) + Nlo;
     1698            int Ne = nGood - Ns + Nlo;
    16531699            int Npt = Ne - Ns;
    16541700# endif
    1655             if ((Npt < 1) || (nGood < MIN_GOOD_PERCENTILE)) {
    1656                 combined->image->data.F32[y][x] = NAN;
    1657                 combined->variance->data.F32[y][x] = NAN;
    1658                 combined->mask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] = blankMaskBits; // probably not needed since it was set above.
    1659                 if (expmaps) {
    1660                     expmaps->image->data.F32[y][x] = 0.0; // XXX should this value be NAN or 0?
    1661                     expmaps->variance->data.F32[y][x] = 0.0;
    1662                     expmaps->mask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] = 0;
    1663                 }
    1664                 continue;
    1665             }
    1666 
    1667             // sort pixelData, pixelVariance, expTime (if it exists)
    1668             SORT_VALUES (pixelData->n);
    1669 
     1701            if ((Npt < 1) || (nGood < MIN_GOOD_PERCENTILE)) ESCAPE;
     1702
     1703            // XXX note that this does not respect the clipping above
    16701704            // set the given (suspect) mask bit if nGoodBits[i] > f*nGood
    16711705            // in other words if more than 65% of the good inputs had one of
     
    17051739            // this coefficient varies between 1.4 (for pure median) and 1.05 for 68% range.
    17061740
    1707             float varValue = varSum / (float) (nGood*nGood);
     1741            float varValue = varSum / (float) (nGoodClip*nGoodClip);
    17081742
    17091743            combined->image->data.F32[y][x] = mean;
     
    17191753            if (expTime) {
    17201754                float sum = 0.0;
    1721                 for (int n = 0; n < nGood; n++) {
     1755                for (int n = Nlo; n < Nhi; n++) {
    17221756                    sum += expTime->data.F32[n];
    17231757                }
    17241758                expmaps->image->data.F32[y][x] = sum;
    17251759            }
    1726             if (expmaps) { expmaps->mask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] = nGood; }
     1760            if (expmaps) { expmaps->mask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] = nGoodClip; }
    17271761        }
    17281762    }
Note: See TracChangeset for help on using the changeset viewer.