Coverage for tests/test_instrument.py: 28%
87 statements
« prev ^ index » next coverage.py v6.5.0, created at 2023-01-13 02:51 -0800
« prev ^ index » next coverage.py v6.5.0, created at 2023-01-13 02:51 -0800
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/>.
22"""Tests of the Instrument class.
23"""
25import datetime
26import unittest
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
34class DummyInstrument(Instrument):
35 @classmethod
36 def getName(cls):
37 return "DummyInstrument"
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)
49 def getRawFormatter(self, dataId):
50 return JsonFormatter
53class BadInstrument(DummyInstrument):
54 """Instrument with wrong class name."""
56 @classmethod
57 def getName(cls):
58 return "BadInstrument"
60 def register(self, registry, update=False):
61 # Register a bad class name
62 record = {
63 "instrument": self.getName(),
64 "class_name": "builtins.str",
65 "detector_max": 1,
66 }
67 registry.syncDimensionData("instrument", record, update=update)
70class UnimportableInstrument(DummyInstrument):
71 """Instrument with class name that does not exist."""
73 @classmethod
74 def getName(cls):
75 return "NoImportInstr"
77 def register(self, registry, update=False):
78 # Register a bad class name
79 record = {
80 "instrument": self.getName(),
81 "class_name": "not.importable",
82 "detector_max": 1,
83 }
84 registry.syncDimensionData("instrument", record, update=update)
87class InstrumentTestCase(unittest.TestCase):
88 """Test for Instrument."""
90 def setUp(self):
91 self.instrument = DummyInstrument()
92 self.name = "DummyInstrument"
94 def test_basics(self):
95 self.assertEqual(self.instrument.getName(), self.name)
96 self.assertEqual(self.instrument.getRawFormatter({}), JsonFormatter)
98 def test_register(self):
99 """Test that register() sets appropriate Dimensions."""
100 registryConfig = RegistryConfig()
101 registryConfig["db"] = "sqlite://"
102 registry = Registry.createFromConfig(registryConfig)
103 # Check that the registry starts out empty.
104 self.instrument.importAll(registry)
105 self.assertFalse(list(registry.queryDimensionRecords("instrument")))
107 # Register and check again.
108 self.instrument.register(registry)
109 instruments = list(registry.queryDimensionRecords("instrument"))
110 self.assertEqual(len(instruments), 1)
111 self.assertEqual(instruments[0].name, self.name)
112 self.assertEqual(instruments[0].detector_max, 2)
113 self.assertIn("DummyInstrument", instruments[0].class_name)
115 self.instrument.importAll(registry)
116 from_registry = DummyInstrument.fromName("DummyInstrument", registry)
117 self.assertIsInstance(from_registry, Instrument)
118 with self.assertRaises(LookupError):
119 Instrument.fromName("NotThrere", registry)
121 # Register a bad instrument.
122 BadInstrument().register(registry)
123 with self.assertRaises(TypeError):
124 Instrument.fromName("BadInstrument", registry)
126 UnimportableInstrument().register(registry)
127 with self.assertRaises(ImportError):
128 Instrument.fromName("NoImportInstr", registry)
130 # This should work even with the bad class name.
131 self.instrument.importAll(registry)
133 def test_defaults(self):
134 self.assertEqual(self.instrument.makeDefaultRawIngestRunName(), "DummyInstrument/raw/all")
135 self.assertEqual(
136 self.instrument.makeUnboundedCalibrationRunName("a", "b"), "DummyInstrument/calib/a/b/unbounded"
137 )
138 self.assertEqual(
139 self.instrument.makeCuratedCalibrationRunName("2018-05-04", "a"),
140 "DummyInstrument/calib/a/curated/20180504T000000Z",
141 )
142 self.assertEqual(self.instrument.makeCalibrationCollectionName("c"), "DummyInstrument/calib/c")
143 self.assertEqual(self.instrument.makeRefCatCollectionName(), "refcats")
144 self.assertEqual(self.instrument.makeRefCatCollectionName("a"), "refcats/a")
145 self.assertEqual(self.instrument.makeUmbrellaCollectionName(), "DummyInstrument/defaults")
147 instrument = DummyInstrument(collection_prefix="Different")
148 self.assertEqual(instrument.makeCollectionName("a"), "Different/a")
149 self.assertEqual(self.instrument.makeCollectionName("a"), "DummyInstrument/a")
151 def test_collection_timestamps(self):
152 self.assertEqual(
153 Instrument.formatCollectionTimestamp("2018-05-03"),
154 "20180503T000000Z",
155 )
156 self.assertEqual(
157 Instrument.formatCollectionTimestamp("2018-05-03T14:32:16"),
158 "20180503T143216Z",
159 )
160 self.assertEqual(
161 Instrument.formatCollectionTimestamp("20180503T143216Z"),
162 "20180503T143216Z",
163 )
164 self.assertEqual(
165 Instrument.formatCollectionTimestamp(datetime.datetime(2018, 5, 3, 14, 32, 16)),
166 "20180503T143216Z",
167 )
168 formattedNow = Instrument.makeCollectionTimestamp()
169 self.assertIsInstance(formattedNow, str)
170 datetimeThen1 = datetime.datetime.strptime(formattedNow, "%Y%m%dT%H%M%S%z")
171 self.assertEqual(datetimeThen1.tzinfo, datetime.timezone.utc)
173 with self.assertRaises(TypeError):
174 Instrument.formatCollectionTimestamp(0)
177if __name__ == "__main__": 177 ↛ 178line 177 didn't jump to line 178, because the condition on line 177 was never true
178 unittest.main()