def testReadLsstSkyWcsStripMetadata(self): metadata = self.makeMetadata() nKeys = len(metadata.toList()) nToStrip = 12 + 6 # WCS "A" is also stripped frameSet1 = readLsstSkyWcs(metadata, strip=False) self.assertEqual(len(metadata.toList()), nKeys) crval = SpherePoint(metadata.getScalar("CRVAL1"), metadata.getScalar("CRVAL2"), degrees) crvalRad = crval.getPosition(radians) desiredCrpix = self.getCrpix(metadata) computedCrpix = frameSet1.applyInverse(crvalRad) self.assertPairsAlmostEqual(desiredCrpix, computedCrpix) # read again, this time stripping metadata frameSet2 = readLsstSkyWcs(metadata, strip=True) self.assertEqual(len(metadata.toList()), nKeys - nToStrip) self.assertEqual(frameSet1, frameSet2) # having stripped the WCS keywords, we should not be able to generate # a WCS from what's left with self.assertRaises(lsst.pex.exceptions.TypeError): readLsstSkyWcs(metadata, strip=False) # try a full WCS with just CRPIX1 or 2 missing for i in (1, 2): metadata = self.makeMetadata() metadata.remove("CRPIX%d" % (i,)) with self.assertRaises(lsst.pex.exceptions.TypeError): readLsstSkyWcs(metadata, strip=False)
def testEquality(self): """Test if tests for equality treat SpherePoints as values. """ # (In)equality is determined by value, not identity. # See DM-2347, DM-2465. These asserts are testing the # functionality of `==` and `!=` and should not be changed. for lon1, lat1 in self._dataset: point1 = SpherePoint(lon1, lat1) self.assertIsInstance(point1 == point1, bool) self.assertIsInstance(point1 != point1, bool) if point1.isFinite(): self.assertTrue(point1 == point1) self.assertFalse(point1 != point1) pointCopy = copy.deepcopy(point1) self.assertIsNot(pointCopy, point1) self.assertEqual(pointCopy, point1) self.assertEqual(point1, pointCopy) self.assertFalse(pointCopy != point1) self.assertFalse(point1 != pointCopy) else: self.assertFalse(point1 == point1) self.assertTrue(point1 != point1) for lon2, lat2 in self._dataset: if lon1 == lon2 and lat1 == lat2: continue point2 = SpherePoint(lon2, lat2) self.assertTrue(point2 != point1) self.assertTrue(point1 != point2) self.assertFalse(point2 == point1) self.assertFalse(point1 == point2) # Test for transitivity (may be assumed by algorithms). for delta in [10.0**(0.1*x) for x in range(-150, -49, 5)]: self.checkTransitive(delta*radians)
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 testAtPoleValue(self): """Test if atPole() returns the expected value. """ poleList = [SpherePoint(42.0*degrees, lat) for lat in self._poleLatitudes] + \ [SpherePoint(42.0*degrees, 0.0*radians - lat) for lat in self._poleLatitudes] + [ SpherePoint(afwGeom.Point3D(0.0, 0.0, 1.0)), SpherePoint(afwGeom.Point3D(0.0, 0.0, -1.0)), ] nonPoleList = [SpherePoint(42.0*degrees, self.nextDown(lat)) for lat in self._poleLatitudes] + \ [SpherePoint(42.0*degrees, self.nextUp(0.0*radians - lat)) for lat in self._poleLatitudes] + [ SpherePoint(afwGeom.Point3D(9.9e-7, 0.0, 1.0)), SpherePoint(afwGeom.Point3D(9.9e-7, 0.0, -1.0)), SpherePoint(0.0*degrees, nan*degrees), ] for pole in poleList: self.assertIsInstance(pole.atPole(), bool) self.assertTrue(pole.atPole()) for nonPole in nonPoleList: self.assertIsInstance(nonPole.atPole(), bool) self.assertFalse(nonPole.atPole())
def testGetDR7(self): obsSdssDir = lsst.utils.getPackageDir('obs_sdss') butler = dafPersist.Butler( root=os.path.join(obsSdssDir, "tests", "data", "dr7", "runs")) sub = butler.subset("fpC", run=5754, camcol=3, field=280, filter="r") self.assertEqual(len(sub), 1) for ref in sub: im = ref.get("fpC") w, h = im.getWidth(), im.getHeight() self.assertEqual(im.__class__, lsst.afw.image.ExposureU) self.assertEqual(w, 2048) self.assertEqual(h, 1489) im_md = ref.get("fpC_md") self.assertEqual(im_md.getScalar("RUN"), 5754) self.assertEqual(im_md.getScalar("FRAME"), 280) self.assertEqual(im_md.getScalar("STRIPE"), 82) msk = ref.get("fpM") w, h = msk.getWidth(), msk.getHeight() self.assertEqual(msk.__class__, lsst.afw.image.Mask[lsst.afw.image.MaskPixel]) self.assertEqual(w, 2048) self.assertEqual(h, 1489) psf = ref.get("psField") k = psf.getKernel() w, h = k.getWidth(), k.getHeight() self.assertEqual(psf.__class__, lsst.meas.algorithms.PcaPsf) self.assertEqual(w, 31) self.assertEqual(h, 31) wcs = ref.get("asTrans") self.assertIsInstance(wcs, SkyWcs) self.assertFalse(wcs.isFlipped) # comparison is to results from lsst.afw.image.TanWcs class self.assertSpherePointsAlmostEqual(wcs.pixelToSky(700, 1000), SpherePoint(343.6507738304687, -0.3509870420713227, degrees)) tsField = ref.get("tsField") self.assertAlmostEqual(tsField.gain, 4.72, 2) self.assertAlmostEqual(tsField.airmass, 1.2815132857671601) self.assertAlmostEqual(tsField.exptime, 53.907456) predDateStart = DateTime(53664.226070589997, DateTime.MJD, DateTime.TAI) predDateAvg = DateTime(predDateStart.nsecs(DateTime.TAI) + int(0.5e9*tsField.exptime), DateTime.TAI) self.assertAlmostEqual(tsField.dateAvg.get(), predDateAvg.get())
def testIsFiniteValue(self): """Test if isFinite() returns the expected value. """ finiteList = [ SpherePoint(0.0*degrees, -90.0*degrees), SpherePoint(afwGeom.Point3D(0.1, 0.2, 0.3)), ] nonFiniteList = [ SpherePoint(0.0*degrees, nan*degrees), SpherePoint(nan*degrees, 0.0*degrees), SpherePoint(inf*degrees, 0.0*degrees), SpherePoint(-inf*degrees, 0.0*degrees), SpherePoint(afwGeom.Point3D(nan, 0.2, 0.3)), SpherePoint(afwGeom.Point3D(0.1, inf, 0.3)), SpherePoint(afwGeom.Point3D(0.1, 0.2, -inf)), ] for finite in finiteList: self.assertIsInstance(finite.isFinite(), bool) self.assertTrue(finite.isFinite()) for nonFinite in nonFiniteList: self.assertIsInstance(nonFinite.isFinite(), bool) self.assertFalse(nonFinite.isFinite())
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 setArgDict(self, md, argDict): """Set an argument dict for makeVisitInfo and pop associated metadata @param[in,out] md metadata, as an lsst.daf.base.PropertyList or PropertySet @param[in,out] argdict a dict of arguments """ #I believe the names in capitals come from the header. You'll need #to change these to reflect your header keywords. startDate = self.popIsoDate(md, "DATE_OBS") argDict["exposureTime"] = self.popFloat(md, 'EXPTIME') argDict['darkTime'] = argDict['exposureTime'] argDict["date"] = self.offsetDate(startDate, 0.5 * argDict["exposureTime"]) argDict["boresightAzAlt"] = SpherePoint( self.popAngle(md, "AZ"), self.popAngle(md, "EL"), ) #argDict["boresightAirmass"] = self.popFloat(md, "AIRMASS") argDict["observatory"] = self.observatory
def testBearingToValueSameLongitude(self): """Test that bearingTo() returns +/- 90 for two points on the same longitude """ for longDeg in (0, 55, 270): for lat0Deg in (-90, -5, 0, 44, 90): sp0 = SpherePoint(longDeg, lat0Deg, degrees) for lat1Deg in (-90, -41, 1, 41, 90): if lat0Deg == lat1Deg: continue sp1 = SpherePoint(longDeg, lat1Deg, degrees) if sp0.atPole() and sp1.atPole(): # the points are at opposite poles; any bearing may be returned continue bearing = sp0.bearingTo(sp1) if lat1Deg > lat0Deg: self.assertAnglesAlmostEqual(bearing, 90 * degrees) else: self.assertAnglesAlmostEqual(bearing, -90 * degrees)
def setArgDict(self, md, argDict): """Set an argument dict for makeVisitInfo and pop associated metadata @param[in,out] md metadata, as an lsst.daf.base.PropertyList or PropertySet @param[in,out] argdict a dict of arguments """ argDict["exposureTime"] = self.popFloat(md, 'EXPTIME') startDate = self.popIsoDate(md, "DATE-OBS") argDict["date"] = self.offsetDate(startDate, 0.5 * argDict["exposureTime"]) argDict["boresightAzAlt"] = SpherePoint( self.popAngle(md, "AZ"), self.popAngle(md, "ALT"), ) argDict["boresightAirmass"] = self.popFloat(md, "AIRMASS") argDict["observatory"] = self.observatory argDict['darkTime'] = argDict['exposureTime']
def astropyPixelsToSky(self, astropyWcs, pixPosList): """Use an astropy wcs to convert pixels to sky @param[in] astropyWcs a celestial astropy.wcs.WCS with 2 axes in RA, Dec order @param[in] pixPosList 0-based pixel positions as lsst.afw.geom.Point2D or similar pairs @returns sky coordinates as a list of lsst.afw.geom.SpherePoint Converts the output to ICRS """ xarr = [p[0] for p in pixPosList] yarr = [p[1] for p in pixPosList] skyCoordList = astropy.wcs.utils.pixel_to_skycoord(xp=xarr, yp=yarr, wcs=astropyWcs, origin=0, mode="all") icrsList = [sc.transform_to("icrs") for sc in skyCoordList] return [ SpherePoint(sc.ra.deg * degrees, sc.dec.deg * degrees) for sc in icrsList ]
def testInit2ArgErrors(self): """Test if 2-argument form of __init__ handles invalid input. """ # Latitude should be checked for out-of-range. for lat in self._poleLatitudes: with self.assertRaises(pexEx.InvalidParameterError): SpherePoint(0.0*degrees, self.nextUp(lat)) with self.assertRaises(pexEx.InvalidParameterError): SpherePoint(0.0*degrees, self.nextDown(0.0*radians - lat)) # Longitude should not be checked for out of range. SpherePoint(360.0*degrees, 45.0*degrees) SpherePoint(-42.0*degrees, 45.0*degrees) SpherePoint(391.0*degrees, 45.0*degrees) # Infinite latitude is not allowed. with self.assertRaises(pexEx.InvalidParameterError): SpherePoint(-42.0*degrees, inf*degrees) with self.assertRaises(pexEx.InvalidParameterError): SpherePoint(-42.0*degrees, -inf*degrees)
def testMakeSimpleWcsMetadata(self): crpix = Point2D(111.1, 222.2) crval = SpherePoint(45.6 * degrees, 12.3 * degrees) scale = 1 * arcseconds for orientation in (0 * degrees, 21 * degrees): cdMatrix = makeCdMatrix(scale=scale, orientation=orientation) for projection in ("TAN", "STG"): metadata = makeSimpleWcsMetadata(crpix=crpix, crval=crval, cdMatrix=cdMatrix, projection=projection) desiredLength = 12 if orientation == 0 * degrees else 14 self.assertEqual(len(metadata.names()), desiredLength) self.assertEqual(metadata.getScalar("RADESYS"), "ICRS") self.assertAlmostEqual(metadata.getScalar("EQUINOX"), 2000.0) self.assertEqual(metadata.getScalar("CTYPE1"), "RA---" + projection) self.assertEqual(metadata.getScalar("CTYPE2"), "DEC--" + projection) for i in range(2): self.assertAlmostEqual( metadata.getScalar("CRPIX%d" % (i + 1, )), crpix[i] + 1) self.assertAlmostEqual( metadata.getScalar("CRVAL%d" % (i + 1, )), crval[i].asDegrees()) self.assertEqual(metadata.getScalar("CUNIT%d" % (i + 1, )), "deg") for i in range(2): for j in range(2): name = "CD%d_%d" % (i + 1, j + 1) if cdMatrix[i, j] != 0: self.assertAlmostEqual(metadata.getScalar(name), cdMatrix[i, j]) else: self.assertFalse(metadata.exists(name))
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()))
def testBearingToValueOnEquator(self): """Test if bearingTo() returns the expected value from a point on the equator """ lon0 = 90.0 lat0 = 0.0 # These tests only work from the equator. arcLen = 10.0 trials = [ # Along celestial equator dict(lon=lon0, lat=lat0, bearing=0.0, lonEnd=lon0 + arcLen, latEnd=lat0), # Along a meridian dict(lon=lon0, lat=lat0, bearing=90.0, lonEnd=lon0, latEnd=lat0 + arcLen), # 180 degree arc (should go to antipodal point) dict(lon=lon0, lat=lat0, bearing=45.0, lonEnd=lon0 + 180.0, latEnd=-lat0), # dict(lon=lon0, lat=lat0, bearing=45.0, lonEnd=lon0 + 90.0, latEnd=lat0 + 45.0), dict(lon=lon0, lat=lat0, bearing=225.0, lonEnd=lon0 - 90.0, latEnd=lat0 - 45.0), dict(lon=lon0, lat=np.nextafter(-90.0, inf), bearing=90.0, lonEnd=lon0, latEnd=0.0), dict(lon=lon0, lat=np.nextafter(-90.0, inf), bearing=0.0, lonEnd=lon0 + 90.0, latEnd=0.0), # Argument at a pole should work dict(lon=lon0, lat=lat0, bearing=270.0, lonEnd=lon0, latEnd=-90.0), # Support for non-finite values dict(lon=lon0, lat=nan, bearing=nan, lonEnd=lon0, latEnd=45.0), dict(lon=lon0, lat=lat0, bearing=nan, lonEnd=nan, latEnd=90.0), dict(lon=inf, lat=lat0, bearing=nan, lonEnd=lon0, latEnd=42.0), dict(lon=lon0, lat=lat0, bearing=nan, lonEnd=-inf, latEnd=42.0), ] for trial in trials: origin = SpherePoint(trial['lon'] * degrees, trial['lat'] * degrees) end = SpherePoint(trial['lonEnd'] * degrees, trial['latEnd'] * degrees) bearing = origin.bearingTo(end) self.assertIsInstance(bearing, afwGeom.Angle) if origin.isFinite() and end.isFinite(): self.assertGreaterEqual(bearing.asDegrees(), 0.0) self.assertLess(bearing.asDegrees(), 360.0) if origin.separation(end).asDegrees() != 180.0: if not math.isnan(trial['bearing']): self.assertAlmostEqual(trial['bearing'], bearing.asDegrees(), 12) else: self.assertTrue(math.isnan(bearing.asRadians()))
def testAtPoleValue(self): """Test if atPole() returns the expected value. """ poleList = \ [SpherePoint(42.0*degrees, lat) for lat in self._poleLatitudes] + \ [SpherePoint(42.0, lat.asDegrees(), degrees) for lat in self._poleLatitudes] + \ [SpherePoint(42.0*degrees, -lat) for lat in self._poleLatitudes] + \ [SpherePoint(42.0, -lat.asDegrees(), degrees) for lat in self._poleLatitudes] + \ [ SpherePoint(lsst.sphgeom.Vector3d(0.0, 0.0, 1.0)), SpherePoint(lsst.sphgeom.Vector3d(0.0, 0.0, -1.0)), ] nonPoleList = \ [SpherePoint(42.0*degrees, self.nextDown(lat)) for lat in self._poleLatitudes] + \ [SpherePoint(42.0, self.nextDown(lat).asDegrees(), degrees) for lat in self._poleLatitudes] + \ [SpherePoint(42.0*degrees, self.nextUp(-lat)) for lat in self._poleLatitudes] + \ [SpherePoint(42.0, self.nextUp(-lat).asDegrees(), degrees) for lat in self._poleLatitudes] + \ [ SpherePoint(lsst.sphgeom.Vector3d(9.9e-7, 0.0, 1.0)), SpherePoint(lsst.sphgeom.Vector3d(9.9e-7, 0.0, -1.0)), SpherePoint(0.0*degrees, nan*degrees), ] for pole in poleList: self.assertIsInstance(pole.atPole(), bool) self.assertTrue(pole.atPole()) for nonPole in nonPoleList: self.assertIsInstance(nonPole.atPole(), bool) self.assertFalse(nonPole.atPole())
def testGetVectorValue(self): """Test if getVector() returns the expected value. The test includes conformance to vector-angle conventions. """ for lon, lat, vector in [ (0.0 * degrees, 0.0 * degrees, lsst.sphgeom.Vector3d(1.0, 0.0, 0.0)), (90.0 * degrees, 0.0 * degrees, lsst.sphgeom.Vector3d(0.0, 1.0, 0.0)), (0.0 * degrees, 90.0 * degrees, lsst.sphgeom.Vector3d(0.0, 0.0, 1.0)), ]: for point in ( SpherePoint(lon, lat), SpherePoint(lon.asDegrees(), lat.asDegrees(), degrees), SpherePoint(lon.asRadians(), lat.asRadians(), radians), ): newVector = point.getVector() self.assertIsInstance(newVector, lsst.sphgeom.UnitVector3d) for oldElement, newElement in zip(vector, newVector): self.assertAlmostEqual(oldElement, newElement) # Convert back to spherical. newLon, newLat = SpherePoint(newVector) self.assertAlmostEqual(newLon.asDegrees(), lon.asDegrees()) self.assertAlmostEqual(newLat.asDegrees(), lat.asDegrees()) # Try some un-normalized ones, too. pointList = [ ((0.0, 0.0), lsst.sphgeom.Vector3d(1.3, 0.0, 0.0)), ((90.0, 0.0), lsst.sphgeom.Vector3d(0.0, 1.2, 0.0)), ((0.0, 90.0), lsst.sphgeom.Vector3d(0.0, 0.0, 2.3)), ((0.0, 0.0), lsst.sphgeom.Vector3d(0.5, 0.0, 0.0)), ((90.0, 0.0), lsst.sphgeom.Vector3d(0.0, 0.7, 0.0)), ((0.0, 90.0), lsst.sphgeom.Vector3d(0.0, 0.0, 0.9)), ] for lonLat, vector in pointList: # Only convert from vector to spherical. point = SpherePoint(vector) newLon, newLat = point self.assertAlmostEqual(lonLat[0], newLon.asDegrees()) self.assertAlmostEqual(lonLat[1], newLat.asDegrees()) vector = lsst.sphgeom.Vector3d(point.getVector()) self.assertAlmostEqual(1.0, vector.getSquaredNorm()) # Ill-defined points should be all NaN after normalization cleanValues = [0.5, -0.3, 0.2] badValues = [nan, inf, -inf] for i in range(3): for badValue in badValues: values = cleanValues[:] values[i] = badValue nonFiniteVector = lsst.sphgeom.Vector3d(*values) for element in SpherePoint(nonFiniteVector).getVector(): self.assertTrue(math.isnan(element))
def testCopyConstructor(self): sp = SpherePoint(-42.0 * degrees, 45.0 * degrees) spcopy = SpherePoint(sp) self.assertEqual(sp, spcopy)
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 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 testOffsetError(self): """Test if offset() correctly handles invalid input. """ northPole = SpherePoint(0.0*degrees, 90.0*degrees) southPole = SpherePoint(0.0*degrees, -90.0*degrees) nonSingularity = SpherePoint(0.0*degrees, 45.0*degrees) with self.assertRaises(pexEx.DomainError): northPole.offset(-90.0*degrees, 10.0*degrees) with self.assertRaises(pexEx.DomainError): southPole.offset(90.0*degrees, 0.1*degrees) with self.assertRaises(pexEx.InvalidParameterError): nonSingularity.offset(90.0*degrees, -0.1*degrees)
def testEqualityAlias(self): """Test if == handles coordinate degeneracies correctly. """ # Longitude wrapping self.assertEqual(SpherePoint(360.0*degrees, -42.0*degrees), SpherePoint(0.0*degrees, -42.0*degrees)) self.assertEqual(SpherePoint(-90.0*degrees, -42.0*degrees), SpherePoint(270.0*degrees, -42.0*degrees)) # Polar degeneracy self.assertEqual(SpherePoint(42.0*degrees, 90.0*degrees), SpherePoint(270.0*degrees, 90.0*degrees)) self.assertEqual(SpherePoint(-42.0*degrees, -90.0*degrees), SpherePoint(83.0*degrees, -90.0*degrees)) self.assertNotEqual(SpherePoint(83.0*degrees, 90.0*degrees), SpherePoint(83.0*degrees, -90.0*degrees)) # White-box test: how are pole/non-pole comparisons handled? self.assertNotEqual(SpherePoint(42.0*degrees, 90.0*degrees), SpherePoint(42.0*degrees, 0.0*degrees))
def testGetLongitudeValue(self): """Test if getLongitude() returns the expected value. """ for lon, lat in self._dataset: point = SpherePoint(lon, lat) self.assertIsInstance(point.getLongitude(), afwGeom.Angle) # Behavior for non-finite points is undefined; depends on internal # data representation if point.isFinite(): self.assertGreaterEqual(point.getLongitude().asDegrees(), 0.0) self.assertLess(point.getLongitude().asDegrees(), 360.0) # Longitude not guaranteed to match input at pole if not point.atPole(): # assertAnglesAlmostEqual handles angle wrapping internally self.assertAnglesAlmostEqual(lon, point.getLongitude()) # Vector construction should return valid longitude even in edge cases. point = SpherePoint(afwGeom.Point3D(0.0, 0.0, -1.0)) self.assertGreaterEqual(point.getLongitude().asDegrees(), 0.0) self.assertLess(point.getLongitude().asDegrees(), 360.0)
def testLonLatConstructorErrors(self): """Test if the longitude, latitude constructors handle invalid input """ # Latitude should be checked for out-of-range. for lat in self._poleLatitudes: with self.assertRaises(pexEx.InvalidParameterError): SpherePoint(0.0 * degrees, self.nextUp(lat)) with self.assertRaises(pexEx.InvalidParameterError): SpherePoint(0.0, self.nextUp(lat).asDegrees(), degrees) with self.assertRaises(pexEx.InvalidParameterError): SpherePoint(0.0 * degrees, self.nextDown(-lat)) with self.assertRaises(pexEx.InvalidParameterError): SpherePoint(0.0, self.nextDown(-lat).asDegrees(), degrees) # Longitude should not be checked for out of range. SpherePoint(360.0 * degrees, 45.0 * degrees) SpherePoint(360.0, 45.0, degrees) SpherePoint(-42.0 * degrees, 45.0 * degrees) SpherePoint(-42.0, 45.0, degrees) SpherePoint(391.0 * degrees, 45.0 * degrees) SpherePoint(391.0, 45.0, degrees) # Infinite latitude is not allowed. with self.assertRaises(pexEx.InvalidParameterError): SpherePoint(-42.0 * degrees, inf * degrees) with self.assertRaises(pexEx.InvalidParameterError): SpherePoint(-42.0, inf, degrees) with self.assertRaises(pexEx.InvalidParameterError): SpherePoint(-42.0 * degrees, -inf * degrees) with self.assertRaises(pexEx.InvalidParameterError): SpherePoint(-42.0, -inf, degrees)
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 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))
import lsst.pex.exceptions as pexExcept import lsst.daf.persistence as dafPersist from lsst.afw.image import RotType from lsst.afw.geom import degrees, radians, arcseconds, SpherePoint # Desired VisitInfo values for visit 229388, shared between test_getRaw.py and # test_getInstcal.py visit229388_info = { "dateAvg": DateTime("2013-09-01T06:06:00.876924000", DateTime.TAI), "exposureTime": 200.0, "darkTime": 201.15662, "era": 1.25232*radians, "boresightRaDec": SpherePoint(42.81995833, -0.00158305, degrees), "boresightAzAlt": SpherePoint(61.24, 90 - 50.46, degrees), "boresightAirmass": 1.57, "boresightRotAngle": 90*degrees, "rotType": RotType.SKY, "obs_longitude": -70.81489000000001*degrees, "obs_latitude": -30.16606*degrees, "obs_elevation": 2215.0, "weath_airTemperature": 11.9, "weath_airPressure": 77900., "weath_humidity": 23.0} class GetRawTestCase(lsst.utils.tests.TestCase): """Testing butler raw image retrieval"""
def testDefaultConstructor(self): sp = SpherePoint() self.assertTrue(math.isnan(sp.getLongitude())) self.assertTrue(math.isnan(sp.getLatitude())) self.assertFalse(sp.isFinite())
def setUp(self): # arbitrary values self.crpix = Point2D(100, 100) self.crval = SpherePoint(30 * degrees, 45 * degrees) self.scale = 1.0 * arcseconds
def testGetVectorValue(self): """Test if getVector() returns the expected value. The test includes conformance to vector-angle conventions. """ pointList = [ ((0.0, 0.0), afwGeom.Point3D(1.0, 0.0, 0.0)), ((90.0, 0.0), afwGeom.Point3D(0.0, 1.0, 0.0)), ((0.0, 90.0), afwGeom.Point3D(0.0, 0.0, 1.0)), ] for lonLat, vector in pointList: # Convert to Point3D. point = SpherePoint(lonLat[0]*degrees, lonLat[1]*degrees) newVector = point.getVector() self.assertIsInstance(newVector, afwGeom.Point3D) for oldElement, newElement in zip(vector, newVector): self.assertAlmostEqual(oldElement, newElement) # Convert back to spherical. newLon, newLat = SpherePoint(newVector) self.assertAlmostEqual(newLon.asDegrees(), lonLat[0]) self.assertAlmostEqual(newLat.asDegrees(), lonLat[1]) # Try some un-normalized ones, too. pointList = [ ((0.0, 0.0), afwGeom.Point3D(1.3, 0.0, 0.0)), ((90.0, 0.0), afwGeom.Point3D(0.0, 1.2, 0.0)), ((0.0, 90.0), afwGeom.Point3D(0.0, 0.0, 2.3)), ((0.0, 0.0), afwGeom.Point3D(0.5, 0.0, 0.0)), ((90.0, 0.0), afwGeom.Point3D(0.0, 0.7, 0.0)), ((0.0, 90.0), afwGeom.Point3D(0.0, 0.0, 0.9)), ] for lonLat, vector in pointList: # Only convert from vector to spherical. point = SpherePoint(vector) newLon, newLat = point self.assertAlmostEqual(lonLat[0], newLon.asDegrees()) self.assertAlmostEqual(lonLat[1], newLat.asDegrees()) self.assertAlmostEqual(1.0, point.getVector().distanceSquared( afwGeom.Point3D(0.0, 0.0, 0.0))) # Ill-defined points should be all NaN after normalization cleanVector = afwGeom.Point3D(0.5, -0.3, 0.2) badValues = [nan, inf, -inf] for i in range(3): for badValue in badValues: # Ensure each subtest is independent dirtyVector = copy.deepcopy(cleanVector) dirtyVector[i] = badValue for element in SpherePoint(dirtyVector).getVector(): self.assertTrue(math.isnan(element))