Coverage for tests/test_cModel.py: 24%

102 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2023-02-01 02:44 -0800

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 

25 

26import lsst.utils.tests 

27import lsst.shapelet 

28import lsst.afw.geom 

29import lsst.geom 

30import lsst.afw.image 

31import lsst.log 

32import lsst.utils.logging 

33import lsst.meas.modelfit 

34import lsst.meas.base 

35 

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

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

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

39 

40 

41def makeMultiShapeletCircularGaussian(sigma): 

42 s = lsst.shapelet.ShapeletFunction(0, lsst.shapelet.HERMITE, sigma) 

43 s.getCoefficients()[0] = 1.0 / lsst.shapelet.ShapeletFunction.FLUX_FACTOR 

44 m = lsst.shapelet.MultiShapeletFunction() 

45 m.addComponent(s) 

46 return m 

47 

48 

49def computePsfFlux(centroid, exposure): 

50 schema = lsst.afw.table.SourceTable.makeMinimalSchema() 

51 pointKey = lsst.afw.table.Point2DKey.addFields(schema, "centroid", "known input centroid", "pixel") 

52 schema.getAliasMap().set("slot_Centroid", "centroid") 

53 algorithm = lsst.meas.base.PsfFluxAlgorithm(lsst.meas.base.PsfFluxControl(), "base_PsfFlux", schema) 

54 table = lsst.afw.table.SourceTable.make(schema) 

55 record = table.makeRecord() 

56 record.set(pointKey, centroid) 

57 algorithm.measure(record, exposure) 

58 return record.get("base_PsfFlux_instFlux"), record.get("base_PsfFlux_instFluxErr") 

59 

60 

61class CModelTestCase(lsst.utils.tests.TestCase): 

62 

63 def setUp(self): 

64 # Setup test data: a single point source, initially with no noise. 

65 numpy.random.seed(500) 

66 crval = lsst.geom.SpherePoint(45.0, 45.0, lsst.geom.degrees) 

67 crpix = lsst.geom.Point2D(0.0, 0.0) 

68 scale = 0.2 * lsst.geom.arcseconds 

69 cdMatrix = lsst.afw.geom.makeCdMatrix(scale=scale, flipX=True) 

70 dataWcs = lsst.afw.geom.makeSkyWcs(crpix=crpix, crval=crval, cdMatrix=cdMatrix) 

71 photoCalib = lsst.afw.image.PhotoCalib(4.0) 

72 self.xyPosition = lsst.geom.Point2D(1.1, -0.8) 

73 bbox = lsst.geom.Box2I(lsst.geom.Point2I(-100, -100), lsst.geom.Point2I(100, 100)) 

74 self.exposure = lsst.afw.image.ExposureF(bbox) 

75 self.exposure.setWcs(dataWcs) 

76 self.exposure.setPhotoCalib(photoCalib) 

77 self.trueFlux = 65.0 

78 self.psfSigma = 2.0 

79 psf = lsst.afw.detection.GaussianPsf(25, 25, self.psfSigma) 

80 self.exposure.setPsf(psf) 

81 psfImage = psf.computeImage(self.xyPosition) 

82 psfImage.getArray()[:, :] *= self.trueFlux 

83 psfBBox = psfImage.getBBox(lsst.afw.image.PARENT) 

84 subImage = lsst.afw.image.ImageF(self.exposure.getMaskedImage().getImage(), psfBBox, 

85 lsst.afw.image.PARENT) 

86 subImage.getArray()[:, :] = psfImage.getArray() 

87 

88 def tearDown(self): 

89 del self.xyPosition 

90 del self.exposure 

91 del self.trueFlux 

92 del self.psfSigma 

93 

94 def testNoNoise(self): 

95 """Test that CModelAlgorithm.apply() works when applied to a postage-stamp 

96 containing only a point source with no noise. 

97 

98 We still have to pretend there is noise (i.e. have nonzero values in 

99 the variance plane) to allow it to compute a likelihood, though. 

100 """ 

101 ctrl = lsst.meas.modelfit.CModelControl() 

102 ctrl.initial.usePixelWeights = False 

103 algorithm = lsst.meas.modelfit.CModelAlgorithm(ctrl) 

104 var = 1E-16 

105 self.exposure.getMaskedImage().getVariance().getArray()[:, :] = var 

106 psfImage = self.exposure.getPsf().computeKernelImage(self.xyPosition).getArray() 

107 expectedFluxErr = var**0.5 * (psfImage**2).sum()**(-0.5) 

108 pos = self.exposure.getPsf().getAveragePosition() 

109 result = algorithm.apply( 

110 self.exposure, makeMultiShapeletCircularGaussian(self.psfSigma), 

111 self.xyPosition, self.exposure.getPsf().computeShape(pos) 

112 ) 

113 self.assertFalse(result.initial.flags[result.FAILED]) 

114 self.assertFloatsAlmostEqual(result.initial.instFlux, self.trueFlux, rtol=0.01) 

115 self.assertFloatsAlmostEqual(result.initial.instFluxErr, expectedFluxErr, rtol=0.01) 

116 self.assertLess(result.initial.ellipse.getDeterminantRadius(), 0.2) 

117 self.assertFalse(result.exp.flags[result.FAILED]) 

118 self.assertFloatsAlmostEqual(result.exp.instFlux, self.trueFlux, rtol=0.01) 

119 self.assertFloatsAlmostEqual(result.exp.instFluxErr, expectedFluxErr, rtol=0.01) 

120 self.assertLess(result.exp.ellipse.getDeterminantRadius(), 0.2) 

121 self.assertFalse(result.dev.flags[result.FAILED]) 

122 self.assertFloatsAlmostEqual(result.dev.instFlux, self.trueFlux, rtol=0.01) 

123 self.assertFloatsAlmostEqual(result.dev.instFluxErr, expectedFluxErr, rtol=0.01) 

124 self.assertLess(result.dev.ellipse.getDeterminantRadius(), 0.2) 

125 self.assertFalse(result.flags[result.FAILED]) 

126 self.assertFloatsAlmostEqual(result.instFlux, self.trueFlux, rtol=0.01) 

127 

128 def testVsPsfFlux(self): 

129 """Test that CModel produces results comparable to PsfFlux when run 

130 on point sources. 

131 """ 

132 noiseSigma = 1.0 

133 for fluxFactor in (1.0, 10.0, 100.0): 

134 exposure = self.exposure.Factory(self.exposure, True) 

135 exposure.getMaskedImage().getImage().getArray()[:] *= fluxFactor 

136 exposure.getMaskedImage().getVariance().getArray()[:] = noiseSigma**2 

137 exposure.getMaskedImage().getImage().getArray()[:] += \ 

138 noiseSigma*numpy.random.randn(exposure.getHeight(), exposure.getWidth()) 

139 ctrl = lsst.meas.modelfit.CModelControl() 

140 algorithm = lsst.meas.modelfit.CModelAlgorithm(ctrl) 

141 pos = self.exposure.getPsf().getAveragePosition() 

142 cmodel = algorithm.apply( 

143 exposure, makeMultiShapeletCircularGaussian(self.psfSigma), 

144 self.xyPosition, self.exposure.getPsf().computeShape(pos) 

145 ) 

146 psfFlux, psfFluxErr = computePsfFlux(self.xyPosition, exposure) 

147 self.assertFloatsAlmostEqual(psfFlux, cmodel.instFlux, rtol=0.1/fluxFactor**0.5) 

148 self.assertFloatsAlmostEqual(psfFluxErr, cmodel.instFluxErr, rtol=0.1/fluxFactor**0.5) 

149 

150 

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

152 pass 

153 

154 

155def setup_module(module): 

156 lsst.utils.tests.init() 

157 

158 

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

160 lsst.utils.tests.init() 

161 unittest.main()