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.utils import getPackageDir 

13from lsst.sims.utils.CodeUtilities import sims_clean_up 

14from lsst.sims.catalogs.definitions import InstanceCatalog 

15from lsst.sims.utils import ObservationMetaData, arcsecFromRadians 

16from lsst.sims.utils import _observedFromAppGeo, _pupilCoordsFromRaDec 

17from lsst.sims.coordUtils import focalPlaneCoordsFromPupilCoords, _focalPlaneCoordsFromRaDec 

18from lsst.sims.coordUtils import chipNameFromPupilCoords, _chipNameFromRaDec 

19from lsst.sims.coordUtils import pixelCoordsFromPupilCoords, _pixelCoordsFromRaDec 

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

21 myTestGals, makeGalTestDB) 

22import lsst.afw.cameraGeom.testUtils as camTestUtils 

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

24 

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

26TEST_STAR_DATABASE = 'AstrometryTestStarDatabase.db' 

27TEST_GALAXY_DATABASE = 'AstrometryTestGalaxyDatabase.db' 

28 

29 

30def setup_module(module): 

31 lsst.utils.tests.init() 

32 

33 

34class AstrometryTestStars(myTestStars): 

35 database = TEST_STAR_DATABASE 

36 

37 

38class AstrometryTestGalaxies(myTestGals): 

39 database = TEST_GALAXY_DATABASE 

40 

41 

42class parallaxTestCatalog(InstanceCatalog, AstrometryStars): 

43 catalog_type = __file__ + 'parallax_test_catalog' 

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

45 'properMotionRa', 'properMotionDec', 

46 'radialVelocity', 'parallax'] 

47 

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

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

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

51 'parallax': arcsecFromRadians} 

52 

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

54 

55 

56class testCatalog(InstanceCatalog, AstrometryStars, CameraCoords): 

57 """ 

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

59 to run the astrometry routines for testing purposes 

60 """ 

61 catalog_type = __file__ + 'test_stars' 

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

63 'parallax', 'radial_velocity', 

64 'x_pupil', 'y_pupil', 

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

66 # Needed to do camera coordinate transforms. 

67 camera = camTestUtils.CameraWrapper().camera 

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

69 

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

71 # (see testClassMethods) 

72 

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

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

75 ('parallax', 1.2, float), 

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

77 

78 

79class testStellarCatalog(InstanceCatalog, AstrometryStars, CameraCoords): 

80 """ 

81 Define a catalog of stars with all possible astrometric columns 

82 """ 

83 

84 camera = camTestUtils.CameraWrapper().camera 

85 

86 column_outputs = ['glon', 'glat', 

87 'x_pupil', 'y_pupil', 

88 'xPix', 'yPix', 

89 'xFocalPlane', 'yFocalPlane', 

90 'chipName', 

91 'raObserved', 'decObserved'] 

92 

93 

94class testGalaxyCatalog(InstanceCatalog, AstrometryGalaxies, CameraCoords): 

95 """ 

96 Define a catalog of galaxies with all possible astrometric columns 

97 """ 

98 

99 camera = camTestUtils.CameraWrapper().camera 

100 

101 column_outputs = ['glon', 'glat', 

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

103 'chipName', 'raObserved', 'decObserved'] 

104 

105 delimiter = '; ' 

106 

107 

108class astrometryUnitTest(unittest.TestCase): 

109 """ 

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

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

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

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

114 to any particular Opsim run. 

115 """ 

116 

117 @classmethod 

118 def setUpClass(cls): 

119 # Create test databases 

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

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

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

123 

124 makeStarTestDB(filename=cls.starDBName, 

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

126 

127 makeGalTestDB(filename=cls.galDBName, 

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

129 

130 @classmethod 

131 def tearDownClass(cls): 

132 sims_clean_up() 

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

134 os.unlink(cls.starDBName) 

135 

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

137 os.unlink(cls.galDBName) 

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

139 shutil.rmtree(cls.scratch_dir) 

140 

141 def setUp(self): 

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

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

144 

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

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

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

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

149 # inputs, these are set arbitrarily by hand 

150 

151 self.obs_metadata = ObservationMetaData(pointingRA=200.0, 

152 pointingDec=-30.0, 

153 rotSkyPos=np.degrees(1.0), 

154 mjd=57388.0, 

155 boundType='circle', 

156 boundLength=0.05) 

157 

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

159 self.tol = 1.0e-5 

160 

161 def tearDown(self): 

162 del self.starDBObject 

163 del self.galaxyDBObject 

164 del self.cat 

165 del self.obs_metadata 

166 del self.tol 

167 

168 def testWritingOfStars(self): 

169 """ 

170 Try writing a catalog with all possible Astrometric columns 

171 """ 

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

173 

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

175 stars.write_catalog(catName) 

176 

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

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

179 

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

181 

182 def testWritingOfGalaxies(self): 

183 """ 

184 Try writing a catalog with all possible Astrometric columns 

185 """ 

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

187 galaxies.delimiter = ';' 

188 

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

190 galaxies.write_catalog(catName) 

191 

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

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

194 

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

196 

197 def testUtilityMethods(self): 

198 """ 

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

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

201 that they are consistent. 

202 """ 

203 

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

205 self.cat.write_catalog(catName) 

206 

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

208 ('raICRS', float), ('decICRS', float), 

209 ('parallax', float), ('radial_velocity', float), 

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

211 ('xPix', float), ('yPix', float), 

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

213 

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

215 

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

217 

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

219 baselineData['decICRS'], 

220 parallax=baselineData['parallax'], 

221 v_rad=baselineData['radial_velocity'], 

222 obs_metadata=self.obs_metadata, 

223 epoch=2000.0) 

224 

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

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

227 self.assertAlmostEqual(xxtest, xx, 6) 

228 self.assertAlmostEqual(yytest, yy, 6) 

229 

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

231 

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

233 parallax=baselineData['parallax'], 

234 v_rad=baselineData['radial_velocity'], 

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

236 camera=self.cat.camera) 

237 

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

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

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

241 

242 self.assertAlmostEqual(xxtest, xx, 6) 

243 self.assertAlmostEqual(yytest, yy, 6) 

244 self.assertAlmostEqual(xxra, xx, 6) 

245 self.assertAlmostEqual(yyra, yy, 6) 

246 

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

248 

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

250 parallax=baselineData['parallax'], 

251 v_rad=baselineData['radial_velocity'], 

252 epoch=self.cat.db_obj.epoch, 

253 obs_metadata=self.cat.obs_metadata, 

254 camera=self.cat.camera) 

255 

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

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

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

259 

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

261 self.assertAlmostEqual(xxtest, xx, 5) 

262 self.assertAlmostEqual(yytest, yy, 5) 

263 self.assertAlmostEqual(xxra, xx, 5) 

264 self.assertAlmostEqual(yyra, yy, 5) 

265 else: 

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

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

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

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

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

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

272 

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

274 camera=self.cat.camera) 

275 

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

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

278 camera=self.cat.camera) 

279 

280 is_none = 0 

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

282 if ncontrol != 'None': 

283 self.assertEqual(ntest, ncontrol) 

284 self.assertEqual(nra, ncontrol) 

285 else: 

286 is_none += 1 

287 self.assertIsNone(ntest) 

288 self.assertIsNone(nra) 

289 

290 self.assertGreater(is_none, 0) 

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

292 

293 def testParallax(self): 

294 """ 

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

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

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

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

299 generating code correctly applied the transformations. 

300 """ 

301 

302 # create and write a catalog that performs astrometric transformations 

303 # on a cartoon star database 

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

305 

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

307 cat.write_catalog(parallaxName) 

308 

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

310 

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

312 

313 epoch = cat.db_obj.epoch 

314 mjd = cat.obs_metadata.mjd 

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

316 for vv in data: 

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

318 # the results to the contents of the catalog 

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

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

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

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

323 rv = vv[6] 

324 px = vv[7] 

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

326 ra_apparent = np.array([ra_apparent]) 

327 dec_apparent = np.array([dec_apparent]) 

328 raObserved, decObserved = _observedFromAppGeo(ra_apparent, dec_apparent, 

329 obs_metadata=cat.obs_metadata) 

330 

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

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

333 

334 

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

336 pass 

337 

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

339 lsst.utils.tests.init() 

340 unittest.main()