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 Parameters 

42 ---------- 

43 n_points : `int` 

44 Number of DiaObject test points to create. 

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

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

47 startPos : `int` 

48 Start position to iterate from when creating test DiaObjects 

49 

50 Returns 

51 ------- 

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

53 Catalog of points to test. 

54 """ 

55 objects = afwTable.SourceCatalog(make_dia_object_schema()) 

56 

57 for src_idx in range(n_points): 

58 src = objects.addNew() 

59 src['id'] = src_idx 

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

61 startPos + src_idx)) 

62 

63 # Add points outside of the CCD. 

64 # Fully outside. 

65 src = objects.addNew() 

66 src['id'] = 10000000 

67 src.setCoord(wcs.pixelToSky(-100000, 

68 -100000)) 

69 # y outside 

70 src = objects.addNew() 

71 src['id'] = 10000001 

72 src.setCoord(wcs.pixelToSky(100, 

73 -100000)) 

74 # x outside 

75 src = objects.addNew() 

76 src['id'] = 10000001 

77 src.setCoord(wcs.pixelToSky(-100000, 

78 100)) 

79 

80 return objects 

81 

82 

83class TestDiaForcedSource(unittest.TestCase): 

84 

85 def setUp(self): 

86 # CFHT Filters from the camera mapper. 

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

88 afwImageUtils.resetFilters() 

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

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

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

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

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

94 

95 # metadata taken from CFHT data 

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

97 self.metadata = dafBase.PropertySet() 

98 

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

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

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

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

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

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

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

106 

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

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

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

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

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

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

113 

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

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

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

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

118 

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

120 

121 self.calibration = 10000 

122 self.calibrationErr = 100 

123 self.exposureId = 1234 

124 self.exposureTime = 200. 

125 self.imageSize = [1024, 1153] 

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

127 

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

129 # variance for each image. 

130 # Direct Image 

131 source_image = afwImage.MaskedImageF( 

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

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

134 source_image.getVariance().set(1) 

135 bbox = lsst.geom.BoxI( 

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

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

138 self.imageSize[1])) 

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

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

141 

142 detector = DetectorWrapper( 

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

144 visit = afwImage.VisitInfo( 

145 exposureId=self.exposureId, 

146 exposureTime=self.exposureTime, 

147 date=dafBase.DateTime(self.dateTime, 

148 dafBase.DateTime.Timescale.TAI)) 

149 self.exposure.setDetector(detector) 

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

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

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

153 

154 # Difference Image 

155 source_image = afwImage.MaskedImageF( 

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

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

158 source_image.getVariance().set(2) 

159 bbox = lsst.geom.BoxI( 

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

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

162 self.imageSize[1])) 

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

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

165 self.diffim.setDetector(detector) 

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

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

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

169 

170 self.expIdBits = 16 

171 

172 FWHM = 5 

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

174 self.exposure.setPsf(psf) 

175 self.diffim.setPsf(psf) 

176 

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

178 self.expected_n_columns = 11 

179 

180 def testRun(self): 

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

182 sensible values. 

183 """ 

184 test_objects = self._convert_to_pandas(self.testDiaObjects) 

185 

186 dfs = DiaForcedSourceTask() 

187 dia_forced_sources = dfs.run( 

188 test_objects, self.expIdBits, self.exposure, self.diffim) 

189 

190 direct_values = [199854.48417094944, 160097.40719241602, 

191 82299.17897267535, 27148.604434624354, 

192 5746.988388215507] 

193 direct_var = [75240.939811168, 75231.42933749466, 

194 75218.89495113207, 75214.88248249644, 

195 75214.41447602339] 

196 diff_values = [399708.9683418989, 320194.81438483205, 

197 164598.3579453507, 54297.20886924871, 

198 11493.976776431015] 

199 diff_var = [106444.28782374493, 106417.39592887461, 

200 106381.94840437356, 106370.59980584883, 

201 106369.27608815048] 

202 

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

204 # outside of the ccd area. 

205 self.assertEqual(len(dia_forced_sources), len(self.testDiaObjects) - 3) 

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

207 self.expected_n_columns) 

208 

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

210 self.testDiaObjects, 

211 direct_values, 

212 diff_values, 

213 direct_var, 

214 diff_var): 

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

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

217 

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

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

220 

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

222 

223 def _convert_to_pandas(self, dia_objects): 

224 """Convert input afw table to pandas. 

225 

226 Parameters 

227 ---------- 

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

229 Catalog to convert 

230 

231 Returns 

232 ------- 

233 output_catalog : `pandas.DataFrame` 

234 Converted catalog 

235 """ 

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

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

238 "coord_ra": "ra", 

239 "coord_dec": "decl"}, 

240 inplace=True) 

241 

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

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

244 

245 return output_catalog 

246 

247 

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

249 pass 

250 

251 

252def setup_module(module): 

253 lsst.utils.tests.init() 

254 

255 

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

257 lsst.utils.tests.init() 

258 unittest.main()