Coverage for tests/test_loadReferenceObjects.py: 16%

Shortcuts 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

150 statements  

1# 

2# LSST Data Management System 

3# 

4# Copyright 2008-2016 AURA/LSST. 

5# 

6# This product includes software developed by the 

7# LSST Project (http://www.lsst.org/). 

8# 

9# This program is free software: you can redistribute it and/or modify 

10# it under the terms of the GNU General Public License as published by 

11# the Free Software Foundation, either version 3 of the License, or 

12# (at your option) any later version. 

13# 

14# This program is distributed in the hope that it will be useful, 

15# but WITHOUT ANY WARRANTY; without even the implied warranty of 

16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 

17# GNU General Public License for more details. 

18# 

19# You should have received a copy of the LSST License Statement and 

20# the GNU General Public License along with this program. If not, 

21# see <https://www.lsstcorp.org/LegalNotices/>. 

22# 

23 

24import itertools 

25import unittest 

26 

27import lsst.afw.table as afwTable 

28import lsst.log 

29from lsst.meas.algorithms import LoadReferenceObjectsTask, getRefFluxField, getRefFluxKeys 

30from lsst.meas.algorithms.loadReferenceObjects import hasNanojanskyFluxUnits, convertToNanojansky 

31import lsst.pex.config 

32import lsst.utils.tests 

33 

34 

35class TrivialLoader(LoadReferenceObjectsTask): 

36 """Minimal subclass of LoadReferenceObjectsTask to allow instantiation 

37 """ 

38 

39 def loadSkyCircle(self, ctrCoord, radius, filterName): 

40 pass 

41 

42 

43class TestLoadReferenceObjects(lsst.utils.tests.TestCase): 

44 """Test case for LoadReferenceObjectsTask abstract base class 

45 

46 Only methods with concrete implementations are tested (hence not loadSkyCircle) 

47 """ 

48 

49 def testFilterMapVsAnyFilterMapsToThis(self): 

50 config = TrivialLoader.ConfigClass() 

51 # check that a filterMap-only config passes validation 

52 config.filterMap = {"b": "a"} 

53 try: 

54 config.validate() 

55 except lsst.pex.config.FieldValidationError: 

56 self.fail("`filterMap`-only LoadReferenceObjectsConfig should not fail validation.") 

57 

58 # anyFilterMapsToThis and filterMap are mutually exclusive 

59 config.anyFilterMapsToThis = "c" 

60 with self.assertRaises(lsst.pex.config.FieldValidationError): 

61 config.validate() 

62 

63 # check that a anyFilterMapsToThis-only config passes validation 

64 config.filterMap = {} 

65 try: 

66 config.validate() 

67 except lsst.pex.config.FieldValidationError: 

68 self.fail("`anyFilterMapsToThis`-only LoadReferenceObjectsConfig should not fail validation.") 

69 

70 def testMakeMinimalSchema(self): 

71 """Make a schema and check it.""" 

72 for filterNameList in (["r"], ["foo", "_bar"]): 

73 for (addIsPhotometric, addIsResolved, addIsVariable, 

74 coordErrDim, addProperMotion, properMotionErrDim, 

75 addParallax) in itertools.product( 

76 (False, True), (False, True), (False, True), 

77 (-1, 0, 1, 2, 3, 4), (False, True), (-1, 0, 1, 2, 3, 4), 

78 (False, True)): 

79 argDict = dict( 

80 filterNameList=filterNameList, 

81 addIsPhotometric=addIsPhotometric, 

82 addIsResolved=addIsResolved, 

83 addIsVariable=addIsVariable, 

84 coordErrDim=coordErrDim, 

85 addProperMotion=addProperMotion, 

86 properMotionErrDim=properMotionErrDim, 

87 addParallax=addParallax, 

88 ) 

89 if coordErrDim not in (0, 2, 3) or \ 

90 (addProperMotion and properMotionErrDim not in (0, 2, 3)): 

91 with self.assertRaises(ValueError): 

92 LoadReferenceObjectsTask.makeMinimalSchema(**argDict) 

93 else: 

94 refSchema = LoadReferenceObjectsTask.makeMinimalSchema(**argDict) 

95 self.assertTrue("coord_ra" in refSchema) 

96 self.assertTrue("coord_dec" in refSchema) 

97 for filterName in filterNameList: 

98 fluxField = filterName + "_flux" 

99 self.assertIn(fluxField, refSchema) 

100 self.assertNotIn("x" + fluxField, refSchema) 

101 fluxErrField = fluxField + "Err" 

102 self.assertIn(fluxErrField, refSchema) 

103 self.assertEqual(getRefFluxField(refSchema, filterName), filterName + "_flux") 

104 self.assertEqual("resolved" in refSchema, addIsResolved) 

105 self.assertEqual("variable" in refSchema, addIsVariable) 

106 self.assertEqual("photometric" in refSchema, addIsPhotometric) 

107 self.assertEqual("photometric" in refSchema, addIsPhotometric) 

108 self.assertEqual("epoch" in refSchema, addProperMotion or addParallax) 

109 self.assertEqual("coord_raErr" in refSchema, coordErrDim > 0) 

110 self.assertEqual("coord_decErr" in refSchema, coordErrDim > 0) 

111 self.assertEqual("coord_ra_dec_Cov" in refSchema, coordErrDim == 3) 

112 self.assertEqual("pm_ra" in refSchema, addProperMotion) 

113 self.assertEqual("pm_dec" in refSchema, addProperMotion) 

114 self.assertEqual("pm_raErr" in refSchema, addProperMotion and properMotionErrDim > 0) 

115 self.assertEqual("pm_decErr" in refSchema, addProperMotion and properMotionErrDim > 0) 

116 self.assertEqual("pm_flag" in refSchema, addProperMotion) 

117 self.assertEqual("pm_ra_dec_Cov" in refSchema, 

118 addProperMotion and properMotionErrDim == 3) 

119 self.assertEqual("parallax" in refSchema, addParallax) 

120 self.assertEqual("parallaxErr" in refSchema, addParallax) 

121 self.assertEqual("parallax_flag" in refSchema, addParallax) 

122 

123 def testFilterAliasMap(self): 

124 """Make a schema with filter aliases.""" 

125 for filterMap in ({}, {"camr": "r"}): 

126 config = TrivialLoader.ConfigClass() 

127 config.filterMap = filterMap 

128 loader = TrivialLoader(config=config) 

129 refSchema = TrivialLoader.makeMinimalSchema(filterNameList="r") 

130 loader._addFluxAliases(refSchema) 

131 

132 self.assertIn("r_flux", refSchema) 

133 self.assertIn("r_fluxErr", refSchema) 

134 

135 # camera filters aliases are named <filter>_camFlux 

136 if "camr" in filterMap: 

137 self.assertEqual(getRefFluxField(refSchema, "camr"), "camr_camFlux") 

138 else: 

139 with self.assertRaisesRegex(RuntimeError, 

140 r"Could not find flux field\(s\) camr_camFlux, camr_flux"): 

141 getRefFluxField(refSchema, "camr") 

142 

143 refCat = afwTable.SimpleCatalog(refSchema) 

144 refObj = refCat.addNew() 

145 refObj["r_flux"] = 1.23 

146 self.assertAlmostEqual(refCat[0].get(getRefFluxField(refSchema, "r")), 1.23) 

147 if "camr" in filterMap: 

148 self.assertAlmostEqual(refCat[0].get(getRefFluxField(refSchema, "camr")), 1.23) 

149 refObj["r_fluxErr"] = 0.111 

150 if "camr" in filterMap: 

151 self.assertEqual(refCat[0].get("camr_camFluxErr"), 0.111) 

152 fluxKey, fluxErrKey = getRefFluxKeys(refSchema, "r") 

153 self.assertEqual(refCat[0].get(fluxKey), 1.23) 

154 self.assertEqual(refCat[0].get(fluxErrKey), 0.111) 

155 if "camr" in filterMap: 

156 fluxKey, fluxErrKey = getRefFluxKeys(refSchema, "camr") 

157 self.assertEqual(refCat[0].get(fluxErrKey), 0.111) 

158 else: 

159 with self.assertRaises(RuntimeError): 

160 getRefFluxKeys(refSchema, "camr") 

161 

162 def testAnyFilterMapsToThisAlias(self): 

163 # test anyFilterMapsToThis 

164 config = TrivialLoader.ConfigClass() 

165 config.anyFilterMapsToThis = "gg" 

166 loader = TrivialLoader(config=config) 

167 refSchema = TrivialLoader.makeMinimalSchema(filterNameList=["gg"]) 

168 loader._addFluxAliases(refSchema) 

169 self.assertEqual(getRefFluxField(refSchema, "r"), "gg_flux") 

170 # raise if "gg" is not in the refcat filter list 

171 with self.assertRaises(RuntimeError): 

172 refSchema = TrivialLoader.makeMinimalSchema(filterNameList=["rr"]) 

173 refSchema = loader._addFluxAliases(refSchema) 

174 

175 def testCheckFluxUnits(self): 

176 """Test that we can identify old style fluxes in a schema.""" 

177 schema = LoadReferenceObjectsTask.makeMinimalSchema(['r', 'z']) 

178 # the default schema should pass 

179 self.assertTrue(hasNanojanskyFluxUnits(schema)) 

180 schema.addField('bad_fluxSigma', doc='old flux units', type=float, units='') 

181 self.assertFalse(hasNanojanskyFluxUnits(schema)) 

182 

183 schema = LoadReferenceObjectsTask.makeMinimalSchema(['r', 'z']) 

184 schema.addField('bad_flux', doc='old flux units', type=float, units='') 

185 self.assertFalse(hasNanojanskyFluxUnits(schema)) 

186 

187 schema = LoadReferenceObjectsTask.makeMinimalSchema(['r', 'z']) 

188 schema.addField('bad_flux', doc='old flux units', type=float, units='Jy') 

189 self.assertFalse(hasNanojanskyFluxUnits(schema)) 

190 

191 schema = LoadReferenceObjectsTask.makeMinimalSchema(['r', 'z']) 

192 schema.addField('bad_fluxErr', doc='old flux units', type=float, units='') 

193 self.assertFalse(hasNanojanskyFluxUnits(schema)) 

194 

195 schema = LoadReferenceObjectsTask.makeMinimalSchema(['r', 'z']) 

196 schema.addField('bad_fluxErr', doc='old flux units', type=float, units='Jy') 

197 self.assertFalse(hasNanojanskyFluxUnits(schema)) 

198 

199 schema = LoadReferenceObjectsTask.makeMinimalSchema(['r', 'z']) 

200 schema.addField('bad_fluxSigma', doc='old flux units', type=float, units='') 

201 self.assertFalse(hasNanojanskyFluxUnits(schema)) 

202 

203 def testConvertOldFluxes(self): 

204 """Check that we can convert old style fluxes in a catalog.""" 

205 flux = 1.234 

206 fluxErr = 5.678 

207 log = lsst.log.Log() 

208 

209 def make_catalog(): 

210 schema = LoadReferenceObjectsTask.makeMinimalSchema(['r', 'z']) 

211 schema.addField('bad_flux', doc='old flux units', type=float, units='') 

212 schema.addField('bad_fluxErr', doc='old flux units', type=float, units='Jy') 

213 refCat = afwTable.SimpleCatalog(schema) 

214 refObj = refCat.addNew() 

215 refObj["bad_flux"] = flux 

216 refObj["bad_fluxErr"] = fluxErr 

217 return refCat 

218 

219 oldRefCat = make_catalog() 

220 newRefCat = convertToNanojansky(oldRefCat, log) 

221 self.assertEqual(newRefCat['bad_flux'], [flux*1e9, ]) 

222 self.assertEqual(newRefCat['bad_fluxErr'], [fluxErr*1e9, ]) 

223 self.assertEqual(newRefCat.schema['bad_flux'].asField().getUnits(), 'nJy') 

224 self.assertEqual(newRefCat.schema['bad_fluxErr'].asField().getUnits(), 'nJy') 

225 

226 # check that doConvert=False returns None (it also logs a summary) 

227 oldRefCat = make_catalog() 

228 newRefCat = convertToNanojansky(oldRefCat, log, doConvert=False) 

229 self.assertIsNone(newRefCat) 

230 

231 

232class TestMemory(lsst.utils.tests.MemoryTestCase): 

233 pass 

234 

235 

236def setup_module(module): 

237 lsst.utils.tests.init() 

238 

239 

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

241 lsst.utils.tests.init() 

242 unittest.main()