def convertVectorFromPupilToBase(vectorPupil, pupilAzAlt): """Given a vector in pupil coordinates and the pupil pointing, compute the vector in base coords. Parameters ---------- vectorPupil : sequence of 3 `float` 3-dimesional vector in the :ref:`pupil frame <lsst.cbp.pupil_frame>`. pupilAzAlt : `lsst.geom.SpherePoint` Pointing of the pupil frame as :ref:`internal azimuth, altitude <lsst.cbp.internal_angles>`. Returns ------- vectorBase : `np.array` of 3 `float` 3-dimensional vector in the :ref:`base frame <lsst.cbp.base_frame>`. """ vectorMag = np.linalg.norm(vectorPupil) vectorSpPupil = SpherePoint(Vector3d(*vectorPupil)) telBase = SpherePoint(0, 0, radians) # rotate vector around pupil -y axis by dalt dalt = pupilAzAlt[1] - telBase[1] negYAxis = SpherePoint(Vector3d(0, -1, 0)) vectorSpRot1 = vectorSpPupil.rotated(axis=negYAxis, amount=dalt) # rotate that around base z axis by daz daz = pupilAzAlt[0] - telBase[0] zaxis = SpherePoint(Vector3d(0, 0, 1)) vectorSpBase = vectorSpRot1.rotated(axis=zaxis, amount=daz) return np.array(vectorSpBase.getVector()) * vectorMag
def convertVectorFromBaseToPupil(vectorBase, pupilAzAlt): """Given a vector in base coordinates and the pupil pointing, compute the vector in pupil coordinates. Parameters ---------- vectorBase : sequence of 3 `float` 3-dimensional vector in the :ref:`base frame <lsst.cbp.base_frame>`. pupilAzAlt : `lsst.geom.SpherePoint` Pointing of the pupil frame as :ref:`internal azimuth, altitude <lsst.cbp.internal_angles>`. Returns ------- vectorPupil : `np.array` of 3 `float` 3-dimensional vector in the :ref:`pupil frame <lsst.cbp.pupil_frame>`. Notes ----- This could be implemented as the following Euler angle rotation matrix, which is: - first rotate about the z axis by azimuth - then rotate about the rotated -y axis by altitude - there is no third rotation c1*c2 -s1 -c1*s2 c2*s1 c1 s1s2 s1 0 c2 where angle 1 = azimuth, angle 2 = altitude, sx = sine(angle x) and cx = cosine(angle x). Knowing this matrix is helpful, e.g. for math inside computeAzAltFromBasePupil. """ vectorMag = np.linalg.norm(vectorBase) vectorSpBase = SpherePoint(Vector3d(*vectorBase)) telBase = SpherePoint(0, 0, radians) # rotate vector around base z axis by -daz daz = pupilAzAlt[0] - telBase[0] zaxis = SpherePoint(Vector3d(0, 0, 1)) vectorSpRot1 = vectorSpBase.rotated(axis=zaxis, amount=-daz) # rotate vector around pupil -y axis by -dalt dalt = pupilAzAlt[1] - telBase[1] negYAxis = SpherePoint(Vector3d(0, -1, 0)) vectorSpPupil = vectorSpRot1.rotated(axis=negYAxis, amount=-dalt) return np.array(vectorSpPupil.getVector()) * vectorMag
def testRotatedAlias(self): """White-box test: all representations of a pole should rotate into the same point. """ longitudes = [0.0, 90.0, 242.0] latitude = 90.0 arcLen = 10.0 pole = SpherePoint(90.0*degrees, 0.0*degrees) for longitude in longitudes: point = SpherePoint(longitude*degrees, latitude*degrees) newPoint = point.rotated(pole, arcLen*degrees) self.assertAlmostEqual(0.0, newPoint.getLongitude().asDegrees()) self.assertAlmostEqual(80.0, newPoint.getLatitude().asDegrees())
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*geom.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()))