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

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 

22import numpy as np 

23import unittest 

24import unittest.mock 

25 

26from lsst.afw.cameraGeom.testUtils import DetectorWrapper 

27import lsst.afw.geom as afwGeom 

28import lsst.afw.image as afwImage 

29import lsst.afw.image.utils as afwImageUtils 

30import lsst.afw.table as afwTable 

31import lsst.daf.base as dafBase 

32import lsst.meas.algorithms as measAlg 

33from lsst.ap.association import \ 

34 DiaForcedSourceTask, \ 

35 make_dia_object_schema 

36import lsst.utils.tests 

37 

38 

39def create_test_dia_objects(n_points, wcs, startPos=100): 

40 """Create dummy DIASources or DIAObjects for use in our tests. 

41 

42 Parameters 

43 ---------- 

44 n_points : `int` 

45 Number of DiaObject test points to create. 

46 wcs : `lsst.afw.geom.SkyWcs` 

47 Wcs to convert RA/Dec to pixel x/y. 

48 startPos : `int` 

49 Start position to iterate from when creating test DiaObjects 

50 

51 Returns 

52 ------- 

53 test_points : `lsst.afw.table.SourceCatalog` 

54 Catalog of points to test. 

55 """ 

56 objects = afwTable.SourceCatalog(make_dia_object_schema()) 

57 

58 for src_idx in range(n_points): 

59 src = objects.addNew() 

60 src['id'] = src_idx 

61 src.setCoord(wcs.pixelToSky(startPos + src_idx, 

62 startPos + src_idx)) 

63 

64 return objects 

65 

66 

67class TestDiaForcedSource(unittest.TestCase): 

68 

69 def setUp(self): 

70 # CFHT Filters from the camera mapper. 

71 self.filter_names = ["u", "g", "r", "i", "z"] 

72 afwImageUtils.resetFilters() 

73 afwImageUtils.defineFilter('u', lambdaEff=374, alias="u.MP9301") 

74 afwImageUtils.defineFilter('g', lambdaEff=487, alias="g.MP9401") 

75 afwImageUtils.defineFilter('r', lambdaEff=628, alias="r.MP9601") 

76 afwImageUtils.defineFilter('i', lambdaEff=778, alias="i.MP9701") 

77 afwImageUtils.defineFilter('z', lambdaEff=1170, alias="z.MP9801") 

78 

79 # metadata taken from CFHT data 

80 # v695856-e0/v695856-e0-c000-a00.sci_img.fits 

81 self.metadata = dafBase.PropertySet() 

82 

83 self.metadata.set("SIMPLE", "T") 

84 self.metadata.set("BITPIX", -32) 

85 self.metadata.set("NAXIS", 2) 

86 self.metadata.set("NAXIS1", 1024) 

87 self.metadata.set("NAXIS2", 1153) 

88 self.metadata.set("RADECSYS", 'FK5') 

89 self.metadata.set("EQUINOX", 2000.) 

90 

91 self.metadata.setDouble("CRVAL1", 215.604025685476) 

92 self.metadata.setDouble("CRVAL2", 53.1595451514076) 

93 self.metadata.setDouble("CRPIX1", 1109.99981456774) 

94 self.metadata.setDouble("CRPIX2", 560.018167811613) 

95 self.metadata.set("CTYPE1", 'RA---SIN') 

96 self.metadata.set("CTYPE2", 'DEC--SIN') 

97 

98 self.metadata.setDouble("CD1_1", 5.10808596133527E-05) 

99 self.metadata.setDouble("CD1_2", 1.85579539217196E-07) 

100 self.metadata.setDouble("CD2_2", -5.10281493481982E-05) 

101 self.metadata.setDouble("CD2_1", -8.27440751733828E-07) 

102 

103 self.wcs = afwGeom.makeSkyWcs(self.metadata) 

104 

105 self.calibration = 10000 

106 self.calibrationErr = 100 

107 self.exposureId = 1234 

108 self.exposureTime = 200. 

109 self.imageSize = [1024, 1153] 

110 self.dateTime = "2014-05-13T17:00:00.000000000" 

111 

112 # Make images with one source in them and distinct values and 

113 # variance for each image. 

114 # Direct Image 

115 source_image = afwImage.MaskedImageF( 

116 lsst.geom.ExtentI(self.imageSize[0] + 1, self.imageSize[1] + 1)) 

117 source_image.image[100, 100, afwImage.LOCAL] = 10 

118 source_image.getVariance().set(1) 

119 bbox = lsst.geom.BoxI( 

120 lsst.geom.PointI(1, 1), 

121 lsst.geom.ExtentI(self.imageSize[0], 

122 self.imageSize[1])) 

123 masked_image = afwImage.MaskedImageF(source_image, bbox, afwImage.LOCAL) 

124 self.exposure = afwImage.makeExposure(masked_image, self.wcs) 

125 

126 detector = DetectorWrapper( 

127 id=23, bbox=self.exposure.getBBox()).detector 

128 visit = afwImage.VisitInfo( 

129 exposureId=self.exposureId, 

130 exposureTime=self.exposureTime, 

131 date=dafBase.DateTime(self.dateTime, 

132 dafBase.DateTime.Timescale.TAI)) 

133 self.exposure.setDetector(detector) 

134 self.exposure.getInfo().setVisitInfo(visit) 

135 self.exposure.setFilter(afwImage.Filter('g')) 

136 self.exposure.setPhotoCalib(afwImage.PhotoCalib(self.calibration, self.calibrationErr)) 

137 

138 # Difference Image 

139 source_image = afwImage.MaskedImageF( 

140 lsst.geom.ExtentI(self.imageSize[0] + 1, self.imageSize[1] + 1)) 

141 source_image.image[100, 100, afwImage.LOCAL] = 20 

142 source_image.getVariance().set(2) 

143 bbox = lsst.geom.BoxI( 

144 lsst.geom.PointI(1, 1), 

145 lsst.geom.ExtentI(self.imageSize[0], 

146 self.imageSize[1])) 

147 masked_image = afwImage.MaskedImageF(source_image, bbox, afwImage.LOCAL) 

148 self.diffim = afwImage.makeExposure(masked_image, self.wcs) 

149 self.diffim.setDetector(detector) 

150 self.diffim.getInfo().setVisitInfo(visit) 

151 self.diffim.setFilter(afwImage.Filter('g')) 

152 self.diffim.setPhotoCalib(afwImage.PhotoCalib(self.calibration, self.calibrationErr)) 

153 

154 self.expIdBits = 16 

155 

156 FWHM = 5 

157 psf = measAlg.DoubleGaussianPsf(15, 15, FWHM/(2*np.sqrt(2*np.log(2)))) 

158 self.exposure.setPsf(psf) 

159 self.diffim.setPsf(psf) 

160 

161 self.testDiaObjects = create_test_dia_objects(5, self.wcs) 

162 # Add additional diaObjects that are outside of the above difference 

163 # and calexp visit images. 

164 # xy outside 

165 src = self.testDiaObjects.addNew() 

166 src['id'] = 10000000 

167 src.setCoord(self.wcs.pixelToSky(-100000, 

168 -100000)) 

169 # y outside 

170 src = self.testDiaObjects.addNew() 

171 src['id'] = 10000001 

172 src.setCoord(self.wcs.pixelToSky(100, 

173 -100000)) 

174 # x outside 

175 src = self.testDiaObjects.addNew() 

176 src['id'] = 10000002 

177 src.setCoord(self.wcs.pixelToSky(-100000, 

178 100)) 

179 # Ids of objects that were "updated" during "ap_association" 

180 # processing. 

181 self.updatedTestIds = np.array([1, 2, 3, 4, 10000001], dtype=np.uint64) 

182 # Expecdted number of sources is the number of updated ids plus 

183 # any that are within the CCD footprint but are not in the 

184 # above list of ids. 

185 self.expectedDiaForcedSources = 6 

186 

187 self.expected_n_columns = 11 

188 

189 def testRun(self): 

190 """Test that forced source catalogs are successfully created and have 

191 sensible values. 

192 """ 

193 test_objects = self._convert_to_pandas(self.testDiaObjects) 

194 test_objects.rename(columns={"id": "diaObjectId"}, 

195 inplace=True) 

196 test_objects.set_index("diaObjectId", inplace=True, drop=False) 

197 dfs = DiaForcedSourceTask() 

198 dia_forced_sources = dfs.run( 

199 test_objects, self.updatedTestIds, self.expIdBits, self.exposure, self.diffim) 

200 

201 direct_values = [199854.48417094944, 160097.40719241602, 

202 82299.17897267535, 27148.604434624354, 

203 5746.988388215507] 

204 direct_var = [75240.939811168, 75231.42933749466, 

205 75218.89495113207, 75214.88248249644, 

206 75214.41447602339] 

207 diff_values = [399708.9683418989, 320194.81438483205, 

208 164598.3579453507, 54297.20886924871, 

209 11493.976776431015] 

210 diff_var = [106444.28782374493, 106417.39592887461, 

211 106381.94840437356, 106370.59980584883, 

212 106369.27608815048] 

213 

214 # Should be number of test objects minus one as one object is purposely 

215 # outside of the ccd area. 

216 self.assertEqual(len(dia_forced_sources), self.expectedDiaForcedSources) 

217 self.assertEqual(len(dia_forced_sources.columns), 

218 self.expected_n_columns) 

219 

220 for (diaFS_id, diaFS), testObj, dirVal, diffVal, dirVar, diffVar in zip(dia_forced_sources.iterrows(), 

221 self.testDiaObjects, 

222 direct_values, 

223 diff_values, 

224 direct_var, 

225 diff_var): 

226 self.assertAlmostEqual(diaFS["psFlux"] / diffVal, 1.) 

227 self.assertAlmostEqual(diaFS["psFluxErr"] / diffVar, 1.) 

228 

229 self.assertAlmostEqual(diaFS["totFlux"] / dirVal, 1.) 

230 self.assertAlmostEqual(diaFS["totFluxErr"] / dirVar, 1.) 

231 

232 self.assertEqual(diaFS["ccdVisitId"], self.exposureId) 

233 

234 def _convert_to_pandas(self, dia_objects): 

235 """Convert input afw table to pandas. 

236 

237 Parameters 

238 ---------- 

239 dia_objects : `lsst.afw.table.SourceCatalog` 

240 Catalog to convert 

241 

242 Returns 

243 ------- 

244 output_catalog : `pandas.DataFrame` 

245 Converted catalog 

246 """ 

247 output_catalog = dia_objects.asAstropy().to_pandas() 

248 output_catalog.rename(columns={"id": "diaObjectId", 

249 "coord_ra": "ra", 

250 "coord_dec": "decl"}, 

251 inplace=True) 

252 

253 output_catalog.loc[:, "ra"] = np.degrees(output_catalog["ra"]) 

254 output_catalog.loc[:, "decl"] = np.degrees(output_catalog["decl"]) 

255 

256 return output_catalog 

257 

258 

259class MemoryTester(lsst.utils.tests.MemoryTestCase): 

260 pass 

261 

262 

263def setup_module(module): 

264 lsst.utils.tests.init() 

265 

266 

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

268 lsst.utils.tests.init() 

269 unittest.main()