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_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 <https://www.gnu.org/licenses/>. 

21 

22""" 

23Test utilities for obs_base and concrete obs* packages. 

24""" 

25 

26__all__ = ( 

27 "ObsTests", 

28 "make_ramp_array", 

29 "make_ramp_exposure_trimmed", 

30 "make_ramp_exposure_untrimmed", 

31) 

32 

33import numpy as np 

34 

35from lsst.log import Log 

36 

37from lsst.afw.image import Exposure 

38from lsst.afw.cameraGeom.utils import calcRawCcdBBox 

39 

40from . import butler_tests 

41from . import mapper_tests 

42from . import camera_tests 

43 

44__all__ = ["ObsTests"] 

45 

46 

47class ObsTests(butler_tests.ButlerGetTests, mapper_tests.MapperTests, 

48 camera_tests.CameraTests): 

49 """Aggregator class for all of the obs_* test classes. 

50 

51 Inherit from this class, then lsst.utils.tests.TestCase, in that order. 

52 

53 Example subclass: 

54 

55 .. code-block:: python 

56 

57 class TestObs(lsst.obs.base.tests.ObsTests, lsst.utils.tests.TestCase): 

58 def setUp(self): 

59 self.setUp_tests(...) 

60 self.setUp_butler_get(...) 

61 self.setUp_mapper(...) 

62 self.setUp_camera(...) 

63 

64 Notes 

65 ----- 

66 The intention is for each obs package to have a single test class that 

67 inherits from this collector class, thus "automatically" getting all new 

68 tests. If those tests require setup that isn't defined in a given obs 

69 package, that obs package will be broken until updated. This is 

70 intentional, as a way to prevent obs packages from falling behind out of 

71 neglect. 

72 """ 

73 

74 def setUp_tests(self, butler, mapper, dataIds): 

75 """Set up the necessary shared variables used by multiple tests. 

76 

77 Parameters 

78 ---------- 

79 butler: lsst.daf.persistence.Butler 

80 A butler object, instantiated on the testdata repository for the 

81 obs package being tested. 

82 mapper: lsst.obs.CameraMapper 

83 A CameraMapper object for your camera, instantiated on the testdata 

84 repository the obs package being tested. 

85 dataIds: dict 

86 dictionary of (exposure name): (dataId of that exposure in the 

87 testdata repository), with unittest.SkipTest as the value for any 

88 exposures you do not have/do not want to test. It must contain a 

89 valid 'raw' dataId, in addition to 'bias','flat','dark', which may 

90 be set to SkipTest. For example:: 

91 

92 self.dataIds = {'raw': {'visit': 1, 'filter': 'g'}, 

93 'bias': {'visit': 1}, 

94 'flat': {'visit': 1}, 

95 'dark': unittest.SkipTest 

96 } 

97 """ 

98 self.butler = butler 

99 self.mapper = mapper 

100 self.dataIds = dataIds 

101 self.log = Log.getLogger('ObsTests') 

102 

103 def tearDown(self): 

104 del self.butler 

105 del self.mapper 

106 super(ObsTests, self).tearDown() 

107 

108 

109def make_ramp_array(bbox, pedestal): 

110 """Make a 2-d ramp array. 

111 

112 Parameters 

113 ---------- 

114 bbox : `lsst.geom.Box2I` 

115 Bounding box for the array. 

116 pedestal : `int` 

117 Minimum value for the ramp. 

118 

119 Returns 

120 ------- 

121 ramp : `np.ndarray` 

122 A 2-d array with shape ``(bbox.getHeight(), bbox.getWidth())``. 

123 end : `int` 

124 One past the maximum value in the ramp (for use as the 

125 pedestal for another box). 

126 """ 

127 end = pedestal + bbox.getArea() 

128 return np.arange(pedestal, end).reshape(bbox.getHeight(), bbox.getWidth()), end 

129 

130 

131def make_ramp_exposure_untrimmed(detector, dtype=None): 

132 """Create an untrimmed, assembled exposure with different ramps for 

133 each sub-amplifier region. 

134 

135 Parameters 

136 ---------- 

137 detector : `lsst.afw.cameraGeom.Detector` 

138 Detector object that the new exposure should match. Must have all amp 

139 flips and offsets set to False/zero (i.e. represent an already- 

140 assembled image). 

141 dtype : `np.dtype`, optional 

142 Type of the new exposure. Defaults to ``int32``. 

143 

144 Returns 

145 ------- 

146 exposure : `lsst.afw.image.Exposure` 

147 New exposure with the given detector attached. 

148 """ 

149 if dtype is None: 

150 dtype = np.dtype(np.int32) 

151 ramp_exposure = Exposure(calcRawCcdBBox(detector), dtype=np.dtype(dtype)) 

152 ramp_exposure.setDetector(detector) 

153 pedestal = 0 

154 for amp in detector: 

155 for name in ("HorizontalOverscan", "VerticalOverscan", "Prescan", "Data"): 

156 bbox = getattr(amp, f"getRaw{name}BBox")() 

157 ramp, pedestal = make_ramp_array(bbox, pedestal) 

158 ramp_exposure.image[bbox].array[:, :] = ramp 

159 return ramp_exposure 

160 

161 

162def make_ramp_exposure_trimmed(detector, dtype=None): 

163 """Create a trimmed, assembled exposure with different ramps for 

164 each amplifier region. 

165 

166 Parameters 

167 ---------- 

168 detector : `lsst.afw.cameraGeom.Detector` 

169 Detector object that the new exposure should match. 

170 dtype : `np.dtype`, optional 

171 Type of the new exposure. Defaults to ``int32``. 

172 

173 Returns 

174 ------- 

175 exposure : `lsst.afw.image.Exposure` 

176 New exposure with the given detector attached. 

177 """ 

178 if dtype is None: 

179 dtype = np.dtype(np.int32) 

180 ramp_exposure = Exposure(detector.getBBox(), dtype=np.dtype(dtype)) 

181 ramp_exposure.setDetector(detector) 

182 pedestal = 0 

183 for amp in detector: 

184 ramp, pedestal = make_ramp_array(amp.getBBox(), pedestal) 

185 ramp_exposure.image[amp.getBBox()].array[:, :] = ramp 

186 return ramp_exposure