Ejemplo n.º 1
0
    def fromCamera(cls, config, camera):
        """Construct from a camera object

        Parameters
        ----------
        config : `FocalPlaneBackgroundConfig`
            Configuration for measuring backgrounds.
        camera : `lsst.afw.cameraGeom.Camera`
            Camera for which to measure backgrounds.
        """
        cameraBox = afwGeom.Box2D()
        for ccd in camera:
            for point in ccd.getCorners(afwCameraGeom.FOCAL_PLANE):
                cameraBox.include(point)

        width, height = cameraBox.getDimensions()
        # Offset so that we run from zero
        offset = afwGeom.Extent2D(cameraBox.getMin())*-1
        # Add an extra pixel buffer on either side
        dims = afwGeom.Extent2I(int(numpy.ceil(width/config.xSize)) + 2,
                                int(numpy.ceil(height/config.ySize)) + 2)
        # Transform takes us from focal plane coordinates --> sample coordinates
        transform = (afwGeom.AffineTransform.makeTranslation(afwGeom.Extent2D(1, 1))*
                     afwGeom.AffineTransform.makeScaling(1.0/config.xSize, 1.0/config.ySize)*
                     afwGeom.AffineTransform.makeTranslation(offset))

        return cls(config, dims, afwGeom.makeTransform(transform))
Ejemplo n.º 2
0
def makePixelToTanPixel(bbox, orientation, focalPlaneToField, pixelSizeMm):
    """!Make a Transform whose forward direction converts PIXELS to TAN_PIXELS for one detector

    PIXELS and TAN_PIXELS are defined in @ref afwCameraGeomCoordSys in doc/cameraGeom.dox

    @param[in] bbox  detector bounding box (an lsst.afw.geom.Box2I)
    @param[in] orientation  orientation of detector in focal plane (an lsst.afw.cameraGeom.Orientation)
    @param[in] focalPlaneToField  an lsst.afw.geom.Transform that converts from focal plane (mm)
        to field angle coordinates (radians) in the forward direction
    @param[in] pixelSizeMm  size of the pixel in mm in X and Y (an lsst.afw.geom.Extent2D)
    @return a TransformPoint2ToPoint2 whose forward direction converts PIXELS to TAN_PIXELS
    """
    pixelToFocalPlane = orientation.makePixelFpTransform(pixelSizeMm)
    pixelToField = pixelToFocalPlane.then(focalPlaneToField)
    # fieldToTanPix is affine and matches fieldToPix at field center
    # Note: focal plane to field angle is typically a radial transform,
    # and linearizing the inverse transform of that may fail,
    # so linearize the forward direction instead. (pixelToField is pixelToFocalPlane,
    # an affine transform, followed by focalPlaneToField,
    # so the same consideration applies to pixelToField)
    pixAtFieldCtr = pixelToField.applyInverse(afwGeom.Point2D(0, 0))
    tanPixToFieldAffine = afwGeom.linearizeTransform(pixelToField,
                                                     pixAtFieldCtr)
    fieldToTanPix = afwGeom.makeTransform(tanPixToFieldAffine.invert())

    return pixelToField.then(fieldToTanPix)
Ejemplo n.º 3
0
    def testTransform2(self):
        if display:
            import matplotlib.pyplot as plt
        scale = 2.0
        shift = lsst.geom.Extent2D(3.0, 4.0)
        affineTransform = lsst.geom.AffineTransform.makeTranslation(shift) * \
            lsst.geom.AffineTransform.makeScaling(scale)
        transform22 = afwGeom.makeTransform(affineTransform)
        for num in range(3, 30):
            small = self.polygon(num, 1.0, 0.0, 0.0)
            large1 = small.transform(affineTransform)
            large2 = small.transform(transform22)
            expect = self.polygon(num, scale, shift[0], shift[1])
            self.assertEqual(large1, expect)
            self.assertEqual(large2, expect)

            if display:
                axes = small.plot(c='k')
                axes.set_aspect("equal")
                axes.set_title("AffineTransform: Polygon nside=%d" % num)
                large1.plot(axes, c='b')
                if not doPause:
                    try:
                        plt.pause(2)
                        plt.close()
                    except Exception:
                        print(
                            "%s: plt.pause() failed. Please close plots when done."
                            % self.__str__())
                        plt.show()
                else:
                    print("%s: Please close plots when done." % self.__str__())
                    plt.show()
Ejemplo n.º 4
0
    def testTransform2(self):
        if display:
            import matplotlib.pyplot as plt
        scale = 2.0
        shift = lsst.geom.Extent2D(3.0, 4.0)
        affineTransform = lsst.geom.AffineTransform.makeTranslation(shift) * \
            lsst.geom.AffineTransform.makeScaling(scale)
        transform22 = afwGeom.makeTransform(affineTransform)
        for num in range(3, 30):
            small = self.polygon(num, 1.0, 0.0, 0.0)
            large1 = small.transform(affineTransform)
            large2 = small.transform(transform22)
            expect = self.polygon(num, scale, shift[0], shift[1])
            self.assertEqual(large1, expect)
            self.assertEqual(large2, expect)

            if display:
                axes = small.plot(c='k')
                axes.set_aspect("equal")
                axes.set_title("AffineTransform: Polygon nside=%d" % num)
                large1.plot(axes, c='b')
                if not doPause:
                    try:
                        plt.pause(2)
                        plt.close()
                    except Exception:
                        print("%s: plt.pause() failed. Please close plots when done." % self.__str__())
                        plt.show()
                else:
                    print("%s: Please close plots when done." % self.__str__())
                    plt.show()
Ejemplo n.º 5
0
 def testLinearize(self):
     for transform, invertible in (
         (afwGeom.TransformPoint2ToPoint2(makeForwardPolyMap(2, 2)), False),
         (afwGeom.makeIdentityTransform(), True),
         (afwGeom.makeTransform(lsst.geom.AffineTransform(np.array([[3.0, -2.0], [2.0, -1.0]]))), True),
         (afwGeom.makeRadialTransform([0.0, 8.0e-05, 0.0, -4.5e-12]), True),
     ):
         self.checkLinearize(transform, invertible)
Ejemplo n.º 6
0
 def testLinearize(self):
     for transform, invertible in (
         (afwGeom.TransformPoint2ToPoint2(makeForwardPolyMap(2, 2)), False),
         (afwGeom.makeIdentityTransform(), True),
         (afwGeom.makeTransform(lsst.geom.AffineTransform(np.array([[3.0, -2.0], [2.0, -1.0]]))), True),
         (afwGeom.makeRadialTransform([0.0, 8.0e-05, 0.0, -4.5e-12]), True),
     ):
         self.checkLinearize(transform, invertible)
Ejemplo n.º 7
0
def makeTransformDict(nativeSys, transformDict, plateScale):
    """Make a dictionary of TransformPoint2ToPoint2s from yaml, mapping from
    nativeSys

    Parameters
    ----------
    nativeSys : `lsst.afw.cameraGeom.CameraSys`
    transformDict : `dict`
        A dict specifying parameters of transforms; keys are camera system
        names.
    plateScale : `lsst.geom.Angle`
        The size of a pixel in angular units/mm (e.g. 20 arcsec/mm for LSST)

    Returns
    -------
    transforms : `dict`
        A dict of `lsst.afw.cameraGeom.CameraSys` :
        `lsst.afw.geom.TransformPoint2ToPoint2`

    The resulting dict's keys are `~lsst.afw.cameraGeom.CameraSys`,
    and the values are Transforms *from* NativeSys *to* CameraSys
    """
    # As other comments note this is required, and this is one function where
    # it's assumed
    assert nativeSys == cameraGeom.FOCAL_PLANE, "Cameras with nativeSys != FOCAL_PLANE are not supported."

    resMap = dict()

    for key, transform in transformDict.items():
        transformType = transform["transformType"]
        knownTransformTypes = ["affine", "radial"]
        if transformType not in knownTransformTypes:
            raise RuntimeError("Saw unknown transform type for %s: %s (known types are: [%s])" % (
                key, transform["transformType"], ", ".join(knownTransformTypes)))

        if transformType == "affine":
            affine = geom.AffineTransform(np.array(transform["linear"]),
                                          np.array(transform["translation"]))

            transform = afwGeom.makeTransform(affine)
        elif transformType == "radial":
            # radial coefficients of the form [0, 1 (no units), C2 (rad),
            # usually 0, C3 (rad^2), ...]
            # Radial distortion is modeled as a radial polynomial that converts
            # from focal plane radius (in mm) to field angle (in radians).
            # The provided coefficients are divided by the plate
            # scale (in radians/mm) meaning that C1 is always 1.
            radialCoeffs = np.array(transform["coeffs"])

            radialCoeffs *= plateScale.asRadians()
            transform = afwGeom.makeRadialTransform(radialCoeffs)
        else:
            raise RuntimeError("Impossible condition \"%s\" is not in: [%s])" % (
                transform["transformType"], ", ".join(knownTransformTypes)))

        resMap[cameraGeom.CameraSys(key)] = transform

    return resMap
Ejemplo n.º 8
0
 def makeAffineTransform(self, offset=(0, 0), rotation=0*lsst.geom.degrees, scale=1.0):
     """Make an affine TransformPoint2ToPoint2 that first adds the specified offset,
     then scales and rotates the result
     """
     rotScale = lsst.geom.AffineTransform(lsst.geom.LinearTransform.makeScaling(scale) *
                                          lsst.geom.LinearTransform.makeRotation(rotation))
     offset = lsst.geom.AffineTransform(lsst.geom.Extent2D(*offset))
     # AffineTransform a*b = b.then(a)
     return afwGeom.makeTransform(rotScale*offset)
Ejemplo n.º 9
0
 def makeAffineTransform(self,
                         offset=(0, 0),
                         rotation=0 * lsst.geom.degrees,
                         scale=1.0):
     """Make an affine TransformPoint2ToPoint2 that first adds the specified offset,
     then scales and rotates the result
     """
     rotScale = lsst.geom.AffineTransform(
         lsst.geom.LinearTransform.makeScaling(scale) *
         lsst.geom.LinearTransform.makeRotation(rotation))
     offset = lsst.geom.AffineTransform(lsst.geom.Extent2D(*offset))
     # AffineTransform a*b = b.then(a)
     return afwGeom.makeTransform(rotScale * offset)
Ejemplo n.º 10
0
    def toCcdBackground(self, detector, bbox):
        """Produce a background model for a CCD

        The superpixel background model is warped back to the
        CCD frame, for application to the individual CCD.

        Parameters
        ----------
        detector : `lsst.afw.cameraGeom.Detector`
            CCD for which to produce background model.
        bbox : `lsst.geom.Box2I`
            Bounding box of CCD exposure.

        Returns
        -------
        bg : `lsst.afw.math.BackgroundList`
            Background model for CCD.
        """
        transform = detector.getTransformMap().getTransform(
            detector.makeCameraSys(afwCameraGeom.PIXELS),
            detector.makeCameraSys(afwCameraGeom.FOCAL_PLANE))
        binTransform = (
            geom.AffineTransform.makeScaling(self.config.binning) *
            geom.AffineTransform.makeTranslation(geom.Extent2D(0.5, 0.5)))

        # Binned image on CCD --> unbinned image on CCD --> focal plane --> binned focal plane
        toSample = afwGeom.makeTransform(binTransform).then(transform).then(
            self.transform)

        focalPlane = self.getStatsImage()
        fpNorm = afwImage.ImageF(focalPlane.getBBox())
        fpNorm.set(1.0)

        image = afwImage.ImageF(bbox.getDimensions() // self.config.binning)
        norm = afwImage.ImageF(image.getBBox())
        ctrl = afwMath.WarpingControl("bilinear")
        afwMath.warpImage(image, focalPlane, toSample.inverted(), ctrl)
        afwMath.warpImage(norm, fpNorm, toSample.inverted(), ctrl)
        image /= norm

        mask = afwImage.Mask(image.getBBox())
        isBad = numpy.isnan(image.getArray())
        mask.getArray()[isBad] = mask.getPlaneBitMask("BAD")
        image.getArray()[isBad] = image.getArray()[~isBad].mean()

        return afwMath.BackgroundList(
            (afwMath.BackgroundMI(bbox, afwImage.makeMaskedImage(image, mask)),
             afwMath.stringToInterpStyle(self.config.interpolation),
             afwMath.stringToUndersampleStyle("REDUCE_INTERP_ORDER"),
             afwMath.ApproximateControl.UNKNOWN, 0, 0, False))
Ejemplo n.º 11
0
 def testTransform(self):
     """Test constructor for Polygon involving transforms"""
     box = lsst.geom.Box2D(lsst.geom.Point2D(0.0, 0.0),
                           lsst.geom.Point2D(123.4, 567.8))
     poly1 = afwGeom.Polygon(box)
     scale = 1.5
     shift = lsst.geom.Extent2D(3.0, 4.0)
     affineTransform = lsst.geom.AffineTransform.makeTranslation(shift) * \
         lsst.geom.AffineTransform.makeScaling(scale)
     transform22 = afwGeom.makeTransform(affineTransform)
     transformedVertices = transform22.applyForward(box.getCorners())
     expect = afwGeom.Polygon(transformedVertices)
     poly1 = afwGeom.Polygon(box, affineTransform)
     poly2 = afwGeom.Polygon(box, transform22)
     self.assertEqual(poly1, expect)
     self.assertEqual(poly2, expect)
Ejemplo n.º 12
0
 def testTransform(self):
     """Test constructor for Polygon involving transforms"""
     box = lsst.geom.Box2D(lsst.geom.Point2D(0.0, 0.0),
                           lsst.geom.Point2D(123.4, 567.8))
     poly1 = afwGeom.Polygon(box)
     scale = 1.5
     shift = lsst.geom.Extent2D(3.0, 4.0)
     affineTransform = lsst.geom.AffineTransform.makeTranslation(shift) * \
         lsst.geom.AffineTransform.makeScaling(scale)
     transform22 = afwGeom.makeTransform(affineTransform)
     transformedVertices = transform22.applyForward(box.getCorners())
     expect = afwGeom.Polygon(transformedVertices)
     poly1 = afwGeom.Polygon(box, affineTransform)
     poly2 = afwGeom.Polygon(box, transform22)
     self.assertEqual(poly1, expect)
     self.assertEqual(poly2, expect)
Ejemplo n.º 13
0
def rotateExposure(exp, nDegrees, kernelName='lanczos4', logger=None):
    """Rotate an exposure by nDegrees clockwise.

    Parameters
    ----------
    exp : `lsst.afw.image.exposure.Exposure`
        The exposure to rotate
    nDegrees : `float`
        Number of degrees clockwise to rotate by
    kernelName : `str`
        Name of the warping kernel, used to instantiate the warper.
    logger : `lsst.log.Log`
        Logger for logging warnings

    Returns
    -------
    rotatedExp : `lsst.afw.image.exposure.Exposure`
        A copy of the input exposure, rotated by nDegrees
    """
    nDegrees = nDegrees % 360

    if not logger:
        logger = lsstLog.getLogger('atmospec.utils')

    wcs = exp.getWcs()
    if not wcs:
        logger.warn(
            "Can't rotate exposure without a wcs - returning exp unrotated")
        return exp.clone(
        )  # return a clone so it's always returning a copy as this is what default does

    warper = afwMath.Warper(kernelName)
    if isinstance(exp, afwImage.ExposureU):
        # TODO: remove once this bug is fixed - DM-20258
        logger.info('Converting ExposureU to ExposureF due to bug')
        logger.info('Remove this workaround after DM-20258')
        exp = afwImage.ExposureF(exp, deep=True)

    affineRotTransform = geom.AffineTransform.makeRotation(nDegrees *
                                                           geom.degrees)
    transformP2toP2 = afwGeom.makeTransform(affineRotTransform)
    rotatedWcs = afwGeom.makeModifiedWcs(transformP2toP2, wcs, False)

    rotatedExp = warper.warpExposure(rotatedWcs, exp)
    # rotatedExp.setXY0(geom.Point2I(0, 0))  # TODO: check no longer required
    return rotatedExp
Ejemplo n.º 14
0
    def testTransform2(self):
        scale = 2.0
        shift = lsst.geom.Extent2D(3.0, 4.0)
        affineTransform = lsst.geom.AffineTransform.makeTranslation(shift) * \
            lsst.geom.AffineTransform.makeScaling(scale)
        transform22 = afwGeom.makeTransform(affineTransform)
        for num in range(3, 30):
            small = self.polygon(num, 1.0, 0.0, 0.0)
            large1 = small.transform(affineTransform)
            large2 = small.transform(transform22)
            expect = self.polygon(num, scale, shift[0], shift[1])
            self.assertEqual(large1, expect)
            self.assertEqual(large2, expect)

            if DEBUG:
                import matplotlib.pyplot as plt
                axes = small.plot(c='k')
                large1.plot(axes, c='b')
                plt.show()