Coverage for tests/test_loadReferenceObjects.py: 12%

163 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2022-12-01 20:41 +0000

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 defaultFilter in ("", "r", "camr"): 

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

127 config = TrivialLoader.ConfigClass() 

128 config.defaultFilter = defaultFilter 

129 config.filterMap = filterMap 

130 loader = TrivialLoader(config=config) 

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

132 try: 

133 loader._addFluxAliases(refSchema) 

134 self.assertNotEqual(defaultFilter, "camr") 

135 except Exception: 

136 # only reference filters are allowed as default filters 

137 self.assertEqual(defaultFilter, "camr") 

138 continue 

139 

140 self.assertIn("r_flux", refSchema) 

141 self.assertIn("r_fluxErr", refSchema) 

142 

143 # camera filters aliases are named <filter>_camFlux 

144 if "camr" in filterMap: 

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

146 else: 

147 with self.assertRaises(RuntimeError): 

148 getRefFluxField(refSchema, "camr") 

149 

150 # if a non-empty default filter is specified then camFlux 

151 # and camFluxErr should be present 

152 hasDefault = bool(defaultFilter) 

153 self.assertEqual("camFlux" in refSchema, hasDefault) 

154 self.assertEqual("camFluxErr" in refSchema, hasDefault) 

155 

156 refCat = afwTable.SimpleCatalog(refSchema) 

157 refObj = refCat.addNew() 

158 refObj["r_flux"] = 1.23 

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

160 if "camr" in filterMap: 

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

162 if hasDefault: 

163 self.assertEqual(getRefFluxField(refSchema, ""), "camFlux") 

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

165 refObj["r_fluxErr"] = 0.111 

166 if "camr" in filterMap: 

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

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

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

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

171 if "camr" in filterMap: 

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

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

174 else: 

175 with self.assertRaises(RuntimeError): 

176 getRefFluxKeys(refSchema, "camr") 

177 

178 def testAnyFilterMapsToThisAlias(self): 

179 # test anyFilterMapsToThis 

180 config = TrivialLoader.ConfigClass() 

181 config.anyFilterMapsToThis = "gg" 

182 loader = TrivialLoader(config=config) 

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

184 loader._addFluxAliases(refSchema) 

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

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

187 with self.assertRaises(RuntimeError): 

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

189 refSchema = loader._addFluxAliases(refSchema) 

190 

191 def testCheckFluxUnits(self): 

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

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

194 # the default schema should pass 

195 self.assertTrue(hasNanojanskyFluxUnits(schema)) 

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

197 self.assertFalse(hasNanojanskyFluxUnits(schema)) 

198 

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

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

201 self.assertFalse(hasNanojanskyFluxUnits(schema)) 

202 

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

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

205 self.assertFalse(hasNanojanskyFluxUnits(schema)) 

206 

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

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

209 self.assertFalse(hasNanojanskyFluxUnits(schema)) 

210 

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

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

213 self.assertFalse(hasNanojanskyFluxUnits(schema)) 

214 

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

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

217 self.assertFalse(hasNanojanskyFluxUnits(schema)) 

218 

219 def testConvertOldFluxes(self): 

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

221 flux = 1.234 

222 fluxErr = 5.678 

223 log = lsst.log.Log() 

224 

225 def make_catalog(): 

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

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

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

229 refCat = afwTable.SimpleCatalog(schema) 

230 refObj = refCat.addNew() 

231 refObj["bad_flux"] = flux 

232 refObj["bad_fluxErr"] = fluxErr 

233 return refCat 

234 

235 oldRefCat = make_catalog() 

236 newRefCat = convertToNanojansky(oldRefCat, log) 

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

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

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

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

241 

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

243 oldRefCat = make_catalog() 

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

245 self.assertIsNone(newRefCat) 

246 

247 

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

249 pass 

250 

251 

252def setup_module(module): 

253 lsst.utils.tests.init() 

254 

255 

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

257 lsst.utils.tests.init() 

258 unittest.main()