Coverage for tests/test_defineVisits.py: 27%

77 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2023-07-14 20:02 +0000

1# This file is part of obs_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 <http://www.gnu.org/licenses/>. 

21 

22import os 

23import pickle 

24import shutil 

25import tempfile 

26import unittest 

27from collections import defaultdict 

28 

29import lsst.daf.butler.tests as butlerTests 

30from lsst.daf.butler import DataCoordinate, DimensionRecord, SerializedDimensionRecord 

31from lsst.obs.base import DefineVisitsTask 

32from lsst.obs.base.instrument_tests import DummyCam 

33from lsst.utils.iteration import ensure_iterable 

34 

35TESTDIR = os.path.dirname(__file__) 

36DATADIR = os.path.join(TESTDIR, "data", "visits") 

37 

38 

39class DefineVisitsTestCase(unittest.TestCase): 

40 def setUp(self): 

41 """Create a new butler for each test since we are changing dimension 

42 records.""" 

43 self.root = tempfile.mkdtemp(dir=TESTDIR) 

44 self.creatorButler = butlerTests.makeTestRepo(self.root, []) 

45 self.butler = butlerTests.makeTestCollection(self.creatorButler) 

46 

47 self.config = DefineVisitsTask.ConfigClass() 

48 self.task = DefineVisitsTask(config=self.config, butler=self.butler) 

49 

50 # Need to register the instrument. 

51 DummyCam().register(self.butler.registry) 

52 

53 # Read the exposure records. 

54 self.records: dict[int, DimensionRecord] = {} 

55 for i in (347, 348, 349): 

56 simple = SerializedDimensionRecord.parse_file(os.path.join(DATADIR, f"exp_{i}.json")) 

57 self.records[i] = DimensionRecord.from_simple(simple, registry=self.butler.registry) 

58 

59 def tearDown(self): 

60 if self.root is not None: 

61 shutil.rmtree(self.root, ignore_errors=True) 

62 

63 def assertVisits(self): 

64 """Check that the visits were registered as expected.""" 

65 visits = list(self.butler.registry.queryDimensionRecords("visit")) 

66 self.assertEqual(len(visits), 4) 

67 self.assertEqual( 

68 {visit.id for visit in visits}, {2022040500347, 2022040500348, 2022040500349, 92022040500348} 

69 ) 

70 

71 # Ensure that the definitions are correct (ignoring order). 

72 defmap = defaultdict(set) 

73 definitions = list(self.butler.registry.queryDimensionRecords("visit_definition")) 

74 for defn in definitions: 

75 defmap[defn.visit].add(defn.exposure) 

76 

77 self.assertEqual( 

78 dict(defmap), 

79 { 

80 92022040500348: {2022040500348}, 

81 2022040500347: {2022040500347}, 

82 2022040500348: {2022040500348, 2022040500349}, 

83 2022040500349: {2022040500349}, 

84 }, 

85 ) 

86 

87 def define_visits( 

88 self, exposures: list[DimensionRecord | list[DimensionRecord]], incremental: bool 

89 ) -> None: 

90 for records in exposures: 

91 self.butler.registry.insertDimensionData("exposure", *ensure_iterable(records)) 

92 # Include all records so far in definition. 

93 dataIds = [d for d in self.butler.registry.queryDataIds("exposure", instrument="DummyCam")] 

94 self.task.run(dataIds, incremental=incremental) 

95 

96 def test_defineVisits(self): 

97 # Test visit definition with all the records. 

98 self.define_visits([[r for r in self.records.values()]], incremental=False) # list inside a list 

99 self.assertVisits() 

100 

101 def test_incremental_cumulative(self): 

102 # Define the visits after each exposure. 

103 self.define_visits([exp for exp in self.records.values()], incremental=True) 

104 self.assertVisits() 

105 

106 def test_incremental_cumulative_reverse(self): 

107 # In reverse order we should still eventually end up with the right 

108 # answer. 

109 with self.assertLogs("lsst.defineVisits.groupExposures", level="WARNING") as cm: 

110 self.define_visits(list(reversed(self.records.values())), incremental=True) 

111 self.assertIn("Skipping the multi-snap definition", "\n".join(cm.output)) 

112 self.assertVisits() 

113 

114 def define_visits_incrementally(self, exposure: DimensionRecord) -> None: 

115 self.butler.registry.insertDimensionData("exposure", exposure) 

116 dataIds = [ 

117 DataCoordinate.standardize( 

118 instrument="DummyCam", exposure=exposure.id, universe=self.butler.dimensions 

119 ) 

120 ] 

121 self.task.run(dataIds, incremental=True) 

122 

123 def test_incremental(self): 

124 for record in self.records.values(): 

125 self.define_visits_incrementally(record) 

126 self.assertVisits() 

127 

128 def test_incremental_reverse(self): 

129 for record in reversed(self.records.values()): 

130 self.define_visits_incrementally(record) 

131 self.assertVisits() 

132 

133 def testPickleTask(self): 

134 stream = pickle.dumps(self.task) 

135 copy = pickle.loads(stream) 

136 self.assertEqual(self.task.getFullName(), copy.getFullName()) 

137 self.assertEqual(self.task.log.name, copy.log.name) 

138 self.assertEqual(self.task.config, copy.config) 

139 self.assertEqual(self.task.butler._config, copy.butler._config) 

140 self.assertEqual(self.task.butler.collections, copy.butler.collections) 

141 self.assertEqual(self.task.butler.run, copy.butler.run) 

142 self.assertEqual(self.task.universe, copy.universe) 

143 

144 

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

146 unittest.main()