Coverage for tests/testPlacement.py : 30%

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
2from builtins import range
3import unittest
4import tempfile
5import shutil
6import lsst.utils.tests
8import numpy as np
9import os
10from lsst.utils import getPackageDir
11import lsst.afw.image as afwImage
12from lsst.sims.utils.CodeUtilities import sims_clean_up
13from lsst.sims.utils import ObservationMetaData, arcsecFromRadians, haversine
14#from lsst.sims.coordUtils.utils import ReturnCamera
15from lsst.sims.coordUtils import _pixelCoordsFromRaDec, _raDecFromPixelCoords
16from lsst.sims.photUtils import Sed, Bandpass
17from lsst.sims.catalogs.db import fileDBObject
18from lsst.sims.GalSimInterface import GalSimStars, SNRdocumentPSF
19from lsst.sims.GalSimInterface import GalSimCameraWrapper
20from testUtils import create_text_catalog
22ROOT = os.path.abspath(os.path.dirname(__file__))
25def setup_module(module):
26 lsst.utils.tests.init()
29class placementFileDBObj(fileDBObject):
30 idColKey = 'test_id'
31 objectTypeId = 88
32 tableid = 'test'
33 raColName = 'ra'
34 decColName = 'dec'
36 columns = [('raJ2000', 'ra*PI()/180.0', np.float),
37 ('decJ2000', 'dec*PI()/180.0', np.float),
38 ('magNorm', 'mag_norm', np.float)]
41class placementCatalog(GalSimStars):
43 bandpassNames = ['u']
45 def get_galacticAv(self):
46 ra = self.column_by_name('raJ2000')
47 return np.array([0.1]*len(ra))
49 default_columns = GalSimStars.default_columns
51 default_columns += [('sedFilename', 'sed_flat.txt', (str, 12)),
52 ('properMotionRa', 0.0, np.float),
53 ('properMotionDec', 0.0, np.float),
54 ('radialVelocity', 0.0, np.float),
55 ('parallax', 0.0, np.float)
56 ]
58@unittest.skip('ReturnCamera deprecated - need replacement')
59class GalSimPlacementTest(unittest.TestCase):
61 @classmethod
62 def tearDownClass(cls):
63 sims_clean_up()
65 def setUp(self):
66 self.magNorm = 19.0
68 def check_placement(self, imageName, raList, decList, fwhmList,
69 countList, gain,
70 detector, camera, obs, epoch=2000.0):
71 """
72 Read in a FITS image and a list of objects meant to be on that
73 image. Verify that the objects were placed at the correct pixel
74 by counting up all of the flux within 2 fwhm of each object's
75 expected location and verifying it with the counts expected for
76 that object.
78 @param [in] imageName is the name of the FITS file to be read in
80 @param [in] raList is a numpy array of the RA coordinates of the objects
81 in the image (in radians)
83 @param [in] decList is a numpy array of the Dec coordinates of the objects
84 in the image (in radians)
86 @param [in] fwhmList is a list of the Full Width at Half Maximum of
87 each object in arcseconds
89 @param [in] countList is a list of the counts expected for each object
91 @param [in] gain is the gain of the detector (electrons per ADU)
93 @param [in] detector is an instantiation of the afw.cameraGeom Detector
94 class characterizing the detector corresponding to this image
96 @param [in] camera is an instantiation of the afw.cameraGeom Camera class
97 characterizing the camera to which detector belongs
99 @param [in] obs is an instantiation of ObservationMetaData characterizing
100 the telescope pointing
102 @param [in] epoch is the epoch in Julian years of the equinox against which
103 RA and Dec are measured.
105 Raises an exception of the counts detected for each object differs from
106 the expected amount by more than 3 sigma.
107 """
109 im = afwImage.ImageF(imageName).getArray()
110 activePixels = np.where(im > 1.0e-10)
112 # I know this seems backwards, but the way numpy handles arrays,
113 # the first index is the row (i.e. the y coordinate)
114 imXList = activePixels[1]
115 imYList = activePixels[0]
117 nameList = [detector.getName()]*len(raList)
118 xPixList, yPixList = _pixelCoordsFromRaDec(raList, decList,
119 chipName=nameList,
120 camera=camera,
121 obs_metadata=obs,
122 epoch=epoch)
124 for rr, dd, xx, yy, fwhm, cc in \
125 zip(raList, decList, xPixList, yPixList, fwhmList, countList):
127 countSigma = np.sqrt(cc/gain)
129 imNameList = [detector.getName()]*len(imXList)
130 raImList, decImList = _raDecFromPixelCoords(imXList, imYList,
131 imNameList,
132 camera=camera,
133 obs_metadata=obs,
134 epoch=epoch)
136 distanceList = arcsecFromRadians(haversine(raImList, decImList, rr, dd))
138 fluxArray = np.array([im[imYList[ix]][imXList[ix]]
139 for ix in range(len(distanceList))
140 if distanceList[ix] < 2.0*fwhm])
142 totalFlux = fluxArray.sum()
143 msg = 'totalFlux %e should be %e diff/sigma %e' \
144 % (totalFlux, cc, np.abs(totalFlux-cc)/countSigma)
146 self.assertLess(np.abs(totalFlux-cc), 3.0*countSigma, msg=msg)
148 def testObjectPlacement(self):
149 """
150 Test that GalSim places objects on the correct pixel by drawing
151 images, reading them in, and then comparing the flux contained in
152 circles of 2 fwhm radii about the object's expected positions with
153 the actual expected flux of the objects.
154 """
155 scratchDir = tempfile.mkdtemp(dir=ROOT, prefix='testObjectPlacement-')
156 catName = os.path.join(scratchDir, 'placementCatalog.dat')
157 imageRoot = os.path.join(scratchDir, 'placementImage')
158 dbFileName = os.path.join(scratchDir, 'placementInputCatalog.dat')
160 cameraDir = os.path.join(getPackageDir('sims_GalSimInterface'), 'tests', 'cameraData')
161 camera = ReturnCamera(cameraDir)
162 detector = camera[0]
163 imageName = '%s_%s_u.fits' % (imageRoot, detector.getName())
165 controlSed = Sed()
166 controlSed.readSED_flambda(os.path.join(getPackageDir('sims_sed_library'),
167 'flatSED', 'sed_flat.txt.gz'))
169 uBandpass = Bandpass()
170 uBandpass.readThroughput(os.path.join(getPackageDir('throughputs'),
171 'baseline', 'total_u.dat'))
173 controlBandpass = Bandpass()
174 controlBandpass.imsimBandpass()
176 ff = controlSed.calcFluxNorm(self.magNorm, uBandpass)
177 controlSed.multiplyFluxNorm(ff)
178 a_int, b_int = controlSed.setupCCM_ab()
179 controlSed.addDust(a_int, b_int, A_v=0.1, R_v=3.1)
181 nSamples = 3
182 rng = np.random.RandomState(42)
183 pointingRaList = rng.random_sample(nSamples)*360.0
184 pointingDecList = rng.random_sample(nSamples)*180.0 - 90.0
185 rotSkyPosList = rng.random_sample(nSamples)*360.0
186 fwhmList = rng.random_sample(nSamples)*1.0 + 0.3
188 actualCounts = None
190 for pointingRA, pointingDec, rotSkyPos, fwhm in \
191 zip(pointingRaList, pointingDecList, rotSkyPosList, fwhmList):
193 obs = ObservationMetaData(pointingRA=pointingRA,
194 pointingDec=pointingDec,
195 boundType='circle',
196 boundLength=4.0,
197 mjd=49250.0,
198 rotSkyPos=rotSkyPos)
200 xDisplacementList = rng.random_sample(nSamples)*60.0-30.0
201 yDisplacementList = rng.random_sample(nSamples)*60.0-30.0
202 create_text_catalog(obs, dbFileName, xDisplacementList, yDisplacementList,
203 mag_norm=[self.magNorm]*len(xDisplacementList))
204 db = placementFileDBObj(dbFileName, runtable='test')
205 cat = placementCatalog(db, obs_metadata=obs)
206 cat.camera_wrapper = GalSimCameraWrapper(camera)
207 if actualCounts is None:
208 actualCounts = controlSed.calcADU(uBandpass, cat.photParams)
210 psf = SNRdocumentPSF(fwhm=fwhm)
211 cat.setPSF(psf)
213 cat.write_catalog(catName)
214 cat.write_images(nameRoot=imageRoot)
216 objRaList = []
217 objDecList = []
218 with open(catName, 'r') as inFile:
219 for line in inFile:
220 if line[0] != '#':
221 words = line.split(';')
222 objRaList.append(np.radians(np.float(words[2])))
223 objDecList.append(np.radians(np.float(words[3])))
225 objRaList = np.array(objRaList)
226 objDecList = np.array(objDecList)
228 self.assertGreater(len(objRaList), 0) # make sure we aren't testing
229 # an empty catalog/image
231 self.check_placement(imageName, objRaList, objDecList,
232 [fwhm]*len(objRaList),
233 np.array([actualCounts]*len(objRaList)),
234 cat.photParams.gain, detector, camera, obs, epoch=2000.0)
236 if os.path.exists(dbFileName):
237 os.unlink(dbFileName)
238 if os.path.exists(catName):
239 os.unlink(catName)
240 if os.path.exists(imageName):
241 os.unlink(imageName)
243 if os.path.exists(scratchDir):
244 shutil.rmtree(scratchDir)
247class MemoryTestClass(lsst.utils.tests.MemoryTestCase):
248 pass
250if __name__ == "__main__": 250 ↛ 251line 250 didn't jump to line 251, because the condition on line 250 was never true
251 lsst.utils.tests.init()
252 unittest.main()