Beispiel #1
0
    def testStrValue(self):
        """Test if __str__ produces output consistent with its spec.

        This is necessarily a loose test, as the behavior of __str__
        is (deliberately) incompletely specified.
        """
        for lon, lat in self._dataset:
            point = SpherePoint(lon, lat)
            numbers = re.findall(r'(?:\+|-)?(?:[\d.]+|nan|inf)', str(point))
            self.assertEqual(2, len(numbers),
                             "String '%s' should have exactly two coordinates." % (point,))

            # Low precision to allow for only a few digits in string.
            if not math.isnan(point.getLongitude().asRadians()):
                self.assertAlmostEqual(
                    point.getLongitude().asDegrees(), float(numbers[0]), delta=1e-6)
            else:
                self.assertRegexpMatches(numbers[0], r'-?nan')
            if not math.isnan(point.getLatitude().asRadians()):
                self.assertAlmostEqual(
                    point.getLatitude().asDegrees(), float(numbers[1]), delta=1e-6)
                # Latitude must be signed
                self.assertTrue(numbers[1].startswith("+") or
                                numbers[1].startswith("-"))
            else:
                # Some C++ compilers will output NaN with a sign, others won't
                self.assertRegexpMatches(numbers[1], r'(?:\+|-)?nan')
Beispiel #2
0
 def testGetLatitudeValue(self):
     """Test if getLatitude() returns the expected value.
     """
     for lon, lat in self._dataset:
         point = SpherePoint(lon, lat)
         self.assertIsInstance(point.getLatitude(), afwGeom.Angle)
         # Behavior for non-finite points is undefined; depends on internal
         # data representation
         if point.isFinite():
             self.assertGreaterEqual(point.getLatitude().asDegrees(), -90.0)
             self.assertLessEqual(point.getLatitude().asDegrees(), 90.0)
             self.assertAnglesAlmostEqual(lat, point.getLatitude())
Beispiel #3
0
    def testIterResult(self):
        """Test if iteration returns the expected values.
        """
        for lon, lat in self._dataset:
            point = SpherePoint(lon, lat)
            if point.isFinite():
                # Test mechanics directly
                it = iter(point)
                self.assertEqual(point.getLongitude(), next(it))
                self.assertEqual(point.getLatitude(), next(it))
                with self.assertRaises(StopIteration):
                    next(it)

                # Intended use case
                lon, lat = point
                self.assertEqual(point.getLongitude(), lon)
                self.assertEqual(point.getLatitude(), lat)
    def testVector3dConstructor(self):
        # test poles
        for z in (-11.3, -1.1, 0.1, 2.5):  # arbitrary non-zero values
            sp = SpherePoint(lsst.sphgeom.Vector3d(0.0, 0.0, z))
            self.assertTrue(sp.atPole())
            self.assertEqual(sp.getLongitude().asRadians(), 0.0)
            if z < 0:
                self.assertAnglesAlmostEqual(sp.getLatitude(), -90 * degrees)
            else:
                self.assertAnglesAlmostEqual(sp.getLatitude(), 90 * degrees)

        spx = SpherePoint(lsst.sphgeom.Vector3d(11.1, 0.0, 0.0))
        self.assertAnglesAlmostEqual(spx.getLongitude(), 0.0 * degrees)
        self.assertAnglesAlmostEqual(spx.getLatitude(), 0.0 * degrees)

        spy = SpherePoint(lsst.sphgeom.Vector3d(0.0, 234234.5, 0.0))
        self.assertAnglesAlmostEqual(spy.getLongitude(), 90.0 * degrees)
        self.assertAnglesAlmostEqual(spy.getLatitude(), 0.0 * degrees)

        spxy = SpherePoint(lsst.sphgeom.Vector3d(7.5, -7.5, 0.0))
        self.assertAnglesAlmostEqual(spxy.getLongitude(), -45.0 * degrees)
        self.assertAnglesAlmostEqual(spxy.getLatitude(), 0.0 * degrees)

        spxz = SpherePoint(lsst.sphgeom.Vector3d(100.0, 0.0, -100.0))
        self.assertAnglesAlmostEqual(spxz.getLongitude(), 0.0 * degrees)
        self.assertAnglesAlmostEqual(spxz.getLatitude(), -45.0 * degrees)

        # Only one singularity: a vector of all zeros
        with self.assertRaises(pexEx.InvalidParameterError):
            SpherePoint(lsst.sphgeom.Vector3d(0.0, 0.0, 0.0))
Beispiel #5
0
    def testGetItemValue(self):
        """Test if indexing returns the expected value.
        """
        for lon, lat in self._dataset:
            point = SpherePoint(lon, lat)
            self.assertIsInstance(point[-2], afwGeom.Angle)
            self.assertIsInstance(point[-1], afwGeom.Angle)
            self.assertIsInstance(point[0], afwGeom.Angle)
            self.assertIsInstance(point[1], afwGeom.Angle)

            if not math.isnan(point.getLongitude().asRadians()):
                self.assertEqual(point.getLongitude(), point[-2])
                self.assertEqual(point.getLongitude(), point[0])
            else:
                self.assertTrue(math.isnan(point[-2].asRadians()))
                self.assertTrue(math.isnan(point[0].asRadians()))
            if not math.isnan(point.getLatitude().asRadians()):
                self.assertEqual(point.getLatitude(), point[-1])
                self.assertEqual(point.getLatitude(), point[1])
            else:
                self.assertTrue(math.isnan(point[-1].asRadians()))
                self.assertTrue(math.isnan(point[1].asRadians()))
Beispiel #6
0
    def testReprValue(self):
        """Test if __repr__ is a machine-readable representation.
        """
        for lon, lat in self._dataset:
            point = SpherePoint(lon, lat)
            pointRepr = repr(point)
            self.assertIn("degrees", pointRepr)
            self.assertEqual(2, len(pointRepr.split(",")))

            spcopy = eval(pointRepr)
            self.assertAnglesAlmostEqual(
                point.getLongitude(), spcopy.getLongitude())
            self.assertAnglesAlmostEqual(
                point.getLatitude(), spcopy.getLatitude())
Beispiel #7
0
    def testBearingToValueSingular(self):
        """White-box test: bearingTo() may be unstable if points are near opposite poles.

        This test is motivated by an error analysis of the `bearingTo`
        implementation. It may become irrelevant if the implementation
        changes.
        """
        southPole = SpherePoint(0.0*degrees, self.nextUp(-90.0*degrees))
        northPoleSame = SpherePoint(0.0*degrees, self.nextDown(90.0*degrees))
        # Don't let it be on exactly the opposite side.
        northPoleOpposite = SpherePoint(
            180.0*degrees, self.nextDown(northPoleSame.getLatitude()))

        self.assertAnglesAlmostEqual(southPole.bearingTo(northPoleSame),
                                     afwGeom.HALFPI*afwGeom.radians)
        self.assertAnglesAlmostEqual(southPole.bearingTo(northPoleOpposite),
                                     (afwGeom.PI + afwGeom.HALFPI)*afwGeom.radians)
    def testSeparationValueAbsolute(self):
        """Test if separation() returns specific values.
        """
        # Test from "Meeus, p. 110" (test originally written for coord::Coord;
        # don't know exact reference)
        spica = SpherePoint(201.2983, -11.1614, degrees)
        arcturus = SpherePoint(213.9154, 19.1825, degrees)

        # Verify to precision of quoted distance and positions.
        self.assertAlmostEqual(32.7930,
                               spica.separation(arcturus).asDegrees(), 4)

        # Verify small angles: along a constant ra, add an arcsec to spica dec.
        epsilon = 1.0 * afwGeom.arcseconds
        spicaPlus = SpherePoint(spica.getLongitude(),
                                spica.getLatitude() + epsilon)

        self.assertAnglesAlmostEqual(epsilon, spicaPlus.separation(spica))
Beispiel #9
0
    def testOffsetValue(self):
        """Test if offset() returns the expected value.
        """
        # This should cover arcs over the meridian, across the pole, etc.
        for lon1, lat1 in self._dataset:
            point1 = SpherePoint(lon1, lat1)
            if point1.atPole():
                continue
            for lon2, lat2 in self._dataset:
                if lon1 == lon2 and lat1 == lat2:
                    continue
                point2 = SpherePoint(lon2, lat2)
                bearing = point1.bearingTo(point2)
                distance = point1.separation(point2)

                newPoint = point1.offset(bearing, distance)
                self.assertIsInstance(newPoint, SpherePoint)
                if point1.isFinite() and point2.isFinite():
                    if not point2.atPole():
                        self.assertAnglesAlmostEqual(
                            point2.getLongitude(), newPoint.getLongitude())
                    self.assertAnglesAlmostEqual(
                        point2.getLatitude(), newPoint.getLatitude())
                else:
                    self.assertTrue(math.isnan(
                        newPoint.getLongitude().asRadians()))
                    self.assertTrue(math.isnan(
                        newPoint.getLatitude().asRadians()))

        # Test precision near the poles
        lon = 123.0*degrees
        almostPole = SpherePoint(lon, self.nextDown(90.0*degrees))
        goSouth = almostPole.offset(-90.0*degrees, 90.0*degrees)
        self.assertAnglesAlmostEqual(lon, goSouth.getLongitude())
        self.assertAnglesAlmostEqual(0.0*degrees, goSouth.getLatitude())
        goEast = almostPole.offset(0.0*degrees, 90.0*degrees)
        self.assertAnglesAlmostEqual(lon + 90.0*degrees, goEast.getLongitude())
        self.assertAnglesAlmostEqual(0.0*degrees, goEast.getLatitude())
    def testOffsetValue(self):
        """Test if offset() returns the expected value.
        """
        # This should cover arcs over the meridian, across the pole, etc.
        for lon1, lat1 in self._dataset:
            point1 = SpherePoint(lon1, lat1)
            for lon2, lat2 in self._dataset:
                if lon1 == lon2 and lat1 == lat2:
                    continue
                point2 = SpherePoint(lon2, lat2)
                bearing = point1.bearingTo(point2)
                distance = point1.separation(point2)

                # offsetting point1 by bearing and distance should produce the same result as point2
                newPoint = point1.offset(bearing, distance)
                self.assertIsInstance(newPoint, SpherePoint)
                self.assertSpherePointsAlmostEqual(point2, newPoint)
                if newPoint.atPole():
                    self.assertAnglesAlmostEqual(newPoint.getLongitude(),
                                                 0 * degrees)

                # measuring the separation and bearing from point1 to the new point
                # should produce the requested separation and bearing
                measuredDistance = point1.separation(newPoint)
                self.assertAnglesAlmostEqual(measuredDistance, distance)
                if abs(measuredDistance.asDegrees() - 180) > 1e-5:
                    # The two points are not opposite each other on the sphere,
                    # so the bearing has a well defined value
                    measuredBearing = point1.bearingTo(newPoint)
                    self.assertAnglesAlmostEqual(measuredBearing, bearing)

                # offset by a negative amount in the opposite direction should produce the same result
                newPoint2 = point1.offset(bearing + 180 * degrees, -distance)
                self.assertIsInstance(newPoint2, SpherePoint)
                # check angular separation (longitude is checked below)
                self.assertSpherePointsAlmostEqual(newPoint, newPoint2)

                if point1.isFinite() and point2.isFinite():
                    if not point2.atPole():
                        self.assertAnglesAlmostEqual(point2.getLongitude(),
                                                     newPoint.getLongitude())
                        self.assertAnglesAlmostEqual(point2.getLongitude(),
                                                     newPoint2.getLongitude())
                    self.assertAnglesAlmostEqual(point2.getLatitude(),
                                                 newPoint.getLatitude())
                    self.assertAnglesAlmostEqual(point2.getLatitude(),
                                                 newPoint2.getLatitude())
                else:
                    self.assertTrue(
                        math.isnan(newPoint.getLongitude().asRadians()))
                    self.assertTrue(
                        math.isnan(newPoint2.getLongitude().asRadians()))
                    self.assertTrue(
                        math.isnan(newPoint.getLatitude().asRadians()))
                    self.assertTrue(
                        math.isnan(newPoint2.getLatitude().asRadians()))

        # Test precision near the poles
        lon = 123.0 * degrees
        almostPole = SpherePoint(lon, self.nextDown(90.0 * degrees))
        goSouth = almostPole.offset(-90.0 * degrees, 90.0 * degrees)
        self.assertAnglesAlmostEqual(lon, goSouth.getLongitude())
        self.assertAnglesAlmostEqual(0.0 * degrees, goSouth.getLatitude())
        goEast = almostPole.offset(0.0 * degrees, 90.0 * degrees)
        self.assertAnglesAlmostEqual(lon + 90.0 * degrees,
                                     goEast.getLongitude())
        self.assertAnglesAlmostEqual(0.0 * degrees, goEast.getLatitude())
    def testRotatedValue(self):
        """Test if rotated() returns the expected value.
        """
        # Try rotating about the equatorial pole (ie. along a parallel).
        longitude = 90.0
        latitudes = [0.0, 30.0, 60.0]
        arcLen = 10.0
        pole = SpherePoint(0.0 * degrees, 90.0 * degrees)
        for latitude in latitudes:
            point = SpherePoint(longitude * degrees, latitude * degrees)
            newPoint = point.rotated(pole, arcLen * degrees)

            self.assertIsInstance(newPoint, SpherePoint)
            self.assertAlmostEqual(longitude + arcLen,
                                   newPoint.getLongitude().asDegrees())
            self.assertAlmostEqual(latitude,
                                   newPoint.getLatitude().asDegrees())

        # Try with pole = vernal equinox and rotate up the 90 degree meridian.
        pole = SpherePoint(0.0 * degrees, 0.0 * degrees)
        for latitude in latitudes:
            point = SpherePoint(longitude * degrees, latitude * degrees)
            newPoint = point.rotated(pole, arcLen * degrees)

            self.assertAlmostEqual(longitude,
                                   newPoint.getLongitude().asDegrees())
            self.assertAlmostEqual(latitude + arcLen,
                                   newPoint.getLatitude().asDegrees())

        # Test accuracy close to coordinate pole
        point = SpherePoint(90.0 * degrees, np.nextafter(90.0, -inf) * degrees)
        newPoint = point.rotated(pole, 90.0 * degrees)
        self.assertAlmostEqual(270.0, newPoint.getLongitude().asDegrees())
        self.assertAlmostEqual(90.0 - np.nextafter(90.0, -inf),
                               newPoint.getLatitude().asDegrees())

        # Generic pole; can't predict position, but test for rotation
        # invariant.
        pole = SpherePoint(283.5 * degrees, -23.6 * degrees)
        for lon, lat in self._dataset:
            point = SpherePoint(lon, lat)
            dist = point.separation(pole)
            newPoint = point.rotated(pole, -32.4 * afwGeom.radians)

            self.assertNotAlmostEqual(point.getLongitude().asDegrees(),
                                      newPoint.getLongitude().asDegrees())
            self.assertNotAlmostEqual(point.getLatitude().asDegrees(),
                                      newPoint.getLatitude().asDegrees())
            self.assertAnglesAlmostEqual(dist, newPoint.separation(pole))

        # Non-finite values give undefined rotations
        for latitude in latitudes:
            point = SpherePoint(longitude * degrees, latitude * degrees)
            nanPoint = point.rotated(pole, nan * degrees)
            infPoint = point.rotated(pole, inf * degrees)

            self.assertTrue(math.isnan(nanPoint.getLongitude().asRadians()))
            self.assertTrue(math.isnan(nanPoint.getLatitude().asRadians()))
            self.assertTrue(math.isnan(infPoint.getLongitude().asRadians()))
            self.assertTrue(math.isnan(infPoint.getLatitude().asRadians()))

        # Non-finite points rotate into non-finite points
        for point in [
                SpherePoint(-inf * degrees, 1.0 * radians),
                SpherePoint(32.0 * degrees, nan * radians),
        ]:
            newPoint = point.rotated(pole, arcLen * degrees)
            self.assertTrue(math.isnan(nanPoint.getLongitude().asRadians()))
            self.assertTrue(math.isnan(nanPoint.getLatitude().asRadians()))
            self.assertTrue(math.isnan(infPoint.getLongitude().asRadians()))
            self.assertTrue(math.isnan(infPoint.getLatitude().asRadians()))

        # Rotation around non-finite poles undefined
        for latitude in latitudes:
            point = SpherePoint(longitude * degrees, latitude * degrees)
            for pole in [
                    SpherePoint(-inf * degrees, 1.0 * radians),
                    SpherePoint(32.0 * degrees, nan * radians),
            ]:
                newPoint = point.rotated(pole, arcLen * degrees)
                self.assertTrue(math.isnan(
                    nanPoint.getLongitude().asRadians()))
                self.assertTrue(math.isnan(nanPoint.getLatitude().asRadians()))
                self.assertTrue(math.isnan(
                    infPoint.getLongitude().asRadians()))
                self.assertTrue(math.isnan(infPoint.getLatitude().asRadians()))
 def testDefaultConstructor(self):
     sp = SpherePoint()
     self.assertTrue(math.isnan(sp.getLongitude()))
     self.assertTrue(math.isnan(sp.getLatitude()))
     self.assertFalse(sp.isFinite())