Example #1
0
    def makeFrameSet(self, nIn, nOut):
        """Create a FrameSet with the specified dimensions.

        The FrameSet shall have the following Frames:
              "base"(nIn, #1)
                    |
                    +--------------
                    |             |
               "mid"(4, #2)  "fork"(1, #4)
                    |
            "current"(nOut, #3)
        """
        frameSet = FrameSet(Frame(nIn, "Ident=base"))
        frameSet.addFrame(FrameSet.CURRENT, makeTwoWayPolyMap(nIn, 4),
                          Frame(4, "Ident=mid"))
        frameSet.addFrame(FrameSet.CURRENT, makeTwoWayPolyMap(4, nOut),
                          Frame(nOut, "Ident=current"))
        frameSet.addFrame(FrameSet.BASE, makeTwoWayPolyMap(nIn, 1),
                          Frame(1, "Ident=fork"))

        frameSet.current = 3
        assert frameSet.nFrame == 4
        assert frameSet.base == 1
        assert frameSet.getFrame(FrameSet.BASE).ident == "base"
        assert frameSet.getFrame(2).ident == "mid"
        assert frameSet.current == 3
        assert frameSet.getFrame(FrameSet.CURRENT).ident == "current"
        assert frameSet.getFrame(4).ident == "fork"
        return frameSet
Example #2
0
    def makeFrameSet(self, nIn, nOut):
        """Create a FrameSet with the specified dimensions.

        The FrameSet shall have the following Frames:
              "base"(nIn, #1)
                    |
                    +--------------
                    |             |
               "mid"(4, #2)  "fork"(1, #4)
                    |
            "current"(nOut, #3)
        """
        frameSet = FrameSet(Frame(nIn, "Ident=base"))
        frameSet.addFrame(FrameSet.CURRENT,
                          makeTwoWayPolyMap(nIn, 4),
                          Frame(4, "Ident=mid"))
        frameSet.addFrame(FrameSet.CURRENT,
                          makeTwoWayPolyMap(4, nOut),
                          Frame(nOut, "Ident=current"))
        frameSet.addFrame(FrameSet.BASE,
                          makeTwoWayPolyMap(nIn, 1),
                          Frame(1, "Ident=fork"))

        frameSet.current = 3
        assert frameSet.nFrame == 4
        assert frameSet.base == 1
        assert frameSet.getFrame(FrameSet.BASE).ident == "base"
        assert frameSet.getFrame(2).ident == "mid"
        assert frameSet.current == 3
        assert frameSet.getFrame(FrameSet.CURRENT).ident == "current"
        assert frameSet.getFrame(4).ident == "fork"
        return frameSet
Example #3
0
    def checkTransformFromMapping(self, fromName, toName):
        """Check Transform_<fromName>_<toName> using the Mapping constructor

        Parameters
        ----------
        fromName, toName : `str`
            Endpoint name prefix for "from" and "to" endpoints, respectively,
            e.g. "Point2" for `lsst.afw.geom.Point2Endpoint`
        fromAxes, toAxes : `int`
            number of axes in fromFrame and toFrame, respectively
        """
        transformClassName = "Transform{}To{}".format(fromName, toName)
        TransformClass = getattr(afwGeom, transformClassName)
        baseMsg = "TransformClass={}".format(TransformClass.__name__)

        # check valid numbers of inputs and outputs
        for nIn, nOut in itertools.product(self.goodNAxes[fromName],
                                           self.goodNAxes[toName]):
            msg = "{}, nIn={}, nOut={}".format(baseMsg, nIn, nOut)
            polyMap = makeTwoWayPolyMap(nIn, nOut)
            transform = TransformClass(polyMap)

            # desired output from `str(transform)`
            desStr = "{}[{}->{}]".format(transformClassName, nIn, nOut)
            self.assertEqual("{}".format(transform), desStr)
            self.assertEqual(repr(transform), "lsst.afw.geom." + desStr)

            self.checkTransformation(transform, polyMap, msg=msg)

            # Forward transform but no inverse
            polyMap = makeForwardPolyMap(nIn, nOut)
            transform = TransformClass(polyMap)
            self.checkTransformation(transform, polyMap, msg=msg)

            # Inverse transform but no forward
            polyMap = makeForwardPolyMap(nOut, nIn).inverted()
            transform = TransformClass(polyMap)
            self.checkTransformation(transform, polyMap, msg=msg)

        # check invalid # of output against valid # of inputs
        for nIn, badNOut in itertools.product(self.goodNAxes[fromName],
                                              self.badNAxes[toName]):
            badPolyMap = makeTwoWayPolyMap(nIn, badNOut)
            msg = "{}, nIn={}, badNOut={}".format(baseMsg, nIn, badNOut)
            with self.assertRaises(InvalidParameterError, msg=msg):
                TransformClass(badPolyMap)

        # check invalid # of inputs against valid and invalid # of outputs
        for badNIn, nOut in itertools.product(
                self.badNAxes[fromName],
                self.goodNAxes[toName] + self.badNAxes[toName]):
            badPolyMap = makeTwoWayPolyMap(badNIn, nOut)
            msg = "{}, badNIn={}, nOut={}".format(baseMsg, nIn, nOut)
            with self.assertRaises(InvalidParameterError, msg=msg):
                TransformClass(badPolyMap)
Example #4
0
    def checkTransformFromMapping(self, fromName, toName):
        """Check Transform_<fromName>_<toName> using the Mapping constructor

        Parameters
        ----------
        fromName, toName : `str`
            Endpoint name prefix for "from" and "to" endpoints, respectively,
            e.g. "Point2" for `lsst.afw.geom.Point2Endpoint`
        fromAxes, toAxes : `int`
            number of axes in fromFrame and toFrame, respectively
        """
        transformClassName = "Transform{}To{}".format(fromName, toName)
        TransformClass = getattr(afwGeom, transformClassName)
        baseMsg = "TransformClass={}".format(TransformClass.__name__)

        # check valid numbers of inputs and outputs
        for nIn, nOut in itertools.product(self.goodNAxes[fromName],
                                           self.goodNAxes[toName]):
            msg = "{}, nIn={}, nOut={}".format(baseMsg, nIn, nOut)
            polyMap = makeTwoWayPolyMap(nIn, nOut)
            transform = TransformClass(polyMap)

            # desired output from `str(transform)`
            desStr = "{}[{}->{}]".format(transformClassName, nIn, nOut)
            self.assertEqual("{}".format(transform), desStr)
            self.assertEqual(repr(transform), "lsst.afw.geom." + desStr)

            self.checkTransformation(transform, polyMap, msg=msg)

            # Forward transform but no inverse
            polyMap = makeForwardPolyMap(nIn, nOut)
            transform = TransformClass(polyMap)
            self.checkTransformation(transform, polyMap, msg=msg)

            # Inverse transform but no forward
            polyMap = makeForwardPolyMap(nOut, nIn).inverted()
            transform = TransformClass(polyMap)
            self.checkTransformation(transform, polyMap, msg=msg)

        # check invalid # of output against valid # of inputs
        for nIn, badNOut in itertools.product(self.goodNAxes[fromName],
                                              self.badNAxes[toName]):
            badPolyMap = makeTwoWayPolyMap(nIn, badNOut)
            msg = "{}, nIn={}, badNOut={}".format(baseMsg, nIn, badNOut)
            with self.assertRaises(InvalidParameterError, msg=msg):
                TransformClass(badPolyMap)

        # check invalid # of inputs against valid and invalid # of outputs
        for badNIn, nOut in itertools.product(self.badNAxes[fromName],
                                              self.goodNAxes[toName] + self.badNAxes[toName]):
            badPolyMap = makeTwoWayPolyMap(badNIn, nOut)
            msg = "{}, badNIn={}, nOut={}".format(baseMsg, nIn, nOut)
            with self.assertRaises(InvalidParameterError, msg=msg):
                TransformClass(badPolyMap)
Example #5
0
    def checkGetInverse(self, fromName, toName):
        """Test Transform<fromName>To<toName>.getInverse

        Parameters
        ----------
        fromName, toName : `str`
            Endpoint name prefix for "from" and "to" endpoints, respectively,
            e.g. "Point2" for `lsst.afw.geom.Point2Endpoint`
        """
        transformClassName = "Transform{}To{}".format(fromName, toName)
        TransformClass = getattr(afwGeom, transformClassName)
        baseMsg = "TransformClass={}".format(TransformClass.__name__)
        for nIn, nOut in itertools.product(self.goodNAxes[fromName],
                                           self.goodNAxes[toName]):
            msg = "{}, nIn={}, nOut={}".format(baseMsg, nIn, nOut)
            self.checkInverseMapping(
                TransformClass,
                makeTwoWayPolyMap(nIn, nOut),
                "{}, Map={}".format(msg, "TwoWay"))
            self.checkInverseMapping(
                TransformClass,
                makeForwardPolyMap(nIn, nOut),
                "{}, Map={}".format(msg, "Forward"))
            self.checkInverseMapping(
                TransformClass,
                makeForwardPolyMap(nOut, nIn).getInverse(),
                "{}, Map={}".format(msg, "Inverse"))

            self.checkInverseFrameSet(TransformClass,
                                      self.makeGoodFrame(fromName, nIn),
                                      self.makeGoodFrame(toName, nOut))
Example #6
0
    def checkInverted(self, fromName, toName):
        """Test Transform<fromName>To<toName>.inverted

        Parameters
        ----------
        fromName, toName : `str`
            Endpoint name prefix for "from" and "to" endpoints, respectively,
            e.g. "Point2" for `lsst.afw.geom.Point2Endpoint`
        """
        transformClassName = "Transform{}To{}".format(fromName, toName)
        TransformClass = getattr(afwGeom, transformClassName)
        baseMsg = "TransformClass={}".format(TransformClass.__name__)
        for nIn, nOut in itertools.product(self.goodNAxes[fromName],
                                           self.goodNAxes[toName]):
            msg = "{}, nIn={}, nOut={}".format(baseMsg, nIn, nOut)
            self.checkInverseMapping(
                TransformClass,
                makeTwoWayPolyMap(nIn, nOut),
                "{}, Map={}".format(msg, "TwoWay"))
            self.checkInverseMapping(
                TransformClass,
                makeForwardPolyMap(nIn, nOut),
                "{}, Map={}".format(msg, "Forward"))
            self.checkInverseMapping(
                TransformClass,
                makeForwardPolyMap(nOut, nIn).inverted(),
                "{}, Map={}".format(msg, "Inverse"))
 def test_ZeroPoints(self):
     """Test that Mapping.applyForward and applyInverse can handle zero points
     """
     mapping = makeTwoWayPolyMap(2, 3)
     out_points1 = mapping.applyForward([])
     self.assertEqual(len(out_points1), 0)
     out_points2 = mapping.applyInverse([])
     self.assertEqual(len(out_points2), 0)
Example #8
0
 def test_ZeroPoints(self):
     """Test that Mapping.applyForward and applyInverse can handle zero points
     """
     mapping = makeTwoWayPolyMap(2, 3)
     out_points1 = mapping.applyForward([])
     self.assertEqual(len(out_points1), 0)
     out_points2 = mapping.applyInverse([])
     self.assertEqual(len(out_points2), 0)
Example #9
0
    def test_AppendIndependent(self):
        """Check that a concatenated FrameSet is not affected by changes
        to its constituents.
        """
        set1 = self.makeFrameSet(3, 3)
        set2 = self.makeFrameSet(3, 3)
        set12 = append(set1, set2)

        nTotal = set12.nFrame
        x = [1.2, 3.4, 5.6]
        y = set12.applyForward(x)

        set1.addFrame(2, makeTwoWayPolyMap(4, 2), Frame(2, "Ident=extra"))
        set1.addFrame(1, makeTwoWayPolyMap(3, 3), Frame(3, "Ident=legume"))
        set1.removeFrame(3)
        set2.addFrame(4, makeForwardPolyMap(1, 4), Frame(4, "Ident=extra"))
        set2.base = 2

        # Use exact equality because nothing should change
        self.assertEquals(set12.nFrame, nTotal)
        self.assertEquals(set12.applyForward(x), y)
Example #10
0
    def test_AppendIndependent(self):
        """Check that a concatenated FrameSet is not affected by changes
        to its constituents.
        """
        set1 = self.makeFrameSet(3, 3)
        set2 = self.makeFrameSet(3, 3)
        set12 = append(set1, set2)

        nTotal = set12.nFrame
        x = [1.2, 3.4, 5.6]
        y = set12.applyForward(x)

        set1.addFrame(2, makeTwoWayPolyMap(4, 2), Frame(2, "Ident=extra"))
        set1.addFrame(1, makeTwoWayPolyMap(3, 3), Frame(3, "Ident=legume"))
        set1.removeFrame(3)
        set2.addFrame(4, makeForwardPolyMap(1, 4), Frame(4, "Ident=extra"))
        set2.base = 2

        # Use exact equality because nothing should change
        self.assertEqual(set12.nFrame, nTotal)
        self.assertEqual(set12.applyForward(x), y)
Example #11
0
    def makeFrameSet(self, baseFrame, currFrame):
        """Make a FrameSet

        The FrameSet will contain 4 frames and three transforms connecting them.
        The idenity of each frame is provided by self.frameIdentDict

        Frame       Index   Mapping from this frame to the next
        `baseFrame`   1     `ast.UnitMap(nIn)`
        Frame(nIn)    2     `polyMap`
        Frame(nOut)   3     `ast.UnitMap(nOut)`
        `currFrame`   4

        where:
        - `nIn` = `baseFrame.nAxes`
        - `nOut` = `currFrame.nAxes`
        - `polyMap` = `makeTwoWayPolyMap(nIn, nOut)`

        Returns
        ------
        `ast.FrameSet`
            The FrameSet as described above

        Parameters
        ----------
        baseFrame : `ast.Frame`
            base frame
        currFrame : `ast.Frame`
            current frame
        """
        nIn = baseFrame.nAxes
        nOut = currFrame.nAxes
        polyMap = makeTwoWayPolyMap(nIn, nOut)

        # The only way to set the Ident of a frame in a FrameSet is to set it in advance,
        # and I don't want to modify the inputs, so replace the input frames with copies
        baseFrame = baseFrame.copy()
        baseFrame.ident = self.frameIdentDict[1]
        currFrame = currFrame.copy()
        currFrame.ident = self.frameIdentDict[4]

        frameSet = ast.FrameSet(baseFrame)
        frame2 = ast.Frame(nIn)
        frame2.ident = self.frameIdentDict[2]
        frameSet.addFrame(ast.FrameSet.CURRENT, ast.UnitMap(nIn), frame2)
        frame3 = ast.Frame(nOut)
        frame3.ident = self.frameIdentDict[3]
        frameSet.addFrame(ast.FrameSet.CURRENT, polyMap, frame3)
        frameSet.addFrame(ast.FrameSet.CURRENT, ast.UnitMap(nOut), currFrame)
        return frameSet
Example #12
0
    def makeFrameSet(self, baseFrame, currFrame):
        """Make a FrameSet

        The FrameSet will contain 4 frames and three transforms connecting them.
        The idenity of each frame is provided by self.frameIdentDict

        Frame       Index   Mapping from this frame to the next
        `baseFrame`   1     `ast.UnitMap(nIn)`
        Frame(nIn)    2     `polyMap`
        Frame(nOut)   3     `ast.UnitMap(nOut)`
        `currFrame`   4

        where:
        - `nIn` = `baseFrame.nAxes`
        - `nOut` = `currFrame.nAxes`
        - `polyMap` = `makeTwoWayPolyMap(nIn, nOut)`

        Returns
        ------
        `ast.FrameSet`
            The FrameSet as described above

        Parameters
        ----------
        baseFrame : `ast.Frame`
            base frame
        currFrame : `ast.Frame`
            current frame
        """
        nIn = baseFrame.nAxes
        nOut = currFrame.nAxes
        polyMap = makeTwoWayPolyMap(nIn, nOut)

        # The only way to set the Ident of a frame in a FrameSet is to set it in advance,
        # and I don't want to modify the inputs, so replace the input frames with copies
        baseFrame = baseFrame.copy()
        baseFrame.ident = self.frameIdentDict[1]
        currFrame = currFrame.copy()
        currFrame.ident = self.frameIdentDict[4]

        frameSet = ast.FrameSet(baseFrame)
        frame2 = ast.Frame(nIn)
        frame2.ident = self.frameIdentDict[2]
        frameSet.addFrame(ast.FrameSet.CURRENT, ast.UnitMap(nIn), frame2)
        frame3 = ast.Frame(nOut)
        frame3.ident = self.frameIdentDict[3]
        frameSet.addFrame(ast.FrameSet.CURRENT, polyMap, frame3)
        frameSet.addFrame(ast.FrameSet.CURRENT, ast.UnitMap(nOut), currFrame)
        return frameSet
Example #13
0
    def checkTransformFromFrameSet(self, fromName, toName):
        """Check Transform_<fromName>_<toName> using the FrameSet constructor

        Parameters
        ----------
        fromName, toName : `str`
            Endpoint name prefix for "from" and "to" endpoints, respectively,
            e.g. "Point2" for `lsst.afw.geom.Point2Endpoint`
        """
        transformClassName = "Transform{}To{}".format(fromName, toName)
        TransformClass = getattr(afwGeom, transformClassName)
        baseMsg = "TransformClass={}".format(TransformClass.__name__)
        for nIn, nOut in itertools.product(self.goodNAxes[fromName],
                                           self.goodNAxes[toName]):
            msg = "{}, nIn={}, nOut={}".format(baseMsg, nIn, nOut)

            baseFrame = self.makeGoodFrame(fromName, nIn)
            currFrame = self.makeGoodFrame(toName, nOut)
            frameSet = self.makeFrameSet(baseFrame, currFrame)
            self.assertEqual(frameSet.nFrame, 4)

            # construct 0 or more frame sets that are invalid for this transform class
            for badBaseFrame in self.makeBadFrames(fromName):
                badFrameSet = self.makeFrameSet(badBaseFrame, currFrame)
                with self.assertRaises(InvalidParameterError):
                    TransformClass(badFrameSet)
                for badCurrFrame in self.makeBadFrames(toName):
                    reallyBadFrameSet = self.makeFrameSet(
                        badBaseFrame, badCurrFrame)
                    with self.assertRaises(InvalidParameterError):
                        TransformClass(reallyBadFrameSet)
            for badCurrFrame in self.makeBadFrames(toName):
                badFrameSet = self.makeFrameSet(baseFrame, badCurrFrame)
                with self.assertRaises(InvalidParameterError):
                    TransformClass(badFrameSet)

            transform = TransformClass(frameSet)

            desStr = "{}[{}->{}]".format(transformClassName, nIn, nOut)
            self.assertEqual("{}".format(transform), desStr)
            self.assertEqual(repr(transform), "lsst.afw.geom." + desStr)

            self.checkPersistence(transform)

            mappingFromTransform = transform.getMapping()
            transformCopy = TransformClass(mappingFromTransform)
            self.assertEqual(type(transform), type(transformCopy))
            self.assertEqual(transform.getMapping(), mappingFromTransform)

            polyMap = makeTwoWayPolyMap(nIn, nOut)

            self.checkTransformation(transform, mapping=polyMap, msg=msg)

            # If the base and/or current frame of frameSet is a SkyFrame,
            # try permuting that frame (in place, so the connected mappings are
            # correctly updated). The Transform constructor should undo the permutation,
            # (via SpherePointEndpoint.normalizeFrame) in its internal copy of frameSet,
            # forcing the axes of the SkyFrame into standard (longitude, latitude) order
            for permutedFS in self.permuteFrameSetIter(frameSet):
                if permutedFS.isBaseSkyFrame:
                    baseFrame = permutedFS.frameSet.getFrame(ast.FrameSet.BASE)
                    # desired base longitude axis
                    desBaseLonAxis = 2 if permutedFS.isBasePermuted else 1
                    self.assertEqual(baseFrame.lonAxis, desBaseLonAxis)
                if permutedFS.isCurrSkyFrame:
                    currFrame = permutedFS.frameSet.getFrame(
                        ast.FrameSet.CURRENT)
                    # desired current base longitude axis
                    desCurrLonAxis = 2 if permutedFS.isCurrPermuted else 1
                    self.assertEqual(currFrame.lonAxis, desCurrLonAxis)

                permTransform = TransformClass(permutedFS.frameSet)
                self.checkTransformation(permTransform,
                                         mapping=polyMap,
                                         msg=msg)
Example #14
0
    def checkThen(self, fromName, midName, toName):
        """Test Transform<fromName>To<midName>.then(Transform<midName>To<toName>)

        Parameters
        ----------
        fromName : `str`
            the prefix of the starting endpoint (e.g., "Point2" for a
            Point2Endpoint) for the final, concatenated Transform
        midName : `str`
            the prefix for the shared endpoint where two Transforms will be
            concatenated
        toName : `str`
            the prefix of the ending endpoint for the final, concatenated
            Transform
        """
        TransformClass1 = getattr(afwGeom,
                                  "Transform{}To{}".format(fromName, midName))
        TransformClass2 = getattr(afwGeom,
                                  "Transform{}To{}".format(midName, toName))
        baseMsg = "{}.then({})".format(TransformClass1.__name__,
                                       TransformClass2.__name__)
        for nIn, nMid, nOut in itertools.product(self.goodNAxes[fromName],
                                                 self.goodNAxes[midName],
                                                 self.goodNAxes[toName]):
            msg = "{}, nIn={}, nMid={}, nOut={}".format(
                baseMsg, nIn, nMid, nOut)
            polyMap1 = makeTwoWayPolyMap(nIn, nMid)
            transform1 = TransformClass1(polyMap1)
            polyMap2 = makeTwoWayPolyMap(nMid, nOut)
            transform2 = TransformClass2(polyMap2)
            transform = transform1.then(transform2)

            fromEndpoint = transform1.fromEndpoint
            toEndpoint = transform2.toEndpoint

            inPoint = fromEndpoint.pointFromData(self.makeRawPointData(nIn))
            outPointMerged = transform.applyForward(inPoint)
            outPointSeparate = transform2.applyForward(
                transform1.applyForward(inPoint))
            assert_allclose(toEndpoint.dataFromPoint(outPointMerged),
                            toEndpoint.dataFromPoint(outPointSeparate),
                            err_msg=msg)

            outPoint = toEndpoint.pointFromData(self.makeRawPointData(nOut))
            inPointMerged = transform.applyInverse(outPoint)
            inPointSeparate = transform1.applyInverse(
                transform2.applyInverse(outPoint))
            assert_allclose(fromEndpoint.dataFromPoint(inPointMerged),
                            fromEndpoint.dataFromPoint(inPointSeparate),
                            err_msg=msg)

        # Mismatched number of axes should fail
        if midName == "Generic":
            nIn = self.goodNAxes[fromName][0]
            nOut = self.goodNAxes[toName][0]
            polyMap = makeTwoWayPolyMap(nIn, 3)
            transform1 = TransformClass1(polyMap)
            polyMap = makeTwoWayPolyMap(2, nOut)
            transform2 = TransformClass2(polyMap)
            with self.assertRaises(InvalidParameterError):
                transform = transform1.then(transform2)

        # Mismatched types of endpoints should fail
        if fromName != midName:
            # Use TransformClass1 for both args to keep test logic simple
            outName = midName
            joinNAxes = set(self.goodNAxes[fromName]).intersection(
                self.goodNAxes[outName])

            for nIn, nMid, nOut in itertools.product(self.goodNAxes[fromName],
                                                     joinNAxes,
                                                     self.goodNAxes[outName]):
                polyMap = makeTwoWayPolyMap(nIn, nMid)
                transform1 = TransformClass1(polyMap)
                polyMap = makeTwoWayPolyMap(nMid, nOut)
                transform2 = TransformClass1(polyMap)
                with self.assertRaises(InvalidParameterError):
                    transform = transform1.then(transform2)
Example #15
0
    def checkThen(self, fromName, midName, toName):
        """Test Transform<fromName>To<midName>.then(Transform<midName>To<toName>)

        Parameters
        ----------
        fromName : `str`
            the prefix of the starting endpoint (e.g., "Point2" for a
            Point2Endpoint) for the final, concatenated Transform
        midName : `str`
            the prefix for the shared endpoint where two Transforms will be
            concatenated
        toName : `str`
            the prefix of the ending endpoint for the final, concatenated
            Transform
        """
        TransformClass1 = getattr(afwGeom,
                                  "Transform{}To{}".format(fromName, midName))
        TransformClass2 = getattr(afwGeom,
                                  "Transform{}To{}".format(midName, toName))
        baseMsg = "{}.then({})".format(TransformClass1.__name__,
                                       TransformClass2.__name__)
        for nIn, nMid, nOut in itertools.product(self.goodNAxes[fromName],
                                                 self.goodNAxes[midName],
                                                 self.goodNAxes[toName]):
            msg = "{}, nIn={}, nMid={}, nOut={}".format(
                baseMsg, nIn, nMid, nOut)
            polyMap1 = makeTwoWayPolyMap(nIn, nMid)
            transform1 = TransformClass1(polyMap1)
            polyMap2 = makeTwoWayPolyMap(nMid, nOut)
            transform2 = TransformClass2(polyMap2)
            transform = transform1.then(transform2)

            fromEndpoint = transform1.fromEndpoint
            toEndpoint = transform2.toEndpoint

            inPoint = fromEndpoint.pointFromData(self.makeRawPointData(nIn))
            outPointMerged = transform.applyForward(inPoint)
            outPointSeparate = transform2.applyForward(
                transform1.applyForward(inPoint))
            assert_allclose(toEndpoint.dataFromPoint(outPointMerged),
                            toEndpoint.dataFromPoint(outPointSeparate),
                            err_msg=msg)

            outPoint = toEndpoint.pointFromData(self.makeRawPointData(nOut))
            inPointMerged = transform.applyInverse(outPoint)
            inPointSeparate = transform1.applyInverse(
                transform2.applyInverse(outPoint))
            assert_allclose(
                fromEndpoint.dataFromPoint(inPointMerged),
                fromEndpoint.dataFromPoint(inPointSeparate),
                err_msg=msg)

        # Mismatched number of axes should fail
        if midName == "Generic":
            nIn = self.goodNAxes[fromName][0]
            nOut = self.goodNAxes[toName][0]
            polyMap = makeTwoWayPolyMap(nIn, 3)
            transform1 = TransformClass1(polyMap)
            polyMap = makeTwoWayPolyMap(2, nOut)
            transform2 = TransformClass2(polyMap)
            with self.assertRaises(InvalidParameterError):
                transform = transform1.then(transform2)

        # Mismatched types of endpoints should fail
        if fromName != midName:
            # Use TransformClass1 for both args to keep test logic simple
            outName = midName
            joinNAxes = set(self.goodNAxes[fromName]).intersection(
                self.goodNAxes[outName])

            for nIn, nMid, nOut in itertools.product(self.goodNAxes[fromName],
                                                     joinNAxes,
                                                     self.goodNAxes[outName]):
                polyMap = makeTwoWayPolyMap(nIn, nMid)
                transform1 = TransformClass1(polyMap)
                polyMap = makeTwoWayPolyMap(nMid, nOut)
                transform2 = TransformClass1(polyMap)
                with self.assertRaises(InvalidParameterError):
                    transform = transform1.then(transform2)
Example #16
0
    def checkTransformFromFrameSet(self, fromName, toName):
        """Check Transform_<fromName>_<toName> using the FrameSet constructor

        Parameters
        ----------
        fromName, toName : `str`
            Endpoint name prefix for "from" and "to" endpoints, respectively,
            e.g. "Point2" for `lsst.afw.geom.Point2Endpoint`
        """
        transformClassName = "Transform{}To{}".format(fromName, toName)
        TransformClass = getattr(afwGeom, transformClassName)
        baseMsg = "TransformClass={}".format(TransformClass.__name__)
        for nIn, nOut in itertools.product(self.goodNAxes[fromName],
                                           self.goodNAxes[toName]):
            msg = "{}, nIn={}, nOut={}".format(baseMsg, nIn, nOut)

            baseFrame = self.makeGoodFrame(fromName, nIn)
            currFrame = self.makeGoodFrame(toName, nOut)
            frameSet = self.makeFrameSet(baseFrame, currFrame)
            self.assertEqual(frameSet.nFrame, 4)

            # construct 0 or more frame sets that are invalid for this transform class
            for badBaseFrame in self.makeBadFrames(fromName):
                badFrameSet = self.makeFrameSet(badBaseFrame, currFrame)
                with self.assertRaises(InvalidParameterError):
                    TransformClass(badFrameSet)
                for badCurrFrame in self.makeBadFrames(toName):
                    reallyBadFrameSet = self.makeFrameSet(badBaseFrame, badCurrFrame)
                    with self.assertRaises(InvalidParameterError):
                        TransformClass(reallyBadFrameSet)
            for badCurrFrame in self.makeBadFrames(toName):
                badFrameSet = self.makeFrameSet(baseFrame, badCurrFrame)
                with self.assertRaises(InvalidParameterError):
                    TransformClass(badFrameSet)

            transform = TransformClass(frameSet)

            desStr = "{}[{}->{}]".format(transformClassName, nIn, nOut)
            self.assertEqual("{}".format(transform), desStr)
            self.assertEqual(repr(transform), "lsst.afw.geom." + desStr)

            self.checkPersistence(transform)

            mappingFromTransform = transform.getMapping()
            transformCopy = TransformClass(mappingFromTransform)
            self.assertEqual(type(transform), type(transformCopy))
            self.assertEqual(transform.getMapping(), mappingFromTransform)

            polyMap = makeTwoWayPolyMap(nIn, nOut)

            self.checkTransformation(transform, mapping=polyMap, msg=msg)

            # If the base and/or current frame of frameSet is a SkyFrame,
            # try permuting that frame (in place, so the connected mappings are
            # correctly updated). The Transform constructor should undo the permutation,
            # (via SpherePointEndpoint.normalizeFrame) in its internal copy of frameSet,
            # forcing the axes of the SkyFrame into standard (longitude, latitude) order
            for permutedFS in self.permuteFrameSetIter(frameSet):
                if permutedFS.isBaseSkyFrame:
                    baseFrame = permutedFS.frameSet.getFrame(ast.FrameSet.BASE)
                    # desired base longitude axis
                    desBaseLonAxis = 2 if permutedFS.isBasePermuted else 1
                    self.assertEqual(baseFrame.lonAxis, desBaseLonAxis)
                if permutedFS.isCurrSkyFrame:
                    currFrame = permutedFS.frameSet.getFrame(ast.FrameSet.CURRENT)
                    # desired current base longitude axis
                    desCurrLonAxis = 2 if permutedFS.isCurrPermuted else 1
                    self.assertEqual(currFrame.lonAxis, desCurrLonAxis)

                permTransform = TransformClass(permutedFS.frameSet)
                self.checkTransformation(permTransform, mapping=polyMap, msg=msg)