Coverage for tests/test_Classification.py: 30%

65 statements  

« prev     ^ index     » next       coverage.py v6.4.1, created at 2022-06-16 02:21 -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 lsst.utils.tests 

25import lsst.geom 

26import lsst.afw.geom 

27import lsst.meas.base.tests 

28import lsst.meas.base as measBase 

29import lsst.meas.base.catalogCalculation as catCalc 

30 

31 

32class ClassificationTestCase(lsst.meas.base.tests.AlgorithmTestCase, lsst.utils.tests.TestCase): 

33 

34 def setUp(self): 

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

36 lsst.geom.Extent2I(250, 150)) 

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

38 # first source is a point 

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

40 # second source is extended 

41 self.dataset.addSource(100000.0, lsst.geom.Point2D(149.9, 50.3), 

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

43 

44 def tearDown(self): 

45 del self.bbox 

46 del self.dataset 

47 

48 def testSingleFramePlugin(self): 

49 config = measBase.SingleFrameMeasurementConfig() 

50 # n.b. we use the truth value as ModelFlux 

51 config.slots.psfFlux = "base_PsfFlux" 

52 config.slots.modelFlux = "truth" 

53 task = self.makeSingleFrameMeasurementTask(config=config) 

54 abTask = catCalc.CatalogCalculationTask(schema=task.schema) 

55 exposure, catalog = self.dataset.realize(10.0, task.schema, randomSeed=0) 

56 task.run(catalog, exposure) 

57 abTask.run(catalog) 

58 self.assertLess(catalog[0].get("base_ClassificationExtendedness_value"), 0.5) 

59 self.assertGreater(catalog[1].get("base_ClassificationExtendedness_value"), 0.5) 

60 

61 def testFlags(self): 

62 """Test for success and check all failure modes. 

63 

64 Test all the failure modes of this algorithm, as well as checking that 

65 it succeeds when it should. 

66 

67 Notes 

68 ----- 

69 Since this algorithm depends on having a ``ModelFlux`` and a 

70 ``PsfFlux`` measurement, it is a failure mode when either is NaN, or 

71 when ``ModelFluxFlag`` or ``PsfFluxFlag`` is ``True``. 

72 

73 When ``psfFluxFactor != 0``, the ``PsfFluxErr`` cannot be NaN, but 

74 otherwise is ignored. 

75 

76 When ``modelFluxFactor != 0``, the ``ModelFluxErr`` cannot be NaN, but 

77 otherwise is ignored. 

78 """ 

79 config = measBase.SingleFrameMeasurementConfig() 

80 config.slots.psfFlux = "base_PsfFlux" 

81 config.slots.modelFlux = "base_GaussianFlux" 

82 

83 abConfig = catCalc.CatalogCalculationConfig() 

84 

85 def runFlagTest(psfFlux=100.0, modelFlux=200.0, 

86 psfFluxErr=1.0, modelFluxErr=2.0, 

87 psfFluxFlag=False, modelFluxFlag=False): 

88 task = self.makeSingleFrameMeasurementTask(config=config) 

89 abTask = catCalc.CatalogCalculationTask(schema=task.schema, config=abConfig) 

90 exposure, catalog = self.dataset.realize(10.0, task.schema, randomSeed=1) 

91 source = catalog[0] 

92 source.set("base_PsfFlux_instFlux", psfFlux) 

93 source.set("base_PsfFlux_instFluxErr", psfFluxErr) 

94 source.set("base_PsfFlux_flag", psfFluxFlag) 

95 source.set("base_GaussianFlux_instFlux", modelFlux) 

96 source.set("base_GaussianFlux_instFluxErr", modelFluxErr) 

97 source.set("base_GaussianFlux_flag", modelFluxFlag) 

98 abTask.plugins["base_ClassificationExtendedness"].calculate(source) 

99 return source.get("base_ClassificationExtendedness_flag") 

100 

101 # Test no error case - all necessary values are set 

102 self.assertFalse(runFlagTest()) 

103 

104 # Test psfFlux flag case - failure in PsfFlux 

105 self.assertTrue(runFlagTest(psfFluxFlag=True)) 

106 

107 # Test modelFlux flag case - failure in ModelFlux 

108 self.assertTrue(runFlagTest(modelFluxFlag=True)) 

109 

110 # Test modelFlux NAN case 

111 self.assertTrue(runFlagTest(modelFlux=float("NaN"), modelFluxFlag=True)) 

112 

113 # Test psfFlux NAN case 

114 self.assertTrue(runFlagTest(psfFlux=float("NaN"), psfFluxFlag=True)) 

115 

116 # Test modelFluxErr NAN case when modelErrFactor is zero and non-zero 

117 abConfig.plugins["base_ClassificationExtendedness"].modelErrFactor = 0. 

118 self.assertFalse(runFlagTest(modelFluxErr=float("NaN"))) 

119 abConfig.plugins["base_ClassificationExtendedness"].modelErrFactor = 1. 

120 self.assertTrue(runFlagTest(modelFluxErr=float("NaN"))) 

121 

122 # Test psfFluxErr NAN case when psfErrFactor is zero and non-zero 

123 abConfig.plugins["base_ClassificationExtendedness"].psfErrFactor = 0. 

124 self.assertFalse(runFlagTest(psfFluxErr=float("NaN"))) 

125 abConfig.plugins["base_ClassificationExtendedness"].psfErrFactor = 1. 

126 self.assertTrue(runFlagTest(psfFluxErr=float("NaN"))) 

127 

128 

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

130 pass 

131 

132 

133def setup_module(module): 

134 lsst.utils.tests.init() 

135 

136 

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

138 lsst.utils.tests.init() 

139 unittest.main()