Coverage for tests/test_generalShapeletPsfApproxPlugins.py: 21%

160 statements  

« prev     ^ index     » next       coverage.py v6.4.4, created at 2022-09-03 09:08 +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# 

23import unittest 

24import numpy 

25import os 

26 

27import lsst.utils.tests 

28import lsst.shapelet 

29import lsst.geom 

30import lsst.afw.geom.ellipses 

31import lsst.afw.table 

32import lsst.afw.detection 

33import lsst.log 

34import lsst.utils.logging 

35import lsst.meas.modelfit 

36import lsst.meas.base 

37import lsst.meas.algorithms 

38 

39# Set trace to 0-5 to view debug messages. Level 5 enables all traces. 

40lsst.utils.logging.trace_set_at("lsst.meas.modelfit.optimizer.Optimizer", -1) 

41lsst.utils.logging.trace_set_at("lsst.meas.modelfit.optimizer.solveTrustRegion", -1) 

42 

43 

44class GeneralShapeletPsfApproxPluginsTestCase(lsst.utils.tests.TestCase): 

45 

46 def makeBlankConfig(self): 

47 config = lsst.meas.base.SingleFrameMeasurementTask.ConfigClass() 

48 config.slots.centroid = None 

49 config.slots.shape = None 

50 config.slots.psfFlux = None 

51 config.slots.apFlux = None 

52 config.slots.gaussianFlux = None 

53 config.slots.modelFlux = None 

54 config.slots.calibFlux = None 

55 config.doReplaceWithNoise = False 

56 return config 

57 

58 def setUp(self): 

59 numpy.random.seed(500) 

60 self.psfSigma = 2.0 

61 self.exposure = lsst.afw.image.ExposureF(41, 41) 

62 self.psf = lsst.afw.detection.GaussianPsf(19, 19, self.psfSigma) 

63 self.schema = lsst.afw.table.SourceTable.makeMinimalSchema() 

64 self.centroidKey = lsst.afw.table.Point2DKey.addFields(self.schema, "centroid", "centroid", "pixel") 

65 self.schema.getAliasMap().set("slot_Centroid", "centroid") 

66 self.psfDir = os.path.join(os.environ["MEAS_MODELFIT_DIR"], "tests", "data", "psfs") 

67 

68 def tearDown(self): 

69 del self.exposure 

70 del self.psf 

71 del self.schema 

72 del self.centroidKey 

73 del self.psfDir 

74 

75 def checkResult(self, msf): 

76 # Because we're fitting multiple shapelets to a single Gaussian (a single 0th-order shapelet) 

77 # we should be able to fit with zero residuals, aside from (single-precision) round-off error. 

78 dataImage = self.exposure.getPsf().computeImage() 

79 modelImage = dataImage.Factory(dataImage.getBBox()) 

80 modelImage.getArray()[:, :] *= -1 

81 msf.evaluate().addToImage(modelImage) 

82 self.assertFloatsAlmostEqual(dataImage.getArray(), modelImage.getArray(), atol=1E-6, 

83 plotOnFailure=False) 

84 

85 def testSingleFrame(self): 

86 self.exposure.setPsf(self.psf) 

87 config = self.makeBlankConfig() 

88 config.plugins.names = ["modelfit_GeneralShapeletPsfApprox"] 

89 config.plugins["modelfit_GeneralShapeletPsfApprox"].sequence = ["SingleGaussian"] 

90 task = lsst.meas.base.SingleFrameMeasurementTask(config=config, schema=self.schema) 

91 measCat = lsst.afw.table.SourceCatalog(self.schema) 

92 measRecord = measCat.addNew() 

93 measRecord.set(self.centroidKey, lsst.geom.Point2D(20.0, 20.0)) 

94 task.run(measCat, self.exposure) 

95 keySingleGaussian = lsst.shapelet.MultiShapeletFunctionKey( 

96 self.schema["modelfit"]["GeneralShapeletPsfApprox"]["SingleGaussian"] 

97 ) 

98 msfSingleGaussian = measRecord.get(keySingleGaussian) 

99 self.assertEqual(len(msfSingleGaussian.getComponents()), 1) 

100 self.checkResult(msfSingleGaussian) 

101 

102 def testForced(self): 

103 self.exposure.setPsf(self.psf) 

104 config = lsst.meas.base.ForcedMeasurementTask.ConfigClass() 

105 config.slots.centroid = "base_TransformedCentroid" 

106 config.slots.shape = None 

107 config.slots.psfFlux = None 

108 config.slots.apFlux = None 

109 config.slots.gaussianFlux = None 

110 config.slots.modelFlux = None 

111 config.doReplaceWithNoise = False 

112 config.slots.centroid = "base_TransformedCentroid" 

113 config.plugins.names = ["base_TransformedCentroid", "modelfit_GeneralShapeletPsfApprox"] 

114 config.plugins["modelfit_GeneralShapeletPsfApprox"].sequence = ["SingleGaussian"] 

115 config.copyColumns = {"id": "objectId", "parent": "parentObjectId"} 

116 refCat = lsst.afw.table.SourceCatalog(self.schema) 

117 refRecord = refCat.addNew() 

118 refRecord.set(self.centroidKey, lsst.geom.Point2D(20.0, 20.0)) 

119 refWcs = self.exposure.getWcs() # same as measurement Wcs 

120 task = lsst.meas.base.ForcedMeasurementTask(config=config, refSchema=self.schema) 

121 measCat = task.generateMeasCat(self.exposure, refCat, refWcs) 

122 task.run(measCat, self.exposure, refCat, refWcs) 

123 measRecord = measCat[0] 

124 measSchema = measCat.schema 

125 keySingleGaussian = lsst.shapelet.MultiShapeletFunctionKey( 

126 measSchema["modelfit"]["GeneralShapeletPsfApprox"]["SingleGaussian"] 

127 ) 

128 msfSingleGaussian = measRecord.get(keySingleGaussian) 

129 self.assertEqual(len(msfSingleGaussian.getComponents()), 1) 

130 self.checkResult(msfSingleGaussian) 

131 

132 def testNanFlag(self): 

133 config = self.makeBlankConfig() 

134 config.plugins.names = ["modelfit_GeneralShapeletPsfApprox"] 

135 config.plugins["modelfit_GeneralShapeletPsfApprox"].sequence = ["Full"] 

136 task = lsst.meas.base.SingleFrameMeasurementTask(config=config, schema=self.schema) 

137 measCat = lsst.afw.table.SourceCatalog(self.schema) 

138 measRecord = measCat.addNew() 

139 psfImage = lsst.afw.image.ImageD(os.path.join(self.psfDir, "galsimPsf_0.9.fits")) 

140 psfImage.getArray()[0, 0] = numpy.nan 

141 psfImage.setXY0(lsst.geom.Point2I(0, 0)) 

142 kernel = lsst.afw.math.FixedKernel(psfImage) 

143 psf = lsst.meas.algorithms.KernelPsf(kernel) 

144 self.exposure.setPsf(psf) 

145 center = lsst.geom.Point2D(psfImage.getArray().shape[0]/2, psfImage.getArray().shape[1]/2) 

146 measRecord.set(self.centroidKey, center) 

147 task.run(measCat, self.exposure) 

148 self.assertTrue(measRecord.get("modelfit_GeneralShapeletPsfApprox_Full_flag")) 

149 self.assertTrue(measRecord.get("modelfit_GeneralShapeletPsfApprox_Full_flag_contains_nan")) 

150 self.assertFalse(measRecord.get("modelfit_GeneralShapeletPsfApprox_Full_flag_max_inner_iterations")) 

151 self.assertFalse(measRecord.get("modelfit_GeneralShapeletPsfApprox_Full_flag_max_outer_iterations")) 

152 self.assertFalse(measRecord.get("modelfit_GeneralShapeletPsfApprox_Full_flag_exception")) 

153 

154 def testInnerIterationsFlag(self): 

155 config = self.makeBlankConfig() 

156 config.plugins.names = ["modelfit_GeneralShapeletPsfApprox"] 

157 config.plugins["modelfit_GeneralShapeletPsfApprox"].sequence = ["Full"] 

158 config.plugins["modelfit_GeneralShapeletPsfApprox"].models["Full"].optimizer.maxInnerIterations = 1 

159 task = lsst.meas.base.SingleFrameMeasurementTask(config=config, schema=self.schema) 

160 measCat = lsst.afw.table.SourceCatalog(self.schema) 

161 measRecord = measCat.addNew() 

162 psfImage = lsst.afw.image.ImageD(os.path.join(self.psfDir, "galsimPsf_0.9.fits")) 

163 psfImage.setXY0(lsst.geom.Point2I(0, 0)) 

164 kernel = lsst.afw.math.FixedKernel(psfImage) 

165 psf = lsst.meas.algorithms.KernelPsf(kernel) 

166 self.exposure.setPsf(psf) 

167 center = lsst.geom.Point2D(psfImage.getArray().shape[0]/2, psfImage.getArray().shape[1]/2) 

168 measRecord.set(self.centroidKey, center) 

169 task.run(measCat, self.exposure) 

170 self.assertTrue(measRecord.get("modelfit_GeneralShapeletPsfApprox_Full_flag")) 

171 self.assertFalse(measRecord.get("modelfit_GeneralShapeletPsfApprox_Full_flag_contains_nan")) 

172 self.assertTrue(measRecord.get("modelfit_GeneralShapeletPsfApprox_Full_flag_max_inner_iterations")) 

173 self.assertFalse(measRecord.get("modelfit_GeneralShapeletPsfApprox_Full_flag_max_outer_iterations")) 

174 self.assertFalse(measRecord.get("modelfit_GeneralShapeletPsfApprox_Full_flag_exception")) 

175 

176 def testOuterIterationsFlag(self): 

177 config = self.makeBlankConfig() 

178 config.plugins.names = ["modelfit_GeneralShapeletPsfApprox"] 

179 config.plugins["modelfit_GeneralShapeletPsfApprox"].sequence = ["Full"] 

180 config.plugins["modelfit_GeneralShapeletPsfApprox"].models["Full"].optimizer.maxOuterIterations = 1 

181 task = lsst.meas.base.SingleFrameMeasurementTask(config=config, schema=self.schema) 

182 measCat = lsst.afw.table.SourceCatalog(self.schema) 

183 measRecord = measCat.addNew() 

184 psfImage = lsst.afw.image.ImageD(os.path.join(self.psfDir, "galsimPsf_0.9.fits")) 

185 psfImage.setXY0(lsst.geom.Point2I(0, 0)) 

186 kernel = lsst.afw.math.FixedKernel(psfImage) 

187 psf = lsst.meas.algorithms.KernelPsf(kernel) 

188 self.exposure.setPsf(psf) 

189 center = lsst.geom.Point2D(psfImage.getArray().shape[0]/2, psfImage.getArray().shape[1]/2) 

190 measRecord.set(self.centroidKey, center) 

191 task.run(measCat, self.exposure) 

192 self.assertTrue(measRecord.get("modelfit_GeneralShapeletPsfApprox_Full_flag")) 

193 self.assertFalse(measRecord.get("modelfit_GeneralShapeletPsfApprox_Full_flag_contains_nan")) 

194 self.assertFalse(measRecord.get("modelfit_GeneralShapeletPsfApprox_Full_flag_max_inner_iterations")) 

195 self.assertTrue(measRecord.get("modelfit_GeneralShapeletPsfApprox_Full_flag_max_outer_iterations")) 

196 self.assertFalse(measRecord.get("modelfit_GeneralShapeletPsfApprox_Full_flag_exception")) 

197 

198 

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

200 pass 

201 

202 

203def setup_module(module): 

204 lsst.utils.tests.init() 

205 

206 

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

208 lsst.utils.tests.init() 

209 unittest.main()