Coverage for tests/testAstrometryMixins.py : 32%

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.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
25ROOT = os.path.abspath(os.path.dirname(__file__))
26TEST_STAR_DATABASE = 'AstrometryTestStarDatabase.db'
27TEST_GALAXY_DATABASE = 'AstrometryTestGalaxyDatabase.db'
30def setup_module(module):
31 lsst.utils.tests.init()
34class AstrometryTestStars(myTestStars):
35 database = TEST_STAR_DATABASE
38class AstrometryTestGalaxies(myTestGals):
39 database = TEST_GALAXY_DATABASE
42class parallaxTestCatalog(InstanceCatalog, AstrometryStars):
43 catalog_type = __file__ + 'parallax_test_catalog'
44 column_outputs = ['raJ2000', 'decJ2000', 'raObserved', 'decObserved',
45 'properMotionRa', 'properMotionDec',
46 'radialVelocity', 'parallax']
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}
53 default_formats = {'f': '%.12f'}
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'}
70 delimiter = ';' # so that np.loadtxt can parse the chipNames which may contain commas
71 # (see testClassMethods)
73 default_columns = [('properMotionRa', 0., float),
74 ('properMotionDec', 0., float),
75 ('parallax', 1.2, float),
76 ('radial_velocity', 0., float)]
79class testStellarCatalog(InstanceCatalog, AstrometryStars, CameraCoords):
80 """
81 Define a catalog of stars with all possible astrometric columns
82 """
84 camera = camTestUtils.CameraWrapper().camera
86 column_outputs = ['glon', 'glat',
87 'x_pupil', 'y_pupil',
88 'xPix', 'yPix',
89 'xFocalPlane', 'yFocalPlane',
90 'chipName',
91 'raObserved', 'decObserved']
94class testGalaxyCatalog(InstanceCatalog, AstrometryGalaxies, CameraCoords):
95 """
96 Define a catalog of galaxies with all possible astrometric columns
97 """
99 camera = camTestUtils.CameraWrapper().camera
101 column_outputs = ['glon', 'glat',
102 'x_pupil', 'y_pupil', 'xPix', 'yPix', 'xFocalPlane', 'yFocalPlane',
103 'chipName', 'raObserved', 'decObserved']
105 delimiter = '; '
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 """
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)
124 makeStarTestDB(filename=cls.starDBName,
125 size=100000, seedVal=1, ramin=199.98*math.pi/180., dra=0.04*math.pi/180.)
127 makeGalTestDB(filename=cls.galDBName,
128 size=100000, seedVal=1, ramin=199.98*math.pi/180., dra=0.04*math.pi/180.)
130 @classmethod
131 def tearDownClass(cls):
132 sims_clean_up()
133 if os.path.exists(cls.starDBName):
134 os.unlink(cls.starDBName)
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)
141 def setUp(self):
142 self.starDBObject = AstrometryTestStars(database=self.starDBName)
143 self.galaxyDBObject = AstrometryTestGalaxies(database=self.galDBName)
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
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)
158 self.cat = testCatalog(self.starDBObject, obs_metadata=self.obs_metadata)
159 self.tol = 1.0e-5
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
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)
174 with lsst.utils.tests.getTempFilePath('.txt') as catName:
175 stars.write_catalog(catName)
177 dtypeList = [(name, np.float) for name in stars._column_outputs]
178 testData = np.genfromtxt(catName, delimiter=', ', dtype=np.dtype(dtypeList))
180 self.assertGreater(len(testData), 0)
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 = ';'
189 with lsst.utils.tests.getTempFilePath('.txt') as catName:
190 galaxies.write_catalog(catName)
192 dtypeList = [(name, np.float) for name in galaxies._column_outputs]
193 testData = np.genfromtxt(catName, dtype=np.dtype(dtypeList), delimiter=';')
195 self.assertGreater(len(testData), 0)
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 """
204 with lsst.utils.tests.getTempFilePath('.txt') as catName:
205 self.cat.write_catalog(catName)
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)]
214 baselineData = np.genfromtxt(catName, dtype=dtype, delimiter=';')
216 self.assertGreater(len(baselineData), 0)
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)
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)
230 focalTest = focalPlaneCoordsFromPupilCoords(pupilTest[0], pupilTest[1], camera=self.cat.camera)
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)
238 for (xxtest, yytest, xxra, yyra, xx, yy) in \
239 zip(focalTest[0], focalTest[1], focalRa[0], focalRa[1],
240 baselineData['xFocalPlane'], baselineData['yFocalPlane']):
242 self.assertAlmostEqual(xxtest, xx, 6)
243 self.assertAlmostEqual(yytest, yy, 6)
244 self.assertAlmostEqual(xxra, xx, 6)
245 self.assertAlmostEqual(yyra, yy, 6)
247 pixTest = pixelCoordsFromPupilCoords(pupilTest[0], pupilTest[1], camera=self.cat.camera)
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)
256 for (xxtest, yytest, xxra, yyra, xx, yy) in \
257 zip(pixTest[0], pixTest[1], pixTestRaDec[0], pixTestRaDec[1],
258 baselineData['xPix'], baselineData['yPix']):
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)
273 nameTest = chipNameFromPupilCoords(pupilTest[0], pupilTest[1],
274 camera=self.cat.camera)
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)
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)
290 self.assertGreater(is_none, 0)
291 self.assertLess(is_none, len(baselineData))
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 """
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)
306 with lsst.utils.tests.getTempFilePath('.sav') as parallaxName:
307 cat.write_catalog(parallaxName)
309 data = np.genfromtxt(parallaxName, delimiter=',')
311 self.assertGreater(len(data), 0)
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)
331 self.assertAlmostEqual(raObserved[0], np.radians(vv[2]), 7)
332 self.assertAlmostEqual(decObserved[0], np.radians(vv[3]), 7)
335class MemoryTestClass(lsst.utils.tests.MemoryTestCase):
336 pass
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()