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 

26import pandas 

27 

28from lsst.afw.cameraGeom.testUtils import DetectorWrapper 

29import lsst.afw.geom as afwGeom 

30import lsst.afw.image as afwImage 

31import lsst.daf.base as dafBase 

32import lsst.meas.algorithms as measAlg 

33from lsst.ap.association import DiaForcedSourceTask 

34import lsst.utils.tests 

35 

36 

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

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

39 

40 Parameters 

41 ---------- 

42 n_points : `int` 

43 Number of DiaObject test points to create. 

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

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

46 startPos : `int` 

47 Start position to iterate from when creating test DiaObjects 

48 

49 Returns 

50 ------- 

51 test_points : `pandas.DataFrame` 

52 Catalog of points to test. 

53 """ 

54 ids = np.arange(n_points, dtype=np.int64) 

55 points = [wcs.pixelToSky(startPos + src_idx, startPos + src_idx) for src_idx in ids] 

56 ra = np.array([point.getRa().asDegrees() for point in points], dtype=float) 

57 decl = np.array([point.getDec().asDegrees() for point in points], dtype=float) 

58 

59 objects = pandas.DataFrame({ 

60 "diaObjectId": ids, 

61 "ra": ra, 

62 "decl": decl 

63 }) 

64 

65 return objects 

66 

67 

68class TestDiaForcedSource(unittest.TestCase): 

69 

70 def setUp(self): 

71 # metadata taken from CFHT data 

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

73 self.metadata = dafBase.PropertySet() 

74 

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

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

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

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

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

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

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

82 

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

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

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

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

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

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

89 

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

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

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

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

94 

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

96 

97 self.calibration = 10000 

98 self.calibrationErr = 100 

99 self.exposureId = 1234 

100 self.exposureTime = 200. 

101 self.imageSize = [1024, 1153] 

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

103 

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

105 # variance for each image. 

106 # Direct Image 

107 source_image = afwImage.MaskedImageF( 

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

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

110 source_image.getVariance().set(1) 

111 bbox = lsst.geom.BoxI( 

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

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

114 self.imageSize[1])) 

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

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

117 

118 detector = DetectorWrapper( 

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

120 visit = afwImage.VisitInfo( 

121 exposureId=self.exposureId, 

122 exposureTime=self.exposureTime, 

123 date=dafBase.DateTime(self.dateTime, 

124 dafBase.DateTime.Timescale.TAI)) 

125 self.exposure.setDetector(detector) 

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

127 self.exposure.setFilterLabel(afwImage.FilterLabel(band='g', physical='g.MP9401')) 

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

129 

130 # Difference 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] = 20 

134 source_image.getVariance().set(2) 

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.diffim = afwImage.makeExposure(masked_image, self.wcs) 

141 self.diffim.setDetector(detector) 

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

143 self.diffim.setFilterLabel(afwImage.FilterLabel(band='g', physical='g.MP9401')) 

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

145 

146 self.expIdBits = 16 

147 

148 FWHM = 5 

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

150 self.exposure.setPsf(psf) 

151 self.diffim.setPsf(psf) 

152 

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

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

155 # and calexp visit images. 

156 objects = [ 

157 (10000000, self.wcs.pixelToSky(-100000, -100000)), # xy outside 

158 (10000001, self.wcs.pixelToSky(100, -100000)), # y outside 

159 (10000002, self.wcs.pixelToSky(-100000, 100)), # x outside 

160 ] 

161 extra = pandas.DataFrame({ 

162 "diaObjectId": np.array([id for id, point in objects], dtype=np.int64), 

163 "ra": [point.getRa().asDegrees() for id, point in objects], 

164 "decl": [point.getDec().asDegrees() for id, point in objects] 

165 }) 

166 self.testDiaObjects = self.testDiaObjects.append(extra, ignore_index=True) 

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

168 # processing. 

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

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

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

172 # above list of ids. 

173 self.expectedDiaForcedSources = 6 

174 

175 self.expected_n_columns = 11 

176 

177 def testRun(self): 

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

179 sensible values. 

180 """ 

181 test_objects = self.testDiaObjects.copy() 

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

183 dfs = DiaForcedSourceTask() 

184 dia_forced_sources = dfs.run( 

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

186 

187 direct_values = [199854.48417094944, 160097.40719241602, 

188 82299.17897267535, 27148.604434624354, 

189 5746.988388215507] 

190 direct_var = [75240.939811168, 75231.42933749466, 

191 75218.89495113207, 75214.88248249644, 

192 75214.41447602339] 

193 diff_values = [399708.9683418989, 320194.81438483205, 

194 164598.3579453507, 54297.20886924871, 

195 11493.976776431015] 

196 diff_var = [106444.28782374493, 106417.39592887461, 

197 106381.94840437356, 106370.59980584883, 

198 106369.27608815048] 

199 

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

201 # outside of the ccd area. 

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

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

204 self.expected_n_columns) 

205 

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

207 direct_values, 

208 diff_values, 

209 direct_var, 

210 diff_var): 

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

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

213 

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

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

216 

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

218 

219 

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

221 pass 

222 

223 

224def setup_module(module): 

225 lsst.utils.tests.init() 

226 

227 

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

229 lsst.utils.tests.init() 

230 unittest.main()