Coverage for tests/test_assemble_cell_coadd.py: 30%

63 statements  

« prev     ^ index     » next       coverage.py v7.5.0, created at 2024-05-04 11:23 +0000

1# This file is part of drp_tasks. 

2# 

3# LSST Data Management System 

4# This product includes software developed by the 

5# LSST Project (http://www.lsst.org/). 

6# See COPYRIGHT file at the top of the source tree. 

7# 

8# This program is free software: you can redistribute it and/or modify 

9# it under the terms of the GNU General Public License as published by 

10# the Free Software Foundation, either version 3 of the License, or 

11# (at your option) any later version. 

12# 

13# This program is distributed in the hope that it will be useful, 

14# but WITHOUT ANY WARRANTY; without even the implied warranty of 

15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 

16# GNU General Public License for more details. 

17# 

18# You should have received a copy of the LSST License Statement and 

19# the GNU General Public License along with this program. If not, 

20# see <https://www.lsstcorp.org/LegalNotices/>. 

21# 

22 

23import unittest 

24 

25import lsst.pipe.base as pipeBase 

26import lsst.utils.tests 

27import numpy as np 

28from assemble_coadd_test_utils import MockCoaddTestData, makeMockSkyInfo 

29from lsst.drp.tasks.assemble_cell_coadd import AssembleCellCoaddConfig, AssembleCellCoaddTask 

30 

31__all__ = ( 

32 "MockAssembleCellCoaddConfig", 

33 "MockAssembleCellCoaddTask", 

34) 

35 

36 

37class MockAssembleCellCoaddConfig(AssembleCellCoaddConfig): 

38 pass 

39 

40 

41class MockAssembleCellCoaddTask(AssembleCellCoaddTask): 

42 """Lightly modified version of `AssembleCellCoaddTask` for unit tests. 

43 

44 The modifications bypass the usual middleware for loading data and setting 

45 up the Task, and instead supply in-memory mock data references to the `run` 

46 method so that the coaddition algorithms can be tested without a Butler. 

47 """ 

48 

49 ConfigClass = MockAssembleCellCoaddConfig 

50 

51 def runQuantum(self, mockSkyInfo, warpRefList): 

52 """Modified interface for testing coaddition algorithms without a 

53 Butler. 

54 

55 Parameters 

56 ---------- 

57 mockSkyInfo : `lsst.pipe.base.Struct` 

58 A simple container that supplies a bounding box and WCS in the 

59 same format as the output of 

60 `lsst.pipe.tasks.CoaddBaseTask.getSkyInfo` 

61 warpRefList : `list` of `lsst.pipe.tasks.MockExposureReference` 

62 Data references to the test exposures that will be coadded, 

63 using the Gen 3 API. 

64 

65 Returns 

66 ------- 

67 retStruct : `lsst.pipe.base.Struct` 

68 The coadded exposure and associated metadata. 

69 """ 

70 

71 self.common = pipeBase.Struct( 

72 units=None, 

73 wcs=mockSkyInfo.wcs, 

74 band="i", 

75 identifiers=pipeBase.Struct(skymap=None, tract=0, patch=42, band="i"), 

76 ) 

77 

78 retStruct = self.run( 

79 warpRefList, 

80 mockSkyInfo, 

81 ) 

82 

83 return retStruct 

84 

85 

86class AssembleCellCoaddTestCase(lsst.utils.tests.TestCase): 

87 """Tests of AssembleCellCoaddTask. 

88 

89 These tests bypass the middleware used for accessing data and managing Task 

90 execution. 

91 """ 

92 

93 @classmethod 

94 def setUpClass(cls) -> None: 

95 patch = 42 

96 tract = 0 

97 testData = MockCoaddTestData(fluxRange=1e4) 

98 exposures = {} 

99 matchedExposures = {} 

100 for expId in range(100, 110): 

101 exposures[expId], matchedExposures[expId] = testData.makeTestImage(expId) 

102 cls.dataRefList = testData.makeDataRefList( 

103 exposures, matchedExposures, "direct", patch=patch, tract=tract 

104 ) 

105 cls.skyInfo = makeMockSkyInfo(testData.bbox, testData.wcs, patch=patch) 

106 

107 config = MockAssembleCellCoaddConfig() 

108 assembleTask = MockAssembleCellCoaddTask(config=config) 

109 cls.result = assembleTask.runQuantum(cls.skyInfo, cls.dataRefList) 

110 

111 def checkRun(self, assembleTask): 

112 """Check that the task runs successfully.""" 

113 result = assembleTask.runQuantum(self.skyInfo, self.dataRefList) 

114 

115 # Check that we produced an exposure. 

116 self.assertTrue(result.multipleCellCoadd is not None) 

117 # Check that the visit_count method returns a number less than or equal 

118 # to the total number of input exposures available. 

119 max_visit_count = len(self.dataRefList) 

120 for cellId, singleCellCoadd in result.multipleCellCoadd.cells.items(): 

121 with self.subTest(x=cellId.x, y=cellId.y): 

122 self.assertLessEqual(singleCellCoadd.visit_count, max_visit_count) 

123 # Check that the inputs are sorted. 

124 packed = -np.inf 

125 for idx, obsId in enumerate(singleCellCoadd.inputs): 

126 with self.subTest(input_number=obsId): 

127 self.assertGreaterEqual(obsId.packed, packed) 

128 packed = obsId.packed 

129 

130 def test_assemble_basic(self): 

131 """Test that AssembleCellCoaddTask runs successfully without errors. 

132 

133 This test does not check the correctness of the coaddition algorithms. 

134 This is intended to prevent the code from bit rotting. 

135 """ 

136 # Check that we produced an exposure. 

137 self.assertTrue(self.result.multipleCellCoadd is not None) 

138 

139 def test_visit_count(self): 

140 """Check that the visit_count method returns a number less than or 

141 equal to the total number of input exposures available. 

142 """ 

143 max_visit_count = len(self.dataRefList) 

144 for cellId, singleCellCoadd in self.result.multipleCellCoadd.cells.items(): 

145 with self.subTest(x=cellId.x, y=cellId.y): 

146 self.assertLessEqual(singleCellCoadd.visit_count, max_visit_count) 

147 

148 def test_inputs_sorted(self): 

149 """Check that the inputs are sorted.""" 

150 for _, singleCellCoadd in self.result.multipleCellCoadd.cells.items(): 

151 packed = -np.inf 

152 for obsId in singleCellCoadd.inputs: 

153 with self.subTest(input_number=obsId): 

154 self.assertGreaterEqual(obsId.packed, packed) 

155 packed = obsId.packed 

156 

157 

158class MyMemoryTestCase(lsst.utils.tests.MemoryTestCase): 

159 pass 

160 

161 

162def setup_module(module): 

163 lsst.utils.tests.init() 

164 

165 

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

167 lsst.utils.tests.init() 

168 unittest.main()