def testOffset(self):
     """Test offset, angularSeparation and orientationTo for offsets over a wide range of angles
     """
     for fromPolarAng in (-87.1, -25.5, 0.43, 36.7, 87.0):
         for fromEquatAng in (0, 41.0): # should not matter
             fromCoord = Coord(fromEquatAng, fromPolarAng)
             for fromOrient in (-89.9, -45.0, 0.01, 12.5, 89.0, 90.0):
                 for dist in (0.0001, 0.01, 0.13, 5.73):
                     sideA = 90.0 - fromPolarAng
                     angB = 90.0 - fromOrient
                     sideC = dist
                     unknownAng, angA, sideB, angC = angSideAng(sideA, angB, sideC)
                     self.assertFalse(unknownAng)
                     predEquatAng = fromEquatAng + angC
                     predPolarAng = 90 - sideB
                     predAng = angA - 90
                     toCoord, toOrient = fromCoord.offset(fromOrient, dist)
                     atPole, toEquatAng, toPolarAng = toCoord.getSphPos()
                     places = 7
                     self.assertAlmostEqual(toEquatAng, predEquatAng, places=places)
                     self.assertAlmostEqual(toPolarAng, predPolarAng, places=places)
                     self.assertAlmostEqual(toOrient, predAng, places=places)
                     fromCoord = Coord(fromEquatAng, fromPolarAng)
                     toCoord = Coord(toEquatAng, toPolarAng)
                     self.assertAlmostEqual(dist, fromCoord.angularSeparation(toCoord))
                     self.assertAlmostEqual(fromOrient, fromCoord.orientationTo(toCoord))
                     self.assertAlmostEqual(toOrient, wrapNear(180 + toCoord.orientationTo(fromCoord), toOrient))
Example #2
0
    def testOffsetSmall(self):
        """Test offset, angularSeparation and orientationTo for small offsets not too near the pole
        
        In this regime delta-long = dist along long / cos(lat) is a reasonable approximation
        but I have no simple way to compute toOrient, except if dist very small then toOrient = fromOrient
        """
        for fromPolarAng in (-40.0, 0.43, 36.7):
            cosPolarAng = cosd(fromPolarAng)
            for fromEquatAng in (0, 41.0):  # should not matter
                fromCoord = Coord(fromEquatAng, fromPolarAng)
                for fromOrient in (-90, -72, -45.0, -30, 0.01, 12.5, 31, 47,
                                   56, 68, 89):
                    cosFromOrient = cosd(fromOrient)
                    sinFromOrient = sind(fromOrient)
                    for dist in (0, 1e-12, 1e-11, 1e-10, 1e-9, 1e-8, 1e-7,
                                 1e-5, 0.001, 0.01, 0.13):
                        predEquatAng = fromEquatAng + (dist * cosFromOrient /
                                                       cosPolarAng)
                        predPolarAng = fromPolarAng + (dist * sinFromOrient)

                        toCoord, toOrient = fromCoord.offset(fromOrient, dist)
                        atPole, toEquatAng, toPolarAng = toCoord.getSphPos()
                        if abs(dist) > 0.1:
                            places = 3
                        else:
                            places = 5
                        if abs(dist) < 0.0001:
                            orientPlaces = 4
                        else:
                            orientPlaces = 7
                        self.assertAlmostEqual(toEquatAng,
                                               predEquatAng,
                                               places=places)
                        self.assertAlmostEqual(toPolarAng,
                                               predPolarAng,
                                               places=places)
                        fromCoord = Coord(fromEquatAng, fromPolarAng)
                        toCoord = Coord(toEquatAng, toPolarAng)
                        self.assertAlmostEqual(
                            dist, fromCoord.angularSeparation(toCoord))
                        predFromOrient = fromCoord.orientationTo(toCoord)
                        if numpy.isfinite(predFromOrient):
                            self.assertAlmostEqual(fromOrient,
                                                   predFromOrient,
                                                   places=orientPlaces)
                            self.assertAlmostEqual(
                                toOrient,
                                wrapNear(
                                    180 + toCoord.orientationTo(fromCoord),
                                    toOrient),
                                places=orientPlaces)
                        else:
                            self.assertLess(dist, 1e-7)
                            self.assertAlmostEqual(fromEquatAng, toEquatAng)
                            self.assertAlmostEqual(fromPolarAng, toPolarAng)
                            self.assertAlmostEqual(fromOrient, toOrient)
Example #3
0
    def testWrap(self):
        for wrap in (-1000, -10, -1, 0, 1, 10, 1000):
            for offset in (-360, -180, -90, 0, 90, 180, 270, 360):
                for epsMult in (-3, -2, -1, 0, 1, 2, 3):
                    ang = offset + (wrap * 360)
                    ang += ang * DoubleEpsilon * epsMult
                    sinAng = sind(ang)
                    cosAng = cosd(ang)
                    pvt = PVT(ang, ang, 35.0)  # pick anything for vel and time

                    posAng = wrapPos(ang)
                    self.assertGreaterEqual(posAng, 0.0)
                    self.assertLess(posAng, 360.0)
                    # prove that posAng and ang are the same angle
                    # sin and cos are a sanity check on wrapCtr
                    self.assertAlmostEqual(wrapCtr(posAng - ang), 0)
                    self.assertAlmostEqual(sind(posAng), sinAng)
                    self.assertAlmostEqual(cosd(posAng), cosAng)

                    posPvt = wrapPos(pvt)
                    self.assertEqual(posPvt.pos, posAng)
                    self.assertEqual(posPvt.vel, pvt.vel)
                    self.assertEqual(posPvt.t, pvt.t)

                    ctrAng = wrapCtr(ang)
                    self.assertGreaterEqual(ctrAng, -180.0)
                    self.assertLess(ctrAng, 180.0)
                    # prove that ctrAng and ang are the same angle
                    self.assertAlmostEqual(wrapCtr(ctrAng - ang), 0)
                    self.assertAlmostEqual(sind(ctrAng), sinAng)
                    self.assertAlmostEqual(cosd(ctrAng), cosAng)

                    ctrPvt = wrapCtr(pvt)
                    self.assertEqual(ctrPvt.pos, ctrAng)
                    self.assertEqual(ctrPvt.vel, pvt.vel)
                    self.assertEqual(ctrPvt.t, pvt.t)

                    for refAngBase in (-180, 0, 180, 360):
                        for refEpsMult in (-3, -2, -1, 0, 1, 2, 3):
                            refAng = refAngBase
                            refAng += refAng * refEpsMult * DoubleEpsilon
                            nearAng = wrapNear(ang, refAng)
                            self.assertGreaterEqual(nearAng - refAng, -180)
                            self.assertLess(nearAng - refAng, 180)
                            # prove that nearAng and ang are the same angle
                            self.assertAlmostEqual(wrapCtr(nearAng - ang), 0)
                            self.assertAlmostEqual(sind(nearAng), sinAng)
                            self.assertAlmostEqual(cosd(nearAng), cosAng)
    def testWrap(self):
        for wrap in (-1000, -10, -1, 0, 1, 10, 1000):
            for offset in (-360, -180, -90, 0, 90, 180, 270, 360):
                for epsMult in (-3, -2, -1, 0, 1, 2, 3):
                    ang = offset + (wrap * 360)
                    ang += ang * DoubleEpsilon * epsMult
                    sinAng = sind(ang)
                    cosAng = cosd(ang)
                    pvt = PVT(ang, ang, 35.0) # pick anything for vel and time

                    posAng = wrapPos(ang)
                    self.assertGreaterEqual(posAng, 0.0)
                    self.assertLess(posAng, 360.0)
                    # prove that posAng and ang are the same angle
                    # sin and cos are a sanity check on wrapCtr
                    self.assertAlmostEqual(wrapCtr(posAng - ang), 0)
                    self.assertAlmostEqual(sind(posAng), sinAng)
                    self.assertAlmostEqual(cosd(posAng), cosAng)

                    posPvt = wrapPos(pvt)
                    self.assertEqual(posPvt.pos, posAng)
                    self.assertEqual(posPvt.vel, pvt.vel)
                    self.assertEqual(posPvt.t, pvt.t)

                    ctrAng = wrapCtr(ang)
                    self.assertGreaterEqual(ctrAng, -180.0)
                    self.assertLess(ctrAng, 180.0)
                    # prove that ctrAng and ang are the same angle
                    self.assertAlmostEqual(wrapCtr(ctrAng - ang), 0)
                    self.assertAlmostEqual(sind(ctrAng), sinAng)
                    self.assertAlmostEqual(cosd(ctrAng), cosAng)

                    ctrPvt = wrapCtr(pvt)
                    self.assertEqual(ctrPvt.pos, ctrAng)
                    self.assertEqual(ctrPvt.vel, pvt.vel)
                    self.assertEqual(ctrPvt.t, pvt.t)
                    
                    for refAngBase in (-180, 0, 180, 360):
                        for refEpsMult in (-3, -2, -1, 0, 1, 2, 3):
                            refAng = refAngBase
                            refAng += refAng * refEpsMult * DoubleEpsilon
                            nearAng = wrapNear(ang, refAng)
                            self.assertGreaterEqual(nearAng - refAng, -180)
                            self.assertLess(nearAng - refAng, 180)
                            # prove that nearAng and ang are the same angle
                            self.assertAlmostEqual(wrapCtr(nearAng - ang), 0)
                            self.assertAlmostEqual(sind(nearAng), sinAng)
                            self.assertAlmostEqual(cosd(nearAng), cosAng)
    def testOffsetSmall(self):
        """Test offset, angularSeparation and orientationTo for small offsets not too near the pole
        
        In this regime delta-long = dist along long / cos(lat) is a reasonable approximation
        but I have no simple way to compute toOrient, except if dist very small then toOrient = fromOrient
        """
        for fromPolarAng in (-40.0, 0.43, 36.7):
            cosPolarAng = cosd(fromPolarAng)
            for fromEquatAng in (0, 41.0): # should not matter
                fromCoord = Coord(fromEquatAng, fromPolarAng)
                for fromOrient in (-90, -72, -45.0, -30, 0.01, 12.5, 31, 47, 56, 68, 89):
                    cosFromOrient = cosd(fromOrient)
                    sinFromOrient = sind(fromOrient)
                    for dist in (0, 1e-12, 1e-11, 1e-10, 1e-9, 1e-8, 1e-7, 1e-5, 0.001, 0.01, 0.13):
                        predEquatAng = fromEquatAng + (dist * cosFromOrient / cosPolarAng)
                        predPolarAng = fromPolarAng + (dist * sinFromOrient)

                        toCoord, toOrient = fromCoord.offset(fromOrient, dist)
                        atPole, toEquatAng, toPolarAng = toCoord.getSphPos()
                        if abs(dist) > 0.1:
                            places = 3
                        else:
                            places = 5
                        if abs(dist) < 0.0001:
                            orientPlaces = 4
                        else:
                            orientPlaces = 7
                        self.assertAlmostEqual(toEquatAng, predEquatAng, places=places)
                        self.assertAlmostEqual(toPolarAng, predPolarAng, places=places)
                        fromCoord = Coord(fromEquatAng, fromPolarAng)
                        toCoord = Coord(toEquatAng, toPolarAng)
                        self.assertAlmostEqual(dist, fromCoord.angularSeparation(toCoord))
                        predFromOrient = fromCoord.orientationTo(toCoord)
                        if numpy.isfinite(predFromOrient):
                            self.assertAlmostEqual(fromOrient, predFromOrient, places=orientPlaces)
                            self.assertAlmostEqual(toOrient, wrapNear(180 + toCoord.orientationTo(fromCoord), toOrient), places=orientPlaces)
                        else:
                            self.assertLess(dist, 1e-7)
                            self.assertAlmostEqual(fromEquatAng, toEquatAng)
                            self.assertAlmostEqual(fromPolarAng, toPolarAng)
                            self.assertAlmostEqual(fromOrient, toOrient)
Example #6
0
 def testOffset(self):
     """Test offset, angularSeparation and orientationTo for offsets over a wide range of angles
     """
     for fromPolarAng in (-87.1, -25.5, 0.43, 36.7, 87.0):
         for fromEquatAng in (0, 41.0):  # should not matter
             fromCoord = Coord(fromEquatAng, fromPolarAng)
             for fromOrient in (-89.9, -45.0, 0.01, 12.5, 89.0, 90.0):
                 for dist in (0.0001, 0.01, 0.13, 5.73):
                     sideA = 90.0 - fromPolarAng
                     angB = 90.0 - fromOrient
                     sideC = dist
                     unknownAng, angA, sideB, angC = angSideAng(
                         sideA, angB, sideC)
                     self.assertFalse(unknownAng)
                     predEquatAng = fromEquatAng + angC
                     predPolarAng = 90 - sideB
                     predAng = angA - 90
                     toCoord, toOrient = fromCoord.offset(fromOrient, dist)
                     atPole, toEquatAng, toPolarAng = toCoord.getSphPos()
                     places = 7
                     self.assertAlmostEqual(toEquatAng,
                                            predEquatAng,
                                            places=places)
                     self.assertAlmostEqual(toPolarAng,
                                            predPolarAng,
                                            places=places)
                     self.assertAlmostEqual(toOrient,
                                            predAng,
                                            places=places)
                     fromCoord = Coord(fromEquatAng, fromPolarAng)
                     toCoord = Coord(toEquatAng, toPolarAng)
                     self.assertAlmostEqual(
                         dist, fromCoord.angularSeparation(toCoord))
                     self.assertAlmostEqual(
                         fromOrient, fromCoord.orientationTo(toCoord))
                     self.assertAlmostEqual(
                         toOrient,
                         wrapNear(180 + toCoord.orientationTo(fromCoord),
                                  toOrient))
    def testFile(self):
        """Test file of coordinate conversions from TCC (data/masscc_out.dat)

        Known issues:
        - radVel does not match; the TCC seems to zero radVel if at infinity, but why?
          Also, the TCC seems to be able to round trip RadVel even if at infinity, but how,
          if it zeros it when at infinity? Once I resolve this, update the testCoord.py
          accordingly, as well as this code.
        - Other problems await at other coordinate systems.
        """
        site = None
        numErrors = 0
        with file(DataFile, "rU") as f:
            gotSiteData = False
            startTime = time.time()
            nTested = 0
            for lineInd, line in enumerate(f):
                line = line.strip()
                if not line or line.startswith("#"):
                    continue
                if not gotSiteData:
                    meanLat, meanLong, elevation, ut1_tai, poleX, poleY = [float(val) for val in line.split()]
                    site = coordConv.Site(meanLong, meanLat, elevation)
                    site.setPoleWander(poleX, poleY)
                    site.ut1_tai = ut1_tai
                    gotSiteData = True
                    continue

                dataList = line.split()
                fromSysCode, fromDate, fromPos1, fromPos2, fromPM1, fromPM2, fromParallax, fromRadVel, fromDir, refCoA, refCoB, \
                    toSysCode, toDate, refToPos1, refToPos2, refToPM1, refToPM2, refToParallax, refToRadVel, \
                    refToDir, refScaleChange, refAtInf, refAtPole, isOK, tai, last \
                    = [cnvFunc(val) for val, cnvFunc in itertools.izip(dataList, CnvList)]
                if not isOK:
                    print "Skipping line %s: %s; isOK false" % (lineInd + 1, line)
                if (fromSysCode == 1) and (fromRadVel != 0) and (fromPM1 == 0) and (fromPM2 == 0):
                    print "Skipping line %s; FK4 with zero PM and nonzero radVel" % (lineInd + 1,)
                    continue

                nTested += 1

                fromCoord = coordConv.Coord(fromPos1, fromPos2, fromParallax, fromPM1, fromPM2, fromRadVel)
                fromPVTCoord = coordConv.PVTCoord(fromCoord, fromCoord, tai, 0.01)
                fromPVTDir = coordConv.PVT(fromDir, 0, tai)

                fromCoordSys = getCoordSys(fromSysCode, fromDate, tai)
                toCoordSys = getCoordSys(toSysCode, toDate, tai)
                site.refCoA = refCoA
                site.refCoB = refCoB

                try:
                    toCoord, toDir, scaleChange = toCoordSys.convertFrom(fromCoordSys, fromCoord, fromDir, site)
                    toPVTDir = coordConv.PVT()
                    toPVTCoord, scaleChange2 = toCoordSys.convertFrom(toPVTDir, fromCoordSys, fromPVTCoord, fromPVTDir, site)
                except Exception:
                    print "Failed on line %s: %s\n" % (lineInd + 1, line)
                    raise

                atPole, toPos1, toPos2 = toCoord.getSphPos()
                toParallax = toCoord.getParallax()
                atPole, toPM1, toPM2 = toCoord.getPM()
                toRadVel = toCoord.getRadVel()
                if toCoord.atInfinity(): # emulate something the TCC does that I don't think my code can do
                    toRadVel = fromRadVel
                predList = (toParallax, toPM1, toPM2, toRadVel)
                refList  = (refToParallax, refToPM1, refToPM2, refToRadVel)
                refToCoord = coordConv.Coord(refToPos1, refToPos2, refToParallax, refToPM1, refToPM2, refToRadVel)

                try:
                    self.assertEqual(toCoord.atPole(), refAtPole)
                    self.assertEqual(toCoord.atInfinity(), refAtInf)
                    if (fromSysCode > 0) and (toSysCode > 0):
                        atol = 1e-7
                    elif (fromSysCode < -1) and (toSysCode < -1):
                        atol = 1e-7
                    else:
                        # the sla_Mappa in the old TCC is giving slightly different answers
                        # thatn the latest slaMappa and that appears to explain a small discrepancy
                        # when converting to/from apparent geocentric coordinates;
                        # the error is most noticeable for the precession/nutation matrix.
                        atol = 1e-3
                    self.assertLess(toCoord.angularSeparation(refToCoord), atol)
                    self.assertLess(toPVTCoord.getCoord(tai).angularSeparation(refToCoord), atol)
                    maxPxDelta = refToParallax * 1000.0
                    self.assertAlmostEqual(toParallax, refToParallax, delta = maxPxDelta)
                    self.assertTrue(numpy.allclose(predList[1:], refList[1:], atol=atol))
                    self.assertAlmostEqual(refToDir, coordConv.wrapNear(toDir, refToDir), places=2)
                    self.assertAlmostEqual(refToDir, coordConv.wrapNear(toPVTDir.getPos(tai), refToDir), places=2)
# scale change bears very little resemblance between old and new.
# I believe this is a bug in the old TCC, since mean->mean should be 1.0
# and the new code is significantly closer to 1.0 than the old code.
#                    self.assertAlmostEqual(refScaleChange, scaleChange, places=5)
                    self.assertAlmostEqual(scaleChange, scaleChange2, places=5)
                    if (fromSysCode > 0) and (toSysCode > 0):
                        self.assertAlmostEqual(scaleChange, 1.0, places=5)

                    if toCoordSys.getDateType() == coordConv.DateType_TAI:
                        # "to" system uses tai as its time; try various strategies that remove proper motion to the given tai date

                        # test the removePM function (which removes proper motion and radial velocity, but not parallax)
                        zpmFromCoord = fromCoordSys.removePM(fromCoord, tai)

                        if fromCoordSys.getName() != "fk4":
                            # FK4 coordinates have fictitious space motion
                            zpmFromAtPole, zpmFromPM1, zpmFromPM2 = zpmFromCoord.getPM()
                            self.assertEqual(fromCoord.atPole(), zpmFromAtPole)
                            self.assertEqual(zpmFromPM1, 0)
                            self.assertEqual(zpmFromPM2, 0)
                            zpmFromRadVel = zpmFromCoord.getRadVel()
                            self.assertEqual(zpmFromRadVel, 0)

                        # zpmFromAtPole, zpmFromPM1, zpmFromPM2 = zpmFromCoord.getPM()
                        # self.assertEqual(fromCoord.atPole(), zpmFromAtPole)
                        # zpmFromRadVel = zpmFromCoord.getRadVel()
                        # self.assertEqual(zpmFromPM1, 0)
                        # self.assertEqual(zpmFromPM2, 0)
                        # self.assertEqual(zpmFromRadVel, 0)

                        zpmToCoord, zpmToDir, zpmScaleChange = toCoordSys.convertFrom(fromCoordSys, zpmFromCoord, fromDir, site)
                        zpmToAtPole, zpmToPos1, zpmToPos2 = zpmToCoord.getSphPos()
                        self.assertEqual(atPole, zpmToAtPole)
                        zpmToAtPole, zpmToPM1, zpmToPM2 = zpmToCoord.getPM()
                        self.assertEqual(atPole, zpmToAtPole)
                        zpmToRadVel = zpmToCoord.getRadVel()

                        self.assertAlmostEqual(toDir, zpmToDir, places=2) # why so poor?
                        self.assertAlmostEqual(scaleChange, zpmScaleChange, places=6)
                        self.assertLess(toCoord.angularSeparation(zpmToCoord), 1e-7)
                        self.assertEqual(zpmToPM1, 0)
                        self.assertEqual(zpmToPM2, 0)
                        self.assertEqual(zpmToRadVel, 0)

                except Exception as e:
                    if ContinueOnError:
                        print
                        print str(e)
                    print "Failed on line %s: %s" % (lineInd + 1, line)
                    print "fromCoordSys=(%s, %s); toCoordSys=(%s, %s)" % (fromCoordSys.getName(), fromCoordSys.getDate(), toCoordSys.getName(), toCoordSys.getDate())
                    print "toSphPos=   ", toPos1, toPos2
                    print "refToSphPos=", refToPos1, refToPos2
                    print "angular sep=", toCoord.angularSeparation(refToCoord) * 3600.0, "arcsec"
                    print "pred parallax, PM and radVel=", predList
                    print "ref  parallax, PM and radVel=", refList
                    print "from parallax, PM and radVel=", (fromParallax, fromPM1, fromPM2, fromRadVel)
                    print "from vec pos, vel=", fromCoord.getVecPos(), fromCoord.getVecPM()
                    print "to   vec pos, vel=", toCoord.getVecPos(),  toCoord.getVecPM()
                    if not ContinueOnError:
                        raise
                    numErrors += 1
        duration = time.time() - startTime
        print "Tested %d conversions in %0.2f seconds: %0.0f conversions/second" % \
            (nTested, duration, nTested/duration)
        self.assertEqual(numErrors, 0, "%s errors" % (numErrors,))
Example #8
0
    def testFile(self):
        """Test file of coordinate conversions from TCC (data/masscc_out.dat)

        Known issues:
        - radVel does not match; the TCC seems to zero radVel if at infinity, but why?
          Also, the TCC seems to be able to round trip RadVel even if at infinity, but how,
          if it zeros it when at infinity? Once I resolve this, update the testCoord.py
          accordingly, as well as this code.
        - Other problems await at other coordinate systems.
        """
        site = None
        numErrors = 0
        with file(DataFile, "rU") as f:
            gotSiteData = False
            startTime = time.time()
            nTested = 0
            for lineInd, line in enumerate(f):
                line = line.strip()
                if not line or line.startswith("#"):
                    continue
                if not gotSiteData:
                    meanLat, meanLong, elevation, ut1_tai, poleX, poleY = [
                        float(val) for val in line.split()
                    ]
                    site = coordConv.Site(meanLong, meanLat, elevation)
                    site.setPoleWander(poleX, poleY)
                    site.ut1_tai = ut1_tai
                    gotSiteData = True
                    continue

                dataList = line.split()
                fromSysCode, fromDate, fromPos1, fromPos2, fromPM1, fromPM2, fromParallax, fromRadVel, fromDir, refCoA, refCoB, \
                    toSysCode, toDate, refToPos1, refToPos2, refToPM1, refToPM2, refToParallax, refToRadVel, \
                    refToDir, refScaleChange, refAtInf, refAtPole, isOK, tai, last \
                    = [cnvFunc(val) for val, cnvFunc in itertools.izip(dataList, CnvList)]
                if not isOK:
                    print "Skipping line %s: %s; isOK false" % (lineInd + 1,
                                                                line)
                if (fromSysCode == 1) and (fromRadVel != 0) and (
                        fromPM1 == 0) and (fromPM2 == 0):
                    print "Skipping line %s; FK4 with zero PM and nonzero radVel" % (
                        lineInd + 1, )
                    continue

                nTested += 1

                fromCoord = coordConv.Coord(fromPos1, fromPos2, fromParallax,
                                            fromPM1, fromPM2, fromRadVel)
                fromPVTCoord = coordConv.PVTCoord(fromCoord, fromCoord, tai,
                                                  0.01)
                fromPVTDir = coordConv.PVT(fromDir, 0, tai)

                fromCoordSys = getCoordSys(fromSysCode, fromDate, tai)
                toCoordSys = getCoordSys(toSysCode, toDate, tai)
                site.refCoA = refCoA
                site.refCoB = refCoB

                try:
                    toCoord, toDir, scaleChange = toCoordSys.convertFrom(
                        fromCoordSys, fromCoord, fromDir, site)
                    toPVTDir = coordConv.PVT()
                    toPVTCoord, scaleChange2 = toCoordSys.convertFrom(
                        toPVTDir, fromCoordSys, fromPVTCoord, fromPVTDir, site)
                except Exception:
                    print "Failed on line %s: %s\n" % (lineInd + 1, line)
                    raise

                atPole, toPos1, toPos2 = toCoord.getSphPos()
                toParallax = toCoord.getParallax()
                atPole, toPM1, toPM2 = toCoord.getPM()
                toRadVel = toCoord.getRadVel()
                if toCoord.atInfinity(
                ):  # emulate something the TCC does that I don't think my code can do
                    toRadVel = fromRadVel
                predList = (toParallax, toPM1, toPM2, toRadVel)
                refList = (refToParallax, refToPM1, refToPM2, refToRadVel)
                refToCoord = coordConv.Coord(refToPos1, refToPos2,
                                             refToParallax, refToPM1, refToPM2,
                                             refToRadVel)

                try:
                    self.assertEqual(toCoord.atPole(), refAtPole)
                    self.assertEqual(toCoord.atInfinity(), refAtInf)
                    if (fromSysCode > 0) and (toSysCode > 0):
                        atol = 1e-7
                    elif (fromSysCode < -1) and (toSysCode < -1):
                        atol = 1e-7
                    else:
                        # the sla_Mappa in the old TCC is giving slightly different answers
                        # thatn the latest slaMappa and that appears to explain a small discrepancy
                        # when converting to/from apparent geocentric coordinates;
                        # the error is most noticeable for the precession/nutation matrix.
                        atol = 1e-3
                    self.assertLess(toCoord.angularSeparation(refToCoord),
                                    atol)
                    self.assertLess(
                        toPVTCoord.getCoord(tai).angularSeparation(refToCoord),
                        atol)
                    maxPxDelta = refToParallax * 1000.0
                    self.assertAlmostEqual(toParallax,
                                           refToParallax,
                                           delta=maxPxDelta)
                    self.assertTrue(
                        numpy.allclose(predList[1:], refList[1:], atol=atol))
                    self.assertAlmostEqual(refToDir,
                                           coordConv.wrapNear(toDir, refToDir),
                                           places=2)
                    self.assertAlmostEqual(refToDir,
                                           coordConv.wrapNear(
                                               toPVTDir.getPos(tai), refToDir),
                                           places=2)
                    # scale change bears very little resemblance between old and new.
                    # I believe this is a bug in the old TCC, since mean->mean should be 1.0
                    # and the new code is significantly closer to 1.0 than the old code.
                    #                    self.assertAlmostEqual(refScaleChange, scaleChange, places=5)
                    self.assertAlmostEqual(scaleChange, scaleChange2, places=5)
                    if (fromSysCode > 0) and (toSysCode > 0):
                        self.assertAlmostEqual(scaleChange, 1.0, places=5)

                    if toCoordSys.getDateType() == coordConv.DateType_TAI:
                        # "to" system uses tai as its time; try various strategies that remove proper motion to the given tai date

                        # test the removePM function (which removes proper motion and radial velocity, but not parallax)
                        zpmFromCoord = fromCoordSys.removePM(fromCoord, tai)

                        if fromCoordSys.getName() != "fk4":
                            # FK4 coordinates have fictitious space motion
                            zpmFromAtPole, zpmFromPM1, zpmFromPM2 = zpmFromCoord.getPM(
                            )
                            self.assertEqual(fromCoord.atPole(), zpmFromAtPole)
                            self.assertEqual(zpmFromPM1, 0)
                            self.assertEqual(zpmFromPM2, 0)
                            zpmFromRadVel = zpmFromCoord.getRadVel()
                            self.assertEqual(zpmFromRadVel, 0)

                        # zpmFromAtPole, zpmFromPM1, zpmFromPM2 = zpmFromCoord.getPM()
                        # self.assertEqual(fromCoord.atPole(), zpmFromAtPole)
                        # zpmFromRadVel = zpmFromCoord.getRadVel()
                        # self.assertEqual(zpmFromPM1, 0)
                        # self.assertEqual(zpmFromPM2, 0)
                        # self.assertEqual(zpmFromRadVel, 0)

                        zpmToCoord, zpmToDir, zpmScaleChange = toCoordSys.convertFrom(
                            fromCoordSys, zpmFromCoord, fromDir, site)
                        zpmToAtPole, zpmToPos1, zpmToPos2 = zpmToCoord.getSphPos(
                        )
                        self.assertEqual(atPole, zpmToAtPole)
                        zpmToAtPole, zpmToPM1, zpmToPM2 = zpmToCoord.getPM()
                        self.assertEqual(atPole, zpmToAtPole)
                        zpmToRadVel = zpmToCoord.getRadVel()

                        self.assertAlmostEqual(toDir, zpmToDir,
                                               places=2)  # why so poor?
                        self.assertAlmostEqual(scaleChange,
                                               zpmScaleChange,
                                               places=6)
                        self.assertLess(toCoord.angularSeparation(zpmToCoord),
                                        1e-7)
                        self.assertEqual(zpmToPM1, 0)
                        self.assertEqual(zpmToPM2, 0)
                        self.assertEqual(zpmToRadVel, 0)

                except Exception as e:
                    if ContinueOnError:
                        print
                        print str(e)
                    print "Failed on line %s: %s" % (lineInd + 1, line)
                    print "fromCoordSys=(%s, %s); toCoordSys=(%s, %s)" % (
                        fromCoordSys.getName(), fromCoordSys.getDate(),
                        toCoordSys.getName(), toCoordSys.getDate())
                    print "toSphPos=   ", toPos1, toPos2
                    print "refToSphPos=", refToPos1, refToPos2
                    print "angular sep=", toCoord.angularSeparation(
                        refToCoord) * 3600.0, "arcsec"
                    print "pred parallax, PM and radVel=", predList
                    print "ref  parallax, PM and radVel=", refList
                    print "from parallax, PM and radVel=", (fromParallax,
                                                            fromPM1, fromPM2,
                                                            fromRadVel)
                    print "from vec pos, vel=", fromCoord.getVecPos(
                    ), fromCoord.getVecPM()
                    print "to   vec pos, vel=", toCoord.getVecPos(
                    ), toCoord.getVecPM()
                    if not ContinueOnError:
                        raise
                    numErrors += 1
        duration = time.time() - startTime
        print "Tested %d conversions in %0.2f seconds: %0.0f conversions/second" % \
            (nTested, duration, nTested/duration)
        self.assertEqual(numErrors, 0, "%s errors" % (numErrors, ))