コード例 #1
0
    def testCurvedFocalPlane(self):
        """Test a curved focal plane (with rectangular pixels)
        """
        bbox = afwGeom.Box2I(afwGeom.Point2I(0, 0),
                             afwGeom.Extent2I(1000, 1000))
        pixelSizeMm = afwGeom.Extent2D(0.02, 0.03)
        plateScale = 25.0  # arcsec/mm
        yaw = afwGeom.Angle(20, afwGeom.degrees)
        # focal-plane position of ref position on detector (mm)
        fpPosition = afwGeom.Point2D(50, 25)
        # ref position on detector (pos of lower left corner)
        refPoint = afwGeom.Point2D(-0.5, -0.5)
        orientation = cameraGeom.Orientation(
            fpPosition,
            refPoint,
            yaw,
        )
        pixelToFocalPlane = orientation.makePixelFpTransform(pixelSizeMm)
        plateScaleRad = afwGeom.Angle(plateScale,
                                      afwGeom.arcseconds).asRadians()
        focalPlaneToField = afwGeom.makeRadialTransform(
            (0.0, plateScaleRad, 0.0, 0.001 * plateScaleRad))
        pixelToField = pixelToFocalPlane.then(focalPlaneToField)

        pixelToTanPixel = makePixelToTanPixel(
            bbox=bbox,
            orientation=orientation,
            focalPlaneToField=focalPlaneToField,
            pixelSizeMm=pixelSizeMm,
        )

        # the center point of the field angle frame should not move
        pixAtFieldCtr = pixelToField.applyInverse(afwGeom.Point2D(0, 0))
        tanPixAtFieldCr = pixelToTanPixel.applyForward(pixAtFieldCtr)
        self.assertPairsAlmostEqual(pixAtFieldCtr, tanPixAtFieldCr)

        # build same camera geometry transforms without optical distortion
        focalPlaneToFieldNoDistortion = afwGeom.makeRadialTransform(
            (0.0, plateScaleRad))
        pixelToFieldNoDistortion = pixelToFocalPlane.then(
            focalPlaneToFieldNoDistortion)

        for x in (100, 200, 1000):
            for y in (100, 500, 800):
                pixPos = afwGeom.Point2D(x, y)
                tanPixPos = pixelToTanPixel.applyForward(pixPos)

                # for a given field angle (which, together with a pointing, gives a position on the sky):
                # - field angle to pixels gives pixPos
                # - undistorted field angle to pixels gives tanPixPos
                fieldPos = pixelToField.applyForward(pixPos)
                desTanPixPos = pixelToFieldNoDistortion.applyInverse(fieldPos)
                # use a degraded accuracy because small Jacobian errors accumulate this far from the center
                self.assertPairsAlmostEqual(desTanPixPos,
                                            tanPixPos,
                                            maxDiff=1e-5)
コード例 #2
0
 def testWarnings(self):
     """Test that approximateWcs raises a UserWarning when it cannot achieve desired tolerance"""
     radialTransform = afwGeom.makeRadialTransform([0, 2.0, 3.0])
     wcs = afwGeom.makeModifiedWcs(pixelTransform=radialTransform, wcs=self.tanWcs,
                                   modifyActualPixels=False)
     with self.assertRaises(UserWarning):
         approximateWcs(wcs=wcs, bbox=self.bbox, order=2)
コード例 #3
0
ファイル: test_wcsUtils.py プロジェクト: HyperSuprime-Cam/afw
    def testDistortion(self):
        """Test computePixelToDistortedPixel with distortion

        pixelToDistortedPixel -> self.tanWcs should match a WCS
        created with makeDistortedTanWcs
        """
        focalPlaneToFieldAngle = afwGeom.makeRadialTransform([0.0, self.radPerMm, 0.0, self.radPerMm])
        pixelToDistortedPixel = computePixelToDistortedPixel(
            pixelToFocalPlane=self.pixelToFocalPlane,
            focalPlaneToFieldAngle=focalPlaneToFieldAngle,
        )
        # Do not try to make pixelToDistortedPixel -> self.tanWcs into a WCS
        # because the frame names will be wrong; use a TransformPoint2Tolsst.geom.SpherePoint instead
        tanWcsTransform = afwGeom.TransformPoint2ToSpherePoint(self.tanWcs.getFrameDict())
        pixelToDistortedSky = pixelToDistortedPixel.then(tanWcsTransform)

        wcs = makeDistortedTanWcs(
            tanWcs=self.tanWcs,
            pixelToFocalPlane=self.pixelToFocalPlane,
            focalPlaneToFieldAngle=focalPlaneToFieldAngle,
        )

        bboxD = lsst.geom.Box2D(self.bbox)
        pixelPoints = bboxD.getCorners()
        pixelPoints.append(bboxD.getCenter())

        skyPoints1 = pixelToDistortedSky.applyForward(pixelPoints)
        skyPoints2 = wcs.pixelToSky(pixelPoints)
        self.assertSpherePointListsAlmostEqual(skyPoints1, skyPoints2)

        pixelPoints1 = pixelToDistortedSky.applyInverse(skyPoints1)
        pixelPoints2 = wcs.skyToPixel(skyPoints1)
        assert_allclose(pixelPoints1, pixelPoints2)
コード例 #4
0
 def testRadial(self):
     """Add a radial transform"""
     for order in (4, 5, 6):
         self.doTest("testRadial",
                     afwGeom.makeRadialTransform([0, 1.001, 0.000003]),
                     order=order,
                     doPlot=False)
コード例 #5
0
    def testDistortion(self):
        """Test computePixelToDistortedPixel with distortion

        pixelToDistortedPixel -> self.tanWcs should match a WCS
        created with makeDistortedTanWcs
        """
        focalPlaneToFieldAngle = afwGeom.makeRadialTransform(
            [0.0, self.radPerMm, 0.0, self.radPerMm])
        pixelToDistortedPixel = computePixelToDistortedPixel(
            pixelToFocalPlane=self.pixelToFocalPlane,
            focalPlaneToFieldAngle=focalPlaneToFieldAngle,
        )
        # Do not try to make pixelToDistortedPixel -> self.tanWcs into a WCS
        # because the frame names will be wrong; use a TransformPoint2Tolsst.geom.SpherePoint instead
        tanWcsTransform = afwGeom.TransformPoint2ToSpherePoint(
            self.tanWcs.getFrameDict())
        pixelToDistortedSky = pixelToDistortedPixel.then(tanWcsTransform)

        wcs = makeDistortedTanWcs(
            tanWcs=self.tanWcs,
            pixelToFocalPlane=self.pixelToFocalPlane,
            focalPlaneToFieldAngle=focalPlaneToFieldAngle,
        )

        bboxD = lsst.geom.Box2D(self.bbox)
        pixelPoints = bboxD.getCorners()
        pixelPoints.append(bboxD.getCenter())

        skyPoints1 = pixelToDistortedSky.applyForward(pixelPoints)
        skyPoints2 = wcs.pixelToSky(pixelPoints)
        self.assertSpherePointListsAlmostEqual(skyPoints1, skyPoints2)

        pixelPoints1 = pixelToDistortedSky.applyInverse(skyPoints1)
        pixelPoints2 = wcs.skyToPixel(skyPoints1)
        assert_allclose(pixelPoints1, pixelPoints2)
コード例 #6
0
ファイル: testUtils.py プロジェクト: provingground-moe/cbp
    def makeCameraGeom(self):
        """Make a camera geometry.

        Returns
        -------
        cameraGeom : `lsst.afw.cameraGeom.Camera`
            Camera geometry.

        Notes
        -----
        There is one field per entry in self.detectorFracPosList
        with specifications set by self.detectorWidthPix,
        self.detectorHeightPix, and self.pixelSizeMm.

        The plate scale is set by self.plateScale
        and the amount of optical distortion is fixed.

        All detectors have the same shape (unlike LSST) and orientation
        (unlike HSC). Varying these is not necessary for testing the CBP
        and having all detectors the same simplifies the code.
        """
        radialCoeff = np.array([0.0, 1.0, 0.0, 0.925
                                ]) / self.plateScale.asRadians()
        fieldAngleToFocalPlane = makeRadialTransform(radialCoeff)
        focalPlaneToFieldAngle = fieldAngleToFocalPlane.inverted()
        cameraTransformMap = cameraGeom.TransformMap(
            cameraGeom.FOCAL_PLANE,
            {cameraGeom.FIELD_ANGLE: focalPlaneToFieldAngle})
        detectorList = self._makeDetectorList(focalPlaneToFieldAngle)
        return cameraGeom.Camera("test", detectorList, cameraTransformMap)
コード例 #7
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)
コード例 #8
0
    def testBadRadial(self):
        """Test radial with invalid coefficients
        """
        for badCoeffs in (
            (0.0,),     # len(coeffs) must be > 1
            (0.1, 1.0),  # coeffs[0] must be zero
            (0.0, 0.0),  # coeffs[1] must be nonzero
            (0.0, 0.0, 0.1),  # coeffs[1] must be nonzero
        ):
            with self.assertRaises(pexExcept.InvalidParameterError):
                afwGeom.makeRadialTransform(badCoeffs)

            radialFactory = afwGeom.transformRegistry["radial"]
            radialConfig = radialFactory.ConfigClass()
            radialConfig.coeffs = badCoeffs
            with self.assertRaises(Exception):
                radialConfig.validate()
コード例 #9
0
 def testWarnings(self):
     """Test that approximateWcs raises a UserWarning when it cannot achieve desired tolerance"""
     radialTransform = afwGeom.makeRadialTransform([0, 2.0, 3.0])
     wcs = afwGeom.makeModifiedWcs(pixelTransform=radialTransform,
                                   wcs=self.tanWcs,
                                   modifyActualPixels=False)
     with self.assertRaises(UserWarning):
         approximateWcs(wcs=wcs, bbox=self.bbox, order=2)
コード例 #10
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)
コード例 #11
0
    def testRadial(self):
        """Add radial distortion"""
        radialTransform = afwGeom.makeRadialTransform([0, 1.02, 1e-6])

        def radialDistortion(x, y):
            x, y = radialTransform.applyForward(lsst.geom.Point2D(x, y))
            return (x, y)
        self.doTest("testRadial", radialDistortion)
コード例 #12
0
    def testBadRadial(self):
        """Test radial with invalid coefficients
        """
        for badCoeffs in (
            (0.0, ),  # len(coeffs) must be > 1
            (0.1, 1.0),  # coeffs[0] must be zero
            (0.0, 0.0),  # coeffs[1] must be nonzero
            (0.0, 0.0, 0.1),  # coeffs[1] must be nonzero
        ):
            with self.assertRaises(pexExcept.InvalidParameterError):
                afwGeom.makeRadialTransform(badCoeffs)

            radialFactory = afwGeom.transformRegistry["radial"]
            radialConfig = radialFactory.ConfigClass()
            radialConfig.coeffs = badCoeffs
            with self.assertRaises(Exception):
                radialConfig.validate()
コード例 #13
0
ファイル: yamlCamera.py プロジェクト: gcmshadow/obs_base
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
コード例 #14
0
    def testRadial(self):
        """Add radial distortion"""
        radialTransform = afwGeom.makeRadialTransform([0, 1.02, 1e-6])

        def radialDistortion(x, y):
            x, y = radialTransform.applyForward(afwGeom.Point2D(x, y))
            return (x, y)

        self.doTest("testRadial", radialDistortion)
コード例 #15
0
 def _makeRadialTransform(self, radialCoeffs):
     """Helper function to get the radial transform given the radial polynomial coefficients given in
        the constructor.
        @param[in]  radialCoeffs  List of coefficients describing a polynomial radial distortion in
                                  normalized units.
        @return     Transform object describing the radial distortion
     """
     pScaleRad = afwGeom.arcsecToRad(self.plateScale)
     return afwGeom.makeRadialTransform(
         [el / pScaleRad for el in radialCoeffs])
コード例 #16
0
    def testRadial(self):
        """Add radial distortion"""
        radialTransform = afwGeom.makeRadialTransform([0, 1.01, 1e-8])

        def radialDistortion(x, y):
            x, y = radialTransform.applyForward(afwGeom.Point2D(x, y))
            return (x, y)
        for order in (4, 5, 6):
            doPrint = order == 5
            self.doTest("testRadial", radialDistortion, order=order, doPrint=doPrint)
コード例 #17
0
    def testRadial(self):
        """Add radial distortion"""
        radialTransform = afwGeom.makeRadialTransform([0, 1.01, 1e-8])

        def radialDistortion(x, y):
            x, y = radialTransform.applyForward(lsst.geom.Point2D(x, y))
            return (x, y)
        for order in (4, 5, 6):
            doPrint = order == 5
            self.doTest("testRadial", radialDistortion, order=order, doPrint=doPrint)
コード例 #18
0
    def testDistortion(self):
        """Test makeDistortedTanWcs using a non-affine transform for pixelToFocalPlane
        """
        # Compute a distorted wcs that matches self.tanWcs at the center of the field;
        # the amount of distortion is 10s of pixels over the detector
        fieldAngleToFocalPlane = afwGeom.makeRadialTransform(
            [0.0, 1 / self.radPerMm, 0.0, 1000 / self.radPerMm])
        focalPlaneToFieldAngle = fieldAngleToFocalPlane.inverted()
        focalPlaneToTanFieldAngle = self.makeAffineTransform(
            scale=self.radPerMm)
        wcs = makeDistortedTanWcs(
            tanWcs=self.tanWcs,
            pixelToFocalPlane=self.pixelToFocalPlane,
            focalPlaneToFieldAngle=focalPlaneToFieldAngle,
        )

        # At the center of the focal plane both WCS should give the same sky position
        pixelAtCtr = self.pixelToFocalPlane.applyInverse(
            lsst.geom.Point2D(0, 0))
        tanSkyAtCtr = self.tanWcs.pixelToSky(pixelAtCtr)
        skyAtCtr = wcs.pixelToSky(pixelAtCtr)
        self.assertPairsAlmostEqual(tanSkyAtCtr, skyAtCtr)

        # At all reasonable sky points the following field angles should be almost equal:
        #   sky -> tanWcs.skyToPixel -> pixelToFocalPlane -> focalPlaneToTanFieldAngle
        #   sky -> wcs.skyToPixel -> pixelToFocalPlane -> focalPlaneToFieldAngle
        # where focalPlaneToTanFieldAngle is the linear approximation to
        # focalPlaneToFieldAngle at the center of the field (where tanWcs and wcs match),
        # since for a given pointing, field angle gives position on the sky
        skyPoints = self.tanWcs.pixelToSky(self.pixelPoints)

        tanFieldAnglePoints = focalPlaneToTanFieldAngle.applyForward(
            self.pixelToFocalPlane.applyForward(
                self.tanWcs.skyToPixel(skyPoints)))
        fieldAnglePoints = focalPlaneToFieldAngle.applyForward(
            self.pixelToFocalPlane.applyForward(wcs.skyToPixel(skyPoints)))
        assert_allclose(tanFieldAnglePoints, fieldAnglePoints)

        # The inverse should also be true: for a set of field angle points
        # the following sky positions should be almost equal:
        # fieldAngle -> fieldAngleToTanFocalPlane -> focalPlaneToPixel -> tanWcs.pixelToSky
        # fieldAngle -> fieldAngleToFocalPlane -> focalPlaneToPixel -> wcs.pixelToSky
        focalPlaneToPixel = self.pixelToFocalPlane.inverted()
        fieldAngleToTanFocalPlane = focalPlaneToTanFieldAngle.inverted()
        tanSkyPoints2 = self.tanWcs.pixelToSky(
            focalPlaneToPixel.applyForward(
                fieldAngleToTanFocalPlane.applyForward(fieldAnglePoints)))

        skyPoints2 = wcs.pixelToSky(
            focalPlaneToPixel.applyForward(
                fieldAngleToFocalPlane.applyForward(fieldAnglePoints)))

        self.assertSpherePointListsAlmostEqual(tanSkyPoints2, skyPoints2)
コード例 #19
0
ファイル: test_wcsUtils.py プロジェクト: HyperSuprime-Cam/afw
    def testDistortion(self):
        """Test makeDistortedTanWcs using a non-affine transform for pixelToFocalPlane
        """
        # Compute a distorted wcs that matches self.tanWcs at the center of the field;
        # the amount of distortion is 10s of pixels over the detector
        fieldAngleToFocalPlane = afwGeom.makeRadialTransform([0.0, 1/self.radPerMm, 0.0, 1000/self.radPerMm])
        focalPlaneToFieldAngle = fieldAngleToFocalPlane.inverted()
        focalPlaneToTanFieldAngle = self.makeAffineTransform(scale=self.radPerMm)
        wcs = makeDistortedTanWcs(
            tanWcs=self.tanWcs,
            pixelToFocalPlane=self.pixelToFocalPlane,
            focalPlaneToFieldAngle=focalPlaneToFieldAngle,
        )

        # At the center of the focal plane both WCS should give the same sky position
        pixelAtCtr = self.pixelToFocalPlane.applyInverse(lsst.geom.Point2D(0, 0))
        tanSkyAtCtr = self.tanWcs.pixelToSky(pixelAtCtr)
        skyAtCtr = wcs.pixelToSky(pixelAtCtr)
        self.assertPairsAlmostEqual(tanSkyAtCtr, skyAtCtr)

        # At all reasonable sky points the following field angles should be almost equal:
        #   sky -> tanWcs.skyToPixel -> pixelToFocalPlane -> focalPlaneToTanFieldAngle
        #   sky -> wcs.skyToPixel -> pixelToFocalPlane -> focalPlaneToFieldAngle
        # where focalPlaneToTanFieldAngle is the linear approximation to
        # focalPlaneToFieldAngle at the center of the field (where tanWcs and wcs match),
        # since for a given pointing, field angle gives position on the sky
        skyPoints = self.tanWcs.pixelToSky(self.pixelPoints)

        tanFieldAnglePoints = focalPlaneToTanFieldAngle.applyForward(
            self.pixelToFocalPlane.applyForward(self.tanWcs.skyToPixel(skyPoints)))
        fieldAnglePoints = focalPlaneToFieldAngle.applyForward(
            self.pixelToFocalPlane.applyForward(wcs.skyToPixel(skyPoints)))
        assert_allclose(tanFieldAnglePoints, fieldAnglePoints)

        # The inverse should also be true: for a set of field angle points
        # the following sky positions should be almost equal:
        # fieldAngle -> fieldAngleToTanFocalPlane -> focalPlaneToPixel -> tanWcs.pixelToSky
        # fieldAngle -> fieldAngleToFocalPlane -> focalPlaneToPixel -> wcs.pixelToSky
        focalPlaneToPixel = self.pixelToFocalPlane.inverted()
        fieldAngleToTanFocalPlane = focalPlaneToTanFieldAngle.inverted()
        tanSkyPoints2 = self.tanWcs.pixelToSky(
            focalPlaneToPixel.applyForward(
                fieldAngleToTanFocalPlane.applyForward(fieldAnglePoints)))

        skyPoints2 = wcs.pixelToSky(
            focalPlaneToPixel.applyForward(
                fieldAngleToFocalPlane.applyForward(fieldAnglePoints)))

        self.assertSpherePointListsAlmostEqual(tanSkyPoints2, skyPoints2)
コード例 #20
0
 def __init__(self):
     plateScale = afwGeom.Angle(20, afwGeom.arcseconds)  # plate scale, in angle on sky/mm
     # Radial distortion is modeled as a radial polynomial that converts from focal plane (in mm)
     # to field angle (in radians). Thus the coefficients are:
     # C0: always 0, for continuity at the center of the focal plane; units are rad
     # C1: 1/plateScale; units are rad/mm
     # C2: usually 0; units are rad/mm^2
     # C3: radial distortion; units are rad/mm^3
     radialCoeff = np.array([0.0, 1.0, 0.0, 0.925]) / plateScale.asRadians()
     fieldAngleToFocalPlane = afwGeom.makeRadialTransform(radialCoeff)
     focalPlaneToFieldAngle = fieldAngleToFocalPlane.inverted()
     cameraTransformMap = cameraGeom.TransformMap(cameraGeom.FOCAL_PLANE,
                                                  {cameraGeom.FIELD_ANGLE: focalPlaneToFieldAngle})
     detectorList = self._makeDetectorList(focalPlaneToFieldAngle)
     cameraGeom.Camera.__init__(self, "test", detectorList, cameraTransformMap)
コード例 #21
0
    def testLargeDistortion(self):
        # This transform is about as extreme as I can get:
        # using 0.0005 in the last value appears to produce numerical issues.
        # It produces a maximum deviation of 459 pixels, which should be sufficient.
        pixelsToTanPixels = afwGeom.makeRadialTransform([0.0, 1.1, 0.0004])
        self.distortedWcs = afwGeom.makeModifiedWcs(pixelTransform=pixelsToTanPixels,
                                                    wcs=self.wcs,
                                                    modifyActualPixels=False)

        def applyDistortion(src):
            out = src.table.copyRecord(src)
            out.set(out.table.getCentroidKey(),
                    pixelsToTanPixels.applyInverse(src.getCentroid()))
            return out

        self.singleTestInstance(self.filename, applyDistortion)
コード例 #22
0
ファイル: testCamera.py プロジェクト: lsst/obs_test
    def __new__(cls):
        plateScale = geom.Angle(20, geom.arcseconds)  # plate scale, in angle on sky/mm
        # Radial distortion is modeled as a radial polynomial that converts from focal plane (in mm)
        # to field angle (in radians). Thus the coefficients are:
        # C0: always 0, for continuity at the center of the focal plane; units are rad
        # C1: 1/plateScale; units are rad/mm
        # C2: usually 0; units are rad/mm^2
        # C3: radial distortion; units are rad/mm^3
        radialCoeff = np.array([0.0, 1.0, 0.0, 0.925]) / plateScale.asRadians()
        fieldAngleToFocalPlane = afwGeom.makeRadialTransform(radialCoeff)
        focalPlaneToFieldAngle = fieldAngleToFocalPlane.inverted()

        camera = cameraGeom.Camera.Builder("test")
        cls._makeDetectors(camera, focalPlaneToFieldAngle)
        camera.setTransformFromFocalPlaneTo(cameraGeom.FIELD_ANGLE, focalPlaneToFieldAngle)
        return camera.finish()
コード例 #23
0
    def testLargeDistortion(self):
        # This transform is about as extreme as I can get:
        # using 0.0005 in the last value appears to produce numerical issues.
        # It produces a maximum deviation of 459 pixels, which should be sufficient.
        pixelsToTanPixels = afwGeom.makeRadialTransform([0.0, 1.1, 0.0004])
        self.distortedWcs = afwGeom.makeModifiedWcs(pixelTransform=pixelsToTanPixels,
                                                    wcs=self.wcs,
                                                    modifyActualPixels=False)

        def applyDistortion(src):
            out = src.table.copyRecord(src)
            out.set(out.table.getCentroidKey(),
                    pixelsToTanPixels.applyInverse(src.getCentroid()))
            return out

        self.singleTestInstance(self.filename, applyDistortion)
コード例 #24
0
 def __init__(self):
     """Construct a TestCamera
     """
     plateScale = afwGeom.Angle(
         13.55, afwGeom.arcseconds)  # plate scale, in angle on sky/mm
     radialDistortion = 0.  # radial distortion in mm/rad^2
     radialCoeff = numpy.array(
         (0.0, 1.0, 0.0, radialDistortion)) / plateScale.asRadians()
     focalPlaneToFieldAngle = afwGeom.makeRadialTransform(radialCoeff)
     fieldAngleToFocalPlane = focalPlaneToFieldAngle.inverted()
     cameraTransformMap = cameraGeom.TransformMap(
         cameraGeom.FOCAL_PLANE,
         {cameraGeom.FIELD_ANGLE: fieldAngleToFocalPlane})
     detectorList = self._makeDetectorList(fieldAngleToFocalPlane,
                                           plateScale)
     cameraGeom.Camera.__init__(self, "monocam", detectorList,
                                cameraTransformMap)
コード例 #25
0
    def testRadial(self):
        """Test radial = radial Transform
        """
        radialFactory = afwGeom.transformRegistry["radial"]
        radialConfig = radialFactory.ConfigClass()
        radialConfig.coeffs = (0.0, 8.5165e-05, 0.0, -4.5014e-12)

        def check(transform):
            self.checkRadial(transform, radialConfig.coeffs)
        self.checkGenericTransform(radialFactory, radialConfig, check)

        invertibleCoeffs = (0.0, 1.0, 0.05)
        inverseCoeffs = (0.0, 1.0, -0.05, 0.005, -0.000625, 0.0000875,
                         -1.3125e-5, 2.0625e-6, -3.3515625e-7, 5.5859375e-8,
                         -9.49609375e-9, 1.640234375e-9, -2.870410156e-10)
        transform = afwGeom.makeRadialTransform(invertibleCoeffs,
                                                inverseCoeffs)
        self.checkRadialInvertible(transform, invertibleCoeffs)
コード例 #26
0
    def testRadial(self):
        """Test radial = radial Transform
        """
        radialFactory = afwGeom.transformRegistry["radial"]
        radialConfig = radialFactory.ConfigClass()
        radialConfig.coeffs = (0.0, 8.5165e-05, 0.0, -4.5014e-12)

        def check(transform):
            self.checkRadial(transform, radialConfig.coeffs)
        self.checkGenericTransform(radialFactory, radialConfig, check)

        invertibleCoeffs = (0.0, 1.0, 0.05)
        inverseCoeffs = (0.0, 1.0, -0.05, 0.005, -0.000625, 0.0000875,
                         -1.3125e-5, 2.0625e-6, -3.3515625e-7, 5.5859375e-8,
                         -9.49609375e-9, 1.640234375e-9, -2.870410156e-10)
        transform = afwGeom.makeRadialTransform(invertibleCoeffs,
                                                inverseCoeffs)
        self.checkRadialInvertible(transform, invertibleCoeffs)
コード例 #27
0
ファイル: test_skyWcs.py プロジェクト: batmanuel-sandbox/afw
    def testMakeModifiedWcsNoActualPixels(self):
        """Test makeModifiedWcs on a SkyWcs that has no ACTUAL_PIXELS frame
        """
        cdMatrix = makeCdMatrix(scale=self.scale)
        originalWcs = makeSkyWcs(crpix=self.crpix,
                                 crval=self.crvalList[0],
                                 cdMatrix=cdMatrix)
        originalFrameDict = originalWcs.getFrameDict()

        # make an arbitrary but reasonable transform to insert using makeModifiedWcs
        pixelTransform = makeRadialTransform([0.0, 1.0, 0.0, 0.0011])
        # the result of the insertion should be as follows
        desiredPixelsToSky = pixelTransform.then(originalWcs.getTransform())

        pixPointList = (  # arbitrary but reasonable
            Point2D(0.0, 0.0),
            Point2D(1000.0, 0.0),
            Point2D(0.0, 2000.0),
            Point2D(-1111.0, -2222.0),
        )
        for modifyActualPixels in (False, True):
            modifiedWcs = makeModifiedWcs(
                pixelTransform=pixelTransform,
                wcs=originalWcs,
                modifyActualPixels=modifyActualPixels)
            modifiedFrameDict = modifiedWcs.getFrameDict()
            skyList = modifiedWcs.pixelToSky(pixPointList)

            # compare pixels to sky
            desiredSkyList = desiredPixelsToSky.applyForward(pixPointList)
            self.assertSpherePointListsAlmostEqual(skyList, desiredSkyList)

            # compare pixels to IWC
            pixelsToIwc = TransformPoint2ToPoint2(
                modifiedFrameDict.getMapping("PIXELS", "IWC"))
            desiredPixelsToIwc = TransformPoint2ToPoint2(
                pixelTransform.getMapping().then(
                    originalFrameDict.getMapping("PIXELS", "IWC")))
            self.assertPairListsAlmostEqual(
                pixelsToIwc.applyForward(pixPointList),
                desiredPixelsToIwc.applyForward(pixPointList))

            self.checkNonFitsWcs(modifiedWcs)
コード例 #28
0
 def __init__(self):
     """Construct a TestCamera
     """
     plateScale = afwGeom.Angle(
         20, afwGeom.arcseconds)  # plate scale, in angle on sky/mm
     # Radial distortion is modeled as a radial polynomial that converts from focal plane (in mm)
     # to field angle (in radians). Thus the coefficients are:
     # C0: always 0, for continuity at the center of the focal plane; units are rad
     # C1: 1/plateScale; units are rad/mm
     # C2: usually 0; units are rad/mm^2
     # C3: radial distortion; units are rad/mm^3
     radialCoeff = np.array([0.0, 1.0, 0.0, 0.925]) / plateScale.asRadians()
     fieldAngleToFocalPlane = afwGeom.makeRadialTransform(radialCoeff)
     focalPlaneToFieldAngle = fieldAngleToFocalPlane.getInverse()
     cameraTransformMap = cameraGeom.TransformMap(
         cameraGeom.FOCAL_PLANE,
         {cameraGeom.FIELD_ANGLE: focalPlaneToFieldAngle})
     detectorList = self._makeDetectorList(focalPlaneToFieldAngle)
     cameraGeom.Camera.__init__(self, "test", detectorList,
                                cameraTransformMap)
コード例 #29
0
    def __init__(self, cameraYamlFile):
        with open(cameraYamlFile) as fd:
            cameraParams = yaml.load(fd, Loader=yaml.Loader)

        plateScale = afwGeom.Angle(cameraParams["plateScale"],
                                   afwGeom.arcseconds)
        # radial coefficients of the form [0, no units, 1/rad but usually 0, 1/rad^2, ...]
        # Radial distortion is modeled as a radial polynomial that converts from focal plane radius (in mm)
        # to field angle (in radians). The coefficients are divided by the plate scale (in mm/radians)
        # meaning that C1 is always 1.
        radialCoeffs = np.array(
            cameraParams["radialCoeffs"]) / plateScale.asRadians()
        fieldAngleToFocalPlane = afwGeom.makeRadialTransform(radialCoeffs)
        focalPlaneToFieldAngle = fieldAngleToFocalPlane.getInverse()
        cameraTransformMap = cameraGeom.TransformMap(
            cameraGeom.FOCAL_PLANE,
            {cameraGeom.FIELD_ANGLE: focalPlaneToFieldAngle})
        detectorList = self._makeDetectorList(cameraParams["CCDs"],
                                              focalPlaneToFieldAngle)
        cameraGeom.Camera.__init__(self, cameraParams["name"], detectorList,
                                   cameraTransformMap)
コード例 #30
0
    def makeCameraGeom(self):
        """Make a camera geometry.

        Returns
        -------
        cameraGeom : `lsst.afw.cameraGeom.Camera`
            Camera geometry.

        Notes
        -----
        There is one field per entry in self.detectorFracPosList
        with specifications set by self.detectorWidthPix,
        self.detectorHeightPix, and self.pixelSizeMm.

        The plate scale is set by self.plateScale
        and the amount of optical distortion is fixed.

        All detectors have the same shape (unlike LSST) and orientation
        (unlike HSC). Varying these is not necessary for testing the CBP
        and having all detectors the same simplifies the code.
        """
        radialCoeff = np.array([0.0, 1.0, 0.0, 0.925
                                ]) / self.plateScale.asRadians()
        fieldAngleToFocalPlane = makeRadialTransform(radialCoeff)
        focalPlaneToFieldAngle = fieldAngleToFocalPlane.inverted()

        cameraBuilder = Camera.Builder("testCamera")
        cameraBuilder.setTransformFromFocalPlaneTo(FIELD_ANGLE,
                                                   focalPlaneToFieldAngle)
        ampBuilder = self._makeAmpBuilder()

        for i, fpPos in enumerate(self.detectorFracPosList):
            detectorConfig = self._makeDetectorConfig(id=i, fpPos=fpPos)
            addDetectorBuilderFromConfig(cameraBuilder, detectorConfig,
                                         [ampBuilder], focalPlaneToFieldAngle)

        return cameraBuilder.finish()
コード例 #31
0
    def testFlatFocalPlane(self):
        """Test an undistorted focal plane (with rectangular pixels)
        """
        bbox = afwGeom.Box2I(afwGeom.Point2I(0, 0),
                             afwGeom.Extent2I(1000, 1000))
        pixelSizeMm = afwGeom.Extent2D(0.02, 0.03)
        plateScale = 25.0  # arcsec/mm
        yaw = afwGeom.Angle(20, afwGeom.degrees)
        # focal-plane position of ref position on detector (mm)
        fpPosition = afwGeom.Point2D(50, 25)
        # ref position on detector (pos of lower left corner)
        refPoint = afwGeom.Point2D(-0.5, -0.5)
        orientation = cameraGeom.Orientation(
            fpPosition,
            refPoint,
            yaw,
        )
        plateScaleRad = afwGeom.Angle(plateScale,
                                      afwGeom.arcseconds).asRadians()
        focalPlaneToField = afwGeom.makeRadialTransform((0.0, plateScaleRad))

        pixelToTanPixel = makePixelToTanPixel(
            bbox=bbox,
            orientation=orientation,
            focalPlaneToField=focalPlaneToField,
            pixelSizeMm=pixelSizeMm,
        )

        # with no distortion, this should be a unity transform
        for pointPix in (
                afwGeom.Point2D(0, 0),
                afwGeom.Point2D(1000, 2000),
                afwGeom.Point2D(-100.5, 27.23),
        ):
            pointTanPix = pixelToTanPixel.applyForward(pointPix)
            self.assertPairsAlmostEqual(pointTanPix, pointPix)
コード例 #32
0
    def testRadial(self):
        """Test fit with radial distortion

        The offset comes from the fact that the CCD is not centered
        """
        self.doTest(afwGeom.makeRadialTransform([0, 1.01, 1e-7]))
コード例 #33
0
 def setUp(self):
     self.nativeSys = cameraGeom.FOCAL_PLANE
     self.fieldTransform = afwGeom.makeRadialTransform([0, 0.5, 0.005])
     transforms = {cameraGeom.FIELD_ANGLE: self.fieldTransform}
     self.transformMap = cameraGeom.TransformMap(self.nativeSys, transforms)
コード例 #34
0
 def setUp(self):
     self.nativeSys = cameraGeom.FOCAL_PLANE
     self.fieldTransform = afwGeom.makeRadialTransform([0, 0.5, 0.005])
     transforms = {cameraGeom.FIELD_ANGLE: self.fieldTransform}
     self.transformMap = cameraGeom.TransformMap(
         self.nativeSys, transforms)
コード例 #35
0
    def __init__(
        self,
        name="detector 1",
        id=1,
        detType=SCIENCE,
        serial="xkcd722",
        bbox=None,  # do not use mutable objects as defaults
        numAmps=3,
        pixelSize=(0.02, 0.02),
        ampExtent=(5, 6),
        orientation=Orientation(),
        plateScale=20.0,
        radialDistortion=0.925,
        crosstalk=None,
        modFunc=None,
        physicalType="CCD",
    ):
        # note that (0., 0.) for the reference position is the center of the
        # first pixel
        self.name = name
        self.id = int(id)
        self.type = detType
        self.serial = serial
        if bbox is None:
            bbox = lsst.geom.Box2I(lsst.geom.Point2I(0, 0),
                                   lsst.geom.Extent2I(1024, 1048))
        self.bbox = bbox
        self.pixelSize = lsst.geom.Extent2D(*pixelSize)
        self.ampExtent = lsst.geom.Extent2I(*ampExtent)
        self.plateScale = float(plateScale)
        self.radialDistortion = float(radialDistortion)
        schema = afwTable.AmpInfoTable.makeMinimalSchema()
        self.ampInfo = afwTable.AmpInfoCatalog(schema)
        for i in range(numAmps):
            record = self.ampInfo.addNew()
            ampName = "amp %d" % (i + 1, )
            record.setName(ampName)
            record.setBBox(
                lsst.geom.Box2I(lsst.geom.Point2I(-1, 1), self.ampExtent))
            record.setGain(1.71234e3)
            record.setReadNoise(0.521237e2)
            record.setReadoutCorner(afwTable.LL)
            record.setHasRawInfo(False)
        self.orientation = orientation

        # compute TAN_PIXELS transform
        pScaleRad = lsst.geom.arcsecToRad(self.plateScale)
        radialDistortCoeffs = [
            0.0, 1.0 / pScaleRad, 0.0, self.radialDistortion / pScaleRad
        ]
        focalPlaneToField = afwGeom.makeRadialTransform(radialDistortCoeffs)
        pixelToTanPixel = makePixelToTanPixel(
            bbox=self.bbox,
            orientation=self.orientation,
            focalPlaneToField=focalPlaneToField,
            pixelSizeMm=self.pixelSize,
        )

        self.transMap = {
            FOCAL_PLANE:
            self.orientation.makePixelFpTransform(self.pixelSize),
            CameraSys(TAN_PIXELS, self.name):
            pixelToTanPixel,
            CameraSys(ACTUAL_PIXELS, self.name):
            afwGeom.makeRadialTransform([0, 0.95, 0.01]),
        }
        if crosstalk is None:
            crosstalk = [[0.0 for _ in range(numAmps)] for _ in range(numAmps)]
        self.crosstalk = crosstalk
        self.physicalType = physicalType
        if modFunc:
            modFunc(self)
        self.detector = Detector(
            self.name,
            self.id,
            self.type,
            self.serial,
            self.bbox,
            self.ampInfo,
            self.orientation,
            self.pixelSize,
            self.transMap,
            np.array(self.crosstalk, dtype=np.float32),
            self.physicalType,
        )
コード例 #36
0
ファイル: testUtils.py プロジェクト: jchiang87/afw
    def __init__(
        self,
        name="detector 1",
        id=1,
        detType=SCIENCE,
        serial="xkcd722",
        bbox=None,  # do not use mutable objects as defaults
        numAmps=3,
        pixelSize=(0.02, 0.02),
        ampExtent=(5, 6),
        orientation=Orientation(),
        plateScale=20.0,
        radialDistortion=0.925,
        crosstalk=None,
        modFunc=None,
    ):
        """!Construct a DetectorWrapper

        @param[in] name  detector name
        @param[in] id  detector ID (int)
        @param[in] detType  detector type (an lsst.afw.cameraGeom.DetectorType)
        @param[in] serial  serial "number" (a string)
        @param[in] bbox  bounding box; defaults to (0, 0), (1024x1024) (an lsst.geom.Box2I)
        @param[in] numAmps  number of amplifiers (int)
        @param[in] pixelSize  pixel size (mm) (an lsst.geom.Point2D)
        @param[in] ampExtent  dimensions of amplifier image bbox (an lsst.geom.Extent2I)
        @param[in] orientation  orientation of CCC in focal plane (lsst.afw.cameraGeom.Orientation)
        @param[in] plateScale  plate scale in arcsec/mm; 20.0 is for LSST
        @param[in] radialDistortion  radial distortion, in mm/rad^2
            (the r^3 coefficient of the radial distortion polynomial
            that converts FIELD_ANGLE in radians to FOCAL_PLANE in mm);
            0.925 is the value Dave Monet measured for lsstSim data
        @param[in] crosstalk  crosstalk coefficient matrix
        @param[in] modFunc  a function that can modify attributes just before constructing the detector;
            modFunc receives one argument: a DetectorWrapper with all attributes except detector set.
        """
        # note that (0., 0.) for the reference position is the center of the
        # first pixel
        self.name = name
        self.id = int(id)
        self.type = detType
        self.serial = serial
        if bbox is None:
            bbox = lsst.geom.Box2I(lsst.geom.Point2I(0, 0),
                                   lsst.geom.Extent2I(1024, 1048))
        self.bbox = bbox
        self.pixelSize = lsst.geom.Extent2D(*pixelSize)
        self.ampExtent = lsst.geom.Extent2I(*ampExtent)
        self.plateScale = float(plateScale)
        self.radialDistortion = float(radialDistortion)
        schema = afwTable.AmpInfoTable.makeMinimalSchema()
        self.ampInfo = afwTable.AmpInfoCatalog(schema)
        for i in range(numAmps):
            record = self.ampInfo.addNew()
            ampName = "amp %d" % (i + 1, )
            record.setName(ampName)
            record.setBBox(
                lsst.geom.Box2I(lsst.geom.Point2I(-1, 1), self.ampExtent))
            record.setGain(1.71234e3)
            record.setReadNoise(0.521237e2)
            record.setReadoutCorner(afwTable.LL)
            record.setHasRawInfo(False)
        self.orientation = orientation

        # compute TAN_PIXELS transform
        pScaleRad = lsst.geom.arcsecToRad(self.plateScale)
        radialDistortCoeffs = [
            0.0, 1.0 / pScaleRad, 0.0, self.radialDistortion / pScaleRad
        ]
        focalPlaneToField = afwGeom.makeRadialTransform(radialDistortCoeffs)
        pixelToTanPixel = makePixelToTanPixel(
            bbox=self.bbox,
            orientation=self.orientation,
            focalPlaneToField=focalPlaneToField,
            pixelSizeMm=self.pixelSize,
        )

        self.transMap = {
            FOCAL_PLANE:
            self.orientation.makePixelFpTransform(self.pixelSize),
            CameraSys(TAN_PIXELS, self.name):
            pixelToTanPixel,
            CameraSys(ACTUAL_PIXELS, self.name):
            afwGeom.makeRadialTransform([0, 0.95, 0.01]),
        }
        if crosstalk is None:
            crosstalk = [[0.0 for _ in range(numAmps)] for _ in range(numAmps)]
        self.crosstalk = crosstalk
        if modFunc:
            modFunc(self)
        self.detector = Detector(
            self.name,
            self.id,
            self.type,
            self.serial,
            self.bbox,
            self.ampInfo,
            self.orientation,
            self.pixelSize,
            self.transMap,
            np.array(self.crosstalk, dtype=np.float32),
        )
コード例 #37
0
ファイル: test_skyWcs.py プロジェクト: batmanuel-sandbox/afw
    def testMakeModifiedWcsWithActualPixels(self):
        """Test makeModifiedWcs on a SkyWcs that has an ACTUAL_PIXELS frame
        """
        cdMatrix = makeCdMatrix(scale=self.scale)
        baseWcs = makeSkyWcs(crpix=self.crpix,
                             crval=self.crvalList[0],
                             cdMatrix=cdMatrix)
        # model actual pixels to pixels as an arbitrary zoom factor;
        # this is not realistic, but is fine for a unit test
        actualPixelsToPixels = TransformPoint2ToPoint2(ast.ZoomMap(2, 0.72))
        originalWcs = addActualPixelsFrame(baseWcs, actualPixelsToPixels)
        originalFrameDict = originalWcs.getFrameDict()

        # make an arbitrary but reasonable transform to insert using makeModifiedWcs
        pixelTransform = makeRadialTransform([0.0, 1.0, 0.0, 0.0011
                                              ])  # arbitrary but reasonable

        pixPointList = (  # arbitrary but reasonable
            Point2D(0.0, 0.0),
            Point2D(1000.0, 0.0),
            Point2D(0.0, 2000.0),
            Point2D(-1111.0, -2222.0),
        )
        for modifyActualPixels in (True, False):
            modifiedWcs = makeModifiedWcs(
                pixelTransform=pixelTransform,
                wcs=originalWcs,
                modifyActualPixels=modifyActualPixels)
            modifiedFrameDict = modifiedWcs.getFrameDict()
            self.assertEqual(
                modifiedFrameDict.getFrame(modifiedFrameDict.BASE).domain,
                "ACTUAL_PIXELS")
            modifiedActualPixelsToPixels = \
                TransformPoint2ToPoint2(modifiedFrameDict.getMapping("ACTUAL_PIXELS", "PIXELS"))
            modifiedPixelsToIwc = TransformPoint2ToPoint2(
                modifiedFrameDict.getMapping("PIXELS", "IWC"))

            # compare pixels to sky
            skyList = modifiedWcs.pixelToSky(pixPointList)
            if modifyActualPixels:
                desiredPixelsToSky = pixelTransform.then(
                    originalWcs.getTransform())
            else:
                originalPixelsToSky = \
                    TransformPoint2ToSpherePoint(originalFrameDict.getMapping("PIXELS", "SKY"))
                desiredPixelsToSky = actualPixelsToPixels.then(
                    pixelTransform).then(originalPixelsToSky)
            desiredSkyList = desiredPixelsToSky.applyForward(pixPointList)
            self.assertSpherePointListsAlmostEqual(skyList, desiredSkyList)

            # compare ACTUAL_PIXELS to PIXELS and PIXELS to IWC
            if modifyActualPixels:
                # check that ACTUAL_PIXELS to PIXELS has been modified as expected
                desiredActualPixelsToPixels = pixelTransform.then(
                    actualPixelsToPixels)
                self.assertPairListsAlmostEqual(
                    modifiedActualPixelsToPixels.applyForward(pixPointList),
                    desiredActualPixelsToPixels.applyForward(pixPointList))

                # check that PIXELS to IWC is unchanged
                originalPixelsToIwc = TransformPoint2ToPoint2(
                    originalFrameDict.getMapping("PIXELS", "IWC"))
                self.assertPairListsAlmostEqual(
                    modifiedPixelsToIwc.applyForward(pixPointList),
                    originalPixelsToIwc.applyForward(pixPointList))

            else:
                # check that ACTUAL_PIXELS to PIXELS is unchanged
                self.assertPairListsAlmostEqual(
                    actualPixelsToPixels.applyForward(pixPointList),
                    actualPixelsToPixels.applyForward(pixPointList))

                # check that PIXELS to IWC has been modified as expected
                desiredPixelsToIwc = TransformPoint2ToPoint2(
                    pixelTransform.getMapping().then(
                        originalFrameDict.getMapping("PIXELS", "IWC")))
                self.assertPairListsAlmostEqual(
                    modifiedPixelsToIwc.applyForward(pixPointList),
                    desiredPixelsToIwc.applyForward(pixPointList))

            self.checkNonFitsWcs(modifiedWcs)
コード例 #38
0
    def testRadial(self):
        """Test fit with radial distortion

        The offset comes from the fact that the CCD is not centered
        """
        self.doTest(afwGeom.makeRadialTransform([0, 1.01, 1e-7]))
コード例 #39
0
    def testSimpleCurvedFocalPlane(self):
        """Test a trivial curved focal plane with square pixels

        The CCD's lower left pixel is centered on the boresight
        pupil center = focal plane center
        CCD x is along focal plane x
        """
        bbox = afwGeom.Box2I(afwGeom.Point2I(0, 0),
                             afwGeom.Extent2I(1000, 1000))
        pixelSizeMm = afwGeom.Extent2D(0.02, 0.02)
        plateScale = 25.0  # arcsec/mm
        yaw = 0 * afwGeom.degrees
        # focal-plane position of ref position on detector (mm)
        fpPosition = afwGeom.Point2D(0, 0)
        # ref position on detector (pos of lower left corner)
        refPoint = afwGeom.Point2D(0, 0)
        orientation = cameraGeom.Orientation(
            fpPosition,
            refPoint,
            yaw,
        )
        pixelToFocalPlane = orientation.makePixelFpTransform(pixelSizeMm)
        plateScaleRad = afwGeom.Angle(  # rad/mm
            plateScale, afwGeom.arcseconds).asRadians()
        focalPlaneToField = afwGeom.makeRadialTransform(
            (0.0, plateScaleRad, 0.0, 0.001 * plateScaleRad))
        pixelToField = pixelToFocalPlane.then(focalPlaneToField)

        pixelToTanPixel = makePixelToTanPixel(
            bbox=bbox,
            orientation=orientation,
            focalPlaneToField=focalPlaneToField,
            pixelSizeMm=pixelSizeMm,
        )

        # field center should be pixel position 0, 0 and tan pixel position 0,
        # 0
        pixAtFieldCtr = pixelToField.applyInverse(afwGeom.Point2D(0, 0))
        self.assertPairsAlmostEqual(pixAtFieldCtr, [0, 0])
        tanPixAtFieldCr = pixelToTanPixel.applyForward(pixAtFieldCtr)
        self.assertPairsAlmostEqual(tanPixAtFieldCr, [0, 0])

        # build same camera geometry transforms without optical distortion
        focalPlaneToFieldNoDistortion = afwGeom.makeRadialTransform(
            (0.0, plateScaleRad))
        pixelToFieldNoDistortion = pixelToFocalPlane.then(
            focalPlaneToFieldNoDistortion)

        for x in (100, 200, 1000):
            for y in (100, 500, 800):
                pixPos = afwGeom.Point2D(x, y)
                tanPixPos = pixelToTanPixel.applyForward(pixPos)
                # pix to tan pix should be radial
                self.assertAlmostEqual(
                    math.atan2(pixPos[1], pixPos[0]),
                    math.atan2(tanPixPos[1], tanPixPos[0]),
                )

                # for a given field angle (which, together with a pointing, gives a position on the sky):
                # - field angle to pixels gives pixPos
                # - undistorted field anle to pixels gives tanPixPos
                fieldPos = pixelToField.applyForward(pixPos)
                desTanPixPos = pixelToFieldNoDistortion.applyInverse(fieldPos)
                self.assertPairsAlmostEqual(desTanPixPos, tanPixPos)
コード例 #40
0
 def testRadial(self):
     """Add a radial transform"""
     for order in (4, 5, 6):
         self.doTest("testRadial", afwGeom.makeRadialTransform([0, 1.001, 0.000003]), order=order,
                     doPlot=False)
コード例 #41
0
ファイル: testUtils.py プロジェクト: HyperSuprime-Cam/afw
    def __init__(self,
                 name="detector 1",
                 id=1,
                 detType=SCIENCE,
                 serial="xkcd722",
                 bbox=None,    # do not use mutable objects as defaults
                 numAmps=3,
                 pixelSize=(0.02, 0.02),
                 ampExtent=(5, 6),
                 orientation=Orientation(),
                 plateScale=20.0,
                 radialDistortion=0.925,
                 crosstalk=None,
                 modFunc=None,
                 physicalType="CCD",
                 ):
        # note that (0., 0.) for the reference position is the center of the
        # first pixel
        self.name = name
        self.id = int(id)
        self.type = detType
        self.serial = serial
        if bbox is None:
            bbox = lsst.geom.Box2I(lsst.geom.Point2I(0, 0), lsst.geom.Extent2I(1024, 1048))
        self.bbox = bbox
        self.pixelSize = lsst.geom.Extent2D(*pixelSize)
        self.ampExtent = lsst.geom.Extent2I(*ampExtent)
        self.plateScale = float(plateScale)
        self.radialDistortion = float(radialDistortion)
        schema = afwTable.AmpInfoTable.makeMinimalSchema()
        self.ampInfo = afwTable.AmpInfoCatalog(schema)
        for i in range(numAmps):
            record = self.ampInfo.addNew()
            ampName = "amp %d" % (i + 1,)
            record.setName(ampName)
            record.setBBox(lsst.geom.Box2I(lsst.geom.Point2I(-1, 1), self.ampExtent))
            record.setGain(1.71234e3)
            record.setReadNoise(0.521237e2)
            record.setReadoutCorner(afwTable.LL)
            record.setHasRawInfo(False)
        self.orientation = orientation

        # compute TAN_PIXELS transform
        pScaleRad = lsst.geom.arcsecToRad(self.plateScale)
        radialDistortCoeffs = [0.0, 1.0/pScaleRad,
                               0.0, self.radialDistortion/pScaleRad]
        focalPlaneToField = afwGeom.makeRadialTransform(radialDistortCoeffs)
        pixelToTanPixel = makePixelToTanPixel(
            bbox=self.bbox,
            orientation=self.orientation,
            focalPlaneToField=focalPlaneToField,
            pixelSizeMm=self.pixelSize,
        )

        self.transMap = {
            FOCAL_PLANE: self.orientation.makePixelFpTransform(self.pixelSize),
            CameraSys(TAN_PIXELS, self.name): pixelToTanPixel,
            CameraSys(ACTUAL_PIXELS, self.name): afwGeom.makeRadialTransform([0, 0.95, 0.01]),
        }
        if crosstalk is None:
            crosstalk = [[0.0 for _ in range(numAmps)] for _ in range(numAmps)]
        self.crosstalk = crosstalk
        self.physicalType = physicalType
        if modFunc:
            modFunc(self)
        self.detector = Detector(
            self.name,
            self.id,
            self.type,
            self.serial,
            self.bbox,
            self.ampInfo,
            self.orientation,
            self.pixelSize,
            self.transMap,
            np.array(self.crosstalk, dtype=np.float32),
            self.physicalType,
        )
コード例 #42
0
    def __init__(
            self,
            name="detector 1",
            id=1,
            detType=DetectorType.SCIENCE,
            serial="xkcd722",
            bbox=None,  # do not use mutable objects as defaults
            numAmps=3,
            pixelSize=(0.02, 0.02),
            ampExtent=(5, 6),
            orientation=Orientation(),
            plateScale=20.0,
            radialDistortion=0.925,
            crosstalk=None,
            modFunc=None,
            physicalType="CCD",
            cameraBuilder=None):
        # note that (0., 0.) for the reference position is the center of the
        # first pixel
        self.name = name
        self.id = int(id)
        self.type = detType
        self.serial = serial
        if bbox is None:
            bbox = lsst.geom.Box2I(lsst.geom.Point2I(0, 0),
                                   lsst.geom.Extent2I(1024, 1048))
        self.bbox = bbox
        self.pixelSize = lsst.geom.Extent2D(*pixelSize)
        self.ampExtent = lsst.geom.Extent2I(*ampExtent)
        self.plateScale = float(plateScale)
        self.orientation = orientation
        self.radialDistortion = float(radialDistortion)

        # compute TAN_PIXELS transform
        pScaleRad = lsst.geom.arcsecToRad(self.plateScale)
        radialDistortCoeffs = [
            0.0, 1.0 / pScaleRad, 0.0, self.radialDistortion / pScaleRad
        ]
        focalPlaneToField = afwGeom.makeRadialTransform(radialDistortCoeffs)
        pixelToTanPixel = makePixelToTanPixel(
            bbox=self.bbox,
            orientation=self.orientation,
            focalPlaneToField=focalPlaneToField,
            pixelSizeMm=self.pixelSize,
        )
        tanPixelSys = CameraSys(TAN_PIXELS, self.name)
        actualPixelSys = CameraSys(ACTUAL_PIXELS, self.name)
        self.transMap = {
            FOCAL_PLANE: self.orientation.makePixelFpTransform(self.pixelSize),
            tanPixelSys: pixelToTanPixel,
            actualPixelSys: afwGeom.makeRadialTransform([0, 0.95, 0.01]),
        }
        if crosstalk is None:
            crosstalk = [[0.0 for _ in range(numAmps)] for _ in range(numAmps)]
        self.crosstalk = crosstalk
        self.physicalType = physicalType
        if cameraBuilder is None:
            cameraBuilder = Camera.Builder("CameraForDetectorWrapper")
        self.ampList = []
        for i in range(numAmps):
            ampBuilder = Amplifier.Builder()
            ampName = f"amp {i + 1}"
            ampBuilder.setName(ampName)
            ampBuilder.setBBox(
                lsst.geom.Box2I(lsst.geom.Point2I(-1, 1), self.ampExtent))
            ampBuilder.setGain(1.71234e3)
            ampBuilder.setReadNoise(0.521237e2)
            ampBuilder.setReadoutCorner(ReadoutCorner.LL)
            self.ampList.append(ampBuilder)
        if modFunc:
            modFunc(self)
        detectorBuilder = cameraBuilder.add(self.name, self.id)
        detectorBuilder.setType(self.type)
        detectorBuilder.setSerial(self.serial)
        detectorBuilder.setPhysicalType(self.physicalType)
        detectorBuilder.setBBox(self.bbox)
        detectorBuilder.setOrientation(self.orientation)
        detectorBuilder.setPixelSize(self.pixelSize)
        detectorBuilder.setTransformFromPixelsTo(tanPixelSys,
                                                 self.transMap[tanPixelSys])
        detectorBuilder.setTransformFromPixelsTo(actualPixelSys,
                                                 self.transMap[actualPixelSys])
        detectorBuilder.setCrosstalk(np.array(self.crosstalk,
                                              dtype=np.float32))
        for ampBuilder in self.ampList:
            detectorBuilder.append(ampBuilder)
        camera = cameraBuilder.finish()
        self.detector = camera[self.name]