Coverage for tests/test_reserveSourcesTask.py: 19%

68 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2023-07-24 10:11 +0000

1# 

2# LSST Data Management System 

3# 

4# Copyright 2008-2017 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# 

23 

24import unittest 

25import numpy as np 

26 

27import lsst.afw.table 

28import lsst.meas.algorithms 

29import lsst.utils.tests 

30 

31from lsst.pipe.base import Struct 

32 

33 

34class ReserveSourcesTaskTest(lsst.utils.tests.TestCase): 

35 """TestCase for the ReserveSourcesTask""" 

36 def setUp(self): 

37 self.num = 100 # Number of sources 

38 self.longMessage = True 

39 

40 def construct(self, name, fraction): 

41 """Construct the test environment 

42 

43 This isn't called 'setUp' because we want to vary the `fraction`. 

44 

45 Parameters 

46 ---------- 

47 name : `str` 

48 Name of column for flagging reserved sources (without "_reserved"). 

49 fraction : `float` 

50 Fraction of sources to reserve. 

51 

52 Return struct elements 

53 ---------------------- 

54 catalog : `lsst.afw.table.SourceCatalog` 

55 Catalog of sources. 

56 task : `lsst.meas.algorithms.ReserveSourcesTask` 

57 Task to do the reservations. 

58 key : `lsst.afw.table.Key` 

59 Key to the flag column. 

60 """ 

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

62 config = lsst.meas.algorithms.ReserveSourcesConfig() 

63 config.fraction = fraction 

64 task = lsst.meas.algorithms.ReserveSourcesTask(columnName=name, schema=schema, 

65 doc="Documentation is good", config=config) 

66 key = schema[name + "_reserved"].asKey() 

67 catalog = lsst.afw.table.SourceCatalog(schema) 

68 catalog.reserve(self.num) 

69 for _ in range(self.num): 

70 catalog.addNew() 

71 return Struct(catalog=catalog, task=task, key=key) 

72 

73 def check(self, sources, task, key, fraction): 

74 """Check that source reservation is working 

75 

76 We test that the source reservation works, that it depends 

77 on the RNG seed and that things behave as we expect when there's 

78 a prior selection. 

79 

80 Parameters 

81 ---------- 

82 catalog : `lsst.afw.table.Catalog` or `list` of `lsst.afw.table.Record` 

83 List of sources. 

84 task : `lsst.meas.algorithms.ReserveSourcesTask` 

85 Task to do the reservations. 

86 key : `lsst.afw.table.Key` 

87 Key to the flag column. 

88 fraction : `float` 

89 Fraction of sources to reserve. 

90 """ 

91 message = "fraction=%s, key=%s" % (fraction, key) 

92 numExpect = int(fraction*len(sources)) 

93 

94 # No prior 

95 results1 = task.run(sources, expId=1) 

96 flagged1 = np.array([ss.get(key) for ss in sources]) 

97 self.assertEqual(flagged1.sum(), numExpect, message) 

98 np.testing.assert_array_equal(results1.reserved, flagged1, message) 

99 np.testing.assert_array_equal(results1.use, np.logical_not(flagged1), message) 

100 

101 # Second run with different seed; clear the flag first 

102 for ss in sources: 

103 ss.set(key, False) 

104 results2 = task.run(sources, expId=2) 

105 flagged2 = np.array([ss.get(key) for ss in sources]) 

106 self.assertEqual(flagged1.sum(), numExpect, message) 

107 np.testing.assert_array_equal(results2.reserved, flagged2, message) 

108 np.testing.assert_array_equal(results2.use, np.logical_not(flagged2), message) 

109 if numExpect > 0: 

110 self.assertFalse(np.all(flagged1 == flagged2), 

111 "Pretty unlikely since different seeds\n" + message) 

112 

113 # Run with prior selection; clear the flag first 

114 for ss in sources: 

115 ss.set(key, False) 

116 prior = np.arange(0, self.num, 1, dtype=int) % 2 == 0 

117 results3 = task.run(sources, prior, expId=1) 

118 flagged3 = np.array([ss.get(key) for ss in sources]) 

119 self.assertEqual(flagged3.sum(), fraction*prior.sum(), message) 

120 if numExpect > 0: 

121 self.assertFalse(np.all(flagged1 == flagged3), 

122 "Flags should change, despite same see\n" + message) 

123 np.testing.assert_array_equal(results3.reserved, flagged3, message) 

124 self.assertEqual((results3.use & flagged3).sum(), 0, 

125 "No sources should be both reserved and used\n" + message) # 

126 self.assertEqual(results3.use.sum(), int((1.0 - fraction)*prior.sum()), message) 

127 self.assertEqual(results3.reserved.sum(), int(fraction*prior.sum()), message) 

128 np.testing.assert_array_equal(results3.use, prior & ~flagged3, 

129 "Actual definition of 'use'\n" + message) 

130 

131 def testCatalog(self): 

132 """Test source reservation with a Catalog 

133 

134 We test multiple reservation fractions. 

135 """ 

136 for fraction in (0.0, 0.1, 0.2, 0.5): 

137 data = self.construct("this_table_is", fraction) 

138 self.check(data.catalog, data.task, data.key, fraction) 

139 

140 def testSources(self): 

141 """Test source reservation with a list of sources""" 

142 fraction = 0.2 

143 data = self.construct("this_table_is", fraction) 

144 sources = [ss for ss in data.catalog] 

145 self.check(sources, data.task, data.key, fraction) 

146 

147 

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

149 pass 

150 

151 

152def setup_module(module): 

153 lsst.utils.tests.init() 

154 

155 

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

157 import sys 

158 setup_module(sys.modules[__name__]) 

159 unittest.main()