Coverage for tests/test_hips.py: 26%

99 statements  

« prev     ^ index     » next       coverage.py v6.4.4, created at 2022-08-25 01:38 -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 def dataId(self): 

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

64 

65 

66class HipsTestCase(unittest.TestCase): 

67 def test_hips_single(self): 

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

69 np.random.seed(12345) 

70 

71 config = HighResolutionHipsConfig() 

72 

73 skymap = self._make_skymap() 

74 

75 tract = 9597 

76 patch = 50 

77 tract_info = skymap[tract] 

78 patch_info = tract_info[patch] 

79 

80 exposure = self._make_noise_exposure(patch_info) 

81 handles = [MockCoaddImageHandle(exposure)] 

82 

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

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

85 

86 hips_task = HighResolutionHipsTask(config=config) 

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

88 

89 # Check that all the pixels are filled. 

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

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

92 

93 # Check that metadata is correct 

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

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

96 

97 def test_hips_double(self): 

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

99 np.random.seed(12345) 

100 

101 config = HighResolutionHipsConfig() 

102 

103 skymap = self._make_skymap() 

104 

105 tract = 9597 

106 patches = [50, 51] 

107 tract_info = skymap[tract] 

108 

109 handles = [] 

110 centers = [] 

111 for patch in patches: 

112 patch_info = tract_info[patch] 

113 exposure = self._make_noise_exposure(patch_info) 

114 handles.append(MockCoaddImageHandle(exposure)) 

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

116 

117 center = lsst.geom.SpherePoint( 

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

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

120 ) 

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

122 

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

124 hips_task = HighResolutionHipsTask(config=config) 

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

126 

127 # Check that not all the pixels are filled. 

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

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

130 

131 # Transform both. 

132 hips_task = HighResolutionHipsTask(config=config) 

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

134 

135 # Check that all the pixels are filled. 

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

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

138 

139 def test_hips_none(self): 

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

141 np.random.seed(12345) 

142 

143 config = HighResolutionHipsConfig() 

144 

145 skymap = self._make_skymap() 

146 

147 tract = 9597 

148 patch = 50 

149 tract_info = skymap[tract] 

150 patch_info = tract_info[patch] 

151 

152 exposure = self._make_noise_exposure(patch_info) 

153 handles = [MockCoaddImageHandle(exposure)] 

154 

155 pixel = 0 

156 

157 hips_task = HighResolutionHipsTask(config=config) 

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

159 

160 # Check that there is no returned image 

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

162 

163 def test_hips_connections(self): 

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

165 config = HighResolutionHipsConfig() 

166 

167 # Test that the connections validate 

168 _ = HighResolutionHipsConnections(config=config) 

169 

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

171 # dimensions mismatch. 

172 config.hips_order = 5 

173 with self.assertRaises(ValueError): 

174 _ = HighResolutionHipsConnections(config=config) 

175 

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

177 

178 def _make_noise_exposure(self, patch_info): 

179 """Make a simple noise exposure. 

180 

181 Parameters 

182 ---------- 

183 patch_info : `lsst.skymap.PatchInfo` 

184 Patch info to use to make the exposure. 

185 

186 Returns 

187 ------- 

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

189 Noise exposure. 

190 """ 

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

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

193 exposure.setWcs(patch_info.wcs) 

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

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

196 

197 return exposure 

198 

199 def _make_skymap(self): 

200 """Make a testing skymap. 

201 

202 Returns 

203 ------- 

204 skymap : `lsst.skymap.RingsSkyMap` 

205 """ 

206 

207 # Generate a skymap 

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

209 skymap_config.numRings = 120 

210 skymap_config.projection = "TAN" 

211 skymap_config.tractOverlap = 1.0/60 

212 skymap_config.pixelScale = 0.168 

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

214 

215 def _get_pixel(self, nside, sphpoint): 

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

217 

218 Parameters 

219 ---------- 

220 nside : `int` 

221 Healpix nside 

222 sphpoint : `lsst.geom.SpherePoint` 

223 Point to compute pixel value. 

224 

225 Returns 

226 ------- 

227 pixel : `int` 

228 Healpix pixel (nest ordering) 

229 """ 

230 pixel = hpg.angle_to_pixel( 

231 nside, 

232 sphpoint.getRa().asDegrees(), 

233 sphpoint.getDec().asDegrees(), 

234 ) 

235 return pixel 

236 

237 

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

239 unittest.main()