Hide keyboard shortcuts

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

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# 

23import unittest 

24import numpy as np 

25 

26import lsst.geom 

27import lsst.afw.image as afwImage 

28import lsst.afw.table as afwTable 

29from lsst.afw.math import ChebyshevBoundedField 

30import lsst.pex.config 

31import lsst.meas.algorithms.measureApCorr as measureApCorr 

32from lsst.meas.base.apCorrRegistry import addApCorrName 

33import lsst.meas.base.tests 

34import lsst.utils.tests 

35 

36 

37def apCorrDefaultMap(value=None, bbox=None): 

38 default_coefficients = np.ones((1, 1), dtype=float) 

39 default_coefficients /= value 

40 default_apCorrMap = ChebyshevBoundedField(bbox, default_coefficients) 

41 default_fill = afwImage.ImageF(bbox) 

42 default_apCorrMap.fillImage(default_fill) 

43 return(default_fill) 

44 

45 

46class MeasureApCorrTestCase(lsst.meas.base.tests.AlgorithmTestCase, lsst.utils.tests.TestCase): 

47 

48 def makeCatalog(self, apCorrScale=1.0, numSources=5): 

49 sourceCat = afwTable.SourceCatalog(self.schema) 

50 fluxName = self.name + "_instFlux" 

51 flagName = self.name + "_flag" 

52 fluxErrName = self.name + "_instFluxErr" 

53 apFluxName = self.apname + "_instFlux" 

54 apFlagName = self.apname + "_flag" 

55 apFluxErrName = self.apname + "_instFluxErr" 

56 fluxKey = self.schema.find(fluxName).key 

57 flagKey = self.schema.find(flagName).key 

58 fluxErrKey = self.schema.find(fluxErrName).key 

59 apFluxKey = self.schema.find(apFluxName).key 

60 apFlagKey = self.schema.find(apFlagName).key 

61 apFluxErrKey = self.schema.find(apFluxErrName).key 

62 centroidKey = afwTable.Point2DKey(self.schema["slot_Centroid"]) 

63 inputFilterFlagKey = self.schema.find(self.meas_apCorr_task.config.sourceSelector.active.field).key 

64 x = np.random.rand(numSources)*self.exposure.getWidth() + self.exposure.getX0() 

65 y = np.random.rand(numSources)*self.exposure.getHeight() + self.exposure.getY0() 

66 for _i in range(numSources): 

67 source_test_instFlux = 5.1 

68 source_test_centroid = lsst.geom.Point2D(x[_i], y[_i]) 

69 source = sourceCat.addNew() 

70 source.set(fluxKey, source_test_instFlux) 

71 source.set(apFluxKey, source_test_instFlux * apCorrScale) 

72 source.set(centroidKey, source_test_centroid) 

73 source.set(fluxErrKey, 0.) 

74 source.set(apFluxErrKey, 0.) 

75 source.set(flagKey, False) 

76 source.set(apFlagKey, False) 

77 source.set(inputFilterFlagKey, True) 

78 return(sourceCat) 

79 

80 def setUp(self): 

81 schema = afwTable.SourceTable.makeMinimalSchema() 

82 name = "test" 

83 apname = "testAp" 

84 calib_flag_name = "cal_source_use" 

85 addApCorrName(apname) 

86 schema.addField(name + "_instFlux", type=float) 

87 schema.addField(name + "_instFluxErr", type=float) 

88 schema.addField(name + "_flag", type="Flag") 

89 schema.addField(apname + "_instFlux", type=float) 

90 schema.addField(apname + "_instFluxErr", type=float) 

91 schema.addField(apname + "_flag", type="Flag") 

92 schema.addField(calib_flag_name, type="Flag") 

93 schema.addField(name + "_Centroid_x", type=float) 

94 schema.addField(name + "_Centroid_y", type=float) 

95 schema.getAliasMap().set('slot_Centroid', name + '_Centroid') 

96 config = measureApCorr.MeasureApCorrTask.ConfigClass() 

97 config.refFluxName = name 

98 config.sourceSelector.active.field = calib_flag_name 

99 self.meas_apCorr_task = measureApCorr.MeasureApCorrTask(schema=schema, config=config) 

100 self.name = name 

101 self.apname = apname 

102 self.schema = schema 

103 self.exposure = lsst.afw.image.ExposureF(10, 10) 

104 

105 def tearDown(self): 

106 del self.schema 

107 del self.meas_apCorr_task 

108 del self.exposure 

109 

110 def testAddFields(self): 

111 """Instantiating the task should add one field to the schema.""" 

112 self.assertIn("apcorr_" + self.name + "_used", self.schema.getNames()) 

113 

114 def testReturnApCorrMap(self): 

115 """The measureApCorr task should return a structure with a single key 'apCorrMap'.""" 

116 struct = self.meas_apCorr_task.run(catalog=self.makeCatalog(), exposure=self.exposure) 

117 self.assertEqual(list(struct.getDict().keys()), ['apCorrMap']) 

118 

119 def testApCorrMapKeys(self): 

120 """An apCorrMap structure should have two keys, based on the name supplied to addApCorrName().""" 

121 apfluxName = self.apname + "_instFlux" 

122 apfluxErrName = self.apname + "_instFluxErr" 

123 struct = self.meas_apCorr_task.run(catalog=self.makeCatalog(), exposure=self.exposure) 

124 key_names = [apfluxName, apfluxErrName] 

125 self.assertEqual(set(struct.apCorrMap.keys()), set(key_names)) 

126 

127 def testTooFewSources(self): 

128 """ If there are too few sources, check that an exception is raised.""" 

129 catalog = afwTable.SourceCatalog(self.schema) 

130 with self.assertRaises(RuntimeError): 

131 self.meas_apCorr_task.run(catalog=catalog, exposure=self.exposure) 

132 # With the measurement algorithm declared as something that might fail, should not get an exception 

133 self.meas_apCorr_task.config.allowFailure.append(self.apname) 

134 self.meas_apCorr_task.run(catalog=catalog, exposure=self.exposure) 

135 

136 def testSourceNotUsed(self): 

137 """ Check that a source outside the bounding box is flagged as not used (False).""" 

138 fluxName = self.name + "_instFlux" 

139 apCorrFlagKey = self.schema.find("apcorr_" + self.name + "_used").key 

140 sourceCat = self.makeCatalog() 

141 source = sourceCat.addNew() 

142 source_test_instFlux = 5.1 

143 source_test_centroid = lsst.geom.Point2D(15, 7.1) 

144 fluxKey = self.schema.find(fluxName).key 

145 centroidKey = afwTable.Point2DKey(self.schema["slot_Centroid"]) 

146 source.set(fluxKey, source_test_instFlux) 

147 source.set(centroidKey, source_test_centroid) 

148 self.meas_apCorr_task.run(catalog=sourceCat, exposure=self.exposure) 

149 self.assertFalse(sourceCat[apCorrFlagKey][-1]) 

150 

151 def testSourceUsed(self): 

152 """Check that valid sources inside the bounding box that are used have their flags set to True.""" 

153 inputFilterFlagKey = self.schema.find(self.meas_apCorr_task.config.sourceSelector.active.field).key 

154 sourceCat = self.makeCatalog() 

155 self.meas_apCorr_task.run(catalog=sourceCat, exposure=self.exposure) 

156 self.assertTrue(sourceCat[inputFilterFlagKey].all()) 

157 

158 def testApertureMeasOnes(self): 

159 """ Check that sources with aperture fluxes exactly the same as their catalog fluxes 

160 returns an aperture correction map of 1s""" 

161 apFluxName = self.apname + "_instFlux" 

162 sourceCat = self.makeCatalog() 

163 struct = self.meas_apCorr_task.run(catalog=sourceCat, exposure=self.exposure) 

164 default_fill = apCorrDefaultMap(value=1.0, bbox=self.exposure.getBBox()) 

165 test_fill = afwImage.ImageF(self.exposure.getBBox()) 

166 struct.apCorrMap[apFluxName].fillImage(test_fill) 

167 np.testing.assert_allclose(test_fill.getArray(), default_fill.getArray()) 

168 

169 def testApertureMeasTens(self): 

170 """Check that aperture correction scales source fluxes in the correct direction.""" 

171 apCorr_factor = 10. 

172 sourceCat = self.makeCatalog(apCorrScale=apCorr_factor) 

173 apFluxName = self.apname + "_instFlux" 

174 struct = self.meas_apCorr_task.run(catalog=sourceCat, exposure=self.exposure) 

175 default_fill = apCorrDefaultMap(value=apCorr_factor, bbox=self.exposure.getBBox()) 

176 test_fill = afwImage.ImageF(self.exposure.getBBox()) 

177 struct.apCorrMap[apFluxName].fillImage(test_fill) 

178 np.testing.assert_allclose(test_fill.getArray(), default_fill.getArray()) 

179 

180 

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

182 pass 

183 

184 

185def setup_module(module): 

186 lsst.utils.tests.init() 

187 

188 

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

190 lsst.utils.tests.init() 

191 unittest.main()