Coverage for tests/test_hips.py: 24%

100 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2023-03-23 02:49 -0700

1# This file is part of pipe_tasks. 

2# 

3# LSST Data Management System 

4# This product includes software developed by the 

5# LSST Project (http://www.lsst.org/). 

6# See COPYRIGHT file at the top of the source tree. 

7# 

8# This program is free software: you can redistribute it and/or modify 

9# it under the terms of the GNU General Public License as published by 

10# the Free Software Foundation, either version 3 of the License, or 

11# (at your option) any later version. 

12# 

13# This program is distributed in the hope that it will be useful, 

14# but WITHOUT ANY WARRANTY; without even the implied warranty of 

15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 

16# GNU General Public License for more details. 

17# 

18# You should have received a copy of the LSST License Statement and 

19# the GNU General Public License along with this program. If not, 

20# see <https://www.lsstcorp.org/LegalNotices/>. 

21# 

22"""Test HIPS code.""" 

23import unittest 

24import numpy as np 

25import hpgeom as hpg 

26 

27import lsst.utils.tests 

28import lsst.daf.butler 

29import lsst.afw.image 

30import lsst.skymap 

31import lsst.geom 

32 

33from lsst.pipe.tasks.hips import ( 

34 HighResolutionHipsTask, 

35 HighResolutionHipsConfig, 

36 HighResolutionHipsConnections 

37) 

38 

39 

40class MockCoaddImageHandle(lsst.daf.butler.DeferredDatasetHandle): 

41 """Simple object that looks like a Gen3 deferred dataset handle 

42 to an exposure. 

43 

44 Parameters 

45 ---------- 

46 exposure : `lsst.afw.image.ExposureF` 

47 Exposure to hold. 

48 """ 

49 def __init__(self, exposure): 

50 self.exposure = exposure 

51 

52 def get(self, **kwargs): 

53 """Retrieve the dataset using the API of the Gen3 Butler. 

54 

55 Returns 

56 ------- 

57 exposure : `lsst.afw.image.ExposureF` 

58 Exposure held in mock handle. 

59 """ 

60 return self.exposure 

61 

62 @property 

63 def dataId(self): 

64 return {'visit': 0, 'detector': 0} 

65 

66 

67class HipsTestCase(unittest.TestCase): 

68 def test_hips_single(self): 

69 """Test creating a single HIPS image.""" 

70 np.random.seed(12345) 

71 

72 config = HighResolutionHipsConfig() 

73 

74 skymap = self._make_skymap() 

75 

76 tract = 9597 

77 patch = 50 

78 tract_info = skymap[tract] 

79 patch_info = tract_info[patch] 

80 

81 exposure = self._make_noise_exposure(patch_info) 

82 handles = [MockCoaddImageHandle(exposure)] 

83 

84 center = patch_info.wcs.pixelToSky(patch_info.inner_bbox.getCenter()) 

85 pixel = self._get_pixel(2**config.hips_order, center) 

86 

87 hips_task = HighResolutionHipsTask(config=config) 

88 output = hips_task.run([pixel], handles) 

89 

90 # Check that all the pixels are filled. 

91 npix = (np.isfinite(output.hips_exposures[pixel].image.array.ravel()).sum()) 

92 self.assertEqual(npix, output.hips_exposures[pixel].image.array.size) 

93 

94 # Check that metadata is correct 

95 self.assertEqual(output.hips_exposures[pixel].getPhotoCalib(), exposure.getPhotoCalib()) 

96 self.assertEqual(output.hips_exposures[pixel].getFilter(), exposure.getFilter()) 

97 

98 def test_hips_double(self): 

99 """Test creating a HIPS image from two neighboring patches.""" 

100 np.random.seed(12345) 

101 

102 config = HighResolutionHipsConfig() 

103 

104 skymap = self._make_skymap() 

105 

106 tract = 9597 

107 patches = [50, 51] 

108 tract_info = skymap[tract] 

109 

110 handles = [] 

111 centers = [] 

112 for patch in patches: 

113 patch_info = tract_info[patch] 

114 exposure = self._make_noise_exposure(patch_info) 

115 handles.append(MockCoaddImageHandle(exposure)) 

116 centers.append(patch_info.wcs.pixelToSky(patch_info.inner_bbox.getCenter())) 

117 

118 center = lsst.geom.SpherePoint( 

119 (centers[0].getRa().asDegrees() + centers[1].getRa().asDegrees())/2.*lsst.geom.degrees, 

120 (centers[0].getDec().asDegrees() + centers[1].getDec().asDegrees())/2.*lsst.geom.degrees 

121 ) 

122 pixel = self._get_pixel(2**config.hips_order, center) 

123 

124 # Just transform one, make sure it falls off the edge. 

125 hips_task = HighResolutionHipsTask(config=config) 

126 output = hips_task.run([pixel], [handles[0]]) 

127 

128 # Check that not all the pixels are filled. 

129 npix = (np.isfinite(output.hips_exposures[pixel].image.array.ravel()).sum()) 

130 self.assertLess(npix, output.hips_exposures[pixel].image.array.size) 

131 

132 # Transform both. 

133 hips_task = HighResolutionHipsTask(config=config) 

134 output = hips_task.run([pixel], handles) 

135 

136 # Check that all the pixels are filled. 

137 npix = (np.isfinite(output.hips_exposures[pixel].image.array.ravel()).sum()) 

138 self.assertEqual(npix, output.hips_exposures[pixel].image.array.size) 

139 

140 def test_hips_none(self): 

141 """Test making a HIPS image with no overlapping inputs.""" 

142 np.random.seed(12345) 

143 

144 config = HighResolutionHipsConfig() 

145 

146 skymap = self._make_skymap() 

147 

148 tract = 9597 

149 patch = 50 

150 tract_info = skymap[tract] 

151 patch_info = tract_info[patch] 

152 

153 exposure = self._make_noise_exposure(patch_info) 

154 handles = [MockCoaddImageHandle(exposure)] 

155 

156 pixel = 0 

157 

158 hips_task = HighResolutionHipsTask(config=config) 

159 output = hips_task.run([pixel], handles) 

160 

161 # Check that there is no returned image 

162 self.assertEqual(len(output.hips_exposures), 0) 

163 

164 def test_hips_connections(self): 

165 """Test that the HIPS connections validate properly.""" 

166 config = HighResolutionHipsConfig() 

167 

168 # Test that the connections validate 

169 _ = HighResolutionHipsConnections(config=config) 

170 

171 # Test that changing hips_order will break things because of the 

172 # dimensions mismatch. 

173 config.hips_order = 5 

174 with self.assertRaises(ValueError): 

175 _ = HighResolutionHipsConnections(config=config) 

176 

177 # I'd like to change the dimensions but I don't know how to do that. 

178 

179 def _make_noise_exposure(self, patch_info): 

180 """Make a simple noise exposure. 

181 

182 Parameters 

183 ---------- 

184 patch_info : `lsst.skymap.PatchInfo` 

185 Patch info to use to make the exposure. 

186 

187 Returns 

188 ------- 

189 exposure : `lsst.afw.image.ExposureF` 

190 Noise exposure. 

191 """ 

192 exposure = lsst.afw.image.ExposureF(patch_info.outer_bbox) 

193 exposure.image.array[:, :] = np.random.normal(scale=1.0, size=exposure.image.array.shape) 

194 exposure.setWcs(patch_info.wcs) 

195 exposure.setPhotoCalib(lsst.afw.image.PhotoCalib(calibrationMean=1.0)) 

196 exposure.setFilter(lsst.afw.image.FilterLabel(band='i')) 

197 

198 return exposure 

199 

200 def _make_skymap(self): 

201 """Make a testing skymap. 

202 

203 Returns 

204 ------- 

205 skymap : `lsst.skymap.RingsSkyMap` 

206 """ 

207 

208 # Generate a skymap 

209 skymap_config = lsst.skymap.ringsSkyMap.RingsSkyMapConfig() 

210 skymap_config.numRings = 120 

211 skymap_config.projection = "TAN" 

212 skymap_config.tractOverlap = 1.0/60 

213 skymap_config.pixelScale = 0.168 

214 return lsst.skymap.ringsSkyMap.RingsSkyMap(skymap_config) 

215 

216 def _get_pixel(self, nside, sphpoint): 

217 """Get the pixel value from a spherepoint. 

218 

219 Parameters 

220 ---------- 

221 nside : `int` 

222 Healpix nside 

223 sphpoint : `lsst.geom.SpherePoint` 

224 Point to compute pixel value. 

225 

226 Returns 

227 ------- 

228 pixel : `int` 

229 Healpix pixel (nest ordering) 

230 """ 

231 pixel = hpg.angle_to_pixel( 

232 nside, 

233 sphpoint.getRa().asDegrees(), 

234 sphpoint.getDec().asDegrees(), 

235 ) 

236 return pixel 

237 

238 

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

240 unittest.main()