Coverage for tests/testSNR.py : 13%

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 os
4import numpy as np
5import unittest
6import lsst.utils
7import lsst.utils.tests
8from lsst.sims.utils import ObservationMetaData
9import lsst.sims.photUtils.SignalToNoise as snr
10from lsst.sims.photUtils import Sed, Bandpass, PhotometricParameters, LSSTdefaults
11from lsst.sims.photUtils.utils import setM5
14def setup_module(module):
15 lsst.utils.tests.init()
18class TestSNRmethods(unittest.TestCase):
20 def setUp(self):
22 starName = os.path.join(lsst.utils.getPackageDir('sims_photUtils'),
23 'tests/cartoonSedTestData/starSed/')
24 starName = os.path.join(starName, 'kurucz', 'km20_5750.fits_g40_5790.gz')
25 self.starSED = Sed()
26 self.starSED.readSED_flambda(starName)
27 imsimband = Bandpass()
28 imsimband.imsimBandpass()
29 fNorm = self.starSED.calcFluxNorm(22.0, imsimband)
30 self.starSED.multiplyFluxNorm(fNorm)
32 hardwareDir = os.path.join(lsst.utils.getPackageDir('throughputs'), 'baseline')
33 componentList = ['detector.dat', 'm1.dat', 'm2.dat', 'm3.dat',
34 'lens1.dat', 'lens2.dat', 'lens3.dat']
35 self.skySed = Sed()
36 self.skySed.readSED_flambda(os.path.join(hardwareDir, 'darksky.dat'))
38 totalNameList = ['total_u.dat', 'total_g.dat', 'total_r.dat', 'total_i.dat',
39 'total_z.dat', 'total_y.dat']
41 self.bpList = []
42 self.hardwareList = []
43 for name in totalNameList:
44 dummy = Bandpass()
45 dummy.readThroughput(os.path.join(hardwareDir, name))
46 self.bpList.append(dummy)
48 dummy = Bandpass()
49 hardwareNameList = [os.path.join(hardwareDir, name)]
50 for component in componentList:
51 hardwareNameList.append(os.path.join(hardwareDir, component))
52 dummy.readThroughputList(hardwareNameList)
53 self.hardwareList.append(dummy)
55 self.filterNameList = ['u', 'g', 'r', 'i', 'z', 'y']
57 def testMagError(self):
58 """
59 Make sure that calcMagError_sed and calcMagError_m5
60 agree to within 0.001
61 """
62 defaults = LSSTdefaults()
63 photParams = PhotometricParameters()
65 # create a cartoon spectrum to test on
66 spectrum = Sed()
67 spectrum.setFlatSED()
68 spectrum.multiplyFluxNorm(1.0e-9)
70 # find the magnitudes of that spectrum in our bandpasses
71 magList = []
72 for total in self.bpList:
73 magList.append(spectrum.calcMag(total))
74 magList = np.array(magList)
76 # try for different normalizations of the skySED
77 for fNorm in np.arange(1.0, 5.0, 1.0):
78 self.skySed.multiplyFluxNorm(fNorm)
80 for total, hardware, filterName, mm in \
81 zip(self.bpList, self.hardwareList, self.filterNameList, magList):
83 FWHMeff = defaults.FWHMeff(filterName)
85 m5 = snr.calcM5(self.skySed, total, hardware, photParams, FWHMeff=FWHMeff)
87 sigma_sed = snr.calcMagError_sed(spectrum, total, self.skySed,
88 hardware, photParams, FWHMeff=FWHMeff)
90 sigma_m5, gamma = snr.calcMagError_m5(mm, total, m5, photParams)
92 self.assertAlmostEqual(sigma_m5, sigma_sed, 3)
94 def testVerboseSNR(self):
95 """
96 Make sure that calcSNR_sed has everything it needs to run in verbose mode
97 """
98 photParams = PhotometricParameters()
100 # create a cartoon spectrum to test on
101 spectrum = Sed()
102 spectrum.setFlatSED()
103 spectrum.multiplyFluxNorm(1.0e-9)
105 snr.calcSNR_sed(spectrum, self.bpList[0], self.skySed,
106 self.hardwareList[0], photParams, FWHMeff=0.7, verbose=True)
108 def testSignalToNoise(self):
109 """
110 Test that calcSNR_m5 and calcSNR_sed give similar results
111 """
112 defaults = LSSTdefaults()
113 photParams = PhotometricParameters()
115 m5 = []
116 for i in range(len(self.hardwareList)):
117 m5.append(snr.calcM5(self.skySed, self.bpList[i],
118 self.hardwareList[i],
119 photParams, FWHMeff=defaults.FWHMeff(self.filterNameList[i])))
121 sedDir = os.path.join(lsst.utils.getPackageDir('sims_photUtils'),
122 'tests/cartoonSedTestData/starSed/')
123 sedDir = os.path.join(sedDir, 'kurucz')
124 fileNameList = os.listdir(sedDir)
126 rng = np.random.RandomState(42)
127 offset = rng.random_sample(len(fileNameList))*2.0
129 for ix, name in enumerate(fileNameList):
130 if ix > 100:
131 break
132 spectrum = Sed()
133 spectrum.readSED_flambda(os.path.join(sedDir, name))
134 ff = spectrum.calcFluxNorm(m5[2]-offset[ix], self.bpList[2])
135 spectrum.multiplyFluxNorm(ff)
136 for i in range(len(self.bpList)):
137 control_snr = snr.calcSNR_sed(spectrum, self.bpList[i],
138 self.skySed,
139 self.hardwareList[i],
140 photParams, defaults.FWHMeff(self.filterNameList[i]))
142 mag = spectrum.calcMag(self.bpList[i])
144 test_snr, gamma = snr.calcSNR_m5(mag, self.bpList[i], m5[i], photParams)
145 self.assertLess((test_snr-control_snr)/control_snr, 0.001)
147 def testSystematicUncertainty(self):
148 """
149 Test that systematic uncertainty is added correctly.
150 """
151 sigmaSys = 0.002
152 m5_list = [23.5, 24.3, 22.1, 20.0, 19.5, 21.7]
153 photParams = PhotometricParameters(sigmaSys=sigmaSys)
155 obs_metadata = ObservationMetaData(pointingRA=23.0, pointingDec=45.0,
156 m5=m5_list, bandpassName=self.filterNameList)
157 magnitude_list = []
158 for bp in self.bpList:
159 mag = self.starSED.calcMag(bp)
160 magnitude_list.append(mag)
162 for bp, hardware, filterName, mm, m5 in \
163 zip(self.bpList, self.hardwareList, self.filterNameList, magnitude_list, m5_list):
165 skyDummy = Sed()
166 skyDummy.readSED_flambda(os.path.join(lsst.utils.getPackageDir('throughputs'),
167 'baseline', 'darksky.dat'))
169 normalizedSkyDummy = setM5(obs_metadata.m5[filterName], skyDummy,
170 bp, hardware,
171 FWHMeff=LSSTdefaults().FWHMeff(filterName),
172 photParams=photParams)
174 sigma, gamma = snr.calcMagError_m5(mm, bp, m5, photParams)
176 snrat = snr.calcSNR_sed(self.starSED, bp, normalizedSkyDummy, hardware,
177 FWHMeff=LSSTdefaults().FWHMeff(filterName),
178 photParams=PhotometricParameters())
180 testSNR, gamma = snr.calcSNR_m5(mm, bp, m5, photParams=PhotometricParameters(sigmaSys=0.0))
182 self.assertAlmostEqual(snrat, testSNR, 10,
183 msg = 'failed on calcSNR_m5 test %e != %e '
184 % (snrat, testSNR))
186 control = np.sqrt(np.power(snr.magErrorFromSNR(testSNR), 2) + np.power(sigmaSys, 2))
188 msg = '%e is not %e; failed' % (sigma, control)
190 self.assertAlmostEqual(sigma, control, 10, msg=msg)
192 def testNoSystematicUncertainty(self):
193 """
194 Test that systematic uncertainty is handled correctly when set to None.
195 """
196 m5_list = [23.5, 24.3, 22.1, 20.0, 19.5, 21.7]
197 photParams = PhotometricParameters(sigmaSys=0.0)
199 obs_metadata = ObservationMetaData(pointingRA=23.0, pointingDec=45.0,
200 m5=m5_list, bandpassName=self.filterNameList)
202 magnitude_list = []
203 for bp in self.bpList:
204 mag = self.starSED.calcMag(bp)
205 magnitude_list.append(mag)
207 for bp, hardware, filterName, mm, m5 in \
208 zip(self.bpList, self.hardwareList, self.filterNameList, magnitude_list, m5_list):
210 skyDummy = Sed()
211 skyDummy.readSED_flambda(os.path.join(lsst.utils.getPackageDir('throughputs'),
212 'baseline', 'darksky.dat'))
214 normalizedSkyDummy = setM5(obs_metadata.m5[filterName], skyDummy,
215 bp, hardware,
216 FWHMeff=LSSTdefaults().FWHMeff(filterName),
217 photParams=photParams)
219 sigma, gamma = snr.calcMagError_m5(mm, bp, m5, photParams)
221 snrat = snr.calcSNR_sed(self.starSED, bp, normalizedSkyDummy, hardware,
222 FWHMeff=LSSTdefaults().FWHMeff(filterName),
223 photParams=PhotometricParameters())
225 testSNR, gamma = snr.calcSNR_m5(mm, bp, m5, photParams=PhotometricParameters(sigmaSys=0.0))
227 self.assertAlmostEqual(snrat, testSNR, 10,
228 msg = 'failed on calcSNR_m5 test %e != %e '
229 % (snrat, testSNR))
231 control = snr.magErrorFromSNR(testSNR)
233 msg = '%e is not %e; failed' % (sigma, control)
235 self.assertAlmostEqual(sigma, control, 10, msg=msg)
237 def testFWHMconversions(self):
238 FWHMeff = 0.8
239 FWHMgeom = snr.FWHMeff2FWHMgeom(FWHMeff)
240 self.assertEqual(FWHMgeom, (0.822*FWHMeff+0.052))
241 FWHMgeom = 0.8
242 FWHMeff = snr.FWHMgeom2FWHMeff(FWHMgeom)
243 self.assertEqual(FWHMeff, (FWHMgeom-0.052)/0.822)
245 def testAstrometricError(self):
246 fwhmGeom = 0.7
247 m5 = 24.5
248 # For bright objects, error should be systematic floor
249 mag = 10
250 astrometricErr = snr.calcAstrometricError(mag, m5, fwhmGeom=fwhmGeom, nvisit=1, systematicFloor=10)
251 self.assertAlmostEqual(astrometricErr, 10, 3)
252 # Even if you increase the number of visits, the systemic floor doesn't change
253 astrometricErr = snr.calcAstrometricError(mag, m5, fwhmGeom=fwhmGeom, nvisit=100)
254 self.assertAlmostEqual(astrometricErr, 10, 3)
255 # For a single visit, fainter source, larger error and nvisits matters
256 mag = 24.5
257 astrometricErr1 = snr.calcAstrometricError(mag, m5, fwhmGeom=fwhmGeom, nvisit=1,
258 systematicFloor=10)
259 astrometricErr100 = snr.calcAstrometricError(mag, m5, fwhmGeom=fwhmGeom, nvisit=100,
260 systematicFloor=10)
261 self.assertGreater(astrometricErr1, astrometricErr100)
262 self.assertAlmostEqual(astrometricErr1, 140.357, 3)
264 def testSNR_arr(self):
265 """
266 Test that calcSNR_m5 works on numpy arrays of magnitudes
267 """
268 rng = np.random.RandomState(17)
269 mag_list = rng.random_sample(100)*5.0 + 15.0
271 photParams = PhotometricParameters()
272 bp = self.bpList[0]
273 m5 = 24.0
274 control_list = []
275 for mm in mag_list:
276 ratio, gamma = snr.calcSNR_m5(mm, bp, m5, photParams)
277 control_list.append(ratio)
278 control_list = np.array(control_list)
280 test_list, gamma = snr.calcSNR_m5(mag_list, bp, m5, photParams)
282 np.testing.assert_array_equal(control_list, test_list)
284 def testError_arr(self):
285 """
286 Test that calcMagError_m5 works on numpy arrays of magnitudes
287 """
288 rng = np.random.RandomState(17)
289 mag_list = rng.random_sample(100)*5.0 + 15.0
291 photParams = PhotometricParameters()
292 bp = self.bpList[0]
293 m5 = 24.0
294 control_list = []
295 for mm in mag_list:
296 sig, gamma = snr.calcMagError_m5(mm, bp, m5, photParams)
297 control_list.append(sig)
298 control_list = np.array(control_list)
300 test_list, gamma = snr.calcMagError_m5(mag_list, bp, m5, photParams)
302 np.testing.assert_array_equal(control_list, test_list)
305class MemoryTestClass(lsst.utils.tests.MemoryTestCase):
306 pass
308if __name__ == "__main__": 308 ↛ 309line 308 didn't jump to line 309, because the condition on line 308 was never true
309 lsst.utils.tests.init()
310 unittest.main()