Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1# This file is part of obs_lsst. 

2# 

3# Developed for the LSST Data Management System. 

4# This product includes software developed by the LSST Project 

5# (http://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 unittest 

24import shutil 

25import tempfile 

26from cProfile import Profile 

27from pstats import Stats 

28 

29import numpy as np 

30 

31from lsst.obs.lsst import (LsstCam, LsstComCam, LsstImSim, LsstPhoSim, 

32 LsstTS8, LsstTS3, LsstUCDCam, Latiss) 

33 

34from lsst.daf.butler import (Butler, DatasetType, FileDescriptor, Location, 

35 StorageClass, StorageClassFactory) 

36 

37TESTDIR = os.path.abspath(os.path.dirname(__file__)) 

38DATAROOT = os.path.join(TESTDIR, os.path.pardir, "data", "input") 

39 

40# This test is unfortunately slow; leave a profiling option in in case we want 

41# to improve it later. Initial version is about 60% YamlCamera construction 

42# (!) and 40% SQLite operations inside Butler. 

43PRINT_PROFILE = False 

44 

45 

46class TestInstruments(unittest.TestCase): 

47 

48 def setUp(self): 

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

50 self.rng = np.random.RandomState(50) # arbitrary deterministic seed 

51 

52 @classmethod 

53 def setUpClass(cls): 

54 if PRINT_PROFILE: 

55 cls.profile = Profile() 

56 cls.profile.enable() 

57 

58 def tearDown(self): 

59 if self.root is not None and os.path.exists(self.root): 

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

61 

62 @classmethod 

63 def tearDownClass(cls): 

64 if PRINT_PROFILE: 

65 stats = Stats(cls.profile) 

66 stats.strip_dirs() 

67 stats.sort_stats("cumtime") 

68 stats.print_stats() 

69 

70 def checkInstrumentWithRegistry(self, cls, testRaw): 

71 

72 Butler.makeRepo(self.root) 

73 butler = Butler(self.root, run="tests") 

74 instrument = cls() 

75 scFactory = StorageClassFactory() 

76 

77 # Check instrument class and metadata translator agree on 

78 # instrument name -- use the raw formatter to do the file reading 

79 rawFormatterClass = instrument.getRawFormatter({}) 

80 formatter = rawFormatterClass(FileDescriptor(Location(DATAROOT, testRaw), StorageClass("x"))) 

81 obsInfo = formatter.observationInfo 

82 self.assertEqual(instrument.getName(), obsInfo.instrument) 

83 

84 # Add Instrument, Detector, and PhysicalFilter entries to the 

85 # Butler Registry. 

86 instrument.register(butler.registry) 

87 

88 # Define a DatasetType for the cameraGeom.Camera, which can be 

89 # accessed just by identifying its Instrument. 

90 # A real-world Camera DatasetType should be identified by a 

91 # validity range as well. 

92 cameraDatasetType = DatasetType("camera", dimensions=["instrument"], 

93 storageClass=scFactory.getStorageClass("Camera"), 

94 universe=butler.registry.dimensions) 

95 butler.registry.registerDatasetType(cameraDatasetType) 

96 

97 # Define a DatasetType for cameraGeom.Detectors, which can be 

98 # accessed by identifying its Instrument and (Butler) Detector. 

99 # A real-world Detector DatasetType probably doesn't need to exist, 

100 # as it would just duplicate information in the Camera, and 

101 # reading a full Camera just to get a single Detector should be 

102 # plenty efficient. 

103 detectorDatasetType = DatasetType("detector", dimensions=["instrument", "detector"], 

104 storageClass=scFactory.getStorageClass("Detector"), 

105 universe=butler.registry.dimensions) 

106 butler.registry.registerDatasetType(detectorDatasetType) 

107 

108 # Put and get the Camera. 

109 dataId = dict(instrument=instrument.instrument) 

110 butler.put(instrument.getCamera(), "camera", dataId=dataId) 

111 camera = butler.get("camera", dataId) 

112 # Full camera comparisons are *slow*; just compare names. 

113 self.assertEqual(instrument.getCamera().getName(), camera.getName()) 

114 

115 # Put and get a random subset of the Detectors. 

116 allDetectors = list(instrument.getCamera()) 

117 numDetectors = min(3, len(allDetectors)) 

118 someDetectors = [allDetectors[i] for i in self.rng.choice(len(allDetectors), 

119 size=numDetectors, replace=False)] 

120 for cameraGeomDetector in someDetectors: 

121 # Right now we only support integer detector IDs in data IDs; 

122 # support for detector names and groups (i.e. rafts) is 

123 # definitely planned but not yet implemented. 

124 dataId = dict(instrument=instrument.instrument, detector=cameraGeomDetector.getId()) 

125 butler.put(cameraGeomDetector, "detector", dataId=dataId) 

126 cameraGeomDetector2 = butler.get("detector", dataId=dataId) 

127 # Full detector comparisons are *slow*; just compare names and 

128 # serials. 

129 self.assertEqual(cameraGeomDetector.getName(), cameraGeomDetector2.getName()) 

130 self.assertEqual(cameraGeomDetector.getSerial(), cameraGeomDetector2.getSerial()) 

131 

132 def testLsstCam(self): 

133 self.checkInstrumentWithRegistry(LsstCam, 

134 "lsstCam/raw/6489D/R10/3019032200002-R10-S22-det035.fits") 

135 

136 def testComCam(self): 

137 self.checkInstrumentWithRegistry(LsstComCam, 

138 "comCam/raw/unknown/R22/3019053000001-R22-S00-det000.fits") 

139 

140 def testImSim(self): 

141 self.checkInstrumentWithRegistry(LsstImSim, 

142 "imsim/raw/204595/R11/00204595-R11-S20-det042.fits") 

143 

144 def testPhoSim(self): 

145 self.checkInstrumentWithRegistry(LsstPhoSim, 

146 "phosim/raw/204595/R11/00204595-R11-S20-det042.fits") 

147 

148 def testTs8(self): 

149 self.checkInstrumentWithRegistry(LsstTS8, 

150 "ts8/raw/6006D/201807241028453-RTM-010-S11-det067.fits") 

151 

152 def testTs3(self): 

153 self.checkInstrumentWithRegistry(LsstTS3, 

154 "ts3/raw/2016-07-22/201607220607067-R071-S00-det071.fits") 

155 

156 def testUcdCam(self): 

157 self.checkInstrumentWithRegistry(LsstUCDCam, 

158 "ucd/raw/2018-12-05/20181205233148-S00-det000.fits") 

159 

160 def testLatiss(self): 

161 self.checkInstrumentWithRegistry(Latiss, 

162 "latiss/raw/2018-09-20/3018092000065-det000.fits") 

163 

164 

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

166 unittest.main()