Coverage for tests/test_instrument.py: 28%

91 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2023-04-14 02:16 -0700

1# This file is part of pipe_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 

22"""Tests of the Instrument class. 

23""" 

24 

25import datetime 

26import unittest 

27 

28from lsst.daf.butler import Registry, RegistryConfig 

29from lsst.daf.butler.formatters.json import JsonFormatter 

30from lsst.pipe.base import Instrument 

31from lsst.utils.introspection import get_full_type_name 

32 

33 

34class DummyInstrument(Instrument): 

35 @classmethod 

36 def getName(cls): 

37 return "DummyInstrument" 

38 

39 def register(self, registry, update=False): 

40 detector_max = 2 

41 record = { 

42 "instrument": self.getName(), 

43 "class_name": get_full_type_name(DummyInstrument), 

44 "detector_max": detector_max, 

45 } 

46 with registry.transaction(): 

47 registry.syncDimensionData("instrument", record, update=update) 

48 

49 def getRawFormatter(self, dataId): 

50 return JsonFormatter 

51 

52 

53class BadInstrument(DummyInstrument): 

54 """Instrument with wrong class name.""" 

55 

56 raw_definition = ("raw2", ("instrument", "detector", "exposure"), "StructuredDataDict") 

57 

58 @classmethod 

59 def getName(cls): 

60 return "BadInstrument" 

61 

62 def register(self, registry, update=False): 

63 # Register a bad class name 

64 record = { 

65 "instrument": self.getName(), 

66 "class_name": "builtins.str", 

67 "detector_max": 1, 

68 } 

69 registry.syncDimensionData("instrument", record, update=update) 

70 

71 

72class UnimportableInstrument(DummyInstrument): 

73 """Instrument with class name that does not exist.""" 

74 

75 @classmethod 

76 def getName(cls): 

77 return "NoImportInstr" 

78 

79 def register(self, registry, update=False): 

80 # Register a bad class name 

81 record = { 

82 "instrument": self.getName(), 

83 "class_name": "not.importable", 

84 "detector_max": 1, 

85 } 

86 registry.syncDimensionData("instrument", record, update=update) 

87 

88 

89class InstrumentTestCase(unittest.TestCase): 

90 """Test for Instrument.""" 

91 

92 def setUp(self): 

93 self.instrument = DummyInstrument() 

94 self.name = "DummyInstrument" 

95 

96 def test_basics(self): 

97 self.assertEqual(self.instrument.getName(), self.name) 

98 self.assertEqual(self.instrument.getRawFormatter({}), JsonFormatter) 

99 self.assertIsNone(DummyInstrument.raw_definition) 

100 raw = BadInstrument.raw_definition 

101 self.assertEqual(raw[2], "StructuredDataDict") 

102 

103 def test_register(self): 

104 """Test that register() sets appropriate Dimensions.""" 

105 registryConfig = RegistryConfig() 

106 registryConfig["db"] = "sqlite://" 

107 registry = Registry.createFromConfig(registryConfig) 

108 # Check that the registry starts out empty. 

109 self.instrument.importAll(registry) 

110 self.assertFalse(list(registry.queryDimensionRecords("instrument"))) 

111 

112 # Register and check again. 

113 self.instrument.register(registry) 

114 instruments = list(registry.queryDimensionRecords("instrument")) 

115 self.assertEqual(len(instruments), 1) 

116 self.assertEqual(instruments[0].name, self.name) 

117 self.assertEqual(instruments[0].detector_max, 2) 

118 self.assertIn("DummyInstrument", instruments[0].class_name) 

119 

120 self.instrument.importAll(registry) 

121 from_registry = DummyInstrument.fromName("DummyInstrument", registry) 

122 self.assertIsInstance(from_registry, Instrument) 

123 with self.assertRaises(LookupError): 

124 Instrument.fromName("NotThrere", registry) 

125 

126 # Register a bad instrument. 

127 BadInstrument().register(registry) 

128 with self.assertRaises(TypeError): 

129 Instrument.fromName("BadInstrument", registry) 

130 

131 UnimportableInstrument().register(registry) 

132 with self.assertRaises(ImportError): 

133 Instrument.fromName("NoImportInstr", registry) 

134 

135 # This should work even with the bad class name. 

136 self.instrument.importAll(registry) 

137 

138 def test_defaults(self): 

139 self.assertEqual(self.instrument.makeDefaultRawIngestRunName(), "DummyInstrument/raw/all") 

140 self.assertEqual( 

141 self.instrument.makeUnboundedCalibrationRunName("a", "b"), "DummyInstrument/calib/a/b/unbounded" 

142 ) 

143 self.assertEqual( 

144 self.instrument.makeCuratedCalibrationRunName("2018-05-04", "a"), 

145 "DummyInstrument/calib/a/curated/20180504T000000Z", 

146 ) 

147 self.assertEqual(self.instrument.makeCalibrationCollectionName("c"), "DummyInstrument/calib/c") 

148 self.assertEqual(self.instrument.makeRefCatCollectionName(), "refcats") 

149 self.assertEqual(self.instrument.makeRefCatCollectionName("a"), "refcats/a") 

150 self.assertEqual(self.instrument.makeUmbrellaCollectionName(), "DummyInstrument/defaults") 

151 

152 instrument = DummyInstrument(collection_prefix="Different") 

153 self.assertEqual(instrument.makeCollectionName("a"), "Different/a") 

154 self.assertEqual(self.instrument.makeCollectionName("a"), "DummyInstrument/a") 

155 

156 def test_collection_timestamps(self): 

157 self.assertEqual( 

158 Instrument.formatCollectionTimestamp("2018-05-03"), 

159 "20180503T000000Z", 

160 ) 

161 self.assertEqual( 

162 Instrument.formatCollectionTimestamp("2018-05-03T14:32:16"), 

163 "20180503T143216Z", 

164 ) 

165 self.assertEqual( 

166 Instrument.formatCollectionTimestamp("20180503T143216Z"), 

167 "20180503T143216Z", 

168 ) 

169 self.assertEqual( 

170 Instrument.formatCollectionTimestamp(datetime.datetime(2018, 5, 3, 14, 32, 16)), 

171 "20180503T143216Z", 

172 ) 

173 formattedNow = Instrument.makeCollectionTimestamp() 

174 self.assertIsInstance(formattedNow, str) 

175 datetimeThen1 = datetime.datetime.strptime(formattedNow, "%Y%m%dT%H%M%S%z") 

176 self.assertEqual(datetimeThen1.tzinfo, datetime.timezone.utc) 

177 

178 with self.assertRaises(TypeError): 

179 Instrument.formatCollectionTimestamp(0) 

180 

181 

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

183 unittest.main()