Coverage for tests/test_NoiseReplacer.py: 39%

62 statements  

« prev     ^ index     » next       coverage.py v7.2.5, created at 2023-05-03 03:05 -0700

1# This file is part of meas_base. 

2# 

3# Developed for the LSST Data Management System. 

4# This product includes software developed by the LSST Project 

5# (https://www.lsst.org). 

6# See the COPYRIGHT file at the top-level directory of this distribution 

7# for details of code ownership. 

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 GNU General Public License 

20# along with this program. If not, see <https://www.gnu.org/licenses/>. 

21 

22import unittest 

23 

24import numpy as np 

25 

26import lsst.geom 

27import lsst.afw.geom 

28import lsst.afw.detection 

29import lsst.afw.table 

30import lsst.meas.base.tests 

31import lsst.utils.tests 

32from lsst.daf.base import PropertyList 

33from lsst.utils.tests import methodParameters 

34 

35 

36@lsst.meas.base.register("test_NoiseReplacer") 

37class NoiseReplacerTestPlugin(lsst.meas.base.SingleFramePlugin): 

38 """Plugin that sums instFlux inside and outside the source footprint. 

39 """ 

40 

41 @staticmethod 

42 def getExecutionOrder(): 

43 return 2.0 

44 

45 def __init__(self, config, name, schema, metadata): 

46 lsst.meas.base.SingleFramePlugin.__init__(self, config, name, schema, metadata) 

47 self.insideKey = schema.addField("%s_inside" % (name,), type=np.float64, 

48 doc="instFlux inside footprint") 

49 self.outsideKey = schema.addField("%s_outside" % (name,), type=np.float64, 

50 doc="instFlux outside footprint") 

51 

52 def measure(self, measRecord, exposure): 

53 footprint = measRecord.getFootprint() 

54 fullArray = exposure.getMaskedImage().getImage().getArray() 

55 insideArray = np.zeros(footprint.getArea(), dtype=fullArray.dtype) 

56 footprint.spans.flatten(insideArray, fullArray, exposure.getXY0()) 

57 insideFlux = float(insideArray.sum()) 

58 outsideFlux = float(fullArray.sum()) - insideFlux 

59 measRecord.set(self.insideKey, insideFlux) 

60 measRecord.set(self.outsideKey, outsideFlux) 

61 

62 

63class NoiseReplacerTestCase(lsst.meas.base.tests.AlgorithmTestCase, lsst.utils.tests.TestCase): 

64 

65 def setUp(self): 

66 self.bbox = lsst.geom.Box2I(lsst.geom.Point2I(-20, -30), 

67 lsst.geom.Extent2I(240, 260)) 

68 self.dataset = lsst.meas.base.tests.TestDataset(self.bbox) 

69 # first source is a point 

70 self.dataset.addSource(100000.0, lsst.geom.Point2D(50.1, 49.8)) 

71 # second source is extended 

72 self.dataset.addSource(120000.0, lsst.geom.Point2D(149.9, 50.3), 

73 lsst.afw.geom.Quadrupole(8, 9, 3)) 

74 with self.dataset.addBlend() as family: 

75 family.addChild(110000.0, lsst.geom.Point2D(65.2, 150.7), 

76 lsst.afw.geom.Quadrupole(7, 5, -1)) 

77 family.addChild(140000.0, lsst.geom.Point2D(72.3, 149.1)) 

78 family.addChild(90000.0, lsst.geom.Point2D(68.5, 156.9)) 

79 

80 @methodParameters(noiseSource=['measure', 'variance', 'meta', 'variance_median'], 

81 variance=[1.0, 1.0, 2.0, 1.0]) 

82 def testNoiseReplacer(self, noiseSource, variance): 

83 """Test noise replacement in SFM with ''measure'' mode. 

84 

85 We compare the instFlux inside and outside source Footprints on an 

86 extremely high S/N image. 

87 """ 

88 # We choose a random seed which causes the test to pass. 

89 task = self.makeSingleFrameMeasurementTask("test_NoiseReplacer") 

90 task.config.noiseReplacer.noiseSource = noiseSource 

91 exposure, catalog = self.dataset.realize(variance, task.schema, randomSeed=0) 

92 if noiseSource == 'meta': 

93 md = PropertyList() 

94 md['BGMEAN'] = variance 

95 exposure.setMetadata(md) 

96 task.run(catalog, exposure) 

97 sumVariance = exposure.getMaskedImage().getVariance().getArray().sum() 

98 for record in catalog: 

99 self.assertFloatsAlmostEqual(record.get("test_NoiseReplacer_inside"), 

100 record.get("truth_instFlux"), rtol=1E-3) 

101 

102 # N.B. Next line checks that a random value is correct to a 

103 # statistical 1-sigma prediction; some RNG seeds may cause it to 

104 # fail (indeed, 67% should) 

105 self.assertLess(record.get("test_NoiseReplacer_outside"), np.sqrt(sumVariance)) 

106 

107 def tearDown(self): 

108 del self.bbox 

109 del self.dataset 

110 

111 

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

113 pass 

114 

115 

116def setup_module(module): 

117 lsst.utils.tests.init() 

118 

119 

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

121 lsst.utils.tests.init() 

122 unittest.main()