Coverage for tests/testAstrometryMixins.py : 33%

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
4import os
5import unittest
6import math
7import palpy as pal
8import tempfile
9import shutil
10import lsst.utils.tests
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
24ROOT = os.path.abspath(os.path.dirname(__file__))
25TEST_STAR_DATABASE = 'AstrometryTestStarDatabase.db'
26TEST_GALAXY_DATABASE = 'AstrometryTestGalaxyDatabase.db'
29def setup_module(module):
30 lsst.utils.tests.init()
33class AstrometryTestStars(myTestStars):
34 database = TEST_STAR_DATABASE
37class AstrometryTestGalaxies(myTestGals):
38 database = TEST_GALAXY_DATABASE
41class parallaxTestCatalog(InstanceCatalog, AstrometryStars):
42 catalog_type = __file__ + 'parallax_test_catalog'
43 column_outputs = ['raJ2000', 'decJ2000', 'raObserved', 'decObserved',
44 'properMotionRa', 'properMotionDec',
45 'radialVelocity', 'parallax']
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}
52 default_formats = {'f': '%.12f'}
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'}
69 delimiter = ';' # so that np.loadtxt can parse the chipNames which may contain commas
70 # (see testClassMethods)
72 default_columns = [('properMotionRa', 0., float),
73 ('properMotionDec', 0., float),
74 ('parallax', 1.2, float),
75 ('radial_velocity', 0., float)]
78class testStellarCatalog(InstanceCatalog, AstrometryStars, CameraCoords):
79 """
80 Define a catalog of stars with all possible astrometric columns
81 """
83 camera = camTestUtils.CameraWrapper().camera
85 column_outputs = ['glon', 'glat',
86 'x_pupil', 'y_pupil',
87 'xPix', 'yPix',
88 'xFocalPlane', 'yFocalPlane',
89 'chipName',
90 'raObserved', 'decObserved']
93class testGalaxyCatalog(InstanceCatalog, AstrometryGalaxies, CameraCoords):
94 """
95 Define a catalog of galaxies with all possible astrometric columns
96 """
98 camera = camTestUtils.CameraWrapper().camera
100 column_outputs = ['glon', 'glat',
101 'x_pupil', 'y_pupil', 'xPix', 'yPix', 'xFocalPlane', 'yFocalPlane',
102 'chipName', 'raObserved', 'decObserved']
104 delimiter = '; '
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 """
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)
123 makeStarTestDB(filename=cls.starDBName,
124 size=100000, seedVal=1, ramin=199.98*math.pi/180., dra=0.04*math.pi/180.)
126 makeGalTestDB(filename=cls.galDBName,
127 size=100000, seedVal=1, ramin=199.98*math.pi/180., dra=0.04*math.pi/180.)
129 @classmethod
130 def tearDownClass(cls):
131 sims_clean_up()
132 if os.path.exists(cls.starDBName):
133 os.unlink(cls.starDBName)
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)
140 def setUp(self):
141 self.starDBObject = AstrometryTestStars(database=self.starDBName)
142 self.galaxyDBObject = AstrometryTestGalaxies(database=self.galDBName)
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
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)
157 self.cat = testCatalog(self.starDBObject, obs_metadata=self.obs_metadata)
158 self.tol = 1.0e-5
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
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)
173 with lsst.utils.tests.getTempFilePath('.txt') as catName:
174 stars.write_catalog(catName)
176 dtypeList = [(name, np.float) for name in stars._column_outputs]
177 testData = np.genfromtxt(catName, delimiter=', ', dtype=np.dtype(dtypeList))
179 self.assertGreater(len(testData), 0)
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 = ';'
188 with lsst.utils.tests.getTempFilePath('.txt') as catName:
189 galaxies.write_catalog(catName)
191 dtypeList = [(name, np.float) for name in galaxies._column_outputs]
192 testData = np.genfromtxt(catName, dtype=np.dtype(dtypeList), delimiter=';')
194 self.assertGreater(len(testData), 0)
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 """
203 with lsst.utils.tests.getTempFilePath('.txt') as catName:
204 self.cat.write_catalog(catName)
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)]
213 baselineData = np.genfromtxt(catName, dtype=dtype, delimiter=';')
215 self.assertGreater(len(baselineData), 0)
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)
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)
229 focalTest = focalPlaneCoordsFromPupilCoords(pupilTest[0], pupilTest[1], camera=self.cat.camera)
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)
237 for (xxtest, yytest, xxra, yyra, xx, yy) in \
238 zip(focalTest[0], focalTest[1], focalRa[0], focalRa[1],
239 baselineData['xFocalPlane'], baselineData['yFocalPlane']):
241 self.assertAlmostEqual(xxtest, xx, 6)
242 self.assertAlmostEqual(yytest, yy, 6)
243 self.assertAlmostEqual(xxra, xx, 6)
244 self.assertAlmostEqual(yyra, yy, 6)
246 pixTest = pixelCoordsFromPupilCoords(pupilTest[0], pupilTest[1], camera=self.cat.camera)
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)
255 for (xxtest, yytest, xxra, yyra, xx, yy) in \
256 zip(pixTest[0], pixTest[1], pixTestRaDec[0], pixTestRaDec[1],
257 baselineData['xPix'], baselineData['yPix']):
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)
272 nameTest = chipNameFromPupilCoords(pupilTest[0], pupilTest[1],
273 camera=self.cat.camera)
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)
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)
289 self.assertGreater(is_none, 0)
290 self.assertLess(is_none, len(baselineData))
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 """
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)
305 with lsst.utils.tests.getTempFilePath('.sav') as parallaxName:
306 cat.write_catalog(parallaxName)
308 data = np.genfromtxt(parallaxName, delimiter=',')
310 self.assertGreater(len(data), 0)
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)
330 self.assertAlmostEqual(raObserved[0], np.radians(vv[2]), 7)
331 self.assertAlmostEqual(decObserved[0], np.radians(vv[3]), 7)
334class MemoryTestClass(lsst.utils.tests.MemoryTestCase):
335 pass
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()