Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1from builtins import zip 

2import numpy as np 

3 

4import os 

5import unittest 

6import math 

7import palpy as pal 

8import tempfile 

9import shutil 

10import lsst.utils.tests 

11 

12from lsst.sims.utils.CodeUtilities import sims_clean_up 

13from lsst.sims.catalogs.definitions import InstanceCatalog 

14from lsst.sims.utils import ObservationMetaData, arcsecFromRadians 

15from lsst.sims.utils import _observedFromAppGeo, _pupilCoordsFromRaDec 

16from lsst.sims.coordUtils import focalPlaneCoordsFromPupilCoords, _focalPlaneCoordsFromRaDec 

17from lsst.sims.coordUtils import chipNameFromPupilCoords, _chipNameFromRaDec 

18from lsst.sims.coordUtils import pixelCoordsFromPupilCoords, _pixelCoordsFromRaDec 

19from lsst.sims.catalogs.utils import (myTestStars, makeStarTestDB, 

20 myTestGals, makeGalTestDB) 

21import lsst.afw.cameraGeom.testUtils as camTestUtils 

22from lsst.sims.catUtils.mixins import AstrometryStars, AstrometryGalaxies, CameraCoords 

23 

24ROOT = os.path.abspath(os.path.dirname(__file__)) 

25TEST_STAR_DATABASE = 'AstrometryTestStarDatabase.db' 

26TEST_GALAXY_DATABASE = 'AstrometryTestGalaxyDatabase.db' 

27 

28 

29def setup_module(module): 

30 lsst.utils.tests.init() 

31 

32 

33class AstrometryTestStars(myTestStars): 

34 database = TEST_STAR_DATABASE 

35 

36 

37class AstrometryTestGalaxies(myTestGals): 

38 database = TEST_GALAXY_DATABASE 

39 

40 

41class parallaxTestCatalog(InstanceCatalog, AstrometryStars): 

42 catalog_type = __file__ + 'parallax_test_catalog' 

43 column_outputs = ['raJ2000', 'decJ2000', 'raObserved', 'decObserved', 

44 'properMotionRa', 'properMotionDec', 

45 'radialVelocity', 'parallax'] 

46 

47 transformations = {'raJ2000': np.degrees, 'decJ2000': np.degrees, 

48 'raObserved': np.degrees, 'decObserved': np.degrees, 

49 'properMotionRa': np.degrees, 'properMotionDec': np.degrees, 

50 'parallax': arcsecFromRadians} 

51 

52 default_formats = {'f': '%.12f'} 

53 

54 

55class testCatalog(InstanceCatalog, AstrometryStars, CameraCoords): 

56 """ 

57 A (somewhat meaningless) instance catalog class that will allow us 

58 to run the astrometry routines for testing purposes 

59 """ 

60 catalog_type = __file__ + 'test_stars' 

61 column_outputs = ['id', 'raICRS', 'decICRS', 

62 'parallax', 'radial_velocity', 

63 'x_pupil', 'y_pupil', 

64 'chipName', 'xPix', 'yPix', 'xFocalPlane', 'yFocalPlane'] 

65 # Needed to do camera coordinate transforms. 

66 camera = camTestUtils.CameraWrapper().camera 

67 default_formats = {'f': '%.12f'} 

68 

69 delimiter = ';' # so that np.loadtxt can parse the chipNames which may contain commas 

70 # (see testClassMethods) 

71 

72 default_columns = [('properMotionRa', 0., float), 

73 ('properMotionDec', 0., float), 

74 ('parallax', 1.2, float), 

75 ('radial_velocity', 0., float)] 

76 

77 

78class testStellarCatalog(InstanceCatalog, AstrometryStars, CameraCoords): 

79 """ 

80 Define a catalog of stars with all possible astrometric columns 

81 """ 

82 

83 camera = camTestUtils.CameraWrapper().camera 

84 

85 column_outputs = ['glon', 'glat', 

86 'x_pupil', 'y_pupil', 

87 'xPix', 'yPix', 

88 'xFocalPlane', 'yFocalPlane', 

89 'chipName', 

90 'raObserved', 'decObserved'] 

91 

92 

93class testGalaxyCatalog(InstanceCatalog, AstrometryGalaxies, CameraCoords): 

94 """ 

95 Define a catalog of galaxies with all possible astrometric columns 

96 """ 

97 

98 camera = camTestUtils.CameraWrapper().camera 

99 

100 column_outputs = ['glon', 'glat', 

101 'x_pupil', 'y_pupil', 'xPix', 'yPix', 'xFocalPlane', 'yFocalPlane', 

102 'chipName', 'raObserved', 'decObserved'] 

103 

104 delimiter = '; ' 

105 

106 

107class astrometryUnitTest(unittest.TestCase): 

108 """ 

109 The bulk of this unit test involves inputting a set list of input values 

110 and comparing the astrometric results to results derived from SLALIB run 

111 with the same input values. We have to create a test catalog artificially (rather than 

112 querying the database) because SLALIB was originally run on values that did not correspond 

113 to any particular Opsim run. 

114 """ 

115 

116 @classmethod 

117 def setUpClass(cls): 

118 # Create test databases 

119 cls.scratch_dir = tempfile.mkdtemp(dir=ROOT, prefix="astrometryUnitTest-") 

120 cls.starDBName = os.path.join(cls.scratch_dir, TEST_STAR_DATABASE) 

121 cls.galDBName = os.path.join(cls.scratch_dir, TEST_GALAXY_DATABASE) 

122 

123 makeStarTestDB(filename=cls.starDBName, 

124 size=100000, seedVal=1, ramin=199.98*math.pi/180., dra=0.04*math.pi/180.) 

125 

126 makeGalTestDB(filename=cls.galDBName, 

127 size=100000, seedVal=1, ramin=199.98*math.pi/180., dra=0.04*math.pi/180.) 

128 

129 @classmethod 

130 def tearDownClass(cls): 

131 sims_clean_up() 

132 if os.path.exists(cls.starDBName): 

133 os.unlink(cls.starDBName) 

134 

135 if os.path.exists(cls.galDBName): 

136 os.unlink(cls.galDBName) 

137 if os.path.exists(cls.scratch_dir): 

138 shutil.rmtree(cls.scratch_dir, ignore_errors=True) 

139 

140 def setUp(self): 

141 self.starDBObject = AstrometryTestStars(database=self.starDBName) 

142 self.galaxyDBObject = AstrometryTestGalaxies(database=self.galDBName) 

143 

144 # below are metadata values that need to be set in order for 

145 # get_getFocalPlaneCoordinates to work. If we had been querying the database, 

146 # these would be set to meaningful values. Because we are generating 

147 # an artificial set of inputs that must comport to the baseline SLALIB 

148 # inputs, these are set arbitrarily by hand 

149 

150 self.obs_metadata = ObservationMetaData(pointingRA=200.0, 

151 pointingDec=-30.0, 

152 rotSkyPos=np.degrees(1.0), 

153 mjd=57388.0, 

154 boundType='circle', 

155 boundLength=0.05) 

156 

157 self.cat = testCatalog(self.starDBObject, obs_metadata=self.obs_metadata) 

158 self.tol = 1.0e-5 

159 

160 def tearDown(self): 

161 del self.starDBObject 

162 del self.galaxyDBObject 

163 del self.cat 

164 del self.obs_metadata 

165 del self.tol 

166 

167 def testWritingOfStars(self): 

168 """ 

169 Try writing a catalog with all possible Astrometric columns 

170 """ 

171 stars = testStellarCatalog(self.starDBObject, obs_metadata=self.obs_metadata) 

172 

173 with lsst.utils.tests.getTempFilePath('.txt') as catName: 

174 stars.write_catalog(catName) 

175 

176 dtypeList = [(name, np.float) for name in stars._column_outputs] 

177 testData = np.genfromtxt(catName, delimiter=', ', dtype=np.dtype(dtypeList)) 

178 

179 self.assertGreater(len(testData), 0) 

180 

181 def testWritingOfGalaxies(self): 

182 """ 

183 Try writing a catalog with all possible Astrometric columns 

184 """ 

185 galaxies = testGalaxyCatalog(self.galaxyDBObject, obs_metadata=self.obs_metadata) 

186 galaxies.delimiter = ';' 

187 

188 with lsst.utils.tests.getTempFilePath('.txt') as catName: 

189 galaxies.write_catalog(catName) 

190 

191 dtypeList = [(name, np.float) for name in galaxies._column_outputs] 

192 testData = np.genfromtxt(catName, dtype=np.dtype(dtypeList), delimiter=';') 

193 

194 self.assertGreater(len(testData), 0) 

195 

196 def testUtilityMethods(self): 

197 """ 

198 Generate a catalog using the methods from AstrometryUtils.py and CameraUtils.py. 

199 Read that data in, and then recalculate the values 'by hand' to make sure 

200 that they are consistent. 

201 """ 

202 

203 with lsst.utils.tests.getTempFilePath('.txt') as catName: 

204 self.cat.write_catalog(catName) 

205 

206 dtype = [('id', int), 

207 ('raICRS', float), ('decICRS', float), 

208 ('parallax', float), ('radial_velocity', float), 

209 ('x_pupil', float), ('y_pupil', float), ('chipName', str, 11), 

210 ('xPix', float), ('yPix', float), 

211 ('xFocalPlane', float), ('yFocalPlane', float)] 

212 

213 baselineData = np.genfromtxt(catName, dtype=dtype, delimiter=';') 

214 

215 self.assertGreater(len(baselineData), 0) 

216 

217 pupilTest = _pupilCoordsFromRaDec(baselineData['raICRS'], 

218 baselineData['decICRS'], 

219 parallax=baselineData['parallax'], 

220 v_rad=baselineData['radial_velocity'], 

221 obs_metadata=self.obs_metadata, 

222 epoch=2000.0) 

223 

224 for (xxtest, yytest, xx, yy) in \ 

225 zip(pupilTest[0], pupilTest[1], baselineData['x_pupil'], baselineData['y_pupil']): 

226 self.assertAlmostEqual(xxtest, xx, 6) 

227 self.assertAlmostEqual(yytest, yy, 6) 

228 

229 focalTest = focalPlaneCoordsFromPupilCoords(pupilTest[0], pupilTest[1], camera=self.cat.camera) 

230 

231 focalRa = _focalPlaneCoordsFromRaDec(baselineData['raICRS'], baselineData['decICRS'], 

232 parallax=baselineData['parallax'], 

233 v_rad=baselineData['radial_velocity'], 

234 epoch=self.cat.db_obj.epoch, obs_metadata=self.cat.obs_metadata, 

235 camera=self.cat.camera) 

236 

237 for (xxtest, yytest, xxra, yyra, xx, yy) in \ 

238 zip(focalTest[0], focalTest[1], focalRa[0], focalRa[1], 

239 baselineData['xFocalPlane'], baselineData['yFocalPlane']): 

240 

241 self.assertAlmostEqual(xxtest, xx, 6) 

242 self.assertAlmostEqual(yytest, yy, 6) 

243 self.assertAlmostEqual(xxra, xx, 6) 

244 self.assertAlmostEqual(yyra, yy, 6) 

245 

246 pixTest = pixelCoordsFromPupilCoords(pupilTest[0], pupilTest[1], camera=self.cat.camera) 

247 

248 pixTestRaDec = _pixelCoordsFromRaDec(baselineData['raICRS'], baselineData['decICRS'], 

249 parallax=baselineData['parallax'], 

250 v_rad=baselineData['radial_velocity'], 

251 epoch=self.cat.db_obj.epoch, 

252 obs_metadata=self.cat.obs_metadata, 

253 camera=self.cat.camera) 

254 

255 for (xxtest, yytest, xxra, yyra, xx, yy) in \ 

256 zip(pixTest[0], pixTest[1], pixTestRaDec[0], pixTestRaDec[1], 

257 baselineData['xPix'], baselineData['yPix']): 

258 

259 if not np.isnan(xx) and not np.isnan(yy): 

260 self.assertAlmostEqual(xxtest, xx, 5) 

261 self.assertAlmostEqual(yytest, yy, 5) 

262 self.assertAlmostEqual(xxra, xx, 5) 

263 self.assertAlmostEqual(yyra, yy, 5) 

264 else: 

265 np.testing.assert_equal(xx, np.NaN) 

266 np.testing.assert_equal(yy, np.NaN) 

267 np.testing.assert_equal(xxra, np.NaN) 

268 np.testing.assert_equal(yyra, np.NaN) 

269 np.testing.assert_equal(xxtest, np.NaN) 

270 np.testing.assert_equal(yytest, np.NaN) 

271 

272 nameTest = chipNameFromPupilCoords(pupilTest[0], pupilTest[1], 

273 camera=self.cat.camera) 

274 

275 nameRA = _chipNameFromRaDec(baselineData['raICRS'], baselineData['decICRS'], 

276 epoch=self.cat.db_obj.epoch, obs_metadata=self.cat.obs_metadata, 

277 camera=self.cat.camera) 

278 

279 is_none = 0 

280 for (ntest, nra, ncontrol) in zip(nameTest, nameRA, baselineData['chipName']): 

281 if ncontrol != 'None': 

282 self.assertEqual(ntest, ncontrol) 

283 self.assertEqual(nra, ncontrol) 

284 else: 

285 is_none += 1 

286 self.assertIsNone(ntest) 

287 self.assertIsNone(nra) 

288 

289 self.assertGreater(is_none, 0) 

290 self.assertLess(is_none, len(baselineData)) 

291 

292 def testParallax(self): 

293 """ 

294 This test will output a catalog of ICRS and observed positions. 

295 It will also output the quantities (proper motion, radial velocity, 

296 and parallax) needed to apply the transformaiton between the two. 

297 It will then run the catalog through PALPY and verify that the catalog 

298 generating code correctly applied the transformations. 

299 """ 

300 

301 # create and write a catalog that performs astrometric transformations 

302 # on a cartoon star database 

303 cat = parallaxTestCatalog(self.starDBObject, obs_metadata=self.obs_metadata) 

304 

305 with lsst.utils.tests.getTempFilePath('.sav') as parallaxName: 

306 cat.write_catalog(parallaxName) 

307 

308 data = np.genfromtxt(parallaxName, delimiter=',') 

309 

310 self.assertGreater(len(data), 0) 

311 

312 epoch = cat.db_obj.epoch 

313 mjd = cat.obs_metadata.mjd 

314 prms = pal.mappa(epoch, mjd.TDB) 

315 for vv in data: 

316 # run the PALPY routines that actuall do astrometry `by hand' and compare 

317 # the results to the contents of the catalog 

318 ra0 = np.radians(vv[0]) 

319 dec0 = np.radians(vv[1]) 

320 pmra = np.radians(vv[4]) 

321 pmdec = np.radians(vv[5]) 

322 rv = vv[6] 

323 px = vv[7] 

324 ra_apparent, dec_apparent = pal.mapqk(ra0, dec0, pmra, pmdec, px, rv, prms) 

325 ra_apparent = np.array([ra_apparent]) 

326 dec_apparent = np.array([dec_apparent]) 

327 raObserved, decObserved = _observedFromAppGeo(ra_apparent, dec_apparent, 

328 obs_metadata=cat.obs_metadata) 

329 

330 self.assertAlmostEqual(raObserved[0], np.radians(vv[2]), 7) 

331 self.assertAlmostEqual(decObserved[0], np.radians(vv[3]), 7) 

332 

333 

334class MemoryTestClass(lsst.utils.tests.MemoryTestCase): 

335 pass 

336 

337if __name__ == "__main__": 337 ↛ 338line 337 didn't jump to line 338, because the condition on line 337 was never true

338 lsst.utils.tests.init() 

339 unittest.main()