Exemple #1
0
    def makeExposure(imgArray, psfArray, imgVariance):
        """Convert an image and corresponding PSF into an exposure.

        Set the (constant) variance plane equal to ``imgVariance``.

        Parameters
        ----------
        imgArray : `numpy.ndarray`
            2D array containing the image.
        psfArray : `numpy.ndarray`
            2D array containing the PSF image.
        imgVariance : `float` or `numpy.ndarray`
            Set the variance plane to this value. If an array, must be broadcastable to ``imgArray.shape``.

        Returns
        -------
        im1ex : `lsst.afw.image.Exposure`
            The new exposure.
        """
        # All this code to convert the template image array/psf array into an exposure.
        bbox = geom.Box2I(geom.Point2I(0, 0), geom.Point2I(imgArray.shape[1] - 1, imgArray.shape[0] - 1))
        im1ex = afwImage.ExposureD(bbox)
        im1ex.image.array[:, :] = imgArray
        im1ex.variance.array[:, :] = imgVariance
        psfBox = geom.Box2I(geom.Point2I(-12, -12), geom.Point2I(12, 12))  # a 25x25 pixel psf
        psf = afwImage.ImageD(psfBox)
        psfBox.shift(geom.Extent2I(-(-size[0]//2), -(-size[1]//2)))  # -N//2 != -(N//2) for odd numbers
        im1_psf_sub = psfArray[psfBox.getMinY():psfBox.getMaxY() + 1, psfBox.getMinX():psfBox.getMaxX() + 1]
        psf.getArray()[:, :] = im1_psf_sub
        psfK = afwMath.FixedKernel(psf)
        psfNew = measAlg.KernelPsf(psfK)
        im1ex.setPsf(psfNew)
        wcs = makeWcs()
        im1ex.setWcs(wcs)
        return im1ex
def get_coadd_psf_bbox_old(x, y, dim):
    """
    This old code only did the right thing for odd coadd dimensions

    compute the bounding box for the coadd, based on the coadd
    center as an integer position (Point2I) and the dimensions

    Parameters
    ----------
    x: int
        The integer center in x.  Should be gotten from bbox.getCenter() to
        provide an integer position
    y: int
        The integer center in x.  Should be gotten from bbox.getCenter() to
        provide an integer position
    dim: int
        The dimensions of the psf, must be odd

    Returns
    -------
    lsst.geom.Box2I
    """

    xpix = int(x)
    ypix = int(y)

    xmin = (xpix - (dim - 1) / 2)
    ymin = (ypix - (dim - 1) / 2)

    return geom.Box2I(
        geom.Point2I(xmin, ymin),
        geom.Point2I(xmin + dim - 1, ymin + dim - 1),
    )
Exemple #3
0
    def exposureToBackground(bgExp):
        """Convert an exposure to background model

        Calibs need to be persisted as an Exposure, so we need to convert
        the persisted Exposure to a background model.

        Parameters
        ----------
        bgExp : `lsst.afw.image.Exposure`
            Background model in Exposure format.

        Returns
        -------
        bg : `lsst.afw.math.BackgroundList`
            Background model
        """
        header = bgExp.getMetadata()
        xMin = header.getScalar("BOX.MINX")
        yMin = header.getScalar("BOX.MINY")
        xMax = header.getScalar("BOX.MAXX")
        yMax = header.getScalar("BOX.MAXY")
        algorithm = header.getScalar("ALGORITHM")
        bbox = geom.Box2I(geom.Point2I(xMin, yMin), geom.Point2I(xMax, yMax))
        return afwMath.BackgroundList(
            (afwMath.BackgroundMI(bbox, bgExp.getMaskedImage()),
             afwMath.stringToInterpStyle(algorithm),
             afwMath.stringToUndersampleStyle("REDUCE_INTERP_ORDER"),
             afwMath.ApproximateControl.UNKNOWN, 0, 0, False))
Exemple #4
0
    def runConvolveAndSubtract2(self, bgOrder=0, xloc=408, yloc=580):
        imsize = int(5 * self.kSize)

        p0 = geom.Point2I(xloc - imsize // 2, yloc - imsize // 2)
        p1 = geom.Point2I(xloc + imsize // 2, yloc + imsize // 2)
        bbox = geom.Box2I(p0, p1)

        tmi = afwImage.MaskedImageF(self.templateImage,
                                    bbox,
                                    origin=afwImage.LOCAL)
        smi = afwImage.MaskedImageF(self.scienceImage,
                                    bbox,
                                    origin=afwImage.LOCAL)
        bgFunc = afwMath.PolynomialFunction2D(
            bgOrder)  # coeffs are 0. by default
        diffIm = ipDiffim.convolveAndSubtract(tmi, smi, self.gaussKernel,
                                              bgFunc)

        bbox = self.gaussKernel.shrinkBBox(
            diffIm.getBBox(origin=afwImage.LOCAL))
        diffIm2 = afwImage.MaskedImageF(diffIm, bbox, origin=afwImage.LOCAL)
        for j in range(diffIm2.getHeight()):
            for i in range(diffIm2.getWidth()):
                self.assertAlmostEqual(diffIm2.image[i, j, afwImage.LOCAL], 0.,
                                       4)
Exemple #5
0
def getAmplifier(image, amp, ampReference=None, offset=2):
    """Extract an image of the amplifier from the CCD, along with an offset
    version

    The amplifier image will be flipped (if required) to match the
    orientation of a nominated reference amplifier.

    An additional image, with the nominated offset applied, is also produced.

    Parameters
    ----------
    image :
        Image of CCD
    amp :
        Index of amplifier
    ampReference :
        Index of reference amplifier
    offset :
        Offset to apply

    Returns
    -------
    amp_image :
        amplifier image, offset amplifier image
    """
    height = image.getHeight()
    ampBox = geom.Box2I(geom.Point2I(amp * 512, 0), geom.Extent2I(512, height))
    ampImage = image.Factory(image, ampBox, afwImage.LOCAL)
    if ampReference is not None and amp % 2 != ampReference % 2:
        ampImage = afwMath.flipImage(ampImage, True, False)
    offBox = geom.Box2I(geom.Point2I(offset if amp == ampReference else 0, 0),
                        geom.Extent2I(510, height))
    offsetImage = ampImage.Factory(ampImage, offBox, afwImage.LOCAL)
    return ampImage, offsetImage
Exemple #6
0
    def calcSpectrumBBox(self, exp, centroid, aperture, order='+1'):
        """Calculate the bbox for the spectrum, given the centroid.

        XXX Longer explanation here, inc. parameters
        TODO: Add support for order = "both"
        """
        extent = self.config.spectrumLengthPixels
        halfWidth = aperture // 2
        translate_y = self.config.offsetFromMainStar
        sourceX = centroid[0]
        sourceY = centroid[1]

        if (order == '-1'):
            translate_y = -extent - self.config.offsetFromMainStar

        xStart = sourceX - halfWidth
        xEnd = sourceX + halfWidth - 1
        yStart = sourceY + translate_y
        yEnd = yStart + extent - 1

        xEnd = min(xEnd, exp.getWidth() - 1)
        yEnd = min(yEnd, exp.getHeight() - 1)
        yStart = max(yStart, 0)
        xStart = max(xStart, 0)
        assert (xEnd > xStart) and (yEnd > yStart)

        self.log.debug('(xStart, xEnd) = (%s, %s)' % (xStart, xEnd))
        self.log.debug('(yStart, yEnd) = (%s, %s)' % (yStart, yEnd))

        bbox = geom.Box2I(geom.Point2I(xStart, yStart),
                          geom.Point2I(xEnd, yEnd))
        return bbox
Exemple #7
0
 def __init__(self, ccd, amp, overscans, task):
     geom = ccd.amp_geom
     self.ccd = ccd
     self.imaging = geom.imaging
     self.image = ccd[amp]  # This is the masked image for the desired amp.
     if task.config.direction == 'p':
         self._bbox = self._parallel_box
         llc = lsstGeom.Point2I(
             geom.parallel_overscan.getMinX(),
             geom.parallel_overscan.getMinY() + overscans)
         urc = geom.parallel_overscan.getCorners()[2]
         self._bias_reg = lsstGeom.Box2I(llc, urc)
         self.lastpix = self.imaging.getMaxY()
     elif task.config.direction == 's':
         self._bbox = self._serial_box
         llc = lsstGeom.Point2I(geom.serial_overscan.getMinX() + overscans,
                                geom.serial_overscan.getMinY())
         urc = geom.serial_overscan.getCorners()[2]
         #
         # Omit the last 4 columns to avoid the bright column in the
         # last overscan column in the e2v vendor data.
         #
         urc[0] -= 4
         self._bias_reg = lsstGeom.Box2I(llc, urc)
         self.lastpix = self.imaging.getMaxX()
     else:
         task.log.error("Unknown scan direction: " + str(direction))
         sys.exit(1)
Exemple #8
0
    def _makeStarImage(self,
                       xc=[15.3],
                       yc=[18.6],
                       flux=[2500],
                       schema=None,
                       randomSeed=None):
        """Generate an exposure and catalog with the given stellar source(s).
        """
        from lsst.meas.base.tests import TestDataset
        bbox = geom.Box2I(geom.Point2I(0, 0),
                          geom.Point2I(self.w - 1, self.h - 1))
        dataset = TestDataset(bbox, psfSigma=self.psfSigma, threshold=1.)

        for i in range(len(xc)):
            dataset.addSource(instFlux=flux[i],
                              centroid=geom.Point2D(xc[i], yc[i]))

        if schema is None:
            schema = TestDataset.makeMinimalSchema()
        exposure, catalog = dataset.realize(noise=self.noise,
                                            schema=schema,
                                            randomSeed=randomSeed)

        if self.gradientParams is not None:
            y, x = np.mgrid[:self.w, :self.h]
            gp = self.gradientParams
            gradient = gp[0] + gp[1] * x + gp[2] * y
            if len(self.gradientParams
                   ) > 3:  # it includes a set of 2nd-order polynomial params
                gradient += gp[3] * x * y + gp[4] * x * x + gp[5] * y * y
            imgArr = exposure.getMaskedImage().getArrays()[0]
            imgArr += gradient

        return exposure, catalog
Exemple #9
0
        def _makeBoxEvenSized(bb):
            """Force a bounding-box to have dimensions that are modulo 2."""

            if bb.getWidth() % 2 == 1:  # grow to the right
                bb.include(geom.Point2I(bb.getMaxX() + 1,
                                        bb.getMaxY()))  # Expand by 1 pixel!
                bb.clip(bbox)
                if bb.getWidth(
                ) % 2 == 1:  # clipped at right -- so grow to the left
                    bb.include(geom.Point2I(bb.getMinX() - 1, bb.getMaxY()))
                    bb.clip(bbox)
            if bb.getHeight() % 2 == 1:  # grow upwards
                bb.include(geom.Point2I(bb.getMaxX(),
                                        bb.getMaxY() +
                                        1))  # Expand by 1 pixel!
                bb.clip(bbox)
                if bb.getHeight() % 2 == 1:  # clipped upwards -- so grow down
                    bb.include(geom.Point2I(bb.getMaxX(), bb.getMinY() - 1))
                    bb.clip(bbox)
            if bb.getWidth() % 2 == 1 or bb.getHeight(
            ) % 2 == 1:  # Box is probably too big
                raise RuntimeError(
                    'Cannot make bounding box even-sized. Probably too big.')

            return bb
Exemple #10
0
    def runConvolveAndSubtract1(self, bgVal=0, xloc=408, yloc=580):
        imsize = int(5 * self.kSize)

        p0 = geom.Point2I(xloc - imsize // 2, yloc - imsize // 2)
        p1 = geom.Point2I(xloc + imsize // 2, yloc + imsize // 2)
        bbox = geom.Box2I(p0, p1)

        tmi = afwImage.MaskedImageF(self.templateImage,
                                    bbox,
                                    origin=afwImage.LOCAL)
        smi = afwImage.MaskedImageF(self.scienceImage,
                                    bbox,
                                    origin=afwImage.LOCAL)
        diffIm = ipDiffim.convolveAndSubtract(tmi, smi, self.gaussKernel,
                                              bgVal)

        bbox = self.gaussKernel.shrinkBBox(
            diffIm.getBBox(origin=afwImage.LOCAL))
        diffIm2 = afwImage.MaskedImageF(diffIm, bbox, origin=afwImage.LOCAL)

        # image is empty (or the additional background you subtracted off)
        for j in range(diffIm2.getHeight()):
            for i in range(diffIm2.getWidth()):
                self.assertAlmostEqual(diffIm2.image[i, j, afwImage.LOCAL],
                                       -1. * bgVal, 3)
Exemple #11
0
    def makeExposure(imgArray, psfArray, imgVariance):
        """! Convert an image numpy.array and corresponding PSF numpy.array into an exposure.

        Add the (constant) variance plane equal to `imgVariance`.

        @param imgArray 2-d numpy.array containing the image
        @param psfArray 2-d numpy.array containing the PSF image
        @param imgVariance variance of input image
        @return a new exposure containing the image, PSF and desired variance plane
        """
        # All this code to convert the template image array/psf array into an exposure.
        bbox = geom.Box2I(
            geom.Point2I(0, 0),
            geom.Point2I(imgArray.shape[1] - 1, imgArray.shape[0] - 1))
        im1ex = afwImage.ExposureD(bbox)
        im1ex.getMaskedImage().getImage().getArray()[:, :] = imgArray
        im1ex.getMaskedImage().getVariance().getArray()[:, :] = imgVariance
        psfBox = geom.Box2I(geom.Point2I(-12, -12),
                            geom.Point2I(12, 12))  # a 25x25 pixel psf
        psf = afwImage.ImageD(psfBox)
        psfBox.shift(geom.Extent2I(size[0] // 2, size[1] // 2))
        im1_psf_sub = psfArray[psfBox.getMinX():psfBox.getMaxX() + 1,
                               psfBox.getMinY():psfBox.getMaxY() + 1]
        psf.getArray()[:, :] = im1_psf_sub
        psfK = afwMath.FixedKernel(psf)
        psfNew = measAlg.KernelPsf(psfK)
        im1ex.setPsf(psfNew)
        wcs = makeWcs()
        im1ex.setWcs(wcs)
        return im1ex
Exemple #12
0
    def setUp(self):
        # Set up local astrometry_net_data
        self.datapath = setupAstrometryNetDataDir('photocal')
        self.config = LoadAstrometryNetObjectsTask.ConfigClass()
        self.config.pixelMargin = 50  # Original default when these tests were written

        self.bbox = geom.Box2I(geom.Point2I(0, 0), geom.Extent2I(3001, 3001))
        self.ctrPix = geom.Point2I(1500, 1500)
        metadata = PropertySet()
        metadata.set("RADESYS", "FK5")
        metadata.set("EQUINOX", 2000.0)
        metadata.set("CTYPE1", "RA---TAN")
        metadata.set("CTYPE2", "DEC--TAN")
        metadata.set("CUNIT1", "deg")
        metadata.set("CUNIT2", "deg")
        metadata.set("CRVAL1", 215.5)
        metadata.set("CRVAL2", 53.0)
        metadata.set("CRPIX1", self.ctrPix[0] + 1)
        metadata.set("CRPIX2", self.ctrPix[1] + 1)
        metadata.set("CD1_1", 5.1e-05)
        metadata.set("CD1_2", 0.0)
        metadata.set("CD2_2", -5.1e-05)
        metadata.set("CD2_1", 0.0)
        self.wcs = afwGeom.makeSkyWcs(metadata)
        self.desNumStarsInPixelBox = 270
        self.desNumStarsInSkyCircle = 410
    def testGood(self):
        ti = afwImage.MaskedImageF(geom.Extent2I(100, 100))
        ti.getVariance().set(0.1)
        ti[50, 50, afwImage.LOCAL] = (1., 0x0, 1.)
        sKernel = self.makeSpatialKernel(2)
        si = afwImage.MaskedImageF(ti.getDimensions())
        convolutionControl = afwMath.ConvolutionControl()
        convolutionControl.setDoNormalize(True)
        afwMath.convolve(si, ti, sKernel, convolutionControl)

        bbox = geom.Box2I(geom.Point2I(25, 25),
                          geom.Point2I(75, 75))
        si = afwImage.MaskedImageF(si, bbox, origin=afwImage.LOCAL)
        ti = afwImage.MaskedImageF(ti, bbox, origin=afwImage.LOCAL)
        kc = ipDiffim.KernelCandidateF(50., 50., ti, si, self.ps)

        sBg = afwMath.PolynomialFunction2D(1)
        bgCoeffs = [0., 0., 0.]
        sBg.setParameters(bgCoeffs)

        # must be initialized
        bskv = ipDiffim.BuildSingleKernelVisitorF(self.kList, self.ps)
        bskv.processCandidate(kc)
        self.assertEqual(kc.isInitialized(), True)

        askv = ipDiffim.AssessSpatialKernelVisitorF(sKernel, sBg, self.ps)
        askv.processCandidate(kc)

        self.assertEqual(askv.getNProcessed(), 1)
        self.assertEqual(askv.getNRejected(), 0)
        self.assertEqual(kc.getStatus(), afwMath.SpatialCellCandidate.GOOD)
    def testPeakRemoval(self):
        '''
        A simple example: three overlapping blobs (detected as 1
        footprint with three peaks).  Additional peaks are added near
        the blob peaks that should be identified as degenerate.
        '''
        H, W = 100, 100

        fpbb = geom.Box2I(geom.Point2I(0, 0), geom.Point2I(W - 1, H - 1))

        afwimg = afwImage.MaskedImageF(fpbb)
        imgbb = afwimg.getBBox()
        img = afwimg.getImage().getArray()

        var = afwimg.getVariance().getArray()
        var[:, :] = 1.

        blob_fwhm = 10.
        blob_psf = doubleGaussianPsf(99, 99, blob_fwhm, 2.*blob_fwhm, 0.03)

        fakepsf_fwhm = 3.
        fakepsf = gaussianPsf(11, 11, fakepsf_fwhm)

        blobimgs = []
        x = 75.
        XY = [(x, 35.), (x, 65.), (50., 50.)]
        flux = 1e6
        for x, y in XY:
            bim = blob_psf.computeImage(geom.Point2D(x, y))
            bbb = bim.getBBox()
            bbb.clip(imgbb)

            bim = bim.Factory(bim, bbb)
            bim2 = bim.getArray()

            blobimg = np.zeros_like(img)
            blobimg[bbb.getMinY():bbb.getMaxY()+1, bbb.getMinX():bbb.getMaxX()+1] += flux*bim2
            blobimgs.append(blobimg)

            img[bbb.getMinY():bbb.getMaxY()+1,
                bbb.getMinX():bbb.getMaxX()+1] += flux * bim2

        # Run the detection code to get a ~ realistic footprint
        thresh = afwDet.createThreshold(5., 'value', True)
        fpSet = afwDet.FootprintSet(afwimg, thresh, 'DETECTED', 1)
        fps = fpSet.getFootprints()

        self.assertTrue(len(fps) == 1)

        # Add new peaks near to the first peaks that will be degenerate
        fp0 = fps[0]
        for x, y in XY:
            fp0.addPeak(x - 10, y + 6, 10)

        deb = deblend(fp0, afwimg, fakepsf, fakepsf_fwhm, verbose=True, removeDegenerateTemplates=True)

        self.assertTrue(deb.deblendedParents[0].peaks[3].degenerate)
        self.assertTrue(deb.deblendedParents[0].peaks[4].degenerate)
        self.assertTrue(deb.deblendedParents[0].peaks[5].degenerate)
def test_coadd_psf_bbox_smoke(dim):
    psf_dim = 51

    bbox = geom.Box2I(geom.Point2I(54, 54), geom.Extent2I(dim, dim))
    cen = geom.Point2I(bbox.getCenter())

    psf_bbox = get_coadd_psf_bbox(cen=cen, dim=psf_dim)
    assert isinstance(psf_bbox, geom.Box2I)
Exemple #16
0
    def run(self, exposure):
        """Mask defects and trim guider shadow for SuprimeCam

        Parameters
        ----------
        exposure : `lsst.afw.image.Exposure`
            Exposure to construct detector-specific masks for.

        """
        assert exposure, "No exposure provided"

        ccd = exposure.getDetector(
        )  # This is Suprime-Cam so we know the Detector is a Ccd
        ccdNum = ccd.getId().getSerial()
        if ccdNum not in (self.config.suprimeMaskLimitSetA +
                          self.config.suprimeMaskLimitSetB):
            # No need to mask
            return

        md = exposure.getMetadata()
        if not md.exists("S_AG-X"):
            self.log.warn("No autoguider position in exposure metadata.")
            return

        xGuider = md.getScalar("S_AG-X")
        if ccdNum in self.config.suprimeMaskLimitSetA:
            maskLimit = int(60.0 * xGuider - 2300.0)  # From SDFRED
        elif ccdNum in self.config.suprimeMaskLimitSetB:
            maskLimit = int(60.0 * xGuider - 2000.0)  # From SDFRED

        mi = exposure.getMaskedImage()
        height = mi.getHeight()
        if height < maskLimit:
            # Nothing to mask!
            return

        # TODO DM-16806: Ensure GUIDER mask is respected downstream.
        if False:
            # XXX This mask plane isn't respected by background subtraction or source detection or measurement
            self.log.info("Masking autoguider shadow at y > %d" % maskLimit)
            mask = mi.getMask()
            bbox = geom.Box2I(geom.Point2I(0, maskLimit - 1),
                              geom.Point2I(mask.getWidth() - 1, height - 1))
            badMask = mask.Factory(mask, bbox, afwImage.LOCAL)

            mask.addMaskPlane("GUIDER")
            badBitmask = mask.getPlaneBitMask("GUIDER")

            badMask |= badBitmask
        else:
            # XXX Temporary solution until a mask plane is respected by downstream processes
            self.log.info(
                "Removing pixels affected by autoguider shadow at y > %d" %
                maskLimit)
            bbox = geom.Box2I(geom.Point2I(0, 0),
                              geom.Extent2I(mi.getWidth(), maskLimit))
            good = mi.Factory(mi, bbox, afwImage.LOCAL)
            exposure.setMaskedImage(good)
Exemple #17
0
    def measureScale(self, image, skyBackground):
        """Measure scale of background model in image

        We treat the sky frame much as we would a fringe frame
        (except the length scale of the variations is different):
        we measure samples on the input image and the sky frame,
        which we will use to determine the scaling factor in the
        'solveScales` method.

        Parameters
        ----------
        image : `lsst.afw.image.Exposure` or `lsst.afw.image.MaskedImage`
            Science image for which to measure scale.
        skyBackground : `lsst.afw.math.BackgroundList`
            Sky background model.

        Returns
        -------
        imageSamples : `numpy.ndarray`
            Sample measurements on image.
        skySamples : `numpy.ndarray`
            Sample measurements on sky frame.
        """
        if isinstance(image, afwImage.Exposure):
            image = image.getMaskedImage()
        # Ensure more samples than pixels
        xNumSamples = min(self.config.xNumSamples, image.getWidth())
        yNumSamples = min(self.config.yNumSamples, image.getHeight())
        xLimits = numpy.linspace(0,
                                 image.getWidth(),
                                 xNumSamples + 1,
                                 dtype=int)
        yLimits = numpy.linspace(0,
                                 image.getHeight(),
                                 yNumSamples + 1,
                                 dtype=int)
        sky = skyBackground.getImage()
        maskVal = image.getMask().getPlaneBitMask(self.config.stats.mask)
        ctrl = afwMath.StatisticsControl(self.config.stats.clip,
                                         self.config.stats.nIter, maskVal)
        statistic = afwMath.stringToStatisticsProperty(
            self.config.stats.statistic)
        imageSamples = []
        skySamples = []
        for xIndex, yIndex in itertools.product(range(xNumSamples),
                                                range(yNumSamples)):
            # -1 on the stop because Box2I is inclusive of the end point and we don't want to overlap boxes
            xStart, xStop = xLimits[xIndex], xLimits[xIndex + 1] - 1
            yStart, yStop = yLimits[yIndex], yLimits[yIndex + 1] - 1
            box = geom.Box2I(geom.Point2I(xStart, yStart),
                             geom.Point2I(xStop, yStop))
            subImage = image.Factory(image, box)
            subSky = sky.Factory(sky, box)
            imageSamples.append(
                afwMath.makeStatistics(subImage, statistic, ctrl).getValue())
            skySamples.append(
                afwMath.makeStatistics(subSky, statistic, ctrl).getValue())
        return imageSamples, skySamples
Exemple #18
0
    def testNoMask(self):
        mask = afwImage.Mask(geom.Extent2I(20, 20))
        mask.set(0)
        fsb = ipDiffim.FindSetBitsU()

        bbox = geom.Box2I(geom.Point2I(0, 10), geom.Point2I(9, 12))
        fsb.apply(afwImage.Mask(mask, bbox, afwImage.LOCAL))

        self.assertEqual(fsb.getBits(), 0)
Exemple #19
0
def get_bbox(keyword, dxmin=0, dymin=0, dxmax=0, dymax=0):
    """
    Parse an NOAO section keyword value (e.g., DATASEC = '[1:509,1:200]') from
    the FITS header and return the corresponding bounding box for sub-image
    retrieval.
    """
    xmin, xmax, ymin, ymax = [val - 1 for val in eval(keyword.replace(':', ','))]
    bbox = lsst_geom.Box2I(lsst_geom.Point2I(xmin + dxmin, ymin + dymin),
                           lsst_geom.Point2I(xmax + dxmax, ymax + dymax))
    return bbox
    def setUp(self):
        schema = afwTable.SourceTable.makeMinimalSchema()
        afwTable.Point2DKey.addFields(schema, "Centroid", "input centroid",
                                      "pixel")
        schema.addField("PsfFlux_instFlux", type=float)
        schema.addField("PsfFlux_instFluxErr", type=float)
        schema.addField("PsfFlux_flag", type="Flag")
        self.table = afwTable.SourceTable.make(schema)
        self.table.definePsfFlux("PsfFlux")
        self.table.defineCentroid("Centroid")
        self.ss = afwTable.SourceCatalog(self.table)

        self.config = ipDiffim.ImagePsfMatchTask.ConfigClass()
        self.config.kernel.name = "DF"
        self.subconfig = self.config.kernel.active

        self.ps = pexConfig.makePropertySet(self.subconfig)
        self.ps[
            'fitForBackground'] = True  # we are testing known background recovery here
        self.ps['checkConditionNumber'] = False  # just in case
        self.ps["useRegularization"] = False

        if defDataDir:
            defSciencePath = os.path.join(defDataDir, "DC3a-Sim", "sci",
                                          "v26-e0", "v26-e0-c011-a10.sci.fits")
            defTemplatePath = os.path.join(defDataDir, "DC3a-Sim", "sci",
                                           "v5-e0", "v5-e0-c011-a10.sci.fits")

            scienceExposure = afwImage.ExposureF(defSciencePath)
            templateExposure = afwImage.ExposureF(defTemplatePath)
            # set XY0 = 0
            scienceExposure.setXY0(geom.Point2I(0, 0))
            templateExposure.setXY0(geom.Point2I(0, 0))
            # do the warping first so we don't have any masked pixels in the postage stamps
            warper = afwMath.Warper.fromConfig(self.subconfig.warpingConfig)
            templateExposure = warper.warpExposure(
                scienceExposure.getWcs(),
                templateExposure,
                destBBox=scienceExposure.getBBox())

            # Change xy0
            # Nice star at position 276, 717
            # And should be at index 40, 40
            # No masked pixels in this one
            self.x02 = 276
            self.y02 = 717
            size = 40
            bbox2 = geom.Box2I(geom.Point2I(self.x02 - size, self.y02 - size),
                               geom.Point2I(self.x02 + size, self.y02 + size))
            self.scienceImage2 = afwImage.ExposureF(scienceExposure,
                                                    bbox2,
                                                    origin=afwImage.LOCAL)
            self.templateExposure2 = afwImage.ExposureF(templateExposure,
                                                        bbox2,
                                                        origin=afwImage.LOCAL)
Exemple #21
0
    def addCcd(self, exposure):
        """Add CCD to model

        We measure the background on the CCD (clipped mean), and record
        the results in the model.  For simplicity, measurements are made
        in a box on the CCD corresponding to the warped coordinates of the
        superpixel rather than accounting for little rotations, etc.
        We also record the number of pixels used in the measurement so we
        can have a measure of confidence in each bin's value.

        Parameters
        ----------
        exposure : `lsst.afw.image.Exposure`
            CCD exposure to measure
        """
        detector = exposure.getDetector()
        transform = detector.getTransformMap().getTransform(
            detector.makeCameraSys(afwCameraGeom.PIXELS),
            detector.makeCameraSys(afwCameraGeom.FOCAL_PLANE))
        image = exposure.getMaskedImage()
        maskVal = image.getMask().getPlaneBitMask(self.config.mask)

        # Warp the binned image to the focal plane
        toSample = transform.then(
            self.transform)  # CCD pixels --> focal plane --> sample

        warped = afwImage.ImageF(self._values.getBBox())
        warpedCounts = afwImage.ImageF(self._numbers.getBBox())
        width, height = warped.getDimensions()

        stats = afwMath.StatisticsControl()
        stats.setAndMask(maskVal)
        stats.setNanSafe(True)
        # Iterating over individual pixels in python is usually bad because it's slow, but there aren't many.
        pixels = itertools.product(range(width), range(height))
        for xx, yy in pixels:
            llc = toSample.applyInverse(geom.Point2D(xx - 0.5, yy - 0.5))
            urc = toSample.applyInverse(geom.Point2D(xx + 0.5, yy + 0.5))
            bbox = geom.Box2I(geom.Point2I(llc), geom.Point2I(urc))
            bbox.clip(image.getBBox())
            if bbox.isEmpty():
                continue
            subImage = image.Factory(image, bbox)
            result = afwMath.makeStatistics(subImage,
                                            afwMath.MEANCLIP | afwMath.NPOINT,
                                            stats)
            mean = result.getValue(afwMath.MEANCLIP)
            num = result.getValue(afwMath.NPOINT)
            if not numpy.isfinite(mean) or not numpy.isfinite(num):
                continue
            warped[xx, yy, afwImage.LOCAL] = mean * num
            warpedCounts[xx, yy, afwImage.LOCAL] = num

        self._values += warped
        self._numbers += warpedCounts
    def _getBboxes(self, centroid):
        x, y = centroid
        bboxes = []

        for offset in self._spectrumBoxOffsets:
            bbox = geom.Box2I(
                geom.Point2I(x - self.spectrumHalfWidth, y + offset),
                geom.Point2I(x + self.spectrumHalfWidth,
                             y + offset + self.spectrumBoxLength))
            bboxes.append(bbox)
        return bboxes
Exemple #23
0
def crossCorrelate(maskedimage1, maskedimage2, maxLag, sigma, binsize):
    """
    Calculate the correlation coefficients.
    """
    sctrl = afwMath.StatisticsControl()
    sctrl.setNumSigmaClip(sigma)

    # Diff the images.
    diff = maskedimage1.clone()
    diff -= maskedimage2.getImage()

    # Subtract background.
    nx = diff.getWidth()//binsize
    ny = diff.getHeight()//binsize
    bctrl = afwMath.BackgroundControl(nx, ny, sctrl, afwMath.MEANCLIP)
    bkgd = afwMath.makeBackground(diff, bctrl)
    bgImg = bkgd.getImageF(afwMath.Interpolate.CUBIC_SPLINE,
                           afwMath.REDUCE_INTERP_ORDER)

    diff -= bgImg

    # Measure the correlations
    x0, y0 = diff.getXY0()
    width, height = diff.getDimensions()
    bbox_extent = lsstGeom.Extent2I(width - maxLag, height - maxLag)

    bbox = lsstGeom.Box2I(lsstGeom.Point2I(x0, y0), bbox_extent)
    dim0 = diff[bbox].clone()
    dim0 -= afwMath.makeStatistics(dim0, afwMath.MEANCLIP, sctrl).getValue()

    xcorr = np.zeros((maxLag + 1, maxLag + 1), dtype=np.float64)
    xcorr_err = np.zeros((maxLag + 1, maxLag + 1), dtype=np.float64)

    for xlag in range(maxLag + 1):
        for ylag in range(maxLag + 1):
            bbox_lag = lsstGeom.Box2I(lsstGeom.Point2I(x0 + xlag, y0 + ylag),
                                      bbox_extent)
            dim_xy = diff[bbox_lag].clone()
            dim_xy -= afwMath.makeStatistics(dim_xy, afwMath.MEANCLIP,
                                             sctrl).getValue()
            dim_xy *= dim0
            xcorr[xlag, ylag] = afwMath.makeStatistics(
                dim_xy, afwMath.MEANCLIP, sctrl).getValue()
            dim_xy_array = dim_xy.getImage().getArray().flatten()/xcorr[0][0]
            N = len(dim_xy_array.flatten())
            if xlag != 0 and ylag != 0:
                f = (1+xcorr[xlag, ylag]/xcorr[0][0]) / \
                    (1-xcorr[xlag, ylag]/xcorr[0][0])
                xcorr_err[xlag, ylag] = (
                    np.std(dim_xy_array)/np.sqrt(N))*np.sqrt(f)
            else:
                xcorr_err[xlag, ylag] = 0
    return xcorr, xcorr_err
Exemple #24
0
    def testGetCollection(self):
        # NOTE - you need to subtract off background from the image
        # you run detection on.  Here it is the template.
        bgConfig = self.subconfig.afwBackgroundConfig
        diffimTools.backgroundSubtract(bgConfig, [
            self.templateImage,
        ])

        detConfig = self.subconfig.detectionConfig
        maskPlane = detConfig.badMaskPlanes[0]
        maskVal = afwImage.Mask.getPlaneBitMask(maskPlane)

        kcDetect = ipDiffim.KernelCandidateDetectionF(
            pexConfig.makePropertySet(detConfig))
        kcDetect.apply(self.templateImage, self.scienceImage)
        fpList1 = kcDetect.getFootprints()

        self.assertNotEqual(len(fpList1), 0)

        for fp in fpList1:
            bbox = fp.getBBox()
            tmi = afwImage.MaskedImageF(self.templateImage,
                                        bbox,
                                        origin=afwImage.LOCAL)
            smi = afwImage.MaskedImageF(self.scienceImage,
                                        bbox,
                                        origin=afwImage.LOCAL)
            tmask = tmi.getMask()
            smask = smi.getMask()

            for j in range(tmask.getHeight()):
                for i in range(tmask.getWidth()):
                    # No masked pixels in either image
                    self.assertEqual(tmask[i, j, afwImage.LOCAL], 0)
                    self.assertEqual(smask[i, j, afwImage.LOCAL], 0)

        # add a masked pixel to the template image and make sure you don't get it
        tp = geom.Point2I(tmask.getWidth() // 2, tmask.getHeight() // 2)
        self.templateImage.mask[fpList1[0].getBBox(),
                                afwImage.LOCAL][tp, afwImage.LOCAL] = maskVal
        kcDetect.apply(self.templateImage, self.scienceImage)
        fpList2 = kcDetect.getFootprints()
        self.assertEqual(len(fpList2), (len(fpList1) - 1))

        # add a masked pixel to the science image and make sure you don't get it
        sp = geom.Point2I(smask.getWidth() // 2, smask.getHeight() // 2)
        self.scienceImage.mask[fpList1[1].getBBox(),
                               afwImage.LOCAL][sp, afwImage.LOCAL] = maskVal
        self.scienceImage.mask[fpList1[2].getBBox(),
                               afwImage.LOCAL][sp, afwImage.LOCAL] = maskVal
        kcDetect.apply(self.templateImage, self.scienceImage)
        fpList3 = kcDetect.getFootprints()
        self.assertEqual(len(fpList3), (len(fpList1) - 3))
Exemple #25
0
    def testConstructors(self):
        # test extent from extent 2-d
        e1 = geom.Extent2I(1, 2)
        e2 = geom.Extent2I(e1)
        self.assertAlmostEqual(tuple(e1), tuple(e2))

        e1 = geom.Extent2D(1.2, 3.4)
        e2 = geom.Extent2D(e1)
        self.assertAlmostEqual(tuple(e1), tuple(e2))

        e1 = geom.Extent2I(1, 2)
        e2 = geom.Extent2D(e1)
        self.assertAlmostEqual(tuple(e1), tuple(e2))

        # test extent from extent 3-d
        e1 = geom.Extent3I(1, 2, 3)
        e2 = geom.Extent3I(e1)
        self.assertAlmostEqual(tuple(e1), tuple(e2))

        e1 = geom.Extent3D(1.2, 3.4, 5.6)
        e2 = geom.Extent3D(e1)
        self.assertAlmostEqual(tuple(e1), tuple(e2))

        e1 = geom.Extent3I(1, 2, 3)
        e2 = geom.Extent3D(e1)
        self.assertAlmostEqual(tuple(e1), tuple(e2))

        # test extent from point 2-d
        e1 = geom.Point2I(1, 2)
        e2 = geom.Extent2I(e1)
        self.assertAlmostEqual(tuple(e1), tuple(e2))

        e1 = geom.Point2D(1.2, 3.4)
        e2 = geom.Extent2D(e1)
        self.assertAlmostEqual(tuple(e1), tuple(e2))

        e1 = geom.Point2I(1, 2)
        e2 = geom.Extent2D(e1)
        self.assertAlmostEqual(tuple(e1), tuple(e2))

        # test extent from point 3-d
        e1 = geom.Point3I(1, 2, 3)
        e2 = geom.Extent3I(e1)
        self.assertAlmostEqual(tuple(e1), tuple(e2))

        e1 = geom.Point3D(1.2, 3.4, 5.6)
        e2 = geom.Extent3D(e1)
        self.assertAlmostEqual(tuple(e1), tuple(e2))

        e1 = geom.Point3I(1, 2, 3)
        e2 = geom.Extent3D(e1)
        self.assertAlmostEqual(tuple(e1), tuple(e2))
Exemple #26
0
    def _testAddToCoaddImpl(self, useMask, uniformWeight=True):
        """Test coadd"""

        trueImageValue = 10.0
        imBBox = geom.Box2I(geom.Point2I(0, 0), geom.Extent2I(10, 20))
        if useMask:
            coadd = afwImage.MaskedImageF(imBBox)
            weightMap = coadd.getImage().Factory(coadd.getBBox())

            badBits = 0x1
            badPixel = (float("NaN"), badBits, 0)
            truth = (trueImageValue, 0x0, 0)
        else:
            coadd = afwImage.ImageF(imBBox)
            weightMap = coadd.Factory(coadd.getBBox())

            badPixel = float("NaN")
            truth = trueImageValue

        for i in range(0, 20, 3):
            image = coadd.Factory(coadd.getDimensions())
            image.set(badPixel)

            subBBox = geom.Box2I(geom.Point2I(0, i),
                                 image.getDimensions() - geom.Extent2I(0, i))
            subImage = image.Factory(image, subBBox, afwImage.LOCAL)
            subImage.set(truth)
            del subImage

            weight = 1.0 if uniformWeight else 1.0 + 0.1 * i
            if useMask:
                coaddUtils.addToCoadd(coadd, weightMap, image, badBits, weight)
            else:
                coaddUtils.addToCoadd(coadd, weightMap, image, weight)

            self.assertEqual(image[-1, -1, afwImage.LOCAL], truth)

        coadd /= weightMap

        if display:
            ds9.mtv(image, title="image", frame=1)
            ds9.mtv(coadd, title="coadd", frame=2)
            ds9.mtv(weightMap, title="weightMap", frame=3)

        stats = afwMath.makeStatistics(coadd, afwMath.MEAN | afwMath.STDEV)

        return [
            trueImageValue,
            stats.getValue(afwMath.MEAN), 0.0,
            stats.getValue(afwMath.STDEV)
        ]
Exemple #27
0
    def testOneMask(self):
        mask = afwImage.Mask(geom.Extent2I(20, 20))
        mask.set(0)
        bitmaskBad = mask.getPlaneBitMask('BAD')
        fsb = ipDiffim.FindSetBitsU()

        bbox = geom.Box2I(geom.Point2I(9, 10), geom.Point2I(11, 12))
        submask = afwImage.Mask(mask, bbox, afwImage.LOCAL)
        submask |= bitmaskBad

        bbox2 = geom.Box2I(geom.Point2I(8, 8), geom.Point2I(19, 19))
        fsb.apply(afwImage.Mask(mask, bbox2, afwImage.LOCAL))

        self.assertEqual(fsb.getBits(), bitmaskBad)
Exemple #28
0
    def testPut(self):
        """Compare put of individual components vs a composite.

        Notes
        -----
        Raw and calibration frames do not round trip (they are saved as
        DecoratedImageU and read in as ExposureU), so create the raw
        and flat manually.
        """
        outputs = (dafPersist.RepositoryArgs(root=self.compositeOutput,
                                             tags='composite'),
                   dafPersist.RepositoryArgs(root=self.nonCompositeOutput,
                                             tags='noncomposite'))
        butler = dafPersist.Butler(inputs=dafPersist.RepositoryArgs(
            root=self.input, mapper='lsst.obs.test.testMapper.TestMapper'),
                                   outputs=outputs)
        bbox = geom.Box2I(geom.Point2I(0, 0), geom.Point2I(10, 10))
        raw = makeRampDecoratedImage(bbox=bbox,
                                     start=100,
                                     raw1=5,
                                     raw2="hello")
        flat = makeRampDecoratedImage(bbox=bbox,
                                      start=-55,
                                      flat1="me",
                                      flat2=47)

        # a hack-ish way of creating a rawAndFlat object; read in the data, then replace it with our own
        rawAndFlat = butler.get('rawAndFlat', dataId=self.dataId)
        rawAndFlat.raw = raw
        rawAndFlat.flat = flat

        butler.put(rawAndFlat,
                   'rawAndFlat',
                   dataId=self.dataId,
                   tags='composite')
        butler.put(raw, 'raw', dataId=self.dataId, tags='noncomposite')
        butler.put(raw, 'flat', dataId=self.dataId, tags='noncomposite')

        self.assertTrue(
            filecmp.cmp(
                os.path.join(self.compositeOutput, 'raw', 'raw_v1_fg.fits.gz'),
                os.path.join(self.nonCompositeOutput, 'raw',
                             'raw_v1_fg.fits.gz')))

        self.assertTrue(
            filecmp.cmp(
                os.path.join(self.compositeOutput, 'flat', 'flat_fg.fits.gz'),
                os.path.join(self.nonCompositeOutput, 'flat',
                             'flat_fg.fits.gz')))
    def setUp(self):

        nSources = 10
        # CFHT Filters from the camera mapper.
        afwImageUtils.resetFilters()
        afwImageUtils.defineFilter('u', lambdaEff=374, alias="u.MP9301")
        afwImageUtils.defineFilter('g', lambdaEff=487, alias="g.MP9401")
        afwImageUtils.defineFilter('r', lambdaEff=628, alias="r.MP9601")
        afwImageUtils.defineFilter('i', lambdaEff=778, alias="i.MP9701")
        afwImageUtils.defineFilter('z', lambdaEff=1170, alias="z.MP9801")

        self.bbox = geom.Box2I(geom.Point2I(0, 0), geom.Extent2I(1024, 1153))
        dataset = measTests.TestDataset(self.bbox)
        for srcIdx in range(nSources):
            dataset.addSource(100000.0, geom.Point2D(100, 100))
        self.inputCatalogNoFlags, _ = make_input_source_catalog(dataset, False)
        self.inputCatalog, self.exposure = \
            make_input_source_catalog(dataset, True)

        detector = DetectorWrapper(id=23,
                                   bbox=self.exposure.getBBox()).detector
        visit = afwImage.VisitInfo(exposureId=4321,
                                   exposureTime=200.,
                                   date=dafBase.DateTime(nsecs=1400000000 *
                                                         10**9))
        self.exposure.setDetector(detector)
        self.exposure.getInfo().setVisitInfo(visit)
        self.exposure.setFilter(afwImage.Filter('g.MP9401'))
        scale = 2
        scaleErr = 1
        self.photoCalib = afwImage.PhotoCalib(scale, scaleErr)
        self.exposure.setPhotoCalib(self.photoCalib)
Exemple #30
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)
        if self.config.notDeblendedMask:
            mask.addMaskPlane(self.config.notDeblendedMask)
            fp.spans.setMask(
                mask, mask.getPlaneBitMask(self.config.notDeblendedMask))

        # Set the center of the parent
        bbox = fp.getBBox()
        centerX = int(bbox.getMinX() + bbox.getWidth() / 2)
        centerY = int(bbox.getMinY() + bbox.getHeight() / 2)
        source.set(self.peakCenter, geom.Point2I(centerX, centerY))
        # There are no deblended children, so nChild = 0
        source.set(self.nChildKey, 0)
        # But we also want to know how many peaks that we would have
        # deblended if the parent wasn't skipped.
        source.set(self.nPeaksKey, len(fp.peaks))
        # Top level parents are not a detected peak, so they have no peakId
        source.set(self.peakIdKey, 0)
        # Top level parents also have no parentNPeaks
        source.set(self.parentNPeaksKey, 0)