Пример #1
0
def main():
    butils = measDeblend.BaselineUtilsF

    foot = buildExample2()

    fbb = foot.getBBox()
    mask1 = afwImg.MaskU(fbb.getWidth(), fbb.getHeight())
    mask1.setXY0(fbb.getMinX(), fbb.getMinY())
    afwDet.setMaskFromFootprint(mask1, foot, 1)

    if plt:
        plt.clf()
        plt.imshow(mask1.getArray(), origin='lower', interpolation='nearest',
                   extent=(fbb.getMinX(), fbb.getMaxX(), fbb.getMinY(), fbb.getMaxY()))
        plt.gray()
        plt.savefig('foot2.png')

        sfoot = butils.symmetrizeFootprint(foot, 355, 227)

        mask2 = afwImg.MaskU(fbb.getWidth(), fbb.getHeight())
        mask2.setXY0(fbb.getMinX(), fbb.getMinY())
        afwDet.setMaskFromFootprint(mask2, sfoot, 1)

        plt.clf()
        plt.imshow(mask2.getArray(), origin='lower', interpolation='nearest',
                   extent=(fbb.getMinX(), fbb.getMaxX(), fbb.getMinY(), fbb.getMaxY()))
        plt.gray()
        plt.savefig('sfoot3.png')
Пример #2
0
    def removeSource(self, id):
        """!
        Remove the heavy footprint of a given source and replace with previous noise

        @param[in]  id   id for current source to insert from original footprint dict

        Also restore the mask plane.
        """
        # remove a single source
        # (Replace this source's pixels by noise again.)
        # Do this by finding the source's top-level ancestor
        mi = self.exposure.getMaskedImage()
        im = mi.getImage()
        mask = mi.getMask()

        # use the same algorithm as in remove Source to find the heavy noise footprint
        # which will undo what insertSource(id) does
        usedid = id
        while self.footprints[usedid][
                0] != 0 and not usedid in self.heavies.keys():
            usedid = self.footprints[usedid][0]
        # Re-insert the noise pixels
        fp = self.heavyNoise[usedid]
        fp.insert(im)
        # Clear the THISDET mask plane.
        afwDet.clearMaskFromFootprint(mask, fp, self.thisbitmask)
        afwDet.setMaskFromFootprint(mask, fp, self.otherbitmask)
    def removeSource(self, id):
        """!
        Remove the heavy footprint of a given source and replace with previous noise

        @param[in]  id   id for current source to insert from original footprint dict

        Also restore the mask plane.
        """
        # remove a single source
        # (Replace this source's pixels by noise again.)
        # Do this by finding the source's top-level ancestor
        mi = self.exposure.getMaskedImage()
        im = mi.getImage()
        mask = mi.getMask()

        # use the same algorithm as in remove Source to find the heavy noise footprint
        # which will undo what insertSource(id) does
        usedid = id
        while self.footprints[usedid][0] != 0 and not usedid in self.heavies.keys():
            usedid = self.footprints[usedid][0]
        # Re-insert the noise pixels
        fp = self.heavyNoise[usedid]
        fp.insert(im)
        # Clear the THISDET mask plane.
        afwDet.clearMaskFromFootprint(mask, fp, self.thisbitmask)
        afwDet.setMaskFromFootprint(mask, fp, self.otherbitmask)
Пример #4
0
def main():
    butils = measDeblend.BaselineUtilsF

    foot = buildExample2()

    fbb = foot.getBBox()
    mask1 = afwImg.MaskU(fbb.getWidth(), fbb.getHeight())
    mask1.setXY0(fbb.getMinX(), fbb.getMinY())
    afwDet.setMaskFromFootprint(mask1, foot, 1)

    if plt:
        plt.clf()
        plt.imshow(mask1.getArray(),
                   origin='lower',
                   interpolation='nearest',
                   extent=(fbb.getMinX(), fbb.getMaxX(), fbb.getMinY(),
                           fbb.getMaxY()))
        plt.gray()
        plt.savefig('foot2.png')

        sfoot = butils.symmetrizeFootprint(foot, 355, 227)

        mask2 = afwImg.MaskU(fbb.getWidth(), fbb.getHeight())
        mask2.setXY0(fbb.getMinX(), fbb.getMinY())
        afwDet.setMaskFromFootprint(mask2, sfoot, 1)

        plt.clf()
        plt.imshow(mask2.getArray(),
                   origin='lower',
                   interpolation='nearest',
                   extent=(fbb.getMinX(), fbb.getMaxX(), fbb.getMinY(),
                           fbb.getMaxY()))
        plt.gray()
        plt.savefig('sfoot3.png')
Пример #5
0
 def insertSource(self, exposure, sourcei):
     # Copy this source's pixels into the image
     mi = exposure.getMaskedImage()
     im = mi.getImage()
     mask = mi.getMask()
     fp = self.heavies[sourcei]
     fp.insert(im)
     afwDet.setMaskFromFootprint(mask, fp, self.thisbitmask)
     afwDet.clearMaskFromFootprint(mask, fp, self.otherbitmask)
Пример #6
0
 def insertSource(self, exposure, sourcei):
     # Copy this source's pixels into the image
     mi = exposure.getMaskedImage()
     im = mi.getImage()
     mask = mi.getMask()
     fp = self.heavies[sourcei]
     fp.insert(im)
     afwDet.setMaskFromFootprint(mask, fp, self.thisbitmask)
     afwDet.clearMaskFromFootprint(mask, fp, self.otherbitmask)
Пример #7
0
def countMaskFromFootprint(mask, footprint, bitmask, ignoreMask):
    """Function to count the number of pixels with a specific mask in a footprint
    """
    bbox = footprint.getBBox()
    bbox.clip(mask.getBBox(afwImage.PARENT))
    fp = afwImage.MaskU(bbox)
    subMask = mask.Factory(mask, bbox, afwImage.PARENT)
    afwDet.setMaskFromFootprint(fp, footprint, bitmask)
    return numpy.logical_and((subMask.getArray() & fp.getArray()) > 0,
                             (subMask.getArray() & ignoreMask) == 0).sum()
Пример #8
0
def getMaskFromFootprint(mask, footprint, bitmask):
    """Function to get which of pixels have a specific mask in footprint
    """
    bbox = footprint.getBBox()
    bbox.clip(mask.getBBox(afwImage.PARENT))
    fp = afwImage.Mask(bbox)
    subMask = mask.Factory(mask, bbox, afwImage.PARENT)
    #fp.getFootprint().span.setMask(
    afwDet.setMaskFromFootprint(fp, footprint, 0x1)
    
    return ((subMask.getArray()&bitmask==0) & (fp.getArray())) > 0
Пример #9
0
def maskPixelsFromDefectList(maskedImage, defectList, maskName='BAD'):
    """Set mask plane based on a defect list

    @param[in,out] maskedImage  afw.image.MaskedImage to process; mask plane is updated
    @param[in] defectList  meas.algorithms.DefectListT
    @param[in] maskName  mask plane name
    """
    # mask bad pixels
    mask = maskedImage.getMask()
    bitmask = mask.getPlaneBitMask(maskName)
    for defect in defectList:
        bbox = defect.getBBox()
        afwDetection.setMaskFromFootprint(mask, afwDetection.Footprint(bbox), bitmask)
Пример #10
0
    def skipParent(self, source, mask):
        """Indicate that the parent source is not being deblended

        We set the appropriate flags and mask.

        @param source  The source to flag as skipped
        @param mask  The mask to update
        """
        fp = source.getFootprint()
        source.set(self.deblendSkippedKey, True)
        source.set(self.nChildKey, len(fp.getPeaks())) # It would have this many if we deblended them all
        if self.config.notDeblendedMask:
            mask.addMaskPlane(self.config.notDeblendedMask)
            afwDet.setMaskFromFootprint(mask, fp, mask.getPlaneBitMask(self.config.notDeblendedMask))
Пример #11
0
def maskPixelsFromDefectList(maskedImage, defectList, maskName='BAD'):
    """Set mask plane based on a defect list

    @param[in,out] maskedImage  afw.image.MaskedImage to process; mask plane is updated
    @param[in] defectList  meas.algorithms.DefectListT
    @param[in] maskName  mask plane name
    """
    # mask bad pixels
    mask = maskedImage.getMask()
    bitmask = mask.getPlaneBitMask(maskName)
    for defect in defectList:
        bbox = defect.getBBox()
        afwDetection.setMaskFromFootprint(mask, afwDetection.Footprint(bbox),
                                          bitmask)
Пример #12
0
 def testInclude(self):
     """Test that we can expand a Footprint to include the union of itself and all others
     provided (must be non-disjoint).
     """
     region = afwGeom.Box2I(afwGeom.Point2I(-6, -6), afwGeom.Point2I(6, 6))
     parent = afwDetect.Footprint(afwGeom.Box2I(afwGeom.Point2I(-2, -2), afwGeom.Point2I(2, 2)), region)
     parent.addPeak(0, 0, float("NaN"))
     child1 = afwDetect.Footprint(afwGeom.Box2I(afwGeom.Point2I(-3, 0), afwGeom.Point2I(0, 3)), region)
     child1.addPeak(-1, 1, float("NaN"))
     child2 = afwDetect.Footprint(afwGeom.Box2I(afwGeom.Point2I(-4, -3), afwGeom.Point2I(-1, 0)), region)
     child3 = afwDetect.Footprint(afwGeom.Box2I(afwGeom.Point2I(4, -1), afwGeom.Point2I(6, 1)))
     merge12 = afwDetect.Footprint(parent)
     merge12.include([child1, child2])
     self.assertTrue(merge12.getBBox().contains(parent.getBBox()))
     self.assertTrue(merge12.getBBox().contains(child1.getBBox()))
     self.assertTrue(merge12.getBBox().contains(child2.getBBox()))
     mask12a = afwImage.MaskU(region)
     mask12b = afwImage.MaskU(region)
     afwDetect.setMaskFromFootprint(mask12a, parent, 1)
     afwDetect.setMaskFromFootprint(mask12a, child1, 1)
     afwDetect.setMaskFromFootprint(mask12a, child2, 1)
     afwDetect.setMaskFromFootprint(mask12b, merge12, 1)
     self.assertEqual(mask12a.getArray().sum(), merge12.getArea())
     self.assertClose(mask12a.getArray(), mask12b.getArray(), rtol=0, atol=0)
     self.assertRaisesLsstCpp(pexExcept.RuntimeError, parent.include, [child1, child2, child3])
Пример #13
0
    def skipParent(self, source, mask):
        """Indicate that the parent source is not being deblended

        We set the appropriate flags and mask.

        @param source  The source to flag as skipped
        @param mask  The mask to update
        """
        fp = source.getFootprint()
        source.set(self.deblendSkippedKey, True)
        source.set(self.nChildKey, len(
            fp.getPeaks()))  # It would have this many if we deblended them all
        if self.config.notDeblendedMask:
            mask.addMaskPlane(self.config.notDeblendedMask)
            afwDet.setMaskFromFootprint(
                mask, fp, mask.getPlaneBitMask(self.config.notDeblendedMask))
Пример #14
0
 def removeSource(self, exposure, sources, source):
     # remove a single source
     # (Replace this source's pixels by noise again.)
     # Do this by finding the source's top-level ancestor
     mi = exposure.getMaskedImage()
     im = mi.getImage()
     mask = mi.getMask()
     ancestor = source
     j = 0
     while ancestor.getParent():
         ancestor = sources.find(ancestor.getParent())
         j += 1
         if not ancestor or j == 100:
             raise RuntimeError('Source hierarchy too deep, or (more likely) your Source table is botched.')
     # Re-insert the noise pixels
     fp = self.heavyNoise[ancestor.getId()]
     fp.insert(im)
     # Clear the THISDET mask plane.
     afwDet.clearMaskFromFootprint(mask, fp, self.thisbitmask)
     afwDet.setMaskFromFootprint(mask, fp, self.otherbitmask)
Пример #15
0
    def insertSource(self, id):
        """!
        Insert the heavy footprint of a given source into the exposure

        @param[in]  id   id for current source to insert from original footprint dict

        Also adjusts the mask plane to show the source of this footprint.
        """
        # Copy this source's pixels into the image
        mi = self.exposure.getMaskedImage()
        im = mi.getImage()
        mask = mi.getMask()
        # usedid can point either to this source, or to the first parent in the
        # parent chain which has a heavy footprint (or to the topmost parent,
        # which always has one)
        usedid = id
        while self.footprints[usedid][0] != 0 and not usedid in self.heavies.keys():
            usedid = self.footprints[usedid][0]
        fp = self.heavies[usedid]
        fp.insert(im)
        afwDet.setMaskFromFootprint(mask, fp, self.thisbitmask)
        afwDet.clearMaskFromFootprint(mask, fp, self.otherbitmask)
Пример #16
0
 def removeSource(self, exposure, sources, source):
     # remove a single source
     # (Replace this source's pixels by noise again.)
     # Do this by finding the source's top-level ancestor
     mi = exposure.getMaskedImage()
     im = mi.getImage()
     mask = mi.getMask()
     ancestor = source
     j = 0
     while ancestor.getParent():
         ancestor = sources.find(ancestor.getParent())
         j += 1
         if not ancestor or j == 100:
             raise RuntimeError(
                 'Source hierarchy too deep, or (more likely) your Source table is botched.'
             )
     # Re-insert the noise pixels
     fp = self.heavyNoise[ancestor.getId()]
     fp.insert(im)
     # Clear the THISDET mask plane.
     afwDet.clearMaskFromFootprint(mask, fp, self.thisbitmask)
     afwDet.setMaskFromFootprint(mask, fp, self.otherbitmask)
Пример #17
0
    def insertSource(self, id):
        """!
        Insert the heavy footprint of a given source into the exposure

        @param[in]  id   id for current source to insert from original footprint dict

        Also adjusts the mask plane to show the source of this footprint.
        """
        # Copy this source's pixels into the image
        mi = self.exposure.getMaskedImage()
        im = mi.getImage()
        mask = mi.getMask()
        # usedid can point either to this source, or to the first parent in the
        # parent chain which has a heavy footprint (or to the topmost parent,
        # which always has one)
        usedid = id
        while self.footprints[usedid][
                0] != 0 and not usedid in self.heavies.keys():
            usedid = self.footprints[usedid][0]
        fp = self.heavies[usedid]
        fp.insert(im)
        afwDet.setMaskFromFootprint(mask, fp, self.thisbitmask)
        afwDet.clearMaskFromFootprint(mask, fp, self.otherbitmask)
Пример #18
0
    def __init__(self,
                 config,
                 exposure,
                 footprints,
                 noiseImage=None,
                 exposureId=None,
                 log=None):
        """!
        Initialize the NoiseReplacer.

        @param[in]      config       instance of NoiseReplacerConfig
        @param[in,out]  exposure     Exposure to be noise replaced. (All sources replaced on return)
        @param[in]      footprints   dict of {id: (parent, footprint)};
        @param[in]      noiseImage   an afw.image.ImageF used as a predictable noise replacement source
                                     (for tests only)
        @param[in]      log          pex.logging.Log object to use for status messages; no status messages
                                     will be printed if None

        'footprints' is a dict of {id: (parent, footprint)}; when used in SFM, the ID will be the
        source ID, but in forced photometry, this will be the reference ID, as that's what we used to
        determine the deblend families.  This routine should create HeavyFootprints for any non-Heavy
        Footprints, and replace them in the dict.  It should then create a dict of HeavyFootprints
        containing noise, but only for parent objects, then replace all sources with noise.
        This should ignore any footprints that lay outside the bounding box of the exposure,
        and clip those that lie on the border.

        NOTE: as the code currently stands, the heavy footprint for a deblended object must be available
        from the input catalog.  If it is not, it cannot be reproduced here.  In that case, the
        topmost parent in the objects parent chain must be used.  The heavy footprint for that source
        is created in this class from the masked image.
        """
        noiseMeanVar = None
        self.noiseSource = config.noiseSource
        self.noiseOffset = config.noiseOffset
        self.noiseSeedMultiplier = config.noiseSeedMultiplier
        self.noiseGenMean = None
        self.noiseGenStd = None
        self.log = log

        # creates heavies, replaces all footprints with noise
        # We need the source table to be sorted by ID to do the parent lookups
        self.exposure = exposure
        self.footprints = footprints
        mi = exposure.getMaskedImage()
        im = mi.getImage()
        mask = mi.getMask()
        # Add temporary Mask planes for THISDET and OTHERDET
        self.removeplanes = []
        bitmasks = []
        for maskname in ['THISDET', 'OTHERDET']:
            try:
                # does it already exist?
                plane = mask.getMaskPlane(maskname)
                if self.log:
                    self.log.logdebug('Mask plane "%s" already existed' %
                                      maskname)
            except:
                # if not, add it; we should delete it when done.
                plane = mask.addMaskPlane(maskname)
                self.removeplanes.append(maskname)
            mask.clearMaskPlane(plane)
            bitmask = mask.getPlaneBitMask(maskname)
            bitmasks.append(bitmask)
            if self.log:
                self.log.logdebug(
                    'Mask plane "%s": plane %i, bitmask %i = 0x%x' %
                    (maskname, plane, bitmask, bitmask))
        self.thisbitmask, self.otherbitmask = bitmasks
        del bitmasks
        self.heavies = {}
        # Start by creating HeavyFootprints for each source which has no parent
        # and just use them for children which do not already have heavy footprints.
        # If a heavy footprint is available for a child, we will use it. Otherwise,
        # we use the first parent in the parent chain which has a heavy footprint,
        # which with the one level deblender will alway be the topmost parent
        # NOTE: heavy footprints get destroyed by the transform process in forcedPhotImage.py,
        # so they are never available for forced measurements.

        # Create in the dict heavies = {id:heavyfootprint}
        for id in footprints.keys():
            fp = footprints[id]
            if fp[1].isHeavy():
                self.heavies[id] = afwDet.cast_HeavyFootprintF(fp[1])
            elif fp[0] == 0:
                self.heavies[id] = afwDet.makeHeavyFootprint(fp[1], mi)

        ### FIXME: the heavy footprint includes the mask
        ### and variance planes, which we shouldn't need
        ### (I don't think we ever want to modify them in
        ### the input image).  Copying them around is
        ### wasteful.

        # We now create a noise HeavyFootprint for each source with has a heavy footprint.
        # We'll put the noise footprints in a dict heavyNoise = {id:heavyNoiseFootprint}
        self.heavyNoise = {}
        noisegen = self.getNoiseGenerator(exposure,
                                          noiseImage,
                                          noiseMeanVar,
                                          exposureId=exposureId)
        #  The noiseGenMean and Std are used by the unit tests
        self.noiseGenMean = noisegen.mean
        self.noiseGenStd = noisegen.std
        if self.log:
            self.log.logdebug('Using noise generator: %s' % (str(noisegen)))
        for id in self.heavies.keys():
            fp = footprints[id][1]
            noiseFp = noisegen.getHeavyFootprint(fp)
            self.heavyNoise[id] = noiseFp
            # Also insert the noisy footprint into the image now.
            # Notice that we're just inserting it into "im", ie,
            # the Image, not the MaskedImage.
            noiseFp.insert(im)
            # Also set the OTHERDET bit
            afwDet.setMaskFromFootprint(mask, fp, self.otherbitmask)
Пример #19
0
    def detectClip(self, exp, tempExpRefList):
        """Detect clipped regions on an exposure and set the mask on the individual tempExp masks

        @param exp: Exposure to run detection on
        @param tempExpRefList: List of data reference to tempExp
        @return struct containg:
        - clippedFootprints: list of clipped footprints
        - clippedIndices: indices for each clippedFootprint in tempExpRefList
        - tempExpClipList: list of new masks for tempExp
        """
        mask = exp.getMaskedImage().getMask()
        maskClipValue = mask.getPlaneBitMask("CLIPPED")
        maskDetValue = mask.getPlaneBitMask("DETECTED") | mask.getPlaneBitMask("DETECTED_NEGATIVE")
        fpSet = self.clipDetection.detectFootprints(exp, doSmooth=True, clearMask=True)
        # Merge positive and negative together footprints together
        fpSet.positive.merge(fpSet.negative)
        footprints = fpSet.positive
        self.log.info('Found %d potential clipped objects' % len(footprints.getFootprints()))
        ignoreMask = self.getBadPixelMask()

        clipFootprints = []
        clipIndices = []

        # build a list with a mask for each visit which can be modified with clipping information
        tempExpClipList = [tmpExpRef.get(self.getTempExpDatasetName(),
                           immediate=True).getMaskedImage().getMask() for tmpExpRef in tempExpRefList]

        for footprint in footprints.getFootprints():
            nPixel = footprint.getArea()
            overlap = [] # hold the overlap with each visit
            maskList = [] # which visit mask match
            indexList = []# index of visit in global list
            for i, tmpExpMask in enumerate(tempExpClipList):
                # Determine the overlap with the footprint
                ignore = countMaskFromFootprint(tmpExpMask, footprint, ignoreMask, 0x0)
                overlapDet = countMaskFromFootprint(tmpExpMask, footprint, maskDetValue, ignoreMask)
                totPixel = nPixel - ignore

                # If we have more bad pixels than detection skip
                if ignore > overlapDet or totPixel <= 0.5*nPixel or overlapDet == 0:
                    continue
                overlap.append(overlapDet/float(totPixel))
                maskList.append(tmpExpMask)
                indexList.append(i)

            overlap = numpy.array(overlap)
            if not len(overlap):
                continue

            keep = False   # Should this footprint be marked as clipped?
            keepIndex = [] # Which tempExps does the clipped footprint belong to

            # If footprint only has one overlap use a lower threshold
            if len(overlap) == 1:
                if overlap[0] > self.config.minClipFootOverlapSingle:
                    keep = True
                    keepIndex = [0]
            else:
                # This is the general case where only visit should be clipped
                clipIndex = numpy.where(overlap > self.config.minClipFootOverlap)[0]
                if len(clipIndex) == 1:
                    keep=True
                    keepIndex = [clipIndex[0]]

                # Test if there are clipped objects that overlap two different visits
                clipIndex = numpy.where(overlap > self.config.minClipFootOverlapDouble)[0]
                if len(clipIndex) == 2 and len(overlap) > 3:
                    clipIndexComp = numpy.where(overlap < self.config.minClipFootOverlapDouble)[0]
                    if numpy.max(overlap[clipIndexComp]) < self.config.maxClipFootOverlapDouble:
                        keep=True
                        keepIndex = clipIndex

            if not keep:
                continue

            for index in keepIndex:
                afwDet.setMaskFromFootprint(maskList[index], footprint, maskClipValue)

            clipIndices.append(numpy.array(indexList)[keepIndex])
            clipFootprints.append(footprint)

        return pipeBase.Struct(clipFootprints=clipFootprints, clipIndices=clipIndices,
                               tempExpClipList=tempExpClipList)
Пример #20
0
    def test1(self):

        # circle
        fp = afwDet.Footprint(afwGeom.Point2I(50,50), 45.)

        #
        psfsig = 1.5
        psffwhm = psfsig * 2.35
        psf1 = measAlg.DoubleGaussianPsf(11, 11, psfsig)

        psf2 = measAlg.DoubleGaussianPsf(100, 100, psfsig)


        fbb = fp.getBBox()
        print 'fbb', fbb.getMinX(), fbb.getMaxX(), fbb.getMinY(), fbb.getMaxY()
        
        fmask = afwImage.MaskU(fbb)
        fmask.setXY0(fbb.getMinX(), fbb.getMinY())
        afwDet.setMaskFromFootprint(fmask, fp, 1)

        sig1 = 10.

        img = afwImage.ImageF(fbb)
        A = img.getArray()
        A += np.random.normal(0, sig1, size=(fbb.getHeight(), fbb.getWidth()))
        print 'img x0,y0', img.getX0(), img.getY0()
        print 'BBox', img.getBBox()

        peaks = afwDet.PeakCatalog(afwDet.PeakTable.makeMinimalSchema())
	def makePeak(x, y):
            p = peaks.addNew()
            p.setFx(x)
            p.setFy(y)
            p.setIx(int(x))
            p.setIy(int(y))
            return p
        pk1 = makePeak(20., 30.)
        pk2 = makePeak(23., 33.)
        pk3 = makePeak(92., 50.)

        ibb = img.getBBox()
        iext = [ibb.getMinX(), ibb.getMaxX(), ibb.getMinY(), ibb.getMaxY()]
        ix0,iy0 = iext[0], iext[2]

        pbbs = []
        pxys = []
        
        fluxes = [10000., 5000., 5000.]
        for pk,f in zip(peaks, fluxes):
            psfim = psf1.computeImage(afwGeom.Point2D(pk.getFx(), pk.getFy()))
            print 'psfim x0,y0', psfim.getX0(), psfim.getY0()
            pbb = psfim.getBBox()
            print 'pbb', pbb.getMinX(), pbb.getMaxX(), pbb.getMinY(), pbb.getMaxY()
            pbb.clip(ibb)
            print 'clipped pbb', pbb.getMinX(), pbb.getMaxX(), pbb.getMinY(), pbb.getMaxY()
            psfim = psfim.Factory(psfim, pbb)

            psfa = psfim.getArray()
            psfa /= psfa.sum()
            img.getArray()[pbb.getMinY() - iy0: pbb.getMaxY()+1 - iy0,
                           pbb.getMinX() - ix0: pbb.getMaxX()+1 - ix0] += f * psfa

            pbbs.append((pbb.getMinX(), pbb.getMaxX(), pbb.getMinY(), pbb.getMaxY()))
            pxys.append((pk.getFx(), pk.getFy()))


        if doPlot:
            plt.clf()
            plt.imshow(img.getArray(), extent=iext, interpolation='nearest', origin='lower')
            ax = plt.axis()
            x0,x1,y0,y1 = fbb.getMinX(), fbb.getMaxX(), fbb.getMinY(), fbb.getMaxY()
            plt.plot([x0,x0,x1,x1,x0], [y0,y1,y1,y0,y0], 'k-')
            for x0,x1,y0,y1 in pbbs:
                plt.plot([x0,x0,x1,x1,x0], [y0,y1,y1,y0,y0], 'r-')
            for x,y in pxys:
                plt.plot(x, y, 'ro')
            plt.axis(ax)
            plt.savefig('img.png')

        varimg = afwImage.ImageF(fbb)
        varimg.set(sig1**2)

        psf_chisq_cut1 = psf_chisq_cut2 = psf_chisq_cut2b = 1.5

        pkres = PerPeak()

        loglvl = pexLogging.Log.INFO
        #if verbose:
        #    loglvl = pexLogging.Log.DEBUG
        log = pexLogging.Log(pexLogging.Log.getDefaultLog(), 'tests.fit_psf', loglvl)

        cpsf = CachingPsf(psf1)

        peaksF = [pk.getF() for pk in peaks]
        pkF = pk1.getF()

        _fitPsf(fp, fmask, pk1, pkF, pkres, fbb, peaks, peaksF, log, cpsf, psffwhm,
                 img, varimg,
                 psf_chisq_cut1, psf_chisq_cut2, psf_chisq_cut2b)
        for k in dir(pkres):
            if k.startswith('__'):
                continue
            print '  ', k, getattr(pkres, k)

        cpsf = CachingPsf(psf2)
        _fitPsf(fp, fmask, pk1, pkF, pkres, fbb, peaks, peaksF, log, cpsf, psffwhm,
                 img, varimg,
                 psf_chisq_cut1, psf_chisq_cut2, psf_chisq_cut2b)
        for k in dir(pkres):
            if k.startswith('__'):
                continue
            print '  ', k, getattr(pkres, k)


        pkF = pk3.getF()
        _fitPsf(fp, fmask, pk3, pkF, pkres, fbb, peaks, peaksF, log, cpsf, psffwhm,
                 img, varimg,
                 psf_chisq_cut1, psf_chisq_cut2, psf_chisq_cut2b)
        for k in dir(pkres):
            if k.startswith('__'):
                continue
            print '  ', k, getattr(pkres, k)
            match = maskFormat.match(datasec)
            if match == None:
                # unable to match mask area!
                print '# WARNING: Extn', nExt, 'unable to parse', maskArea
                continue
            group = map(int, match.groups())

            # ACB : by visual inspection, the y0 values can be too
            # high by 1.  however, since some of the y0 values are '1'
            # in the mask string, i can't decrement this by 2 without
            # going off the image.  we just deal with this for dc3a.
            bbox = afwImage.BBox(afwImage.PointI(group[0] - 1, group[1] - 1),
                                 afwImage.PointI(group[2] - 1, group[3] - 1))

            fp = afwDetection.Footprint(bbox)
            afwDetection.setMaskFromFootprint(mask, fp, bitmask)

    # debugging
    #outfile0 = '%d.fits' % (i)
    #print '# Writing', outfile0
    #mask.writeFits(outfile0)

    # trim this thing!  it includes the overscan etc...

    bboxA = afwImage.BBox(afwImage.PointI(32, 0), afwImage.PointI(1055, 4611))

    bboxB = afwImage.BBox(afwImage.PointI(1055, 0),
                          afwImage.PointI(2111 - 32, 4611))

    #bboxA = afwImage.BBox(afwImage.PointI(0,0),
    #                      afwImage.PointI(1055,4611))
Пример #22
0
    def testInclude(self):
        """Test that we can expand a Footprint to include the union of itself and all others provided."""
        region = afwGeom.Box2I(afwGeom.Point2I(-6, -6), afwGeom.Point2I(6, 6))
        parent = afwDetect.Footprint(
            afwGeom.Box2I(afwGeom.Point2I(-2, -2), afwGeom.Point2I(2, 2)),
            region)
        parent.addPeak(0, 0, float("NaN"))
        child1 = afwDetect.Footprint(
            afwGeom.Box2I(afwGeom.Point2I(-3, 0), afwGeom.Point2I(0, 3)),
            region)
        child1.addPeak(-1, 1, float("NaN"))
        child2 = afwDetect.Footprint(
            afwGeom.Box2I(afwGeom.Point2I(-4, -3), afwGeom.Point2I(-1, 0)),
            region)
        child3 = afwDetect.Footprint(
            afwGeom.Box2I(afwGeom.Point2I(4, -1), afwGeom.Point2I(6, 1)))
        merge123 = afwDetect.Footprint(parent)
        merge123.include([child1, child2, child3])
        self.assertTrue(merge123.getBBox().contains(parent.getBBox()))
        self.assertTrue(merge123.getBBox().contains(child1.getBBox()))
        self.assertTrue(merge123.getBBox().contains(child2.getBBox()))
        self.assertTrue(merge123.getBBox().contains(child3.getBBox()))
        mask123a = afwImage.MaskU(region)
        mask123b = afwImage.MaskU(region)
        afwDetect.setMaskFromFootprint(mask123a, parent, 1)
        afwDetect.setMaskFromFootprint(mask123a, child1, 1)
        afwDetect.setMaskFromFootprint(mask123a, child2, 1)
        afwDetect.setMaskFromFootprint(mask123a, child3, 1)
        afwDetect.setMaskFromFootprint(mask123b, merge123, 1)
        self.assertEqual(mask123a.getArray().sum(), merge123.getArea())
        self.assertClose(mask123a.getArray(),
                         mask123b.getArray(),
                         rtol=0,
                         atol=0)

        # Test that ignoreSelf=True works for include
        ignoreParent = True
        childOnly = afwDetect.Footprint()
        childOnly.include([child1, child2, child3])
        merge123 = afwDetect.Footprint(parent)
        merge123.include([child1, child2, child3], ignoreParent)
        maskChildren = afwImage.MaskU(region)
        mask123 = afwImage.MaskU(region)
        afwDetect.setMaskFromFootprint(maskChildren, childOnly, 1)
        afwDetect.setMaskFromFootprint(mask123, merge123, 1)
        self.assertTrue(np.all(maskChildren.getArray() == mask123.getArray()))
Пример #23
0
    def __call__(self, source, exposure):
        fp     = source.getFootprint()
        peaks  = fp.getPeaks()
        peaksF = [pk.getF() for pk in peaks]
        fbb    = fp.getBBox()
        fmask  = afwImage.MaskU(fbb)
        fmask.setXY0(fbb.getMinX(), fbb.getMinY())
        afwDetect.setMaskFromFootprint(fmask, fp, 1)

        psf        = exposure.getPsf()
        psfSigPix  = psf.computeShape().getDeterminantRadius()
        psfFwhmPix = psfSigPix * self.sigma2fwhm
        subimage   = afwImage.ExposureF(exposure, fbb, True)
        cpsf       = deblendBaseline.CachingPsf(psf)

        # if fewer than 2 peaks, just return a copy of the source
        if len(peaks) < 2:
            return source.getTable().copyRecord(source)

        # make sure you only deblend 2 peaks; take the brighest and faintest
        speaks = [(p.getPeakValue(), p) for p in peaks]
        speaks.sort()
        dpeaks = [speaks[0][1], speaks[-1][1]]

        # and only set these peaks in the footprint (peaks is mutable)
        peaks.clear()
        for peak in dpeaks:
            peaks.append(peak)

        if True:
            # Call top-level deblend task
            fpres = deblendBaseline.deblend(fp, exposure.getMaskedImage(), psf, psfFwhmPix,
                                            log = self.log,
                                            psfChisqCut1 = self.psfChisqCut1,
                                            psfChisqCut2 = self.psfChisqCut2,
                                            psfChisqCut2b = self.psfChisqCut2b)
        else:
            # Call lower-level _fit_psf task

            # Prepare results structure
            fpres = deblendBaseline.PerFootprint()
            fpres.peaks = []
            for pki,pk in enumerate(dpeaks):
                pkres = deblendBaseline.PerPeak()
                pkres.peak = pk
                pkres.pki = pki
                fpres.peaks.append(pkres)

            for pki,(pk,pkres,pkF) in enumerate(zip(dpeaks, fpres.peaks, peaksF)):
                self.log.logdebug('Peak %i' % pki)
                deblendBaseline._fitPsf(fp, fmask, pk, pkF, pkres, fbb, dpeaks, peaksF, self.log,
                                         cpsf, psfFwhmPix,
                                         subimage.getMaskedImage().getImage(),
                                         subimage.getMaskedImage().getVariance(),
                                         self.psfChisqCut1, self.psfChisqCut2, self.psfChisqCut2b)


        deblendedSource = source.getTable().copyRecord(source)
        deblendedSource.setParent(source.getId())
        peakList        = deblendedSource.getFootprint().getPeaks()
        peakList.clear()

        for i, peak in enumerate(fpres.peaks):
            if peak.psfFitFlux > 0:
                suffix = "pos"
            else:
                suffix = "neg"
            c = peak.psfFitCenter
            self.log.info("deblended.centroid.dipole.psf.%s %f %f" % (
                suffix, c[0], c[1]))
            self.log.info("deblended.chi2dof.dipole.%s %f" % (
                suffix, peak.psfFitChisq / peak.psfFitDof))
            self.log.info("deblended.flux.dipole.psf.%s %f" % (
                suffix, peak.psfFitFlux * np.sum(peak.templateImage.getArray())))
            peakList.append(peak.peak)
        return deblendedSource
Пример #24
0
    def __call__(self, source, exposure):
        fp = source.getFootprint()
        peaks = fp.getPeaks()
        peaksF = [pk.getF() for pk in peaks]
        fbb = fp.getBBox()
        fmask = afwImage.MaskU(fbb)
        fmask.setXY0(fbb.getMinX(), fbb.getMinY())
        afwDetect.setMaskFromFootprint(fmask, fp, 1)

        psf = exposure.getPsf()
        psfSigPix = psf.computeShape().getDeterminantRadius()
        psfFwhmPix = psfSigPix * self.sigma2fwhm
        subimage = afwImage.ExposureF(exposure, fbb, True)
        cpsf = deblendBaseline.CachingPsf(psf)

        # if fewer than 2 peaks, just return a copy of the source
        if len(peaks) < 2:
            return source.getTable().copyRecord(source)

        # make sure you only deblend 2 peaks; take the brighest and faintest
        speaks = [(p.getPeakValue(), p) for p in peaks]
        speaks.sort()
        dpeaks = [speaks[0][1], speaks[-1][1]]

        # and only set these peaks in the footprint (peaks is mutable)
        peaks.clear()
        for peak in dpeaks:
            peaks.append(peak)

        if True:
            # Call top-level deblend task
            fpres = deblendBaseline.deblend(fp,
                                            exposure.getMaskedImage(),
                                            psf,
                                            psfFwhmPix,
                                            log=self.log,
                                            psfChisqCut1=self.psfChisqCut1,
                                            psfChisqCut2=self.psfChisqCut2,
                                            psfChisqCut2b=self.psfChisqCut2b)
        else:
            # Call lower-level _fit_psf task

            # Prepare results structure
            fpres = deblendBaseline.PerFootprint()
            fpres.peaks = []
            for pki, pk in enumerate(dpeaks):
                pkres = deblendBaseline.PerPeak()
                pkres.peak = pk
                pkres.pki = pki
                fpres.peaks.append(pkres)

            for pki, (pk, pkres,
                      pkF) in enumerate(zip(dpeaks, fpres.peaks, peaksF)):
                self.log.logdebug('Peak %i' % pki)
                deblendBaseline._fitPsf(
                    fp, fmask, pk, pkF, pkres, fbb, dpeaks, peaksF, self.log,
                    cpsf, psfFwhmPix,
                    subimage.getMaskedImage().getImage(),
                    subimage.getMaskedImage().getVariance(), self.psfChisqCut1,
                    self.psfChisqCut2, self.psfChisqCut2b)

        deblendedSource = source.getTable().copyRecord(source)
        deblendedSource.setParent(source.getId())
        peakList = deblendedSource.getFootprint().getPeaks()
        peakList.clear()

        for i, peak in enumerate(fpres.peaks):
            if peak.psfFitFlux > 0:
                suffix = "pos"
            else:
                suffix = "neg"
            c = peak.psfFitCenter
            self.log.info("deblended.centroid.dipole.psf.%s %f %f" %
                          (suffix, c[0], c[1]))
            self.log.info("deblended.chi2dof.dipole.%s %f" %
                          (suffix, peak.psfFitChisq / peak.psfFitDof))
            self.log.info("deblended.flux.dipole.psf.%s %f" %
                          (suffix, peak.psfFitFlux *
                           np.sum(peak.templateImage.getArray())))
            peakList.append(peak.peak)
        return deblendedSource
Пример #25
0
    footPrintSet = afwDetect.FootprintSet(footPrintSet, grow, isotropic)

    footPrints = footPrintSet.getFootprints()
    footPrintSet.setMask(mi.getMask(), "DETECTED")
    print footPrints.size(), "footPrint(s) found\n"

    
    mask = mi.getMask()
    mask.addMaskPlane('MUON')
    mask.addMaskPlane('WORM')
    mask.addMaskPlane('SPOT')
    mask.printMaskPlanes()
    muon_bit, worm_bit, spot_bit = mask.getPlaneBitMask('MUON'), mask.getPlaneBitMask('WORM'), mask.getPlaneBitMask('SPOT')
#    print muon_bit, worm_bit, spot_bit
    
    afwDetect.setMaskFromFootprint(mask, footPrints[9], muon_bit)
    
    ShowImage(mi, ROI_Bbox = footPrints[9].getBBox(), border = 0)
    
    

#    exit()




#===============================================================================
# Shape extraction
    if DISPLAY_LEVEL >= 1:
        try: # initialise DS9, deal with a bug in its launching
            ds9.initDS9(False)
Пример #26
0
    def testInclude(self):
        """Test that we can expand a Footprint to include the union of itself and all others provided."""
        region = afwGeom.Box2I(afwGeom.Point2I(-6, -6), afwGeom.Point2I(6, 6))
        parent = afwDetect.Footprint(afwGeom.Box2I(afwGeom.Point2I(-2, -2), afwGeom.Point2I(2, 2)), region)
        parent.addPeak(0, 0, float("NaN"))
        child1 = afwDetect.Footprint(afwGeom.Box2I(afwGeom.Point2I(-3, 0), afwGeom.Point2I(0, 3)), region)
        child1.addPeak(-1, 1, float("NaN"))
        child2 = afwDetect.Footprint(afwGeom.Box2I(afwGeom.Point2I(-4, -3), afwGeom.Point2I(-1, 0)), region)
        child3 = afwDetect.Footprint(afwGeom.Box2I(afwGeom.Point2I(4, -1), afwGeom.Point2I(6, 1)))
        merge123 = afwDetect.Footprint(parent)
        merge123.include([child1, child2, child3])
        self.assertTrue(merge123.getBBox().contains(parent.getBBox()))
        self.assertTrue(merge123.getBBox().contains(child1.getBBox()))
        self.assertTrue(merge123.getBBox().contains(child2.getBBox()))
        self.assertTrue(merge123.getBBox().contains(child3.getBBox()))
        mask123a = afwImage.MaskU(region)
        mask123b = afwImage.MaskU(region)
        afwDetect.setMaskFromFootprint(mask123a, parent, 1)
        afwDetect.setMaskFromFootprint(mask123a, child1, 1)
        afwDetect.setMaskFromFootprint(mask123a, child2, 1)
        afwDetect.setMaskFromFootprint(mask123a, child3, 1)
        afwDetect.setMaskFromFootprint(mask123b, merge123, 1)
        self.assertEqual(mask123a.getArray().sum(), merge123.getArea())
        self.assertClose(mask123a.getArray(), mask123b.getArray(), rtol=0, atol=0)

        # Test that ignoreSelf=True works for include
        ignoreParent = True
        childOnly = afwDetect.Footprint()
        childOnly.include([child1, child2, child3])
        merge123 = afwDetect.Footprint(parent)
        merge123.include([child1, child2, child3], ignoreParent)
        maskChildren = afwImage.MaskU(region)
        mask123 = afwImage.MaskU(region)
        afwDetect.setMaskFromFootprint(maskChildren, childOnly, 1)
        afwDetect.setMaskFromFootprint(mask123, merge123, 1)
        self.assertTrue(numpy.all(maskChildren.getArray() == mask123.getArray()))
Пример #27
0
    def __init__(self, config, exposure, footprints, noiseImage=None, exposureId=None, log=None):
        """!
        Initialize the NoiseReplacer.

        @param[in]      config       instance of NoiseReplacerConfig
        @param[in,out]  exposure     Exposure to be noise replaced. (All sources replaced on return)
        @param[in]      footprints   dict of {id: (parent, footprint)};
        @param[in]      noiseImage   an afw.image.ImageF used as a predictable noise replacement source
                                     (for tests only)
        @param[in]      log          pex.logging.Log object to use for status messages; no status messages
                                     will be printed if None

        'footprints' is a dict of {id: (parent, footprint)}; when used in SFM, the ID will be the
        source ID, but in forced photometry, this will be the reference ID, as that's what we used to
        determine the deblend families.  This routine should create HeavyFootprints for any non-Heavy
        Footprints, and replace them in the dict.  It should then create a dict of HeavyFootprints
        containing noise, but only for parent objects, then replace all sources with noise.
        This should ignore any footprints that lay outside the bounding box of the exposure,
        and clip those that lie on the border.

        NOTE: as the code currently stands, the heavy footprint for a deblended object must be available
        from the input catalog.  If it is not, it cannot be reproduced here.  In that case, the
        topmost parent in the objects parent chain must be used.  The heavy footprint for that source
        is created in this class from the masked image.
        """
        noiseMeanVar=None
        self.noiseSource = config.noiseSource
        self.noiseOffset = config.noiseOffset
        self.noiseSeedMultiplier = config.noiseSeedMultiplier
        self.noiseGenMean = None
        self.noiseGenStd = None
        self.log = log

        # creates heavies, replaces all footprints with noise
        # We need the source table to be sorted by ID to do the parent lookups
        self.exposure = exposure
        self.footprints = footprints
        mi = exposure.getMaskedImage()
        im = mi.getImage()
        mask = mi.getMask()
        # Add temporary Mask planes for THISDET and OTHERDET
        self.removeplanes = []
        bitmasks = []
        for maskname in ['THISDET', 'OTHERDET']:
            try:
                # does it already exist?
                plane = mask.getMaskPlane(maskname)
                if self.log: self.log.logdebug('Mask plane "%s" already existed' % maskname)
            except:
                # if not, add it; we should delete it when done.
                plane = mask.addMaskPlane(maskname)
                self.removeplanes.append(maskname)
            mask.clearMaskPlane(plane)
            bitmask = mask.getPlaneBitMask(maskname)
            bitmasks.append(bitmask)
            if self.log: self.log.logdebug('Mask plane "%s": plane %i, bitmask %i = 0x%x'
                % (maskname, plane, bitmask, bitmask))
        self.thisbitmask,self.otherbitmask = bitmasks
        del bitmasks
        self.heavies = {}
        # Start by creating HeavyFootprints for each source which has no parent
        # and just use them for children which do not already have heavy footprints.
        # If a heavy footprint is available for a child, we will use it. Otherwise,
        # we use the first parent in the parent chain which has a heavy footprint,
        # which with the one level deblender will alway be the topmost parent
        # NOTE: heavy footprints get destroyed by the transform process in forcedPhotImage.py,
        # so they are never available for forced measurements.

        # Create in the dict heavies = {id:heavyfootprint}
        for id in footprints.keys():
            fp = footprints[id]
            if fp[1].isHeavy():
                self.heavies[id] = afwDet.cast_HeavyFootprintF(fp[1])
            elif fp[0] == 0:
                self.heavies[id] = afwDet.makeHeavyFootprint(fp[1], mi)

        ### FIXME: the heavy footprint includes the mask
        ### and variance planes, which we shouldn't need
        ### (I don't think we ever want to modify them in
        ### the input image).  Copying them around is
        ### wasteful.

        # We now create a noise HeavyFootprint for each source with has a heavy footprint.
        # We'll put the noise footprints in a dict heavyNoise = {id:heavyNoiseFootprint}
        self.heavyNoise = {}
        noisegen = self.getNoiseGenerator(exposure, noiseImage, noiseMeanVar, exposureId=exposureId)
        #  The noiseGenMean and Std are used by the unit tests
        self.noiseGenMean = noisegen.mean
        self.noiseGenStd = noisegen.std
        if self.log: self.log.logdebug('Using noise generator: %s' % (str(noisegen)))
        for id in self.heavies.keys():
            fp = footprints[id][1]
            noiseFp = noisegen.getHeavyFootprint(fp)
            self.heavyNoise[id] = noiseFp
            # Also insert the noisy footprint into the image now.
            # Notice that we're just inserting it into "im", ie,
            # the Image, not the MaskedImage.
            noiseFp.insert(im)
            # Also set the OTHERDET bit
            afwDet.setMaskFromFootprint(mask, fp, self.otherbitmask)
Пример #28
0
    def begin(self, exposure, sources, noiseImage=None, noiseMeanVar=None):
        # creates heavies, replaces all footprints with noise
        # We need the source table to be sorted by ID to do the parent lookups
        # (sources.find() below)
        if not sources.isSorted():
            sources.sort()
        mi = exposure.getMaskedImage()
        im = mi.getImage()
        mask = mi.getMask()

        # Add temporary Mask planes for THISDET and OTHERDET
        self.removeplanes = []
        bitmasks = []
        for maskname in ['THISDET', 'OTHERDET']:
            try:
                # does it already exist?
                plane = mask.getMaskPlane(maskname)
                self.log.logdebug('Mask plane "%s" already existed' % maskname)
            except:
                # if not, add it; we should delete it when done.
                plane = mask.addMaskPlane(maskname)
                self.removeplanes.append(maskname)
            mask.clearMaskPlane(plane)
            bitmask = mask.getPlaneBitMask(maskname)
            bitmasks.append(bitmask)
            self.log.logdebug('Mask plane "%s": plane %i, bitmask %i = 0x%x' %
                              (maskname, plane, bitmask, bitmask))
        self.thisbitmask, self.otherbitmask = bitmasks
        del bitmasks

        # Start by creating HeavyFootprints for each source.
        #
        # The "getParent()" checks are here because top-level
        # sources (ie, those with no parents) are not supposed to
        # have HeavyFootprints, but child sources (ie, those that
        # have been deblended) should have HeavyFootprints
        # already.
        self.heavies = []
        for source in sources:
            fp = source.getFootprint()
            hfp = afwDet.cast_HeavyFootprintF(fp)
            if source.getParent() and hfp is not None:
                # this source has been deblended; "fp" should
                # already be a HeavyFootprint (but may not be
                # if read from disk).
                # Swig downcasts it to Footprint, so we have to re-cast.
                self.heavies.append(hfp)
            else:
                # top-level source: copy pixels from the input
                # image.
                ### FIXME: the heavy footprint includes the mask
                ### and variance planes, which we shouldn't need
                ### (I don't think we ever want to modify them in
                ### the input image).  Copying them around is
                ### wasteful.
                heavy = afwDet.makeHeavyFootprint(fp, mi)
                self.heavies.append(heavy)

        # We now create a noise HeavyFootprint for each top-level Source.
        # We'll put the noisy footprints in a map from id -> HeavyFootprint:
        self.heavyNoise = {}
        noisegen = self.getNoiseGenerator(exposure, noiseImage, noiseMeanVar)
        self.log.logdebug('Using noise generator: %s' % (str(noisegen)))
        for source in sources:
            if source.getParent():
                continue
            fp = source.getFootprint()
            heavy = noisegen.getHeavyFootprint(fp)
            self.heavyNoise[source.getId()] = heavy
            # Also insert the noisy footprint into the image now.
            # Notice that we're just inserting it into "im", ie,
            # the Image, not the MaskedImage.
            heavy.insert(im)
            # Also set the OTHERDET bit
            afwDet.setMaskFromFootprint(mask, fp, self.otherbitmask)
Пример #29
0
    def begin(self, exposure, sources, noiseImage=None, noiseMeanVar=None):
        # creates heavies, replaces all footprints with noise
        # We need the source table to be sorted by ID to do the parent lookups
        # (sources.find() below)
        if not sources.isSorted():
            sources.sort()
        mi = exposure.getMaskedImage()
        im = mi.getImage()
        mask = mi.getMask()

        # Add temporary Mask planes for THISDET and OTHERDET
        self.removeplanes = []
        bitmasks = []
        for maskname in ['THISDET', 'OTHERDET']:
            try:
                # does it already exist?
                plane = mask.getMaskPlane(maskname)
                self.log.logdebug('Mask plane "%s" already existed' % maskname)
            except:
                # if not, add it; we should delete it when done.
                plane = mask.addMaskPlane(maskname)
                self.removeplanes.append(maskname)
            mask.clearMaskPlane(plane)
            bitmask = mask.getPlaneBitMask(maskname)
            bitmasks.append(bitmask)
            self.log.logdebug('Mask plane "%s": plane %i, bitmask %i = 0x%x' %
                              (maskname, plane, bitmask, bitmask))
        self.thisbitmask,self.otherbitmask = bitmasks
        del bitmasks

        # Start by creating HeavyFootprints for each source.
        #
        # The "getParent()" checks are here because top-level
        # sources (ie, those with no parents) are not supposed to
        # have HeavyFootprints, but child sources (ie, those that
        # have been deblended) should have HeavyFootprints
        # already.
        self.heavies = []
        for source in sources:
            fp = source.getFootprint()
            hfp = afwDet.cast_HeavyFootprintF(fp)
            if source.getParent() and hfp is not None:
                # this source has been deblended; "fp" should
                # already be a HeavyFootprint (but may not be
                # if read from disk).
                # Swig downcasts it to Footprint, so we have to re-cast.
                self.heavies.append(hfp)
            else:
                # top-level source: copy pixels from the input
                # image.
                ### FIXME: the heavy footprint includes the mask
                ### and variance planes, which we shouldn't need
                ### (I don't think we ever want to modify them in
                ### the input image).  Copying them around is
                ### wasteful.
                heavy = afwDet.makeHeavyFootprint(fp, mi)
                self.heavies.append(heavy)

        # We now create a noise HeavyFootprint for each top-level Source.
        # We'll put the noisy footprints in a map from id -> HeavyFootprint:
        self.heavyNoise = {}
        noisegen = self.getNoiseGenerator(exposure, noiseImage, noiseMeanVar)
        self.log.logdebug('Using noise generator: %s' % (str(noisegen)))
        for source in sources:
            if source.getParent():
                continue
            fp = source.getFootprint()
            heavy = noisegen.getHeavyFootprint(fp)
            self.heavyNoise[source.getId()] = heavy
            # Also insert the noisy footprint into the image now.
            # Notice that we're just inserting it into "im", ie,
            # the Image, not the MaskedImage.
            heavy.insert(im)
            # Also set the OTHERDET bit
            afwDet.setMaskFromFootprint(mask, fp, self.otherbitmask)
            match = maskFormat.match(datasec)
            if match == None:
                # unable to match mask area!
                print '# WARNING: Extn', nExt, 'unable to parse', maskArea
                continue
            group = map(int, match.groups())

            # ACB : by visual inspection, the y0 values can be too
            # high by 1.  however, since some of the y0 values are '1'
            # in the mask string, i can't decrement this by 2 without
            # going off the image.  we just deal with this for dc3a.
            bbox  = afwImage.BBox(afwImage.PointI(group[0]-1, group[1]-1),
                                  afwImage.PointI(group[2]-1, group[3]-1))
            
            fp      = afwDetection.Footprint(bbox)
            afwDetection.setMaskFromFootprint(mask, fp, bitmask)

    # debugging
    #outfile0 = '%d.fits' % (i)
    #print '# Writing', outfile0
    #mask.writeFits(outfile0)

    # trim this thing!  it includes the overscan etc...
    
    bboxA = afwImage.BBox(afwImage.PointI(32,0),
                          afwImage.PointI(1055,4611))

    bboxB = afwImage.BBox(afwImage.PointI(1055,0),
                          afwImage.PointI(2111-32,4611))

    #bboxA = afwImage.BBox(afwImage.PointI(0,0),