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 testNonsenseCircularConstraints(self): """ Test that a query performed on a circle bound gets all of the objects (and only all of the objects) within that circle """ radius = 20.0 raCenter = 210.0 decCenter = -60.0 mycolumns = ['NonsenseId','NonsenseRaJ2000','NonsenseDecJ2000','NonsenseMag'] circObsMd = ObservationMetaData(boundType='circle',unrefractedRA=raCenter,unrefractedDec=decCenter, boundLength=radius, mjd=52000., bandpassName='r') circQuery = self.myNonsense.query_columns(colnames = mycolumns, obs_metadata=circObsMd, chunk_size=100) raCenter = numpy.radians(raCenter) decCenter = numpy.radians(decCenter) radius = numpy.radians(radius) goodPoints = [] for chunk in circQuery: for row in chunk: distance = haversine(raCenter,decCenter,row[1],row[2]) self.assertTrue(distance<radius) dex = numpy.where(self.baselineData['id'] == row[0])[0][0] #store a list of which objects fell within our circle bound goodPoints.append(row[0]) self.assertAlmostEqual(numpy.radians(self.baselineData['ra'][dex]),row[1],3) self.assertAlmostEqual(numpy.radians(self.baselineData['dec'][dex]),row[2],3) self.assertAlmostEqual(self.baselineData['mag'][dex],row[3],3) for entry in [xx for xx in self.baselineData if xx[0] not in goodPoints]: #make sure that all of the points not returned by the query were, in fact, outside of #the circle bound distance = haversine(raCenter,decCenter,numpy.radians(entry[1]),numpy.radians(entry[2])) self.assertTrue(distance>radius) #make sure that the CatalogDBObject which used a header gets the same result headerQuery = self.myNonsenseHeader.query_columns(colnames = mycolumns,obs_metadata=circObsMd, chunk_size=100) goodPointsHeader = [] for chunk in headerQuery: for row in chunk: distance = haversine(raCenter,decCenter,row[1],row[2]) dex = numpy.where(self.baselineData['id'] == row[0])[0][0] goodPointsHeader.append(row[0]) self.assertAlmostEqual(numpy.radians(self.baselineData['ra'][dex]),row[1],3) self.assertAlmostEqual(numpy.radians(self.baselineData['dec'][dex]),row[2],3) self.assertAlmostEqual(self.baselineData['mag'][dex],row[3],3) self.assertEqual(len(goodPoints),len(goodPointsHeader)) for xx in goodPoints: self.assertTrue(xx in goodPointsHeader)
def testCircBounds(self): """ Make sure that circular_bound_constraint in sims.catalogs.db.dbConnection.py does not admit any objects outside of the bounding circle """ catName = os.path.join(self.scratch_dir, 'circular_test_catalog.txt') if os.path.exists(catName): os.unlink(catName) myCatalog = self.starDB.getCatalog('bounds_catalog', obs_metadata=self.obsMdCirc) myIterator = myCatalog.iter_catalog(chunk_size=10) for line in myIterator: rtest = np.degrees( haversine(np.radians(self.RAcenter), np.radians(self.DECcenter), np.radians(line[1]), np.radians(line[2]))) self.assertLess(rtest, self.radius) myCatalog.write_catalog(catName) # now we will test for the completeness of the circular bounds dtype = np.dtype([('id', np.int), ('raJ2000', np.float), ('decJ2000', np.float)]) testData = np.genfromtxt(catName, dtype=dtype, delimiter=', ') self.assertGreater(len(testData), 0) for line in testData: dl = np.degrees( haversine(np.radians(line['raJ2000']), np.radians(line['decJ2000']), np.radians(self.RAcenter), np.radians(self.DECcenter))) self.assertLess(dl, self.radius) ct = 0 for line in self.starControlData: if line['id'] not in testData['id']: ct += 1 dl = np.degrees( haversine(np.radians(line['raJ2000']), np.radians(line['decJ2000']), np.radians(self.RAcenter), np.radians(self.DECcenter))) self.assertGreater(dl, self.radius) self.assertGreater(ct, 0) if os.path.exists(catName): os.unlink(catName)
def testNonsenseCircularConstraints(self): """ Test that a query performed on a circle bound gets all of the objects (and only all of the objects) within that circle """ myNonsense = CatalogDBObject.from_objid('Nonsense') radius = 20.0 raCenter = 210.0 decCenter = -60.0 mycolumns = [ 'NonsenseId', 'NonsenseRaJ2000', 'NonsenseDecJ2000', 'NonsenseMag' ] circObsMd = ObservationMetaData(boundType='circle', unrefractedRA=raCenter, unrefractedDec=decCenter, boundLength=radius, mjd=52000., bandpassName='r') circQuery = myNonsense.query_columns(colnames=mycolumns, obs_metadata=circObsMd, chunk_size=100) raCenter = numpy.radians(raCenter) decCenter = numpy.radians(decCenter) radius = numpy.radians(radius) goodPoints = [] for chunk in circQuery: for row in chunk: distance = haversine(raCenter, decCenter, row[1], row[2]) self.assertTrue(distance < radius) dex = numpy.where(self.baselineData['id'] == row[0])[0][0] #store a list of which objects fell within our circle bound goodPoints.append(row[0]) self.assertAlmostEqual( numpy.radians(self.baselineData['ra'][dex]), row[1], 3) self.assertAlmostEqual( numpy.radians(self.baselineData['dec'][dex]), row[2], 3) self.assertAlmostEqual(self.baselineData['mag'][dex], row[3], 3) for entry in [ xx for xx in self.baselineData if xx[0] not in goodPoints ]: #make sure that all of the points not returned by the query were, in fact, outside of #the circle bound distance = haversine(raCenter, decCenter, numpy.radians(entry[1]), numpy.radians(entry[2])) self.assertTrue(distance > radius)
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 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 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 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 testCircBounds(self): """ Make sure that circular_bound_constraint in sims.catalogs.generation.db.dbConnection.py does not admit any objects outside of the bounding circle """ catName = os.path.join(getPackageDir('sims_catalogs_measures'), 'tests', 'scratchSpace', 'circular_test_catalog.txt') if os.path.exists(catName): os.unlink(catName) myCatalog = self.starDB.getCatalog('bounds_catalog',obs_metadata = self.obsMdCirc) myIterator = myCatalog.iter_catalog(chunk_size=10) for line in myIterator: rtest = np.degrees(haversine(np.radians(self.RAcenter), np.radians(self.DECcenter), np.radians(line[1]), np.radians(line[2]))) self.assertLess(rtest, self.radius) myCatalog.write_catalog(catName) #now we will test for the completeness of the circular bounds dtype = np.dtype([('id', np.int), ('raJ2000', np.float), ('decJ2000', np.float)]) testData = np.genfromtxt(catName, dtype=dtype, delimiter=', ') self.assertGreater(len(testData), 0) for line in testData: dl = np.degrees(haversine(np.radians(line['raJ2000']), np.radians(line['decJ2000']), np.radians(self.RAcenter), np.radians(self.DECcenter))) self.assertLess(dl, self.radius) ct = 0 for line in self.starControlData: if line['id'] not in testData['id']: ct += 1 dl = np.degrees(haversine(np.radians(line['raJ2000']), np.radians(line['decJ2000']), np.radians(self.RAcenter), np.radians(self.DECcenter))) self.assertGreater(dl, self.radius) self.assertGreater(ct, 0) if os.path.exists(catName): os.unlink(catName)
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 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 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 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 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 match(catsim, jpl, match_tol=match_tol): times = np.unique(np.concatenate([catsim['expMJD'], jpl['epoch_mjd']])) dra = [] ddec = [] dmag = [] ra_jpl = np.radians(jpl['ra_deg']) dec_jpl = np.radians(jpl['dec_deg']) ra_catsim = np.radians(catsim['raJ2000']) dec_catsim = np.radians(catsim['decJ2000']) for t in times: dra_t = [] ddec_t = [] dmag_t = [] tmatch_catsim = np.where(np.abs(catsim['expMJD'] - t) < 15./60./60./24.0)[0] tmatch_jpl = np.where(np.abs(jpl['epoch_mjd'] - t) < 15./60./60./24.)[0] if len(tmatch_catsim) and len(tmatch_jpl) > 0: # catsim and jpl ids are different. Have to match on ra/dec. for ra, dec, mag, objid in zip(ra_catsim[tmatch_catsim], dec_catsim[tmatch_catsim], catsim['magFilter'][tmatch_catsim], catsim['#objid'][tmatch_catsim]): sep = haversine(ra_jpl[tmatch_jpl], dec_jpl[tmatch_jpl], ra, dec) sep = np.degrees(sep) if sep.min() < match_tol: match = np.where(sep == sep.min())[0] dra_t.append(np.degrees(ra-ra_jpl[tmatch_jpl][match])*3600.) ddec_t.append(np.degrees(dec-dec_jpl[tmatch_jpl][match])*3600.) dmag_t.append(mag - jpl['mag'][tmatch_jpl][match]) if sep.min() > 0.1: print objid, jpl['object_name'][tmatch_jpl][match] if len(dra_t) > 0: dra.append(np.array(dra_t).flatten()) ddec.append(np.array(ddec_t).flatten()) dmag.append(np.array(dmag_t).flatten()) return dra, ddec, dmag
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 testCircleBounds(self): """Test Sql Server circular search region. exepectedFailure used despite expectation of success because the test depends on a network connection. """ column_outputs = ['raJ2000', 'decJ2000'] for objname, objcls in CatalogDBObject.registry.iteritems(): if not objcls.doRunTest \ or (objcls.testObservationMetaData is None) \ or (objcls.testObservationMetaData.bounds is None) \ or (objcls.testObservationMetaData.bounds.boundType != 'circle'): continue print "Running tests for", objname obs_metadata = objcls.testObservationMetaData dbobj = objcls(verbose=False) result = dbobj.query_columns(column_outputs, obs_metadata=obs_metadata) #testObservationMetadata gives few enough results for one chunk try: result = result.next() except StopIteration: raise RuntimeError("No results for %s."%(objname)) #confirm radius > distance from all points to center self.assertGreater(obs_metadata.bounds.radius + 1.e-4, max(haversine(numpy.radians(obs_metadata.unrefractedRA), numpy.radians(obs_metadata.unrefractedDec), result['raJ2000'], result['decJ2000'])))
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 testCircleBounds(self): """Test Sql Server circular search region. exepectedFailure used despite expectation of success because the test depends on a network connection. """ column_outputs = ['raJ2000', 'decJ2000'] for objname, objcls in CatalogDBObject.registry.items(): if (not objcls.doRunTest or (objcls.testObservationMetaData is None) or (objcls.testObservationMetaData.bounds is None) or (objcls.testObservationMetaData.bounds.boundType != 'circle')): continue print("Running tests for", objname) obs_metadata = objcls.testObservationMetaData dbobj = objcls(verbose=False) result = dbobj.query_columns(column_outputs, obs_metadata=obs_metadata) # testObservationMetadata gives few enough results for one chunk try: result = next(result) except StopIteration: raise RuntimeError("No results for %s."%(objname)) # confirm radius > distance from all points to center self.assertGreater(obs_metadata.bounds.radius + 1.e-4, max(haversine(numpy.radians(obs_metadata.pointingRA), numpy.radians(obs_metadata.pointingDec), result['raJ2000'], result['decJ2000'])))
def ssoInFov(self, interpfuncs, simdata, rFov=np.radians(1.75), useCamera=True, simdataRaCol = 'fieldRA', simdataDecCol='fieldDec'): """ Return the indexes of the simdata observations where the object was inside the fov. """ # See if the object is within 'rFov' of the center of the boresight. raSso = np.radians(interpfuncs['ra'](simdata['expMJD'])) decSso = np.radians(interpfuncs['dec'](simdata['expMJD'])) sep = haversine(raSso, decSso, simdata[simdataRaCol], simdata[simdataDecCol]) if not useCamera: idxObsRough = np.where(sep<rFov)[0] return idxObsRough # Or go on and use the camera footprint. try: self.camera except AttributeError: self._setupCamera() idxObs = [] idxObsRough = np.where(sep<self.cameraFov)[0] for idx in idxObsRough: mjd = simdata[idx]['expMJD'] obs_metadata = ObservationMetaData(unrefractedRA=np.degrees(simdata[idx][simdataRaCol]), unrefractedDec=np.degrees(simdata[idx][simdataDecCol]), rotSkyPos=np.degrees(simdata[idx]['rotSkyPos']), mjd=simdata[idx]['expMJD']) raObj = np.radians(np.array([interpfuncs['ra'](simdata[idx]['expMJD'])])) decObj = np.radians(np.array([interpfuncs['dec'](simdata[idx]['expMJD'])])) raObj, decObj = observedFromICRS(raObj, decObj, obs_metadata=obs_metadata, epoch=self.epoch) chipNames = findChipName(ra=raObj,dec=decObj, epoch=self.epoch, camera=self.camera, obs_metadata=obs_metadata) if chipNames != [None]: idxObs.append(idx) idxObs = np.array(idxObs) return idxObs
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 testDistanceToSunArray(self): """ Test _distanceToSun on numpy arrays of RA, Dec using solar RA, Dec calculated from http://aa.usno.navy.mil/data/docs/JulianDate.php http://aa.usno.navy.mil/data/docs/geocentric.php """ numpy.random.seed(77) nStars = 100 hour = numpy.radians(360.0/24.0) minute = hour/60.0 second = minute/60.0 mjd_list = [57026.0, 57543.625] sun_ra_list = [18.0*hour + 56.0*minute + 51.022*second, 4.0*hour + 51.0*minute + 22.776*second,] sun_dec_list = [numpy.radians(-22.0-47.0/60.0-40.27/3600.0), numpy.radians(22.0+30.0/60.0+0.73/3600.0)] for mjd, raS, decS in zip(mjd_list, sun_ra_list, sun_dec_list): ra_list = numpy.random.random_sample(nStars)*2.0*numpy.pi dec_list =(numpy.random.random_sample(nStars)-0.5)*numpy.pi distance_list = _distanceToSun(ra_list, dec_list, mjd) distance_control = haversine(ra_list, dec_list, numpy.array([raS]*nStars), numpy.array([decS]*nStars)) numpy.testing.assert_array_almost_equal(distance_list, distance_control, 5)
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 _setupPointGrid(self): """ Setup the points for the interpolation functions. """ # Switch to Dublin Julian Date for pyephem self.Observatory.date = mjd2djd(self.mjd) sun = ephem.Sun() sun.compute(self.Observatory) self.sunAlt = sun.alt self.sunAz = sun.az self.sunRA = sun.ra self.sunDec = sun.dec # Compute airmass the same way as ESO model self.airmass = 1./np.cos(np.pi/2.-self.alts) self.points['airmass'] = self.airmass self.points['nightTimes'] = 2 self.points['alt'] = self.alts self.points['az'] = self.azs if self.twilight: self.points['sunAlt'] = self.sunAlt self.azRelSun = wrapRA(self.azs - self.sunAz) self.points['azRelSun'] = self.azRelSun if self.moon: moon = ephem.Moon() moon.compute(self.Observatory) self.moonPhase = moon.phase self.moonAlt = moon.alt self.moonAz = moon.az self.moonRA = moon.ra self.moonDec = moon.dec # Calc azimuth relative to moon self.azRelMoon = calcAzRelMoon(self.azs, self.moonAz) self.moonTargSep = haversine(self.azs, self.alts, self.moonAz, self.moonAlt) self.points['moonAltitude'] += np.degrees(self.moonAlt) self.points['azRelMoon'] += self.azRelMoon self.moonSunSep = self.moonPhase/100.*180. self.points['moonSunSep'] += self.moonSunSep if self.zodiacal: self.eclipLon = np.zeros(self.npts) self.eclipLat = np.zeros(self.npts) for i, temp in enumerate(self.ra): eclip = ephem.Ecliptic(ephem.Equatorial(self.ra[i], self.dec[i], epoch='2000')) self.eclipLon[i] += eclip.lon self.eclipLat[i] += eclip.lat # Subtract off the sun ecliptic longitude sunEclip = ephem.Ecliptic(sun) self.sunEclipLon = sunEclip.lon self.points['altEclip'] += self.eclipLat self.points['azEclipRelSun'] += wrapRA(self.eclipLon - self.sunEclipLon) self.mask = np.where((self.airmass > self.airmassLimit) | (self.airmass < 1.))[0] self.goodPix = np.where((self.airmass <= self.airmassLimit) & (self.airmass >= 1.))[0]
def slew_time(ra0, dec0, ra1, dec1): ang_speed = np.radians(5.) """ Compute slew time to new ra, dec position """ dist = haversine(ra1, dec1, ra0, dec0) time = dist / ang_speed return time
def testSunMoon(self): """ Test that the sun moon interpolation is good enough """ if self.data_present: sm = self.sm telescope = utils.Site('LSST') Observatory = ephem.Observer() Observatory.lat = telescope.latitude_rad Observatory.lon = telescope.longitude_rad Observatory.elevation = telescope.height sun = ephem.Sun() moon = ephem.Moon() mjd1 = sm.info['mjds'][0] mjd2 = sm.info['mjds'][3] mjds = np.linspace(mjd1, mjd2, 20) # Demand Moon and Sun Positions match to within 3 arcmin arcmin_places = np.abs(np.floor(np.log10(3. / 60. / 180. * np.pi))).astype(int) for mjd in mjds: Observatory.date = mjd2djd(mjd) sun.compute(Observatory) moon.compute(Observatory) pre_calced = sm.returnSunMoon(mjd) self.assertLess(np.abs(pre_calced['sunAlt'] - sun.alt), arcmin_places) sun_dist = haversine(sun.ra, sun.dec, pre_calced['sunRA'], pre_calced['sunDec']) self.assertAlmostEqual(sun_dist, 0., places=arcmin_places) self.assertLess(np.abs(pre_calced['moonAlt'] - moon.alt), arcmin_places) moon_dist = haversine(moon.ra, moon.dec, pre_calced['moonRA'], pre_calced['moonDec']) self.assertAlmostEqual(moon_dist, 0., places=arcmin_places) self.assertAlmostEqual(np.radians(pre_calced['moonSunSep']), np.radians(moon.phase / 100. * 180.), places=arcmin_places)
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 setParams(self, airmass=1.,azs=90., alts=None, moonPhase=31.67, moonAlt=45., moonAz=0., sunAlt=-12., sunAz=0., sunEclipLon=0., eclipLon=135., eclipLat=90., degrees=True, solarFlux=130.): """ Set paramters manually. Note, you can put in unphysical combinations of paramters if you want to (e.g., put a full moon at zenith at sunset). if the alts kwarg is set it will override the airmass kwarg. MoonPhase is percent of moon illuminated (0-100) """ # Convert all values to radians for internal use. if degrees: convertFunc = np.radians else: convertFunc = justReturn self.solarFlux=solarFlux self.sunAlt = convertFunc(sunAlt) self.moonPhase = moonPhase self.moonAlt = convertFunc(moonAlt) self.moonAz = convertFunc(moonAz) self.eclipLon = convertFunc(eclipLon) self.eclipLat = convertFunc(eclipLat) self.sunEclipLon = convertFunc(sunEclipLon) self.azs = convertFunc(azs) if alts is not None: self.airmass = 1./np.cos(np.pi/2.-convertFunc(alts)) self.alts = convertFunc(alts) else: self.airmass = airmass self.alts = np.pi/2.-np.arccos(1./airmass) self.moonTargSep = haversine(azs, alts, moonAz, self.moonAlt) self.npts = np.size(airmass) self._initPoints() self.points['airmass'] = self.airmass self.points['nightTimes'] = 2 self.points['alt'] = self.alts self.points['az'] = self.azs self.azRelMoon = wrapRA(self.azs - self.moonAz) over = np.where(self.azRelMoon > np.pi) self.azRelMoon[over] = 2.*np.pi - self.azRelMoon[over] self.points['moonAltitude'] += np.degrees(self.moonAlt) self.points['azRelMoon'] = self.azRelMoon self.points['moonSunSep'] += self.moonPhase/100.*180. self.eclipLon = convertFunc(eclipLon) self.eclipLat = convertFunc(eclipLat) self.sunEclipLon = convertFunc(sunEclipLon) self.points['altEclip'] += self.eclipLat self.points['azEclipRelSun'] += wrapRA(self.eclipLon - self.sunEclipLon) self.sunAz = convertFunc(sunAz) self.points['sunAlt'] = self.sunAlt self.points['azRelSun'] = wrapRA(self.azs - self.sunAz) self.points['solarFlux'] = solarFlux
def testHaversine(self): arg1 = 7.853981633974482790e-01 arg2 = 3.769911184307751517e-01 arg3 = 5.026548245743668986e+00 arg4 = -6.283185307179586232e-01 output = utils.haversine(arg1, arg2, arg3, arg4) self.assertAlmostEqual(output, 2.162615946398791955e+00, 10)
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 healpixels2dist(nside, hp1, hp2): """ Compute the angular distance between 2 healpixels """ lat1, ra1 = hp.pix2ang(nside, hp1) lat2, ra2 = hp.pix2ang(nside, hp2) dec1 = np.pi / 2.0 - lat1 dec2 = np.pi / 2.0 - lat2 angDist = haversine(ra1, dec1, ra2, dec2) return angDist
def healpixels2dist(nside, hp1,hp2): """ Compute the angular distance between 2 healpixels """ lat1, ra1 = hp.pix2ang(nside,hp1) lat2, ra2 = hp.pix2ang(nside,hp2) dec1 = np.pi/2.0 - lat1 dec2 = np.pi/2.0 - lat2 angDist = haversine(ra1,dec1,ra2,dec2) return angDist
def testaltaz2radec(self): np.random.seed(42) az = np.random.rand(100) * np.pi * 2 alt = np.random.rand(100) * np.pi - np.pi / 2 site = Site('LSST') mjd = 55000 omd = ObservationMetaData(mjd=mjd, site=site) trueRA, trueDec = _raDecFromAltAz(alt, az, omd) fastRA, fastDec = sb.stupidFast_altAz2RaDec(alt, az, site.latitude_rad, site.longitude_rad, mjd) distanceDiff = haversine(trueRA, trueDec, fastRA, fastDec) degreeTol = 2. # 2-degree tolerance on the fast transform assert (np.degrees(distanceDiff.max()) < degreeTol)
def get_shift(self): """ A getter for the angular distance between the unrefracted raJ2000, decJ2000 and the corrected raObserved, decObserved Note that because all angles are handled inside of the stack as radians, the returned angular distance will also be in radians """ r0 = self.column_by_name('raJ2000') d0 = self.column_by_name('decJ2000') r1 = self.column_by_name('raObserved') d1 = self.column_by_name('decObserved') return haversine(r0, d0, r1, d1)
def testaltaz2radec(self): np.random.seed(42) az = np.random.rand(100)*np.pi*2 alt = np.random.rand(100)*np.pi-np.pi/2 site = Site('LSST') mjd = 55000 omd = ObservationMetaData(mjd=mjd,site=site) trueRA,trueDec = _raDecFromAltAz(alt,az, omd) fastRA,fastDec = sb.stupidFast_altAz2RaDec(alt,az,site.latitude_rad, site.longitude_rad,mjd) distanceDiff = haversine(trueRA,trueDec, fastRA,fastDec) degreeTol =2. # 2-degree tolerance on the fast transform assert(np.degrees(distanceDiff.max()) < degreeTol)
def diff_image(mjd, mjd2, filter_name='R'): """ Let's just load up a single image and difference it with the one taken before """ sm.setRaDecMjd(ra, dec, mjd) frame = single_frame(mjd, filter_name=filter_name) dist2moon = haversine(sm.azs, sm.alts, sm.moonAz, sm.moonAlt) frame[np.where(dist2moon < np.radians(moonLimit))] = hp.UNSEEN template_frame = single_frame(mjd2, filter_name=filter_name) good = np.where((frame != hp.UNSEEN) & (template_frame != hp.UNSEEN) & (sm.airmass >= 1.) & (sm.airmass <= am_limit) & (~np.isnan(frame)) & (~np.isnan(template_frame))) diff = np.zeros(frame.size, dtype=float) + hp.UNSEEN diff[good] = frame[good] - template_frame[good] return diff
def _distanceToSun(ra, dec, mjd, epoch=2000.0): """ Calculate the distance from an (ra, dec) point to the Sun (in radians). @param [in] ra in radians @param [in] dec in radians @param [in] mjd is the date (TDB) in question as an MJD @param [in] epoch is the epoch of the coordinate system (default is 2000.0) @param [out] distance on the sky to the Sun in radians """ sunRa, sunDec = _solarRaDec(mjd, epoch=epoch) if hasattr(ra, '__len__'): return haversine(ra, dec, numpy.array([sunRa]*len(ra)), numpy.array([sunDec]*len(ra))) return haversine(ra, dec,sunRa, sunDec)
def testradec2altaz(self): np.random.seed(42) ra = np.random.rand(100)*np.pi*2 dec = np.random.rand(100)*np.pi-np.pi/2 site = Site('LSST') mjd = 55000 omd = ObservationMetaData(mjd=mjd,site=site) trueAlt,trueAz,pa = _altAzPaFromRaDec(ra,dec,omd) fastAlt,fastAz = sb.stupidFast_RaDec2AltAz(ra,dec, site.latitude_rad, site.longitude_rad,mjd) distanceDiff = haversine(trueAz,trueAlt, fastAz,fastAlt) degreeTol =2. # 2-degree tolerance on the fast transform assert(np.degrees(distanceDiff.max()) < degreeTol)
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 diff_image(mjd, mjd2, filter_name="R"): """ Let's just load up a single image and difference it with the one taken before """ sm.setRaDecMjd(ra, dec, mjd) frame = single_frame(mjd, filter_name=filter_name) dist2moon = haversine(sm.azs, sm.alts, sm.moonAz, sm.moonAlt) frame[np.where(dist2moon < np.radians(moonLimit))] = hp.UNSEEN template_frame = single_frame(mjd2, filter_name=filter_name) good = np.where( (frame != hp.UNSEEN) & (template_frame != hp.UNSEEN) & (sm.airmass >= 1.0) & (sm.airmass <= am_limit) & (~np.isnan(frame)) & (~np.isnan(template_frame)) ) diff = np.zeros(frame.size, dtype=float) + hp.UNSEEN diff[good] = frame[good] - template_frame[good] return diff
def _distanceToSun(ra, dec, mjd, epoch=2000.0): """ Calculate the distance from an (ra, dec) point to the Sun (in radians). @param [in] ra in radians @param [in] dec in radians @param [in] mjd is the date represented as a ModifiedJulianDate object. @param [in] epoch is the epoch of the coordinate system (default is 2000.0) @param [out] distance on the sky to the Sun in radians """ sunRa, sunDec = _solarRaDec(mjd, epoch=epoch) return haversine(ra, dec, sunRa, sunDec)
def testRaDecVector(self): """ Test that raDecFromNativeLonLat does invert nativeLonLatFromRaDec (make sure it works in a vectorized way) """ np.random.seed(42) nSamples = 100 latList = np.random.random_sample(nSamples)*360.0 lonList = np.random.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 testradec2altaz(self): np.random.seed(42) ra = np.random.rand(100) * np.pi * 2 dec = np.random.rand(100) * np.pi - np.pi / 2 site = Site('LSST') mjd = 55000 omd = ObservationMetaData(mjd=mjd, site=site) trueAlt, trueAz, pa = _altAzPaFromRaDec(ra, dec, omd) fastAlt, fastAz = sb.stupidFast_RaDec2AltAz(ra, dec, site.latitude_rad, site.longitude_rad, mjd) distanceDiff = haversine(trueAz, trueAlt, fastAz, fastAlt) degreeTol = 2. # 2-degree tolerance on the fast transform assert (np.degrees(distanceDiff.max()) < degreeTol) # make sure we don't have nans alt, az = sb.stupidFast_RaDec2AltAz(np.radians(np.array([0.])), np.radians(np.array([-90.])), np.radians(-30.2444), np.radians(-70.7494), 59582.05125) assert (~np.isnan(alt)) assert (~np.isnan(az))
def testAltAzRADecRoundTrip(self): """ Test that altAzPaFromRaDec and raDecFromAltAz really invert each other """ np.random.seed(42) 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.assertFalse(np.isnan(ra_in).any()) self.assertFalse(np.isnan(dec_in).any()) alt_out, az_out, pa_out = utils.altAzPaFromRaDec(ra_in, dec_in, obs) self.assertFalse(np.isnan(pa_out).any()) 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) # not sure why 0.2 arcsec is the limiting precision of this test
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 testHaversine(self): """ Test that haversine() returns the same thing as _angularSeparation """ ra1 = 0.2 dec1 = 1.3 ra2 = 2.1 dec2 = -0.5 ra3 = np.array([1.9, 2.1, 0.3]) dec3 = np.array([-1.1, 0.34, 0.01]) control = utils._angularSeparation(ra1, dec1, ra2, dec2) test = utils.haversine(ra1, dec1, ra2, dec2) self.assertIsInstance(test, float) self.assertEqual(test, control) control = utils._angularSeparation(ra1, dec1, ra3, dec3) test = utils.haversine(ra1, dec1, ra3, dec3) np.testing.assert_array_equal(test, control) control = utils._angularSeparation(np.array([ra1]), np.array([dec1]), ra3, dec3) test = utils.haversine(np.array([ra1]), np.array([dec1]), ra3, dec3) np.testing.assert_array_equal(test, control) control = utils._angularSeparation(ra3, dec3, np.array([ra1]), np.array([dec1])) test = utils.haversine(ra3, dec3, np.array([ra1]), np.array([dec1])) np.testing.assert_array_equal(test, control) control = utils._angularSeparation(ra2, dec2, np.array([ra1]), np.array([dec1])) test = utils.haversine(ra2, dec2, np.array([ra1]), np.array([dec1])) self.assertIsInstance(test, float) self.assertEqual(test, control) control = utils._angularSeparation(np.array([ra1]), np.array([dec1]), ra2, dec2) test = utils.haversine(np.array([ra1]), np.array([dec1]), ra2, dec2) self.assertIsInstance(test, float) self.assertEqual(test, control)
def testNonsenseCircularConstraints(self): """ Test that a query performed on a circle bound gets all of the objects (and only all of the objects) within that circle """ radius = 20.0 raCenter = 210.0 decCenter = -60.0 mycolumns = ['NonsenseId', 'NonsenseRaJ2000', 'NonsenseDecJ2000', 'NonsenseMag'] circObsMd = ObservationMetaData(boundType='circle', pointingRA=raCenter, pointingDec=decCenter, boundLength=radius, mjd=52000., bandpassName='r') circQuery = self.myNonsense.query_columns(colnames = mycolumns, obs_metadata=circObsMd, chunk_size=100) raCenter = numpy.radians(raCenter) decCenter = numpy.radians(decCenter) radius = numpy.radians(radius) goodPoints = [] ct = 0 for chunk in circQuery: for row in chunk: ct += 1 distance = haversine(raCenter, decCenter, row[1], row[2]) self.assertLess(distance, radius) dex = numpy.where(self.baselineData['id'] == row[0])[0][0] #store a list of which objects fell within our circle bound goodPoints.append(row[0]) self.assertAlmostEqual(numpy.radians(self.baselineData['ra'][dex]), row[1], 3) self.assertAlmostEqual(numpy.radians(self.baselineData['dec'][dex]), row[2], 3) self.assertAlmostEqual(self.baselineData['mag'][dex], row[3], 3) self.assertGreater(ct, 0) ct = 0 for entry in [xx for xx in self.baselineData if xx[0] not in goodPoints]: #make sure that all of the points not returned by the query were, in fact, outside of #the circle bound distance = haversine(raCenter, decCenter, numpy.radians(entry[1]), numpy.radians(entry[2])) self.assertGreater(distance, radius) ct += 1 self.assertGreater(ct, 0) #make sure that the CatalogDBObject which used a header gets the same result headerQuery = self.myNonsenseHeader.query_columns(colnames = mycolumns, obs_metadata=circObsMd, chunk_size=100) goodPointsHeader = [] for chunk in headerQuery: for row in chunk: distance = haversine(raCenter, decCenter, row[1], row[2]) dex = numpy.where(self.baselineData['id'] == row[0])[0][0] goodPointsHeader.append(row[0]) self.assertAlmostEqual(numpy.radians(self.baselineData['ra'][dex]), row[1], 3) self.assertAlmostEqual(numpy.radians(self.baselineData['dec'][dex]), row[2], 3) self.assertAlmostEqual(self.baselineData['mag'][dex], row[3], 3) self.assertEqual(len(goodPoints), len(goodPointsHeader)) for xx in goodPoints: self.assertIn(xx, goodPointsHeader)
def setParams(self, airmass=1., azs=90., alts=None, moonPhase=31.67, moonAlt=45., moonAz=0., sunAlt=-12., sunAz=0., sunEclipLon=0., eclipLon=135., eclipLat=90., degrees=True, solarFlux=130., filterNames=['u', 'g', 'r', 'i', 'z', 'y']): """ Set parameters manually. Note, you can put in unphysical combinations of paramters if you want to (e.g., put a full moon at zenith at sunset). if the alts kwarg is set it will override the airmass kwarg. MoonPhase is percent of moon illuminated (0-100) """ # Convert all values to radians for internal use. self.filterNames = filterNames if self.mags: self.npix = len(self.filterNames) if degrees: convertFunc = np.radians else: convertFunc = justReturn self.solarFlux = solarFlux self.sunAlt = convertFunc(sunAlt) self.moonPhase = moonPhase self.moonAlt = convertFunc(moonAlt) self.moonAz = convertFunc(moonAz) self.eclipLon = convertFunc(eclipLon) self.eclipLat = convertFunc(eclipLat) self.sunEclipLon = convertFunc(sunEclipLon) self.azs = convertFunc(azs) if alts is not None: self.airmass = 1. / np.cos(np.pi / 2. - convertFunc(alts)) self.alts = convertFunc(alts) else: self.airmass = airmass self.alts = np.pi / 2. - np.arccos(1. / airmass) self.moonTargSep = haversine(self.azs, self.alts, moonAz, self.moonAlt) self.npts = np.size(self.airmass) self._initPoints() self.points['airmass'] = self.airmass self.points['nightTimes'] = 2 self.points['alt'] = self.alts self.points['az'] = self.azs self.azRelMoon = calcAzRelMoon(self.azs, self.moonAz) self.points['moonAltitude'] += np.degrees(self.moonAlt) self.points['azRelMoon'] = self.azRelMoon self.points['moonSunSep'] += self.moonPhase / 100. * 180. self.eclipLon = convertFunc(eclipLon) self.eclipLat = convertFunc(eclipLat) self.sunEclipLon = convertFunc(sunEclipLon) self.points['altEclip'] += self.eclipLat self.points['azEclipRelSun'] += wrapRA(self.eclipLon - self.sunEclipLon) self.sunAz = convertFunc(sunAz) self.points['sunAlt'] = self.sunAlt self.points['azRelSun'] = wrapRA(self.azs - self.sunAz) self.points['solarFlux'] = solarFlux self.paramsSet = True self.mask = np.where((self.airmass > self.airmassLimit) | (self.airmass < 1.))[0] self.goodPix = np.where((self.airmass <= self.airmassLimit) & (self.airmass >= 1.))[0] # Interpolate the templates to the set paramters self._interpSky()
def _setupPointGrid(self): """ Setup the points for the interpolation functions. """ # Switch to Dublin Julian Date for pyephem self.Observatory.date = mjd2djd(self.mjd) sun = ephem.Sun() sun.compute(self.Observatory) self.sunAlt = sun.alt self.sunAz = sun.az self.sunRA = sun.ra self.sunDec = sun.dec # Compute airmass the same way as ESO model self.airmass = 1. / np.cos(np.pi / 2. - self.alts) self.points['airmass'] = self.airmass self.points['nightTimes'] = 2 self.points['alt'] = self.alts self.points['az'] = self.azs if self.twilight: self.points['sunAlt'] = self.sunAlt self.azRelSun = wrapRA(self.azs - self.sunAz) self.points['azRelSun'] = self.azRelSun if self.moon: moon = ephem.Moon() moon.compute(self.Observatory) self.moonPhase = moon.phase self.moonAlt = moon.alt self.moonAz = moon.az self.moonRA = moon.ra self.moonDec = moon.dec # Calc azimuth relative to moon self.azRelMoon = calcAzRelMoon(self.azs, self.moonAz) self.moonTargSep = haversine(self.azs, self.alts, self.moonAz, self.moonAlt) self.points['moonAltitude'] += np.degrees(self.moonAlt) self.points['azRelMoon'] += self.azRelMoon self.moonSunSep = self.moonPhase / 100. * 180. self.points['moonSunSep'] += self.moonSunSep if self.zodiacal: self.eclipLon = np.zeros(self.npts) self.eclipLat = np.zeros(self.npts) for i, temp in enumerate(self.ra): eclip = ephem.Ecliptic( ephem.Equatorial(self.ra[i], self.dec[i], epoch='2000')) self.eclipLon[i] += eclip.lon self.eclipLat[i] += eclip.lat # Subtract off the sun ecliptic longitude sunEclip = ephem.Ecliptic(sun) self.sunEclipLon = sunEclip.lon self.points['altEclip'] += self.eclipLat self.points['azEclipRelSun'] += wrapRA(self.eclipLon - self.sunEclipLon) self.mask = np.where((self.airmass > self.airmassLimit) | (self.airmass < 1.))[0] self.goodPix = np.where((self.airmass <= self.airmassLimit) & (self.airmass >= 1.))[0]
def testStarLike(self): """ Write a couple of catalogs. Verify that the objects that end up in the catalog fall within the pointing and that the objects that do not end up in the catalog fall outside of the pointing """ catName = os.path.join(getPackageDir('sims_catalogs_measures'), 'tests', 'scratchSpace', '_starLikeCat.txt') if os.path.exists(catName): os.unlink(catName) # this dtype corresponds to the outputs of the catalog dtype = np.dtype([ ('id', np.int), ('raJ2000', np.float), ('decJ2000', np.float), ('umag', np.float), ('gmag', np.float), ('rmag', np.float), ('imag', np.float), ('zmag', np.float), ('ymag', np.float), ('ra_corr', np.float), ('dec_corr', np.float) ]) t = self.starDB.getCatalog('custom_catalog', obs_metadata=self.obsMd) t.write_catalog(catName) testData = np.genfromtxt(catName, delimiter = ', ', dtype=dtype) # make sure that something ended up in the catalog self.assertGreater(len(testData), 0) # iterate over the lines in the catalog # verify that those line exist in the control data # also verify that those lines fall within the requested field of view for line in testData: ic = np.where(self.starControlData['id']==line['id'])[0][0] self.assertAlmostEqual(line['umag'], self.starControlData['umag'][ic], 6) self.assertAlmostEqual(line['gmag'], self.starControlData['gmag'][ic], 6) self.assertAlmostEqual(line['rmag'], self.starControlData['rmag'][ic], 6) self.assertAlmostEqual(line['imag'], self.starControlData['imag'][ic], 6) self.assertAlmostEqual(line['zmag'], self.starControlData['zmag'][ic], 6) self.assertAlmostEqual(line['ymag'], self.starControlData['ymag'][ic], 6) self.assertAlmostEqual(line['raJ2000'], self.starControlData['raJ2000'][ic], 6) self.assertAlmostEqual(line['decJ2000'], self.starControlData['decJ2000'][ic], 6) self.assertAlmostEqual(line['ra_corr'], line['raJ2000']+0.001, 6) self.assertAlmostEqual(line['dec_corr'], line['decJ2000']+0.001, 6) dl = haversine(np.radians(line['raJ2000']), np.radians(line['decJ2000']), self.obsMd._pointingRA, self.obsMd._pointingDec) self.assertLess(np.degrees(dl), self.obsMd.boundLength) # examine the lines that did not fall in the catalog lines_not_in_catalog = np.where(self.starControlData['id'] not in testData['id'])[0] self.assertGreater(len(lines_not_in_catalog), 0) # make sure that those lines are, indeed, outside of the field of view for ic in lines_not_in_catalog: dl = haversine(self.obsMd._pointingRA, self.obsMd._pointingDec, np.radians(self.starControlData['raJ2000'][ic]), np.radians(self.starControlData['decJ2000'][ic])) self.assertGreater(np.degrees(dl), self.obsMd.boundLength) if os.path.exists(catName): os.unlink(catName) # now do the same thing for the basic catalog class dtype = np.dtype([ ('id', np.int), ('raJ2000', np.float), ('decJ2000', np.float), ('umag', np.float), ('gmag', np.float), ('rmag', np.float), ('imag', np.float), ('zmag', np.float), ('ymag', np.float) ]) t = self.starDB.getCatalog('basic_catalog', obs_metadata=self.obsMd) t.write_catalog(catName) testData = np.genfromtxt(catName, delimiter = ', ', dtype=dtype) # make sure that something ended up in the catalog self.assertGreater(len(testData), 0) # iterate over the lines in the catalog # verify that those line exist in the control data # also verify that those lines fall within the requested field of view for line in testData: ic = np.where(self.starControlData['id']==line['id'])[0][0] self.assertAlmostEqual(line['umag'], self.starControlData['umag'][ic], 6) self.assertAlmostEqual(line['gmag'], self.starControlData['gmag'][ic], 6) self.assertAlmostEqual(line['rmag'], self.starControlData['rmag'][ic], 6) self.assertAlmostEqual(line['imag'], self.starControlData['imag'][ic], 6) self.assertAlmostEqual(line['zmag'], self.starControlData['zmag'][ic], 6) self.assertAlmostEqual(line['ymag'], self.starControlData['ymag'][ic], 6) self.assertAlmostEqual(line['raJ2000'], self.starControlData['raJ2000'][ic], 6) self.assertAlmostEqual(line['decJ2000'], self.starControlData['decJ2000'][ic], 6) dl = haversine(np.radians(line['raJ2000']), np.radians(line['decJ2000']), self.obsMd._pointingRA, self.obsMd._pointingDec) self.assertLess(np.degrees(dl), self.obsMd.boundLength) # examine the lines that did not fall in the catalog lines_not_in_catalog = np.where(self.starControlData['id'] not in testData['id'])[0] self.assertGreater(len(lines_not_in_catalog), 0) # make sure that those lines are, indeed, outside of the field of view for ic in lines_not_in_catalog: dl = haversine(self.obsMd._pointingRA, self.obsMd._pointingDec, np.radians(self.starControlData['raJ2000'][ic]), np.radians(self.starControlData['decJ2000'][ic])) self.assertGreater(np.degrees(dl), self.obsMd.boundLength) if os.path.exists(catName): os.unlink(catName)
def testOutputWcsOfImage(self): """ Test that, when GalSim generates an image, in encodes the WCS in a way afw can read. This is done by creating an image,then reading it back in, getting its WCS, and comparing the pixel-to-sky conversion both for the read WCS and the original afw.cameraGeom.detector. Raise an exception if the median difference between the two is greater than 0.01 arcseconds. """ scratchDir = os.path.join(getPackageDir('sims_GalSimInterface'), 'tests', 'scratchSpace') catName = os.path.join(scratchDir, 'outputWcs_test_Catalog.dat') imageRoot = os.path.join(scratchDir, 'outputWcs_test_Image') dbFileName = os.path.join(scratchDir, 'outputWcs_test_InputCatalog.dat') baseDir = os.path.join(getPackageDir('sims_GalSimInterface'), 'tests', 'cameraData') camera = ReturnCamera(baseDir) detector = camera[0] detName = detector.getName() imageName = '%s_%s_u.fits' % (imageRoot, detName) nSamples = 3 rng = np.random.RandomState(42) pointingRaList = rng.random_sample(nSamples) * 360.0 pointingDecList = rng.random_sample(nSamples) * 180.0 - 90.0 rotSkyPosList = rng.random_sample(nSamples) * 360.0 for raPointing, decPointing, rotSkyPos in \ zip(pointingRaList, pointingDecList, rotSkyPosList): obs = ObservationMetaData(pointingRA=raPointing, pointingDec=decPointing, boundType='circle', boundLength=4.0, rotSkyPos=rotSkyPos, mjd=49250.0) fwhm = 0.7 create_text_catalog(obs, dbFileName, np.array([3.0]), np.array([1.0])) db = outputWcsFileDBObj(dbFileName, runtable='test') cat = outputWcsCat(db, obs_metadata=obs) cat.camera = camera psf = SNRdocumentPSF(fwhm=fwhm) cat.setPSF(psf) cat.write_catalog(catName) cat.write_images(nameRoot=imageRoot) # 20 March 2017 # the 'try' block is how it worked in SWIG; # the 'except' block is how it works in pybind11 try: exposure = afwImage.ExposureD_readFits(imageName) except AttributeError: exposure = afwImage.ExposureD.readFits(imageName) wcs = exposure.getWcs() xxTestList = [] yyTestList = [] raImage = [] decImage = [] for xx in np.arange(0.0, 4001.0, 100.0): for yy in np.arange(0.0, 4001.0, 100.0): xxTestList.append(xx) yyTestList.append(yy) pt = afwGeom.Point2D(xx, yy) skyPt = wcs.pixelToSky(pt).getPosition() raImage.append(skyPt.getX()) decImage.append(skyPt.getY()) xxTestList = np.array(xxTestList) yyTestList = np.array(yyTestList) raImage = np.radians(np.array(raImage)) decImage = np.radians(np.array(decImage)) raControl, \ decControl = _raDecFromPixelCoords(xxTestList, yyTestList, [detector.getName()]*len(xxTestList), camera=camera, obs_metadata=obs, epoch=2000.0) errorList = arcsecFromRadians( haversine(raControl, decControl, raImage, decImage)) medianError = np.median(errorList) msg = 'medianError was %e' % medianError self.assertLess(medianError, 0.01, msg=msg) if os.path.exists(catName): os.unlink(catName) if os.path.exists(dbFileName): os.unlink(dbFileName) if os.path.exists(imageName): os.unlink(imageName)