Coverage for tests/test_makeSurveyPropertyMaps.py: 19%

127 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2023-01-28 02:53 -0800

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 HealSparsePropertyMapTask. 

23""" 

24import unittest 

25import numpy as np 

26import healsparse as hsp 

27import esutil 

28import warnings 

29 

30import lsst.utils.tests 

31import lsst.daf.butler 

32import lsst.afw.table as afwTable 

33import lsst.afw.geom as afwGeom 

34import lsst.afw.image as afwImage 

35from lsst.skymap.discreteSkyMap import DiscreteSkyMap 

36import lsst.geom as geom 

37 

38from lsst.pipe.tasks.healSparseMapping import HealSparsePropertyMapTask 

39from lsst.pipe.tasks.healSparseMappingProperties import (register_property_map, 

40 BasePropertyMap) 

41 

42from surveyPropertyMapsTestUtils import (makeMockVisitSummary, 

43 MockVisitSummaryReference, 

44 MockCoaddReference, 

45 MockInputMapReference) 

46 

47 

48# Test creation of an arbitrary new property map by registering it here 

49# and using it in the test class. 

50@register_property_map("dist_times_psfarea") 

51class DistTimesPsfAreaPropertyMap(BasePropertyMap): 

52 """Property map to compute the distance from the boresight center 

53 by the psf area. Do not try this at home.""" 

54 requires_psf = True 

55 

56 def _compute(self, row, ra, dec, scalings, psf_array=None): 

57 boresight = row.getVisitInfo().getBoresightRaDec() 

58 dist = esutil.coords.sphdist(ra, dec, 

59 boresight.getRa().asDegrees(), boresight.getDec().asDegrees()) 

60 return np.deg2rad(dist)*psf_array['psf_area'] 

61 

62 

63class HealSparsePropertyMapTaskTestCase(lsst.utils.tests.TestCase): 

64 """Test of HealSparsePropertyMapTask. 

65 

66 These tests bypass the middleware used for accessing data and 

67 managing Task execution. 

68 """ 

69 def setUp(self): 

70 tract = 0 

71 band = 'r' 

72 patch = 0 

73 visits = [100, 101] 

74 # Good to test crossing 0. 

75 ra_center = 0.0 

76 dec_center = -45.0 

77 pixel_scale = 0.2 

78 coadd_zp = 27.0 

79 

80 # Generate a mock skymap with one patch 

81 config = DiscreteSkyMap.ConfigClass() 

82 config.raList = [ra_center] 

83 config.decList = [dec_center] 

84 config.radiusList = [150*pixel_scale/3600.] 

85 config.patchInnerDimensions = (350, 350) 

86 config.patchBorder = 50 

87 config.tractOverlap = 0.0 

88 config.pixelScale = pixel_scale 

89 sky_map = DiscreteSkyMap(config) 

90 

91 visit_summaries = [makeMockVisitSummary(visit, 

92 ra_center=ra_center, 

93 dec_center=dec_center) 

94 for visit in visits] 

95 visit_summary_refs = [MockVisitSummaryReference(visit_summary, visit) 

96 for visit_summary, visit in zip(visit_summaries, visits)] 

97 self.visit_summary_dict = {visit: ref.get() 

98 for ref, visit in zip(visit_summary_refs, visits)} 

99 

100 # Generate an input map. Note that this does not need to be consistent 

101 # with the visit_summary projections, we're just tracking values. 

102 with warnings.catch_warnings(): 

103 # Healsparse will emit a warning if nside coverage is greater than 

104 # 128. In the case of generating patch input maps, and not global 

105 # maps, high nside coverage works fine, so we can suppress this 

106 # warning. 

107 warnings.simplefilter("ignore") 

108 input_map = hsp.HealSparseMap.make_empty(nside_coverage=256, 

109 nside_sparse=32768, 

110 dtype=hsp.WIDE_MASK, 

111 wide_mask_maxbits=len(visits)*2) 

112 

113 patch_poly = afwGeom.Polygon(geom.Box2D(sky_map[tract][patch].getOuterBBox())) 

114 sph_pts = sky_map[tract].getWcs().pixelToSky(patch_poly.convexHull().getVertices()) 

115 patch_poly_radec = np.array([(sph.getRa().asDegrees(), sph.getDec().asDegrees()) 

116 for sph in sph_pts]) 

117 poly = hsp.Polygon(ra=patch_poly_radec[: -1, 0], 

118 dec=patch_poly_radec[: -1, 1], 

119 value=[0]) 

120 poly_pixels = poly.get_pixels(nside=input_map.nside_sparse) 

121 # The input map has full coverage for bits 0 and 1 

122 input_map.set_bits_pix(poly_pixels, [0]) 

123 input_map.set_bits_pix(poly_pixels, [1]) 

124 

125 input_map_ref = MockInputMapReference(input_map, patch=patch, tract=tract) 

126 self.input_map_dict = {patch: input_map_ref} 

127 

128 coadd = afwImage.ExposureF(sky_map[tract][patch].getOuterBBox(), 

129 sky_map[tract].getWcs()) 

130 instFluxMag0 = 10.**(coadd_zp/2.5) 

131 pc = afwImage.makePhotoCalibFromCalibZeroPoint(instFluxMag0) 

132 coadd.setPhotoCalib(pc) 

133 

134 # Mock the coadd input ccd table 

135 schema = afwTable.ExposureTable.makeMinimalSchema() 

136 schema.addField("ccd", type="I") 

137 schema.addField("visit", type="I") 

138 schema.addField("weight", type="F") 

139 ccds = afwTable.ExposureCatalog(schema) 

140 ccds.resize(2) 

141 ccds['id'] = np.arange(2) 

142 ccds['visit'][0] = visits[0] 

143 ccds['visit'][1] = visits[1] 

144 ccds['ccd'][0] = 0 

145 ccds['ccd'][1] = 1 

146 ccds['weight'] = 10.0 

147 for ccd_row in ccds: 

148 summary = self.visit_summary_dict[ccd_row['visit']].find(ccd_row['ccd']) 

149 ccd_row.setWcs(summary.getWcs()) 

150 ccd_row.setPsf(summary.getPsf()) 

151 ccd_row.setBBox(summary.getBBox()) 

152 ccd_row.setPhotoCalib(summary.getPhotoCalib()) 

153 

154 inputs = afwImage.CoaddInputs() 

155 inputs.ccds = ccds 

156 coadd.getInfo().setCoaddInputs(inputs) 

157 

158 coadd_ref = MockCoaddReference(coadd, patch=patch, tract=tract) 

159 self.coadd_dict = {patch: coadd_ref} 

160 

161 self.tract = tract 

162 self.band = band 

163 self.sky_map = sky_map 

164 self.input_map = input_map 

165 

166 def testPropertyMapCreation(self): 

167 """Test creation of property maps.""" 

168 config = HealSparsePropertyMapTask.ConfigClass() 

169 

170 # Add our new test map to the set of maps 

171 config.property_maps.names |= ['dist_times_psfarea'] 

172 config.property_maps['dist_times_psfarea'].do_min = True 

173 config.property_maps['dist_times_psfarea'].do_max = True 

174 config.property_maps['dist_times_psfarea'].do_mean = True 

175 

176 property_task = HealSparsePropertyMapTask(config=config) 

177 

178 property_task.run(self.sky_map, 

179 self.tract, 

180 self.band, 

181 self.coadd_dict, 

182 self.input_map_dict, 

183 self.visit_summary_dict) 

184 

185 valid_pixels = self.input_map.valid_pixels 

186 

187 # Verify each map exists and has the correct pixels set. 

188 for name, map_config, PropertyMapClass in config.property_maps.apply(): 

189 self.assertTrue(name in property_task.property_maps) 

190 property_map = property_task.property_maps[name] 

191 if map_config.do_min: 

192 self.assertTrue(hasattr(property_map, 'min_map')) 

193 np.testing.assert_array_equal(property_map.min_map.valid_pixels, valid_pixels) 

194 else: 

195 self.assertFalse(hasattr(property_map, 'min_map')) 

196 if map_config.do_max: 

197 self.assertTrue(hasattr(property_map, 'max_map')) 

198 np.testing.assert_array_equal(property_map.max_map.valid_pixels, valid_pixels) 

199 else: 

200 self.assertFalse(hasattr(property_map, 'max_map')) 

201 if map_config.do_mean: 

202 self.assertTrue(hasattr(property_map, 'mean_map')) 

203 np.testing.assert_array_equal(property_map.mean_map.valid_pixels, valid_pixels) 

204 else: 

205 self.assertFalse(hasattr(property_map, 'mean_map')) 

206 if map_config.do_weighted_mean: 

207 self.assertTrue(hasattr(property_map, 'weighted_mean_map')) 

208 np.testing.assert_array_equal(property_map.weighted_mean_map.valid_pixels, valid_pixels) 

209 else: 

210 self.assertFalse(hasattr(property_map, 'weighted_mean_map')) 

211 if map_config.do_sum: 

212 self.assertTrue(hasattr(property_map, 'sum_map')) 

213 np.testing.assert_array_equal(property_map.sum_map.valid_pixels, valid_pixels) 

214 else: 

215 self.assertFalse(hasattr(property_map, 'sum_map')) 

216 

217 

218class MyMemoryTestCase(lsst.utils.tests.MemoryTestCase): 

219 pass 

220 

221 

222def setup_module(module): 

223 lsst.utils.tests.init() 

224 

225 

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

227 lsst.utils.tests.init() 

228 unittest.main()