def test_trixel_bounding_circle(self): """ Verify that the trixel's bounding_circle method returns a circle that contains all of the corners of the trixel """ rng = np.random.RandomState(142) n_test_cases = 5 for i_test in range(n_test_cases): htmid = (13 << 6)+rng.randint(1, 2**6-1) trixel = trixelFromHtmid(htmid) bounding_circle = trixel.bounding_circle ra_0, dec_0 = sphericalFromCartesian(bounding_circle[0]) ra_list = [] dec_list = [] for cc in trixel.corners: ra, dec = sphericalFromCartesian(cc) ra_list.append(ra) dec_list.append(dec) ra_list = np.array(ra_list) dec_list = np.array(dec_list) distance = _angularSeparation(ra_0, dec_0, ra_list, dec_list) distance = arcsecFromRadians(distance) radius = arcsecFromRadians(bounding_circle[2]) self.assertLessEqual(distance.max()-radius, 1.0e-8) self.assertLess(np.abs(distance.max()-radius), 1.0e-8)
def testAppGeoFromICRS(self): mjd = 42350.0 for pmRaList in [self.pm_raList, None]: for pmDecList in [self.pm_decList, None]: for pxList in [self.pxList, None]: for vRadList in [self.v_radList, None]: raRad, decRad = utils._appGeoFromICRS(self.raList, self.decList, pmRaList, pmDecList, pxList, vRadList, mjd=ModifiedJulianDate(TAI=mjd)) raDeg, decDeg = utils.appGeoFromICRS(np.degrees(self.raList), np.degrees(self.decList), utils.arcsecFromRadians(pmRaList), utils.arcsecFromRadians(pmDecList), utils.arcsecFromRadians(pxList), vRadList, mjd=ModifiedJulianDate(TAI=mjd)) dRa = utils.arcsecFromRadians( raRad - np.radians(raDeg)) np.testing.assert_array_almost_equal( dRa, np.zeros(self.nStars), 9) dDec = utils.arcsecFromRadians( raRad - np.radians(raDeg)) np.testing.assert_array_almost_equal( dDec, np.zeros(self.nStars), 9)
def testIcrsFromObserved(self): obs = ObservationMetaData(pointingRA=35.0, pointingDec=-45.0, mjd=43572.0) for includeRefraction in [True, False]: raRad, decRad = utils._icrsFromObserved( self.raList, self.decList, obs_metadata=obs, epoch=2000.0, includeRefraction=includeRefraction) raDeg, decDeg = utils.icrsFromObserved( np.degrees(self.raList), np.degrees(self.decList), obs_metadata=obs, epoch=2000.0, includeRefraction=includeRefraction) dRa = utils.arcsecFromRadians(raRad - np.radians(raDeg)) np.testing.assert_array_almost_equal(dRa, np.zeros(self.nStars), 9) dDec = utils.arcsecFromRadians(decRad - np.radians(decDeg)) np.testing.assert_array_almost_equal(dDec, np.zeros(self.nStars), 9)
def test_trixel_bounding_circle(self): """ Verify that the trixel's bounding_circle method returns a circle that contains all of the corners of the trixel """ rng = np.random.RandomState(142) n_test_cases = 5 for i_test in range(n_test_cases): htmid = (13 << 6) + rng.randint(1, 2**6 - 1) trixel = trixelFromHtmid(htmid) bounding_circle = trixel.bounding_circle ra_0, dec_0 = sphericalFromCartesian(bounding_circle[0]) ra_list = [] dec_list = [] for cc in trixel.corners: ra, dec = sphericalFromCartesian(cc) ra_list.append(ra) dec_list.append(dec) ra_list = np.array(ra_list) dec_list = np.array(dec_list) distance = _angularSeparation(ra_0, dec_0, ra_list, dec_list) distance = arcsecFromRadians(distance) radius = arcsecFromRadians(bounding_circle[2]) self.assertLessEqual(distance.max() - radius, 1.0e-8) self.assertLess(np.abs(distance.max() - radius), 1.0e-8)
def testObservedFromICRS(self): obs = ObservationMetaData(pointingRA=35.0, pointingDec=-45.0, mjd=43572.0) for pmRaList in [self.pm_raList, None]: for pmDecList in [self.pm_decList, None]: for pxList in [self.pxList, None]: for vRadList in [self.v_radList, None]: for includeRefraction in [True, False]: raRad, decRad = utils._observedFromICRS(self.raList, self.decList, pm_ra=pmRaList, pm_dec=pmDecList, parallax=pxList, v_rad=vRadList, obs_metadata=obs, epoch=2000.0, includeRefraction=includeRefraction) raDeg, decDeg = utils.observedFromICRS(np.degrees(self.raList), np.degrees(self.decList), pm_ra=utils.arcsecFromRadians(pmRaList), pm_dec=utils.arcsecFromRadians(pmDecList), parallax=utils.arcsecFromRadians(pxList), v_rad=vRadList, obs_metadata=obs, epoch=2000.0, includeRefraction=includeRefraction) dRa = utils.arcsecFromRadians(raRad-np.radians(raDeg)) np.testing.assert_array_almost_equal(dRa, np.zeros(self.nStars), 9) dDec = utils.arcsecFromRadians(decRad-np.radians(decDeg)) np.testing.assert_array_almost_equal(dDec, np.zeros(self.nStars), 9)
def testpupilCoordsFromRaDec(self): obs = ObservationMetaData(pointingRA=23.5, pointingDec=-115.0, mjd=42351.0, rotSkyPos=127.0) # need to make sure the test points are tightly distributed around the bore site, or # PALPY will throw an error raList = self.rng.random_sample( self.nStars) * np.radians(1.0) + np.radians(23.5) decList = self.rng.random_sample( self.nStars) * np.radians(1.0) + np.radians(-115.0) xpControl, ypControl = utils._pupilCoordsFromRaDec(raList, decList, obs_metadata=obs, epoch=2000.0) xpTest, ypTest = utils.pupilCoordsFromRaDec(np.degrees(raList), np.degrees(decList), obs_metadata=obs, epoch=2000.0) dx = utils.arcsecFromRadians(xpControl - xpTest) np.testing.assert_array_almost_equal(dx, np.zeros(self.nStars), 9) dy = utils.arcsecFromRadians(ypControl - ypTest) np.testing.assert_array_almost_equal(dy, np.zeros(self.nStars), 9)
def test_raDecAltAz_noRefraction_degVsRadians(self): """ Check that raDecFromAltAz and altAzPaFromRaDec are consistent in a degrees-versus-radians sense when refraction is turned off """ rng = np.random.RandomState(34) n_samples = 10 ra_in = rng.random_sample(n_samples)*360.0 dec_in = rng.random_sample(n_samples)*180.0 - 90.0 mjd = 43000.0 obs = utils.ObservationMetaData(mjd=mjd) alt, az, pa = utils.altAzPaFromRaDec(ra_in, dec_in, obs, includeRefraction=False) alt_rad, az_rad, pa_rad = utils._altAzPaFromRaDec(np.radians(ra_in), np.radians(dec_in), obs, includeRefraction=False) distance = utils.haversine(az_rad, alt_rad, np.radians(az), np.radians(alt)) self.assertLess(utils.arcsecFromRadians(distance).min(), 0.001) np.testing.assert_array_almost_equal(pa, np.degrees(pa_rad), decimal=12) ra, dec = utils.raDecFromAltAz(alt, az, obs, includeRefraction=False) ra_rad, dec_rad = utils._raDecFromAltAz(alt_rad, az_rad, obs, includeRefraction=False) distance = utils.haversine(ra_rad, dec_rad, np.radians(ra), np.radians(dec)) self.assertLess(utils.arcsecFromRadians(distance).min(), 0.001)
def testAppGeoFromICRS(self): mjd = 42350.0 for pmRaList in [self.pm_raList, None]: for pmDecList in [self.pm_decList, None]: for pxList in [self.pxList, None]: for vRadList in [self.v_radList, None]: raRad, decRad = utils._appGeoFromICRS( self.raList, self.decList, pmRaList, pmDecList, pxList, vRadList, mjd=ModifiedJulianDate(TAI=mjd)) raDeg, decDeg = utils.appGeoFromICRS( np.degrees(self.raList), np.degrees(self.decList), utils.arcsecFromRadians(pmRaList), utils.arcsecFromRadians(pmDecList), utils.arcsecFromRadians(pxList), vRadList, mjd=ModifiedJulianDate(TAI=mjd)) dRa = utils.arcsecFromRadians(raRad - np.radians(raDeg)) np.testing.assert_array_almost_equal( dRa, np.zeros(self.nStars), 9) dDec = utils.arcsecFromRadians(raRad - np.radians(raDeg)) np.testing.assert_array_almost_equal( dDec, np.zeros(self.nStars), 9)
def testAppGeoFromObserved(self): obs = ObservationMetaData(pointingRA=35.0, pointingDec=-45.0, mjd=43572.0) for includeRefraction in (True, False): for wavelength in (0.5, 0.2, 0.3): raRad, decRad = utils._appGeoFromObserved( self.raList, self.decList, includeRefraction=includeRefraction, wavelength=wavelength, obs_metadata=obs) raDeg, decDeg = utils.appGeoFromObserved( np.degrees(self.raList), np.degrees(self.decList), includeRefraction=includeRefraction, wavelength=wavelength, obs_metadata=obs) dRa = utils.arcsecFromRadians(raRad - np.radians(raDeg)) np.testing.assert_array_almost_equal(dRa, np.zeros(len(dRa)), 9) dDec = utils.arcsecFromRadians(decRad - np.radians(decDeg)) np.testing.assert_array_almost_equal(dDec, np.zeros(len(dDec)), 9)
def test_de_precession(self): """ test de-precession by de-precessing a list of RA, Dec and verifying that the distance between the de-precessed points is the same as the distance between the input points. Also verify that the observed boresite gets de-precessed correctly """ rng = np.random.RandomState(12) n_samples = 5 pra = 34.0 pdec = 65.0 obs = ObservationMetaData(pointingRA=pra, pointingDec=pdec, mjd=58324.1) raObs, decObs = _observedFromICRS(np.array([np.radians(pra)]), np.array([np.radians(pdec)]), obs_metadata=obs, epoch=2000.0, includeRefraction=False) ra_list = [] dec_list = [] ra_list.append(raObs[0]) dec_list.append(decObs[0]) for rr, dd in zip( rng.random_sample(n_samples) * 2.0 * np.pi, (rng.random_sample(n_samples) - 0.5) * np.pi): ra_list.append(rr) dec_list.append(dd) ra_list = np.array(ra_list) dec_list = np.array(dec_list) raDecTransformed = PhoSimAstrometryBase()._dePrecess( ra_list, dec_list, obs) dd = arcsecFromRadians( haversine(np.radians(pra), np.radians(pdec), raDecTransformed[0][0], raDecTransformed[1][0])) self.assertLess(dd, 1.0e-6) dd0 = arcsecFromRadians( haversine(raObs[0], decObs[0], np.radians(pra), np.radians(pdec))) self.assertLess(dd, dd0) for ix in range(n_samples + 1): for iy in range(n_samples + 1): if ix != iy: dd1 = arcsecFromRadians( haversine(ra_list[ix], dec_list[ix], ra_list[iy], dec_list[iy])) dd2 = arcsecFromRadians( haversine(raDecTransformed[0][ix], raDecTransformed[1][ix], raDecTransformed[0][iy], raDecTransformed[1][iy])) self.assertAlmostEqual(dd1, dd2, delta=6)
def test_altAzPaFromRaDec_no_refraction(self): """ Test that altAzPaFromRaDec gives a sane answer when you turn off refraction. """ rng = np.random.RandomState(44) n_samples = 10 n_batches = 10 for i_batch in range(n_batches): # first, generate some sane RA, Dec values by generating sane # Alt, Az values with refraction and converting them into # RA, Dec alt_sane = rng.random_sample(n_samples)*45.0 + 45.0 az_sane = rng.random_sample(n_samples)*360.0 mjd_input = rng.random_sample(n_samples)*10000.0 + 40000.0 mjd_list = utils.ModifiedJulianDate.get_list(TAI=mjd_input) ra_sane = [] dec_sane = [] obs_sane = [] for alt, az, mjd in zip(alt_sane, az_sane, mjd_list): obs = utils.ObservationMetaData(mjd=mjd) ra, dec = utils.raDecFromAltAz(alt, az, obs) ra_sane.append(ra) dec_sane.append(dec) obs_sane.append(obs) # Now, loop over our refracted RA, Dec, Alt, Az values. # Convert from RA, Dec to unrefracted Alt, Az. Then, apply refraction # with our applyRefraction method. Check that the resulting refracted # zenith distance is: # 1) within 0.1 arcsec of the zenith distance of the already refracted # alt value calculated above # # 2) closer to the zenith distance calculated above than to the # unrefracted zenith distance for ra, dec, obs, alt_ref, az_ref in \ zip(ra_sane, dec_sane, obs_sane, alt_sane, az_sane): alt, az, pa = utils.altAzPaFromRaDec(ra, dec, obs, includeRefraction = False) tanz, tanz3 = utils.refractionCoefficients(site=obs.site) refracted_zd = utils.applyRefraction(np.radians(90.0-alt), tanz, tanz3) # Check that the two independently refracted zenith distances agree # to within 0.1 arcsec self.assertLess(np.abs(utils.arcsecFromRadians(refracted_zd) - utils.arcsecFromRadians(np.radians(90.0-alt_ref))), 0.1) # Check that the two refracted zenith distances are closer to each other # than to the unrefracted zenith distance self.assertLess(np.abs(np.degrees(refracted_zd)-(90.0-alt_ref)), np.abs((90.0-alt_ref) - (90.0-alt))) self.assertLess(np.abs(np.degrees(refracted_zd)-(90.0-alt_ref)), np.abs(np.degrees(refracted_zd) - (90.0-alt)))
def testTanSipWcs(self): """ Test that tanSipWcsFromDetector works by fitting a TAN WCS and a TAN-SIP WCS to a detector with distortions and verifying that the TAN-SIP WCS better approximates the truth. """ tanWcs = tanWcsFromDetector(self.detector.getName(), self.camera_wrapper, self.obs, self.epoch) tanSipWcs = tanSipWcsFromDetector(self.detector.getName(), self.camera_wrapper, self.obs, self.epoch) tanWcsRa = [] tanWcsDec = [] tanSipWcsRa = [] tanSipWcsDec = [] xPixList = [] yPixList = [] for xx in np.arange(0.0, 4001.0, 100.0): for yy in np.arange(0.0, 4001.0, 100.0): xPixList.append(xx) yPixList.append(yy) pt = afwGeom.Point2D(xx, yy) skyPt = tanWcs.pixelToSky(pt).getPosition(LsstGeom.degrees) tanWcsRa.append(skyPt.getX()) tanWcsDec.append(skyPt.getY()) skyPt = tanSipWcs.pixelToSky(pt).getPosition(LsstGeom.degrees) tanSipWcsRa.append(skyPt.getX()) tanSipWcsDec.append(skyPt.getY()) tanWcsRa = np.radians(np.array(tanWcsRa)) tanWcsDec = np.radians(np.array(tanWcsDec)) tanSipWcsRa = np.radians(np.array(tanSipWcsRa)) tanSipWcsDec = np.radians(np.array(tanSipWcsDec)) xPixList = np.array(xPixList) yPixList = np.array(yPixList) (raTest, decTest) = self.camera_wrapper._raDecFromPixelCoords(xPixList, yPixList, [self.detector.getName()]*len(xPixList), obs_metadata=self.obs, epoch=self.epoch) tanDistanceList = arcsecFromRadians(haversine(raTest, decTest, tanWcsRa, tanWcsDec)) tanSipDistanceList = arcsecFromRadians(haversine(raTest, decTest, tanSipWcsRa, tanSipWcsDec)) maxDistanceTan = tanDistanceList.max() maxDistanceTanSip = tanSipDistanceList.max() msg = 'max error in TAN WCS %e arcsec; in TAN-SIP %e arcsec' % (maxDistanceTan, maxDistanceTanSip) self.assertLess(maxDistanceTanSip, 0.01, msg=msg) self.assertGreater(maxDistanceTan-maxDistanceTanSip, 1.0e-10, msg=msg)
def _dePrecess(self, ra_in, dec_in, obs): """ Transform a set of RA, Dec pairs by subtracting out a rotation which represents the effects of precession, nutation, and aberration. Specifically: Calculate the displacement between the boresite and the boresite corrected for precession, nutation, and aberration (not refraction). Convert boresite and corrected boresite to Cartesian coordinates. Calculate the rotation matrix to go between those Cartesian vectors. Convert [ra_in, dec_in] into Cartesian coordinates. Apply the rotation vector to those Cartesian coordinates. Convert back to ra, dec-like coordinates @param [in] ra_in is a numpy array of RA in radians @param [in] dec_in is a numpy array of Dec in radians @param [in] obs is an ObservationMetaData @param [out] ra_out is a numpy array of de-precessed RA in radians @param [out] dec_out is a numpy array of de-precessed Dec in radians """ if len(ra_in) == 0: return np.array([[], []]) precessedRA, precessedDec = _observedFromICRS(obs._pointingRA, obs._pointingDec, obs_metadata=obs, epoch=2000.0, includeRefraction=False) if (not hasattr(self, '_icrs_to_phosim_rotator') or arcsecFromRadians( _angularSeparation(obs._pointingRA, obs._pointingDec, self._icrs_to_phosim_rotator._ra1, self._icrs_to_phosim_rotator._dec1)) > 1.0e-6 or arcsecFromRadians( _angularSeparation(precessedRA, precessedDec, self._icrs_to_phosim_rotator._ra0, self._icrs_to_phosim_rotator._dec0)) > 1.0e-6): self._icrs_to_phosim_rotator = _FieldRotator( precessedRA, precessedDec, obs._pointingRA, obs._pointingDec) ra_deprecessed, dec_deprecessed = self._icrs_to_phosim_rotator.transform( ra_in, dec_in) return np.array([ra_deprecessed, dec_deprecessed])
def testTanSipWcs(self): """ Test that tanSipWcsFromDetector works by fitting a TAN WCS and a TAN-SIP WCS to a detector with distortions and verifying that the TAN-SIP WCS better approximates the truth. """ tanWcs = tanWcsFromDetector(self.detector, self.camera, self.obs, self.epoch) tanSipWcs = tanSipWcsFromDetector(self.detector, self.camera, self.obs, self.epoch) tanWcsRa = [] tanWcsDec = [] tanSipWcsRa = [] tanSipWcsDec = [] xPixList = [] yPixList = [] for xx in numpy.arange(0.0, 4001.0, 100.0): for yy in numpy.arange(0.0, 4001.0, 100.0): xPixList.append(xx) yPixList.append(yy) pt = afwGeom.Point2D(xx ,yy) skyPt = tanWcs.pixelToSky(pt).getPosition() tanWcsRa.append(skyPt.getX()) tanWcsDec.append(skyPt.getY()) skyPt = tanSipWcs.pixelToSky(pt).getPosition() tanSipWcsRa.append(skyPt.getX()) tanSipWcsDec.append(skyPt.getY()) tanWcsRa = numpy.radians(numpy.array(tanWcsRa)) tanWcsDec = numpy.radians(numpy.array(tanWcsDec)) tanSipWcsRa = numpy.radians(numpy.array(tanSipWcsRa)) tanSipWcsDec = numpy.radians(numpy.array(tanSipWcsDec)) xPixList = numpy.array(xPixList) yPixList = numpy.array(yPixList) raTest, decTest = _raDecFromPixelCoords(xPixList, yPixList, [self.detector.getName()]*len(xPixList), camera=self.camera, obs_metadata=self.obs, epoch=self.epoch) tanDistanceList = arcsecFromRadians(haversine(raTest, decTest, tanWcsRa, tanWcsDec)) tanSipDistanceList = arcsecFromRadians(haversine(raTest, decTest, tanSipWcsRa, tanSipWcsDec)) maxDistanceTan = tanDistanceList.max() maxDistanceTanSip = tanSipDistanceList.max() msg = 'max error in TAN WCS %e arcsec; in TAN-SIP %e arcsec' % (maxDistanceTan, maxDistanceTanSip) self.assertLess(maxDistanceTanSip, 0.01, msg=msg) self.assertGreater(maxDistanceTan-maxDistanceTanSip, 1.0e-10, msg=msg)
def testRaDecFromPupil(self): """ Test conversion from pupil coordinates back to Ra, Dec """ mjd = ModifiedJulianDate(TAI=52000.0) solarRA, solarDec = solarRaDec(mjd) # to make sure that we are more than 45 degrees from the Sun as required # for _icrsFromObserved to be at all accurate raCenter = solarRA + 100.0 decCenter = solarDec - 30.0 obs = ObservationMetaData(pointingRA=raCenter, pointingDec=decCenter, boundType='circle', boundLength=0.1, rotSkyPos=23.0, mjd=mjd) nSamples = 1000 rng = np.random.RandomState(42) ra = (rng.random_sample(nSamples) * 0.1 - 0.2) + np.radians(raCenter) dec = (rng.random_sample(nSamples) * 0.1 - 0.2) + np.radians(decCenter) xp, yp = _pupilCoordsFromRaDec(ra, dec, obs_metadata=obs, epoch=2000.0) raTest, decTest = _raDecFromPupilCoords(xp, yp, obs_metadata=obs, epoch=2000.0) distance = arcsecFromRadians(haversine(ra, dec, raTest, decTest)) dex = np.argmax(distance) worstSolarDistance = distanceToSun(np.degrees(ra[dex]), np.degrees(dec[dex]), mjd) msg = "_raDecFromPupilCoords off by %e arcsec at distance to Sun of %e degrees" % \ (distance.max(), worstSolarDistance) self.assertLess(distance.max(), 1.0e-6, msg=msg) # now check that passing in the xp, yp values one at a time still gives # the right answer for ix in range(len(ra)): ra_f, dec_f = _raDecFromPupilCoords(xp[ix], yp[ix], obs_metadata=obs, epoch=2000.0) self.assertIsInstance(ra_f, np.float) self.assertIsInstance(dec_f, np.float) dist_f = arcsecFromRadians( haversine(ra_f, dec_f, raTest[ix], decTest[ix])) self.assertLess(dist_f, 1.0e-9)
def testRaDecFromPupil_noRefraction(self): """ Test conversion from pupil coordinates back to Ra, Dec with includeRefraction=False """ mjd = ModifiedJulianDate(TAI=52000.0) solarRA, solarDec = solarRaDec(mjd) # to make sure that we are more than 45 degrees from the Sun as required # for _icrsFromObserved to be at all accurate raCenter = solarRA + 100.0 decCenter = solarDec - 30.0 obs = ObservationMetaData(pointingRA=raCenter, pointingDec=decCenter, boundType='circle', boundLength=0.1, rotSkyPos=23.0, mjd=mjd) nSamples = 1000 rng = np.random.RandomState(42) ra = (rng.random_sample(nSamples) * 0.1 - 0.2) + np.radians(raCenter) dec = (rng.random_sample(nSamples) * 0.1 - 0.2) + np.radians(decCenter) xp, yp = _pupilCoordsFromRaDec(ra, dec, obs_metadata=obs, epoch=2000.0, includeRefraction=False) raTest, decTest = _raDecFromPupilCoords( xp, yp, obs_metadata=obs, epoch=2000.0, includeRefraction=False) distance = arcsecFromRadians(haversine(ra, dec, raTest, decTest)) dex = np.argmax(distance) worstSolarDistance = distanceToSun( np.degrees(ra[dex]), np.degrees(dec[dex]), mjd) msg = "_raDecFromPupilCoords off by %e arcsec at distance to Sun of %e degrees" % \ (distance.max(), worstSolarDistance) self.assertLess(distance.max(), 1.0e-6, msg=msg) # now check that passing in the xp, yp values one at a time still gives # the right answer for ix in range(len(ra)): ra_f, dec_f = _raDecFromPupilCoords(xp[ix], yp[ix], obs_metadata=obs, epoch=2000.0, includeRefraction=False) self.assertIsInstance(ra_f, np.float) self.assertIsInstance(dec_f, np.float) dist_f = arcsecFromRadians(haversine(ra_f, dec_f, raTest[ix], decTest[ix])) self.assertLess(dist_f, 1.0e-9)
def _dePrecess(self, ra_in, dec_in, obs): """ Transform a set of RA, Dec pairs by subtracting out a rotation which represents the effects of precession, nutation, and aberration. Specifically: Calculate the displacement between the boresite and the boresite corrected for precession, nutation, and aberration (not refraction). Convert boresite and corrected boresite to Cartesian coordinates. Calculate the rotation matrix to go between those Cartesian vectors. Convert [ra_in, dec_in] into Cartesian coordinates. Apply the rotation vector to those Cartesian coordinates. Convert back to ra, dec-like coordinates @param [in] ra_in is a numpy array of RA in radians @param [in] dec_in is a numpy array of Dec in radians @param [in] obs is an ObservationMetaData @param [out] ra_out is a numpy array of de-precessed RA in radians @param [out] dec_out is a numpy array of de-precessed Dec in radians """ if len(ra_in) == 0: return np.array([[], []]) precessedRA, precessedDec = _observedFromICRS(obs._pointingRA,obs._pointingDec, obs_metadata=obs, epoch=2000.0, includeRefraction=False) if (not hasattr(self, '_icrs_to_phosim_rotator') or arcsecFromRadians(_angularSeparation(obs._pointingRA, obs._pointingDec, self._icrs_to_phosim_rotator._ra1, self._icrs_to_phosim_rotator._dec1))>1.0e-6 or arcsecFromRadians(_angularSeparation(precessedRA, precessedDec, self._icrs_to_phosim_rotator._ra0, self._icrs_to_phosim_rotator._dec0))>1.0e-6): self._icrs_to_phosim_rotator = _FieldRotator(precessedRA, precessedDec, obs._pointingRA, obs._pointingDec) ra_deprecessed, dec_deprecessed = self._icrs_to_phosim_rotator.transform(ra_in, dec_in) return np.array([ra_deprecessed, dec_deprecessed])
def testApplyProperMotion(self): for mjd in self.mjdList: raRad, decRad = utils._applyProperMotion( self.raList, self.decList, self.pm_raList, self.pm_decList, self.pxList, self.v_radList, mjd=ModifiedJulianDate(TAI=mjd)) raDeg, decDeg = utils.applyProperMotion( np.degrees(self.raList), np.degrees(self.decList), utils.arcsecFromRadians(self.pm_raList), utils.arcsecFromRadians(self.pm_decList), utils.arcsecFromRadians(self.pxList), self.v_radList, mjd=ModifiedJulianDate(TAI=mjd)) dRa = utils.arcsecFromRadians(raRad - np.radians(raDeg)) np.testing.assert_array_almost_equal(dRa, np.zeros(self.nStars), 9) dDec = utils.arcsecFromRadians(raRad - np.radians(raDeg)) np.testing.assert_array_almost_equal(dDec, np.zeros(self.nStars), 9) for ra, dec, pm_ra, pm_dec, px, v_rad in \ zip(self.raList, self.decList, self.pm_raList, self.pm_decList, self.pxList, self.v_radList): raRad, decRad = utils._applyProperMotion( ra, dec, pm_ra, pm_dec, px, v_rad, mjd=ModifiedJulianDate(TAI=self.mjdList[0])) raDeg, decDeg = utils.applyProperMotion( np.degrees(ra), np.degrees(dec), utils.arcsecFromRadians(pm_ra), utils.arcsecFromRadians(pm_dec), utils.arcsecFromRadians(px), v_rad, mjd=ModifiedJulianDate(TAI=self.mjdList[0])) self.assertAlmostEqual( utils.arcsecFromRadians(raRad - np.radians(raDeg)), 0.0, 9) self.assertAlmostEqual( utils.arcsecFromRadians(decRad - np.radians(decDeg)), 0.0, 9)
def testraDecFromPupilCoords(self): obs = ObservationMetaData(pointingRA=23.5, pointingDec=-115.0, mjd=42351.0, rotSkyPos=127.0) xpList = np.random.random_sample(100)*0.25*np.pi ypList = np.random.random_sample(100)*0.25*np.pi raRad, decRad = utils._raDecFromPupilCoords(xpList, ypList, obs_metadata=obs, epoch=2000.0) raDeg, decDeg = utils.raDecFromPupilCoords(xpList, ypList, obs_metadata=obs, epoch=2000.0) dRa = utils.arcsecFromRadians(raRad-np.radians(raDeg)) np.testing.assert_array_almost_equal(dRa, np.zeros(len(xpList)), 9) dDec = utils.arcsecFromRadians(decRad-np.radians(decDeg)) np.testing.assert_array_almost_equal(dDec, np.zeros(len(xpList)), 9)
def __init__(self, galSimType, sed, ra, dec, xPupil, yPupil, halfLightRadius, minorAxis, majorAxis, positionAngle, sindex, fluxDict): """ @param [in] galSimType is a string, either 'pointSource' or 'sersic' denoting the shape of the object @param [in] sed is the SED of the object (an instantiation of the Sed class defined in sims_photUtils/../../Sed.py @param [in] ra is the RA coordinate of the object in radians (ICRS) @param [in] dec is the Dec coordinate of the object in radians (ICRS) @param [in] xPupil is the x pupil coordinate of the object in radians @param [in] yPupil is the y pupil coordinate of the object in radians @param [in] halfLightRadius is the halfLightRadius of the object in radians @param [in] minorAxis is the semi-minor axis of the object in radians @param [in] majorAxis is the semi-major axis of the object in radians @param [in] positionAngle is the position angle of the object in radians @param [in] sindex is the sersic index of the object @param [in] fluxDict is a dict of electron count (not ADU) values keyed to bandpass names, i.e. {'u':44000, 'g':41000} would mean the source produces 44000 electrons in the u band and 41000 electrons in the g band. """ self._galSimType = galSimType self._sed = sed self._raRadians = ra self._decRadians = dec self._xPupilRadians = xPupil self._xPupilArcsec = arcsecFromRadians(xPupil) self._yPupilRadians = yPupil self._yPupilArcsec = arcsecFromRadians(yPupil) self._halfLightRadiusRadians = halfLightRadius self._halfLightRadiusArcsec = arcsecFromRadians(halfLightRadius) self._minorAxisRadians = minorAxis self._majorAxisRadians = majorAxis self._positionAngleRadians = positionAngle self._sindex = sindex self._fluxDict = fluxDict
def test_de_precession(self): """ test de-precession by de-precessing a list of RA, Dec and verifying that the distance between the de-precessed points is the same as the distance between the input points. Also verify that the observed boresite gets de-precessed correctly """ rng = np.random.RandomState(12) n_samples = 5 pra = 34.0 pdec = 65.0 obs = ObservationMetaData(pointingRA=pra, pointingDec=pdec, mjd=58324.1) raObs, decObs = _observedFromICRS(np.array([np.radians(pra)]), np.array([np.radians(pdec)]), obs_metadata=obs, epoch=2000.0, includeRefraction=False) ra_list = [] dec_list = [] ra_list.append(raObs[0]) dec_list.append(decObs[0]) for rr, dd in zip(rng.random_sample(n_samples)*2.0*np.pi, (rng.random_sample(n_samples)-0.5)*np.pi): ra_list.append(rr) dec_list.append(dd) ra_list = np.array(ra_list) dec_list = np.array(dec_list) raDecTransformed = PhoSimAstrometryBase()._dePrecess(ra_list, dec_list, obs) dd = arcsecFromRadians(haversine(np.radians(pra), np.radians(pdec), raDecTransformed[0][0], raDecTransformed[1][0])) self.assertLess(dd, 1.0e-6) dd0 = arcsecFromRadians(haversine(raObs[0], decObs[0], np.radians(pra), np.radians(pdec))) self.assertLess(dd, dd0) for ix in range(n_samples+1): for iy in range(n_samples+1): if ix != iy: dd1 = arcsecFromRadians(haversine(ra_list[ix], dec_list[ix], ra_list[iy], dec_list[iy])) dd2 = arcsecFromRadians(haversine(raDecTransformed[0][ix], raDecTransformed[1][ix], raDecTransformed[0][iy], raDecTransformed[1][iy])) self.assertAlmostEqual(dd1, dd2, delta=6)
def testApplyPrecession(self): for mjd in self.mjdList: raRad, decRad = utils._applyPrecession(self.raList, self.decList, mjd=ModifiedJulianDate(TAI=mjd)) raDeg, decDeg = utils.applyPrecession(np.degrees(self.raList), np.degrees(self.decList), mjd=ModifiedJulianDate(TAI=mjd)) dRa = utils.arcsecFromRadians(raRad-np.radians(raDeg)) np.testing.assert_array_almost_equal(dRa, np.zeros(self.nStars), 9) dDec = utils.arcsecFromRadians(raRad-np.radians(raDeg)) np.testing.assert_array_almost_equal(dDec, np.zeros(self.nStars), 9)
def test_raDecFromAltAz_noref(self): """ test that raDecFromAltAz correctly inverts altAzPaFromRaDec, even when refraction is turned off """ rng = np.random.RandomState(55) n_samples = 10 n_batches = 10 for i_batch in range(n_batches): d_sun = 0.0 while d_sun < 45.0: # because ICRS->Observed transformation breaks down close to the sun alt_in = rng.random_sample(n_samples)*50.0 + 20.0 az_in = rng.random_sample(n_samples)*360.0 obs = utils.ObservationMetaData(mjd=43000.0) ra_in, dec_in = utils.raDecFromAltAz(alt_in, az_in, obs=obs, includeRefraction=False) d_sun = utils.distanceToSun(ra_in, dec_in, obs.mjd).min() alt_out, az_out, pa_out = utils.altAzPaFromRaDec(ra_in, dec_in, obs=obs, includeRefraction=False) dd = utils.haversine(np.radians(alt_out), np.radians(az_out), np.radians(alt_in), np.radians(az_in)) self.assertLess(utils.arcsecFromRadians(dd).max(), 0.01)
def testRaDecFromPupil(self): """ Test conversion from pupil coordinates back to Ra, Dec """ mjd = ModifiedJulianDate(TAI=52000.0) solarRA, solarDec = solarRaDec(mjd.TDB) # to make sure that we are more than 45 degrees from the Sun as required # for _icrsFromObserved to be at all accurate raCenter = solarRA + 100.0 decCenter = solarDec - 30.0 obs = ObservationMetaData(pointingRA=raCenter, pointingDec=decCenter, boundType='circle', boundLength=0.1, rotSkyPos=23.0, mjd=mjd) nSamples = 1000 numpy.random.seed(42) ra = (numpy.random.random_sample(nSamples)*0.1-0.2) + numpy.radians(raCenter) dec = (numpy.random.random_sample(nSamples)*0.1-0.2) + numpy.radians(decCenter) xp, yp = _pupilCoordsFromRaDec(ra, dec, obs_metadata=obs, epoch=2000.0) raTest, decTest = _raDecFromPupilCoords(xp, yp, obs_metadata=obs, epoch=2000.0) distance = arcsecFromRadians(haversine(ra, dec, raTest, decTest)) dex = numpy.argmax(distance) worstSolarDistance = distanceToSun(numpy.degrees(ra[dex]), numpy.degrees(dec[dex]), mjd.TDB) msg = "_raDecFromPupilCoords off by %e arcsec at distance to Sun of %e degrees" % \ (distance.max(), worstSolarDistance) self.assertLess(distance.max(), 0.005, msg=msg)
def testApplyPrecession(self): for mjd in self.mjdList: raRad, decRad = utils._applyPrecession( self.raList, self.decList, mjd=ModifiedJulianDate(TAI=mjd)) raDeg, decDeg = utils.applyPrecession( np.degrees(self.raList), np.degrees(self.decList), mjd=ModifiedJulianDate(TAI=mjd)) dRa = utils.arcsecFromRadians(raRad - np.radians(raDeg)) np.testing.assert_array_almost_equal(dRa, np.zeros(self.nStars), 9) dDec = utils.arcsecFromRadians(raRad - np.radians(raDeg)) np.testing.assert_array_almost_equal(dDec, np.zeros(self.nStars), 9)
def testNativeLonLatVector(self): """ Test that nativeLonLatFromRaDec works in a vectorized way; we do this by performing a bunch of tansformations passing in ra and dec as numpy arrays and then comparing them to results computed in an element-wise way """ obs = ObservationMetaData(pointingRA=123.0, pointingDec=43.0, mjd=53467.2) raPoint = 145.0 decPoint = -35.0 nSamples = 100 np.random.seed(42) raList = np.random.random_sample(nSamples)*360.0 decList = np.random.random_sample(nSamples)*180.0 - 90.0 lonList, latList = nativeLonLatFromRaDec(raList, decList, obs) for rr, dd, lon, lat in zip(raList, decList, lonList, latList): lonControl, latControl = nativeLonLatFromRaDec(rr, dd, obs) distance = arcsecFromRadians(haversine(np.radians(lon), np.radians(lat), np.radians(lonControl), np.radians(latControl))) self.assertLess(distance, 0.0001)
def testNativeLonLat(self): """ Test that nativeLonLatFromRaDec works by considering stars and pointings at intuitive locations """ mjd = 53855.0 raList_obs = [0.0, 0.0, 0.0, 270.0] decList_obs = [90.0, 90.0, 0.0, 0.0] raPointList_obs = [0.0, 270.0, 270.0, 0.0] decPointList_obs = [0.0, 0.0,0.0, 0.0] lonControlList = [180.0, 180.0, 90.0, 270.0] latControlList = [0.0, 0.0, 0.0, 0.0] for rr_obs, dd_obs, rp_obs, dp_obs, lonc, latc in \ zip(raList_obs, decList_obs, raPointList_obs, decPointList_obs, lonControlList, latControlList): obsTemp = ObservationMetaData(mjd=mjd) rr, dd = icrsFromObserved(np.array([rr_obs, rp_obs]), np.array([dd_obs, dp_obs]), obs_metadata=obsTemp, epoch=2000.0, includeRefraction=True) obs = ObservationMetaData(pointingRA=rr[1], pointingDec=dd[1], mjd=mjd) lon, lat = nativeLonLatFromRaDec(rr[0], dd[0], obs) distance = arcsecFromRadians(haversine(lon, lat, lonc, latc)) self.assertLess(distance, 1.0)
def testObservedFromPupil(self): """ Test conversion from pupil coordinates to observed coordinates """ mjd = ModifiedJulianDate(TAI=53000.0) solarRA, solarDec = solarRaDec(mjd) # to make sure that we are more than 45 degrees from the Sun as required # for _icrsFromObserved to be at all accurate raCenter = solarRA + 100.0 decCenter = solarDec - 30.0 obs = ObservationMetaData(pointingRA=raCenter, pointingDec=decCenter, boundType='circle', boundLength=0.1, rotSkyPos=23.0, mjd=mjd) nSamples = 1000 rng = np.random.RandomState(4453) ra = (rng.random_sample(nSamples) * 0.1 - 0.2) + np.radians(raCenter) dec = (rng.random_sample(nSamples) * 0.1 - 0.2) + np.radians(decCenter) xp, yp = _pupilCoordsFromRaDec(ra, dec, obs_metadata=obs, epoch=2000.0, includeRefraction=True) raObs, decObs = _observedFromICRS(ra, dec, obs_metadata=obs, epoch=2000.0, includeRefraction=True) raObs_test, decObs_test = _observedFromPupilCoords(xp, yp, obs_metadata=obs, epoch=2000.0, includeRefraction=True) dist = arcsecFromRadians(haversine(raObs, decObs, raObs_test, decObs_test)) self.assertLess(dist.max(), 1.0e-6) # test output in degrees raObs_deg, decObs_deg = observedFromPupilCoords(xp, yp, obs_metadata=obs, epoch=2000.0, includeRefraction=True) np.testing.assert_array_almost_equal(raObs_deg, np.degrees(raObs_test), decimal=16) np.testing.assert_array_almost_equal(decObs_deg, np.degrees(decObs_test), decimal=16) # test one-at-a-time input for ii in range(len(raObs)): rr, dd = _observedFromPupilCoords(xp[ii], yp[ii], obs_metadata=obs, epoch=2000.0, includeRefraction=True) self.assertAlmostEqual(rr, raObs_test[ii], 16) self.assertAlmostEqual(dd, decObs_test[ii], 16) rr, dd = observedFromPupilCoords(xp[ii], yp[ii], obs_metadata=obs, epoch=2000.0, includeRefraction=True) self.assertAlmostEqual(rr, raObs_deg[ii], 16) self.assertAlmostEqual(dd, decObs_deg[ii], 16)
def testNativeLonLat(self): """ Test that nativeLonLatFromRaDec works by considering stars and pointings at intuitive locations """ mjd = 53855.0 raList_obs = [0.0, 0.0, 0.0, 270.0] decList_obs = [90.0, 90.0, 0.0, 0.0] raPointList_obs = [0.0, 270.0, 270.0, 0.0] decPointList_obs = [0.0, 0.0, 0.0, 0.0] lonControlList = [180.0, 180.0, 90.0, 270.0] latControlList = [0.0, 0.0, 0.0, 0.0] for rr_obs, dd_obs, rp_obs, dp_obs, lonc, latc in \ zip(raList_obs, decList_obs, raPointList_obs, decPointList_obs, lonControlList, latControlList): obsTemp = ObservationMetaData(mjd=mjd) rr, dd = icrsFromObserved(np.array([rr_obs, rp_obs]), np.array([dd_obs, dp_obs]), obs_metadata=obsTemp, epoch=2000.0, includeRefraction=True) obs = ObservationMetaData(pointingRA=rr[1], pointingDec=dd[1], mjd=mjd) lon, lat = nativeLonLatFromRaDec(rr[0], dd[0], obs) distance = arcsecFromRadians(haversine(lon, lat, lonc, latc)) self.assertLess(distance, 1.0)
def testNativeLonLatVector(self): """ Test that nativeLonLatFromRaDec works in a vectorized way; we do this by performing a bunch of tansformations passing in ra and dec as numpy arrays and then comparing them to results computed in an element-wise way """ obs = ObservationMetaData(pointingRA=123.0, pointingDec=43.0, mjd=53467.2) nSamples = 100 rng = np.random.RandomState(42) raList = rng.random_sample(nSamples) * 360.0 decList = rng.random_sample(nSamples) * 180.0 - 90.0 lonList, latList = nativeLonLatFromRaDec(raList, decList, obs) for rr, dd, lon, lat in zip(raList, decList, lonList, latList): lonControl, latControl = nativeLonLatFromRaDec(rr, dd, obs) distance = arcsecFromRadians( haversine(np.radians(lon), np.radians(lat), np.radians(lonControl), np.radians(latControl))) self.assertLess(distance, 0.0001)
def testAltAzFromRaDec(self): """ Test conversion from RA, Dec to Alt, Az """ nSamples = 100 ra = self.rng.random_sample(nSamples)*2.0*np.pi dec = (self.rng.random_sample(nSamples)-0.5)*np.pi lon_rad = 1.467 lat_rad = -0.234 controlAlt, controlAz = controlAltAzFromRaDec(ra, dec, lon_rad, lat_rad, self.mjd) obs = utils.ObservationMetaData(mjd=utils.ModifiedJulianDate(UTC=self.mjd), site=utils.Site(longitude=np.degrees(lon_rad), latitude=np.degrees(lat_rad), name='LSST')) # verify parallactic angle against an expression from # http://www.astro.washington.edu/groups/APO/Mirror.Motions/Feb.2000.Image.Jumps/report.html#Image%20motion%20directions # ra_obs, dec_obs = utils._observedFromICRS(ra, dec, obs_metadata=obs, epoch=2000.0, includeRefraction=True) lmst, last = utils.calcLmstLast(obs.mjd.UT1, lon_rad) hourAngle = np.radians(last * 15.0) - ra_obs controlSinPa = np.sin(hourAngle) * np.cos(lat_rad) / np.cos(controlAlt) testAlt, testAz, testPa = utils._altAzPaFromRaDec(ra, dec, obs) distance = utils.arcsecFromRadians(utils.haversine(controlAz, controlAlt, testAz, testAlt)) self.assertLess(distance.max(), 0.0001) self.assertLess(np.abs(np.sin(testPa) - controlSinPa).max(), self.tolerance) # test non-vectorized version for r, d in zip(ra, dec): controlAlt, controlAz = controlAltAzFromRaDec(r, d, lon_rad, lat_rad, self.mjd) testAlt, testAz, testPa = utils._altAzPaFromRaDec(r, d, obs) lmst, last = utils.calcLmstLast(obs.mjd.UT1, lon_rad) r_obs, dec_obs = utils._observedFromICRS(r, d, obs_metadata=obs, epoch=2000.0, includeRefraction=True) hourAngle = np.radians(last * 15.0) - r_obs controlSinPa = np.sin(hourAngle) * np.cos(lat_rad) / np.cos(controlAlt) distance = utils.arcsecFromRadians(utils.haversine(controlAz, controlAlt, testAz, testAlt)) self.assertLess(distance, 0.0001) self.assertLess(np.abs(np.sin(testPa) - controlSinPa), self.tolerance)
def _appGeoFromPhoSim(self, raPhoSim, decPhoSim, obs): """ This method will convert from the 'deprecessed' coordinates expected by PhoSim to apparent geocentric coordinates Parameters ---------- raPhoSim is the PhoSim RA-like coordinate (in radians) decPhoSim is the PhoSim Dec-like coordinate (in radians) obs is an ObservationMetaData characterizing the telescope pointing Returns ------- apparent geocentric RA in radians apparent geocentric Dec in radians """ precessedRA, precessedDec = _observedFromICRS(obs._pointingRA, obs._pointingDec, obs_metadata=obs, epoch=2000.0, includeRefraction=False) if (not hasattr(self, '_phosim_to_icrs_rotator') or arcsecFromRadians( _angularSeparation(obs._pointingRA, obs._pointingDec, self._phosim_to_icrs_rotator._ra0, self._phosim_to_icrs_rotator._dec0)) > 1.0e-6 or arcsecFromRadians( _angularSeparation(precessedRA, precessedDec, self._phosim_to_icrs_rotator._ra1, self._phosim_to_icrs_rotator._dec1)) > 1.0e-6): self._phosim_to_icrs_rotator = _FieldRotator( obs._pointingRA, obs._pointingDec, precessedRA, precessedDec) ra_obs, dec_obs = self._phosim_to_icrs_rotator.transform( raPhoSim, decPhoSim) return _appGeoFromObserved(ra_obs, dec_obs, includeRefraction=False, obs_metadata=obs)
def test_stellar_astrometry_radians(self): """ Test that we can go from raPhoSim, decPhoSim to ICRS coordinates in the case of stars (in radians) """ cat_name = os.path.join(self.scratch_dir, 'phosim_ast_star_cat_rad.txt') if os.path.exists(cat_name): os.unlink(cat_name) db = testStarsDBObj(driver='sqlite', database=self.db_name) cat = StarTestCatalog(db, obs_metadata=self.obs) cat.write_catalog(cat_name) dtype = np.dtype([('raICRS', float), ('decICRS', float), ('raPhoSim', float), ('decPhoSim', float)]) data = np.genfromtxt(cat_name, dtype=dtype) self.assertGreater(len(data), 100) ra_pho_rad = np.radians(data['raPhoSim']) dec_pho_rad = np.radians(data['decPhoSim']) # verify that, when transforming back to ICRS, we are within # 10^-3 arcsec ra_icrs, dec_icrs = PhoSimAstrometryBase._icrsFromPhoSim( ra_pho_rad, dec_pho_rad, self.obs) dist = _angularSeparation(np.radians(data['raICRS']), np.radians(data['decICRS']), ra_icrs, dec_icrs) dist = arcsecFromRadians(dist) self.assertLess(dist.max(), 0.001) # verify that the distance between raPhoSim, decPhoSim and # raICRS, decICRS is greater than the distance between # the original raICRS, decICRS and the newly-calculated # raICRS, decICRS dist_bad = _angularSeparation(ra_pho_rad, dec_pho_rad, np.radians(data['raICRS']), np.radians(data['decICRS'])) dist_bad = arcsecFromRadians(dist_bad) self.assertGreater(dist_bad.min(), dist.max()) if os.path.exists(cat_name): os.unlink(cat_name) del db
def testIcrsFromAppGeo(self): for mjd in (53525.0, 54316.3, 58463.7): for epoch in(2000.0, 1950.0, 2010.0): raRad, decRad = utils._icrsFromAppGeo(self.raList, self.decList, epoch=epoch, mjd=ModifiedJulianDate(TAI=mjd)) raDeg, decDeg = utils.icrsFromAppGeo(np.degrees(self.raList), np.degrees(self.decList), epoch=epoch, mjd=ModifiedJulianDate(TAI=mjd)) dRa = utils.arcsecFromRadians(np.abs(raRad - np.radians(raDeg))) self.assertLess(dRa.max(), 1.0e-9) dDec = utils.arcsecFromRadians(np.abs(decRad - np.radians(decDeg))) self.assertLess(dDec.max(), 1.0e-9)
def distance_in_arcminutes(ra1, dec1, ra2, dec2): """ all ra and dec are in degrees """ dd = haversine(np.radians(ra1), np.radians(dec1), np.radians(ra2), np.radians(dec2)) return arcsecFromRadians(dd) / 60.0
def get_flux_in_half_light_radius(self, fileName, hlr, detector, camera, obs, epoch=2000.0): """ Read in a FITS image. Return the total flux in that image as well as the flux contained within a specified radius of the maximum pixel of the image. @param [in] fileName is the name of the FITS file to be read in @param [in] hlr is the half light radius to be tested (in arc seconds) @param [in] detector is an instantiation of the afw.cameraGeom Detector class characterizing the detector corresponding to this image @param [in] camera is an instantiation of the afw.cameraGeom Camera class characterizing the camera to which detector belongs @param [in] obs is an instantiation of ObservationMetaData characterizing the telescope pointing @param [in] epoch is the epoch in Julian years of the equinox against which RA and Dec are measured. @param [out] totalFlux is the total number of counts in the images @param [out] measuredHalfFlux is the measured flux within hlr of the maximum pixel """ im = afwImage.ImageF(fileName).getArray() totalFlux = im.sum() _maxPixel = numpy.array([im.argmax()/im.shape[1], im.argmax()%im.shape[1]]) maxPixel = numpy.array([_maxPixel[1], _maxPixel[0]]) raMax, decMax = _raDecFromPixelCoords(maxPixel[0:1], maxPixel[1:2], [detector.getName()], camera=camera, obs_metadata=obs, epoch=epoch) activePoints = numpy.where(im>1.0e-10) self.assertGreater(len(activePoints), 0) xPixList = activePoints[1] # this looks backwards, but remember: the way numpy handles yPixList = activePoints[0] # arrays, the first index indicates what row it is in (the y coordinate) chipNameList = [detector.getName()]*len(xPixList) raList, decList = _raDecFromPixelCoords(xPixList, yPixList, chipNameList, camera=camera, obs_metadata=obs, epoch=epoch) distanceList = arcsecFromRadians(haversine(raList, decList, raMax[0], decMax[0])) dexContained = [ix for ix, dd in enumerate(distanceList) if dd<=hlr] measuredHalfFlux = numpy.array([im[yPixList[dex]][xPixList[dex]] for dex in dexContained]).sum() return totalFlux, measuredHalfFlux
def test_stellar_astrometry_radians(self): """ Test that we can go from raPhoSim, decPhoSim to ICRS coordinates in the case of stars (in radians) """ db = testStarsDBObj(driver='sqlite', database=self.db_name) cat = StarTestCatalog(db, obs_metadata=self.obs) with lsst.utils.tests.getTempFilePath('.txt') as cat_name: cat.write_catalog(cat_name) dtype = np.dtype([('raICRS', float), ('decICRS', float), ('raPhoSim', float), ('decPhoSim', float), ('raJ2000', float), ('decJ2000', float), ('pmRA', float), ('pmDec', float), ('parallax', float), ('vRad', float)]) data = np.genfromtxt(cat_name, dtype=dtype) self.assertGreater(len(data), 100) ra_pho_rad = np.radians(data['raPhoSim']) dec_pho_rad = np.radians(data['decPhoSim']) # verify that, when transforming back to ICRS, we are within # 10^-3 arcsec ra_icrs, dec_icrs = PhoSimAstrometryBase._icrsFromPhoSim(ra_pho_rad, dec_pho_rad, self.obs) dist = _angularSeparation(np.radians(data['raICRS']), np.radians(data['decICRS']), ra_icrs, dec_icrs) dist = arcsecFromRadians(dist) self.assertLess(dist.max(), 0.001) # verify that the distance between raPhoSim, decPhoSim and # raICRS, decICRS is greater than the distance between # the original raICRS, decICRS and the newly-calculated # raICRS, decICRS dist_bad = _angularSeparation(ra_pho_rad, dec_pho_rad, np.radians(data['raICRS']), np.radians(data['decICRS'])) dist_bad = arcsecFromRadians(dist_bad) self.assertGreater(dist_bad.min(), dist.max()) del db
def testIcrsFromObserved(self): obs = ObservationMetaData(pointingRA=35.0, pointingDec=-45.0, mjd=43572.0) for includeRefraction in [True, False]: raRad, decRad = utils._icrsFromObserved(self.raList, self.decList, obs_metadata=obs, epoch=2000.0, includeRefraction=includeRefraction) raDeg, decDeg = utils.icrsFromObserved(np.degrees(self.raList), np.degrees(self.decList), obs_metadata=obs, epoch=2000.0, includeRefraction=includeRefraction) dRa = utils.arcsecFromRadians(raRad-np.radians(raDeg)) np.testing.assert_array_almost_equal(dRa, np.zeros(self.nStars), 9) dDec = utils.arcsecFromRadians(decRad-np.radians(decDeg)) np.testing.assert_array_almost_equal(dDec, np.zeros(self.nStars), 9)
def testpupilCoordsFromRaDec(self): obs = ObservationMetaData(pointingRA=23.5, pointingDec=-115.0, mjd=42351.0, rotSkyPos=127.0) # need to make sure the test points are tightly distributed around the bore site, or # PALPY will throw an error raList = np.random.random_sample(self.nStars)*np.radians(1.0) + np.radians(23.5) decList = np.random.random_sample(self.nStars)*np.radians(1.0) + np.radians(-115.0) xpControl, ypControl = utils._pupilCoordsFromRaDec(raList, decList, obs_metadata=obs, epoch=2000.0) xpTest, ypTest = utils.pupilCoordsFromRaDec(np.degrees(raList), np.degrees(decList), obs_metadata=obs, epoch=2000.0) dx = utils.arcsecFromRadians(xpControl-xpTest) np.testing.assert_array_almost_equal(dx, np.zeros(self.nStars), 9) dy = utils.arcsecFromRadians(ypControl-ypTest) np.testing.assert_array_almost_equal(dy, np.zeros(self.nStars), 9)
def __init__(self, galSimType, sed, ra, dec, xPupil, yPupil, halfLightRadius, minorAxis, majorAxis, positionAngle, sindex): """ @param [in] galSimType is a string, either 'pointSource' or 'sersic' denoting the shape of the object @param [in] sed is the SED of the object (an instantiation of the Sed class defined in sims_photUtils/../../Sed.py @param [in] ra is the observed RA coordinate of the object in radians @param [in] dec is the observed Dec coordinate of the object in radians @param [in] xPupil is the x pupil coordinate of the object in radians @param [in] yPupil is the y pupil coordinate of the object in radians @param [in] halfLightRadius is the halfLightRadius of the object in radians @param [in] minorAxis is the semi-minor axis of the object in radians @param [in] majorAxis is the semi-major axis of the object in radians @param [in] positionAngle is the position angle of the object in radians @param [in] sindex is the sersic index of the object """ self._galSimType = galSimType self._sed = sed self._raRadians = ra self._decRadians = dec self._xPupilRadians = xPupil self._xPupilArcsec = arcsecFromRadians(xPupil) self._yPupilRadians = yPupil self._yPupilArcsec = arcsecFromRadians(yPupil) self._halfLightRadiusRadians = halfLightRadius self._halfLightRadiusArcsec = arcsecFromRadians(halfLightRadius) self._minorAxisRadians = minorAxis self._majorAxisRadians = majorAxis self._positionAngleRadians = positionAngle self._sindex = sindex
def testApplyProperMotion(self): for mjd in self.mjdList: raRad, decRad = utils._applyProperMotion(self.raList, self.decList, self.pm_raList, self.pm_decList, self.pxList, self.v_radList, mjd=ModifiedJulianDate(TAI=mjd)) raDeg, decDeg = utils.applyProperMotion(np.degrees(self.raList), np.degrees(self.decList), utils.arcsecFromRadians( self.pm_raList), utils.arcsecFromRadians( self.pm_decList), utils.arcsecFromRadians( self.pxList), self.v_radList, mjd=ModifiedJulianDate(TAI=mjd)) dRa = utils.arcsecFromRadians(raRad - np.radians(raDeg)) np.testing.assert_array_almost_equal(dRa, np.zeros(self.nStars), 9) dDec = utils.arcsecFromRadians(raRad - np.radians(raDeg)) np.testing.assert_array_almost_equal( dDec, np.zeros(self.nStars), 9) for ra, dec, pm_ra, pm_dec, px, v_rad in \ zip(self.raList, self.decList, self.pm_raList, self.pm_decList, self.pxList, self.v_radList): raRad, decRad = utils._applyProperMotion(ra, dec, pm_ra, pm_dec, px, v_rad, mjd=ModifiedJulianDate(TAI=self.mjdList[0])) raDeg, decDeg = utils.applyProperMotion(np.degrees(ra), np.degrees(dec), utils.arcsecFromRadians(pm_ra), utils.arcsecFromRadians(pm_dec), utils.arcsecFromRadians(px), v_rad, mjd=ModifiedJulianDate(TAI=self.mjdList[0])) self.assertAlmostEqual(utils.arcsecFromRadians( raRad - np.radians(raDeg)), 0.0, 9) self.assertAlmostEqual(utils.arcsecFromRadians( decRad - np.radians(decDeg)), 0.0, 9)
def testObservedFromICRS(self): obs = ObservationMetaData(pointingRA=35.0, pointingDec=-45.0, mjd=43572.0) for pmRaList in [self.pm_raList, None]: for pmDecList in [self.pm_decList, None]: for pxList in [self.pxList, None]: for vRadList in [self.v_radList, None]: for includeRefraction in [True, False]: raRad, decRad = utils._observedFromICRS( self.raList, self.decList, pm_ra=pmRaList, pm_dec=pmDecList, parallax=pxList, v_rad=vRadList, obs_metadata=obs, epoch=2000.0, includeRefraction=includeRefraction) raDeg, decDeg = utils.observedFromICRS( np.degrees(self.raList), np.degrees(self.decList), pm_ra=utils.arcsecFromRadians(pmRaList), pm_dec=utils.arcsecFromRadians(pmDecList), parallax=utils.arcsecFromRadians(pxList), v_rad=vRadList, obs_metadata=obs, epoch=2000.0, includeRefraction=includeRefraction) dRa = utils.arcsecFromRadians(raRad - np.radians(raDeg)) np.testing.assert_array_almost_equal( dRa, np.zeros(self.nStars), 9) dDec = utils.arcsecFromRadians(decRad - np.radians(decDeg)) np.testing.assert_array_almost_equal( dDec, np.zeros(self.nStars), 9)
def test_stellar_observed_degrees(self): """ Test ability to go all the way to observed RA, Dec from PhoSim (this is necessary for the ImSim software that DESC is working on) """ db = testStarsDBObj(driver='sqlite', database=self.db_name) cat = StarTestCatalog(db, obs_metadata=self.obs) with lsst.utils.tests.getTempFilePath('.txt') as cat_name: cat.write_catalog(cat_name) dtype = np.dtype([('raICRS', float), ('decICRS', float), ('raPhoSim', float), ('decPhoSim', float), ('raJ2000', float), ('decJ2000', float), ('pmRA', float), ('pmDec', float), ('parallax', float), ('vRad', float)]) data = np.genfromtxt(cat_name, dtype=dtype) self.assertGreater(len(data), 100) (ra_obs, dec_obs) = observedFromICRS(np.degrees(data['raJ2000']), np.degrees(data['decJ2000']), obs_metadata=self.obs, pm_ra=arcsecFromRadians(data['pmRA']), pm_dec=arcsecFromRadians(data['pmDec']), parallax=arcsecFromRadians(data['parallax']), v_rad=data['vRad'], includeRefraction=True, epoch=2000.0) (ra_appGeo, dec_appGeo) = PhoSimAstrometryBase.appGeoFromPhoSim(data['raPhoSim'], data['decPhoSim'], self.obs) (ra_obs_2, dec_obs_2) = observedFromAppGeo(ra_appGeo, dec_appGeo, obs_metadata=self.obs, includeRefraction=True) dd = 3600.0*angularSeparation(ra_obs, dec_obs, ra_obs_2, dec_obs_2) self.assertLess(dd.max(), 1.0e-5)
def test_stellar_observed_degrees(self): """ Test ability to go all the way to observed RA, Dec from PhoSim (this is necessary for the ImSim software that DESC is working on) """ db = testStarsDBObj(driver='sqlite', database=self.db_name) cat = StarTestCatalog(db, obs_metadata=self.obs) with lsst.utils.tests.getTempFilePath('.txt') as cat_name: cat.write_catalog(cat_name) dtype = np.dtype([('raICRS', float), ('decICRS', float), ('raPhoSim', float), ('decPhoSim', float), ('raJ2000', float), ('decJ2000', float), ('pmRA', float), ('pmDec', float), ('parallax', float), ('vRad', float)]) data = np.genfromtxt(cat_name, dtype=dtype) self.assertGreater(len(data), 100) (ra_obs, dec_obs) = observedFromICRS( np.degrees(data['raJ2000']), np.degrees(data['decJ2000']), obs_metadata=self.obs, pm_ra=arcsecFromRadians(data['pmRA']), pm_dec=arcsecFromRadians(data['pmDec']), parallax=arcsecFromRadians(data['parallax']), v_rad=data['vRad'], includeRefraction=True, epoch=2000.0) (ra_appGeo, dec_appGeo) = PhoSimAstrometryBase.appGeoFromPhoSim( data['raPhoSim'], data['decPhoSim'], self.obs) (ra_obs_2, dec_obs_2) = observedFromAppGeo(ra_appGeo, dec_appGeo, obs_metadata=self.obs, includeRefraction=True) dd = 3600.0 * angularSeparation(ra_obs, dec_obs, ra_obs_2, dec_obs_2) self.assertLess(dd.max(), 1.0e-5)
def test_galaxy_astrometry_radians(self): """ Test that we can go from raPhoSim, decPhoSim to ICRS coordinates in the case of galaxies (in radians) """ db = testGalaxyDiskDBObj(driver='sqlite', database=self.db_name) cat = GalaxyTestCatalog(db, obs_metadata=self.obs) with lsst.utils.tests.getTempFilePath('.txt') as cat_name: cat.write_catalog(cat_name) dtype = np.dtype([('raICRS', float), ('decICRS', float), ('raPhoSim', float), ('decPhoSim', float)]) data = np.genfromtxt(cat_name, dtype=dtype) self.assertGreater(len(data), 100) ra_pho_rad = np.radians(data['raPhoSim']) dec_pho_rad = np.radians(data['decPhoSim']) # verify that, when transforming back to ICRS, we are within # 10^-3 arcsec ra_icrs, dec_icrs = PhoSimAstrometryBase._icrsFromPhoSim( ra_pho_rad, dec_pho_rad, self.obs) dist = _angularSeparation(np.radians(data['raICRS']), np.radians(data['decICRS']), ra_icrs, dec_icrs) dist = arcsecFromRadians(dist) self.assertLess(dist.max(), 0.001) # verify that the distance between raPhoSim, decPhoSim and # raICRS, decICRS is greater than the distance between # the original raICRS, decICRS and the newly-calculated # raICRS, decICRS dist_bad = _angularSeparation(ra_pho_rad, dec_pho_rad, np.radians(data['raICRS']), np.radians(data['decICRS'])) dist_bad = arcsecFromRadians(dist_bad) self.assertGreater(dist_bad.min(), dist.max()) del db
def _appGeoFromPhoSim(self, raPhoSim, decPhoSim, obs): """ This method will convert from the 'deprecessed' coordinates expected by PhoSim to apparent geocentric coordinates Parameters ---------- raPhoSim is the PhoSim RA-like coordinate (in radians) decPhoSim is the PhoSim Dec-like coordinate (in radians) obs is an ObservationMetaData characterizing the telescope pointing Returns ------- apparent geocentric RA in radians apparent geocentric Dec in radians """ precessedRA, precessedDec = _observedFromICRS(obs._pointingRA,obs._pointingDec, obs_metadata=obs, epoch=2000.0, includeRefraction=False) if (not hasattr(self, '_phosim_to_icrs_rotator') or arcsecFromRadians(_angularSeparation(obs._pointingRA, obs._pointingDec, self._phosim_to_icrs_rotator._ra0, self._phosim_to_icrs_rotator._dec0))>1.0e-6 or arcsecFromRadians(_angularSeparation(precessedRA, precessedDec, self._phosim_to_icrs_rotator._ra1, self._phosim_to_icrs_rotator._dec1))>1.0e-6): self._phosim_to_icrs_rotator = _FieldRotator(obs._pointingRA, obs._pointingDec, precessedRA, precessedDec) ra_obs, dec_obs = self._phosim_to_icrs_rotator.transform(raPhoSim, decPhoSim) return _appGeoFromObserved(ra_obs, dec_obs, includeRefraction=False, obs_metadata=obs)
def testAppGeoFromObserved(self): obs = ObservationMetaData(pointingRA=35.0, pointingDec=-45.0, mjd=43572.0) for includeRefraction in (True, False): for wavelength in (0.5, 0.2, 0.3): raRad, decRad = utils._appGeoFromObserved(self.raList, self.decList, includeRefraction=includeRefraction, wavelength=wavelength, obs_metadata=obs) raDeg, decDeg = utils.appGeoFromObserved(np.degrees(self.raList), np.degrees(self.decList), includeRefraction=includeRefraction, wavelength=wavelength, obs_metadata=obs) dRa = utils.arcsecFromRadians(raRad - np.radians(raDeg)) np.testing.assert_array_almost_equal(dRa, np.zeros(len(dRa)), 9) dDec = utils.arcsecFromRadians(decRad - np.radians(decDeg)) np.testing.assert_array_almost_equal(dDec, np.zeros(len(dDec)), 9)
def testraDecFromPupilCoords(self): obs = ObservationMetaData(pointingRA=23.5, pointingDec=-115.0, mjd=42351.0, rotSkyPos=127.0) xpList = self.rng.random_sample(100) * 0.25 * np.pi ypList = self.rng.random_sample(100) * 0.25 * np.pi raRad, decRad = utils._raDecFromPupilCoords(xpList, ypList, obs_metadata=obs, epoch=2000.0) raDeg, decDeg = utils.raDecFromPupilCoords(xpList, ypList, obs_metadata=obs, epoch=2000.0) dRa = utils.arcsecFromRadians(raRad - np.radians(raDeg)) np.testing.assert_array_almost_equal(dRa, np.zeros(len(xpList)), 9) dDec = utils.arcsecFromRadians(decRad - np.radians(decDeg)) np.testing.assert_array_almost_equal(dDec, np.zeros(len(xpList)), 9)
def testIcrsFromAppGeo(self): for mjd in (53525.0, 54316.3, 58463.7): for epoch in (2000.0, 1950.0, 2010.0): raRad, decRad = utils._icrsFromAppGeo( self.raList, self.decList, epoch=epoch, mjd=ModifiedJulianDate(TAI=mjd)) raDeg, decDeg = utils.icrsFromAppGeo( np.degrees(self.raList), np.degrees(self.decList), epoch=epoch, mjd=ModifiedJulianDate(TAI=mjd)) dRa = utils.arcsecFromRadians(np.abs(raRad - np.radians(raDeg))) self.assertLess(dRa.max(), 1.0e-9) dDec = utils.arcsecFromRadians( np.abs(decRad - np.radians(decDeg))) self.assertLess(dDec.max(), 1.0e-9)
def testAltAzRADecRoundTrip(self): """ Test that altAzPaFromRaDec and raDecFromAltAz really invert each other """ mjd = 58350.0 alt_in = [] az_in = [] for alt in np.arange(0.0, 90.0, 10.0): for az in np.arange(0.0, 360.0, 10.0): alt_in.append(alt) az_in.append(az) alt_in = np.array(alt_in) az_in = np.array(az_in) for lon in (0.0, 90.0, 135.0): for lat in (60.0, 30.0, -60.0, -30.0): obs = utils.ObservationMetaData(mjd=mjd, site=utils.Site(longitude=lon, latitude=lat, name='LSST')) ra_in, dec_in = utils.raDecFromAltAz(alt_in, az_in, obs) self.assertIsInstance(ra_in, np.ndarray) self.assertIsInstance(dec_in, np.ndarray) self.assertFalse(np.isnan(ra_in).any(), msg='there were NaNs in ra_in') self.assertFalse(np.isnan(dec_in).any(), msg='there were NaNs in dec_in') # test that passing them in one at a time gives the same answer for ix in range(len(alt_in)): ra_f, dec_f = utils.raDecFromAltAz(alt_in[ix], az_in[ix], obs) self.assertIsInstance(ra_f, np.float) self.assertIsInstance(dec_f, np.float) self.assertAlmostEqual(ra_f, ra_in[ix], 12) self.assertAlmostEqual(dec_f, dec_in[ix], 12) alt_out, az_out, pa_out = utils.altAzPaFromRaDec(ra_in, dec_in, obs) self.assertFalse(np.isnan(pa_out).any(), msg='there were NaNs in pa_out') for alt_c, az_c, alt_t, az_t in \ zip(np.radians(alt_in), np.radians(az_in), np.radians(alt_out), np.radians(az_out)): distance = utils.arcsecFromRadians(utils.haversine(az_c, alt_c, az_t, alt_t)) self.assertLess(distance, 0.2)
def testTanWcs(self): """ Test method to return a Tan WCS by generating a bunch of pixel coordinates in the undistorted TAN-PIXELS coordinate system. Then, use sims_coordUtils to convert those pixel coordinates into RA and Dec. Compare these to the RA and Dec returned by the WCS. Demand agreement to witin 0.001 arcseconds. Note: if you use a bigger camera, it is possible to have disagreements of order a few milliarcseconds. """ detector = self.camera[0] xPixList = [] yPixList = [] tanWcs = tanWcsFromDetector(detector, self.camera, self.obs, self.epoch) wcsRa = [] wcsDec = [] for xx in numpy.arange(0.0, 4001.0, 1000.0): for yy in numpy.arange(0.0, 4001.0, 1000.0): xPixList.append(xx) yPixList.append(yy) pt = afwGeom.Point2D(xx ,yy) skyPt = tanWcs.pixelToSky(pt).getPosition() wcsRa.append(skyPt.getX()) wcsDec.append(skyPt.getY()) wcsRa = numpy.radians(numpy.array(wcsRa)) wcsDec = numpy.radians(numpy.array(wcsDec)) xPixList = numpy.array(xPixList) yPixList = numpy.array(yPixList) raTest, decTest = _raDecFromPixelCoords(xPixList, yPixList, [detector.getName()]*len(xPixList), camera=self.camera, obs_metadata=self.obs, epoch=self.epoch) distanceList = arcsecFromRadians(haversine(raTest, decTest, wcsRa, wcsDec)) maxDistance = distanceList.max() msg = 'maxError in tanWcs was %e ' % maxDistance self.assertTrue(maxDistance<0.001, msg=msg)
def testObservedFromAppGeo(self): obs = ObservationMetaData(pointingRA=35.0, pointingDec=-45.0, mjd=43572.0) for includeRefraction in [True, False]: raRad, decRad = utils._observedFromAppGeo(self.raList, self.decList, includeRefraction=includeRefraction, altAzHr=False, obs_metadata=obs) raDeg, decDeg = utils.observedFromAppGeo(np.degrees(self.raList), np.degrees(self.decList), includeRefraction=includeRefraction, altAzHr=False, obs_metadata=obs) dRa = utils.arcsecFromRadians(raRad-np.radians(raDeg)) np.testing.assert_array_almost_equal(dRa, np.zeros(self.nStars), 9) dDec = utils.arcsecFromRadians(raRad-np.radians(raDeg)) np.testing.assert_array_almost_equal(dDec, np.zeros(self.nStars), 9) raDec, altAz = utils._observedFromAppGeo(self.raList, self.decList, includeRefraction=includeRefraction, altAzHr=True, obs_metadata=obs) raRad = raDec[0] decRad = raDec[1] altRad = altAz[0] azRad = altAz[1] raDec, altAz = utils.observedFromAppGeo(np.degrees(self.raList), np.degrees(self.decList), includeRefraction=includeRefraction, altAzHr=True, obs_metadata=obs) raDeg = raDec[0] decDeg = raDec[1] altDeg = altAz[0] azDeg = altAz[1] dRa = utils.arcsecFromRadians(raRad-np.radians(raDeg)) np.testing.assert_array_almost_equal(dRa, np.zeros(self.nStars), 9) dDec = utils.arcsecFromRadians(raRad-np.radians(raDeg)) np.testing.assert_array_almost_equal(dDec, np.zeros(self.nStars), 9) dAz = utils.arcsecFromRadians(azRad-np.radians(azDeg)) np.testing.assert_array_almost_equal(dAz, np.zeros(self.nStars), 9) dAlt = utils.arcsecFromRadians(altRad-np.radians(altDeg)) np.testing.assert_array_almost_equal(dAlt, np.zeros(self.nStars), 9)
def testUnitConversion(self): """ Test that arcsecFromRadians, arcsecFromDegrees, radiansFromArcsec, and degreesFromArcsec are all self-consistent """ radList = self.rng.random_sample(100) * 2.0 * np.pi degList = np.degrees(radList) arcsecRadList = utils.arcsecFromRadians(radList) arcsecDegList = utils.arcsecFromDegrees(degList) np.testing.assert_array_equal(arcsecRadList, arcsecDegList) arcsecList = self.rng.random_sample(100) * 1.0 radList = utils.radiansFromArcsec(arcsecList) degList = utils.degreesFromArcsec(arcsecList) np.testing.assert_array_equal(np.radians(degList), radList)
def testRaDecVector(self): """ Test that raDecFromNativeLonLat does invert nativeLonLatFromRaDec (make sure it works in a vectorized way) """ rng = np.random.RandomState(42) nSamples = 100 latList = rng.random_sample(nSamples) * 360.0 lonList = rng.random_sample(nSamples) * 180.0 - 90.0 raPoint = 95.0 decPoint = 75.0 obs = ObservationMetaData(pointingRA=raPoint, pointingDec=decPoint, mjd=53467.89) raList, decList = raDecFromNativeLonLat(lonList, latList, obs) for lon, lat, ra0, dec0 in zip(lonList, latList, raList, decList): ra1, dec1 = raDecFromNativeLonLat(lon, lat, obs) distance = arcsecFromRadians( haversine(np.radians(ra0), np.radians(dec0), np.radians(ra1), np.radians(dec1))) self.assertLess(distance, 0.1)
def __init__(self, detectorName, cameraWrapper, obs_metadata, epoch, photParams=None): """ @param [in] detectorName is the name of the detector as stored by afw @param [in] cameraWrapper is an instantionat of a GalSimCameraWrapper @param [in] photParams is an instantiation of the PhotometricParameters class that carries details about the photometric response of the telescope. This class will generate its own internal variable self.fileName which is the name of the detector as it will appear in the output FITS files """ if not isinstance(cameraWrapper, GalSimCameraWrapper): raise RuntimeError("You must pass GalSimDetector an instantiation " "of GalSimCameraWrapper or one of its daughter " "classes") if detectorName not in cameraWrapper.camera: raise RuntimeError( "detectorName needs to be in the camera wrapped by " "cameraWrapper when instantiating a GalSimDetector\n" "%s is not in your cameraWrapper.camera" % detectorName) if photParams is None: raise RuntimeError( "You need to specify an instantiation of PhotometricParameters " + "when constructing a GalSimDetector") self._wcs = None # this will be created when it is actually called for self._name = detectorName self._cameraWrapper = cameraWrapper self._obs_metadata = obs_metadata self._epoch = epoch self._detector_type = self._cameraWrapper.camera[self._name].getType() # Default Tree Ring properties, i.e., no tree rings: self._tree_rings = TreeRingInfo(galsim.PositionD(0, 0), None) # We are transposing the coordinates because of the difference # between how DM defines pixel coordinates and how the # Camera team defines pixel coordinates bbox = self._cameraWrapper.getBBox(self._name) self._xMinPix = bbox.getMinX() self._xMaxPix = bbox.getMaxX() self._yMinPix = bbox.getMinY() self._yMaxPix = bbox.getMaxY() self._bbox = afwGeom.Box2D(bbox) centerPupil = self._cameraWrapper.getCenterPupil(self._name) self._xCenterArcsec = arcsecFromRadians(centerPupil.getX()) self._yCenterArcsec = arcsecFromRadians(centerPupil.getY()) centerPixel = self._cameraWrapper.getCenterPixel(self._name) self._xCenterPix = centerPixel.getX() self._yCenterPix = centerPixel.getY() self._xMinArcsec = None self._yMinArcsec = None self._xMaxArcsec = None self._yMaxArcsec = None for cameraPointPupil in self._cameraWrapper.getCornerPupilList( self._name): xx = arcsecFromRadians(cameraPointPupil.getX()) yy = arcsecFromRadians(cameraPointPupil.getY()) if self._xMinArcsec is None or xx < self._xMinArcsec: self._xMinArcsec = xx if self._xMaxArcsec is None or xx > self._xMaxArcsec: self._xMaxArcsec = xx if self._yMinArcsec is None or yy < self._yMinArcsec: self._yMinArcsec = yy if self._yMaxArcsec is None or yy > self._yMaxArcsec: self._yMaxArcsec = yy self._photParams = photParams self._fileName = self._getFileName()