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

2# 

3# Developed for the LSST Data Management System. 

4# This product includes software developed by the LSST Project 

5# (http://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 <http://www.gnu.org/licenses/>. 

21 

22import unittest 

23 

24import numpy as np 

25 

26import lsst.utils.tests 

27from lsst.daf.base import PropertyList 

28from lsst.geom import Box2I, Point2I, Extent2I, Point2D, Box2D, SpherePoint, degrees 

29from lsst.afw.geom import makeSkyWcs, Polygon 

30from lsst.afw.table import ExposureTable 

31from lsst.afw.image import (Image, Mask, Exposure, LOCAL, PARENT, MaskPixel, VariancePixel, 

32 ImageFitsReader, MaskFitsReader, MaskedImageFitsReader, ExposureFitsReader, 

33 Filter, PhotoCalib, ApCorrMap, VisitInfo, TransmissionCurve, CoaddInputs) 

34from lsst.afw.image.utils import defineFilter 

35from lsst.afw.detection import GaussianPsf 

36from lsst.afw.cameraGeom.testUtils import DetectorWrapper 

37 

38 

39class FitsReaderTestCase(lsst.utils.tests.TestCase): 

40 

41 def setUp(self): 

42 self.dtypes = [np.dtype(t) for t in (np.uint16, np.int32, np.float32, np.float64)] 

43 self.bbox = Box2I(Point2I(2, 1), Extent2I(5, 7)) 

44 self.args = [ 

45 (), 

46 (Box2I(Point2I(3, 4), Extent2I(2, 1)),), 

47 (Box2I(Point2I(3, 4), Extent2I(2, 1)), PARENT), 

48 (Box2I(Point2I(1, 0), Extent2I(3, 2)), LOCAL), 

49 ] 

50 

51 def testImageFitsReader(self): 

52 for n, dtypeIn in enumerate(self.dtypes): 

53 with self.subTest(dtypeIn=dtypeIn): 

54 imageIn = Image(self.bbox, dtype=dtypeIn) 

55 imageIn.array[:, :] = np.random.randint(low=1, high=5, size=imageIn.array.shape) 

56 with lsst.utils.tests.getTempFilePath(".fits") as fileName: 

57 imageIn.writeFits(fileName) 

58 reader = ImageFitsReader(fileName) 

59 self.assertEqual(reader.readBBox(), self.bbox) 

60 self.assertEqual(reader.readDType(), dtypeIn) 

61 self.assertEqual(reader.fileName, fileName) 

62 for args in self.args: 

63 with self.subTest(args=args): 

64 array1 = reader.readArray(*args) 

65 image1 = reader.read(*args) 

66 subIn = imageIn.subset(*args) if args else imageIn 

67 self.assertEqual(dtypeIn, array1.dtype) 

68 self.assertTrue(np.all(subIn.array == array1)) 

69 self.assertEqual(subIn.getXY0(), reader.readXY0(*args)) 

70 self.assertImagesEqual(subIn, image1) 

71 for dtype2 in self.dtypes[n:]: 

72 for args in self.args: 

73 with self.subTest(dtype2=dtype2, args=args): 

74 subIn = imageIn.subset(*args) if args else imageIn 

75 array2 = reader.readArray(*args, dtype=dtype2) 

76 image2 = reader.read(*args, dtype=dtype2) 

77 self.assertEqual(dtype2, array2.dtype) 

78 self.assertTrue(np.all(subIn.array == array2)) 

79 self.assertEqual(subIn.getXY0(), reader.readXY0(*args)) 

80 self.assertEqual(subIn.getBBox(), image2.getBBox()) 

81 self.assertTrue(np.all(image2.array == array2)) 

82 

83 def testMaskFitsReader(self): 

84 maskIn = Mask(self.bbox, dtype=MaskPixel) 

85 maskIn.array[:, :] = np.random.randint(low=1, high=5, size=maskIn.array.shape) 

86 with lsst.utils.tests.getTempFilePath(".fits") as fileName: 

87 maskIn.writeFits(fileName) 

88 reader = MaskFitsReader(fileName) 

89 self.assertEqual(reader.readBBox(), self.bbox) 

90 self.assertEqual(reader.readDType(), MaskPixel) 

91 self.assertEqual(reader.fileName, fileName) 

92 for args in self.args: 

93 with self.subTest(args=args): 

94 array = reader.readArray(*args) 

95 mask = reader.read(*args) 

96 subIn = maskIn.subset(*args) if args else maskIn 

97 self.assertEqual(MaskPixel, array.dtype) 

98 self.assertTrue(np.all(subIn.array == array)) 

99 self.assertEqual(subIn.getXY0(), reader.readXY0(*args)) 

100 self.assertImagesEqual(subIn, mask) 

101 

102 def checkMultiPlaneReader(self, reader, objectIn, fileName, dtypesOut, compare): 

103 """Test operations common to MaskedImageFitsReader and ExposureFitsReader. 

104 

105 Parameters 

106 ---------- 

107 reader : `MaskedImageFitsReader` or `ExposureFitsReader` instance 

108 Reader object to test. 

109 objectIn : `MaskedImage` or `Exposure` 

110 Object originally saved, to compare against. 

111 fileName : `str` 

112 Name of the file the reader is reading. 

113 dtypesOut : sequence of `numpy.dype` 

114 Compatible image pixel types to try to read in. 

115 compare : callable 

116 Callable that compares objects of the same type as objectIn and 

117 asserts if they are not equal. 

118 """ 

119 dtypeIn = objectIn.image.dtype 

120 self.assertEqual(reader.readBBox(), self.bbox) 

121 self.assertEqual(reader.readImageDType(), dtypeIn) 

122 self.assertEqual(reader.readMaskDType(), MaskPixel) 

123 self.assertEqual(reader.readVarianceDType(), VariancePixel) 

124 self.assertEqual(reader.fileName, fileName) 

125 for args in self.args: 

126 with self.subTest(args=args): 

127 object1 = reader.read(*args) 

128 subIn = objectIn.subset(*args) if args else objectIn 

129 self.assertEqual(object1.image.array.dtype, dtypeIn) 

130 self.assertEqual(object1.mask.array.dtype, MaskPixel) 

131 self.assertEqual(object1.variance.array.dtype, VariancePixel) 

132 self.assertImagesEqual(subIn.image, reader.readImage(*args)) 

133 self.assertImagesEqual(subIn.mask, reader.readMask(*args)) 

134 self.assertImagesEqual(subIn.variance, reader.readVariance(*args)) 

135 compare(subIn, object1) 

136 for dtype2 in dtypesOut: 

137 with self.subTest(dtype2=dtype2, args=args): 

138 object2 = reader.read(*args, dtype=dtype2) 

139 image2 = reader.readImage(*args, dtype=dtype2) 

140 self.assertEqual(object2.image.array.dtype, dtype2) 

141 self.assertEqual(object2.mask.array.dtype, MaskPixel) 

142 self.assertEqual(object2.variance.array.dtype, VariancePixel) 

143 self.assertImagesEqual(subIn.image, Image(image2, deep=True, dtype=dtypeIn)) 

144 self.assertImagesEqual(image2, object2.image) 

145 compare(subIn, object2) 

146 

147 def checkMaskedImageFitsReader(self, exposureIn, fileName, dtypesOut): 

148 """Test MaskedImageFitsReader. 

149 

150 Parameters 

151 ---------- 

152 exposureIn : `Exposure` 

153 Object originally saved, to compare against. 

154 fileName : `str` 

155 Name of the file the reader is reading. 

156 dtypesOut : sequence of `numpy.dype` 

157 Compatible image pixel types to try to read in. 

158 """ 

159 reader = MaskedImageFitsReader(fileName) 

160 self.checkMultiPlaneReader(reader, exposureIn.maskedImage, fileName, dtypesOut, 

161 compare=self.assertMaskedImagesEqual) 

162 

163 def checkExposureFitsReader(self, exposureIn, fileName, dtypesOut): 

164 """Test ExposureFitsReader. 

165 

166 Parameters 

167 ---------- 

168 exposureIn : `Exposure` 

169 Object originally saved, to compare against. 

170 fileName : `str` 

171 Name of the file the reader is reading. 

172 dtypesOut : sequence of `numpy.dype` 

173 Compatible image pixel types to try to read in. 

174 """ 

175 reader = ExposureFitsReader(fileName) 

176 self.assertIn('EXPINFO_V', reader.readMetadata().toDict(), "metadata is automatically versioned") 

177 reader.readMetadata().remove('EXPINFO_V') 

178 self.assertEqual(exposureIn.getMetadata().toDict(), reader.readMetadata().toDict()) 

179 self.assertWcsAlmostEqualOverBBox(exposureIn.getWcs(), reader.readWcs(), self.bbox, 

180 maxDiffPix=0, maxDiffSky=0*degrees) 

181 self.assertEqual(exposureIn.getFilter(), reader.readFilter()) 

182 self.assertEqual(exposureIn.getPhotoCalib(), reader.readPhotoCalib()) 

183 self.assertImagesEqual(exposureIn.getPsf().computeImage(), reader.readPsf().computeImage()) 

184 self.assertEqual(exposureIn.getInfo().getValidPolygon(), reader.readValidPolygon()) 

185 self.assertCountEqual(exposureIn.getInfo().getApCorrMap(), reader.readApCorrMap()) 

186 self.assertEqual(exposureIn.getInfo().getVisitInfo().getExposureTime(), 

187 reader.readVisitInfo().getExposureTime()) 

188 point = Point2D(2.3, 3.1) 

189 wavelengths = np.linspace(4000, 5000, 5) 

190 self.assertFloatsEqual(exposureIn.getInfo().getTransmissionCurve().sampleAt(point, wavelengths), 

191 reader.readTransmissionCurve().sampleAt(point, wavelengths)) 

192 # Because we persisted the same instances, we should get back the same 

193 # instances for *archive* components, and hence equality comparisons 

194 # should work even if it just amounts to C++ pointer equality. 

195 record = reader.readCoaddInputs().ccds[0] 

196 self.assertEqual(record.getWcs(), reader.readWcs()) 

197 self.assertEqual(record.getPsf(), reader.readPsf()) 

198 self.assertEqual(record.getValidPolygon(), reader.readValidPolygon()) 

199 self.assertEqual(record.getApCorrMap(), reader.readApCorrMap()) 

200 self.assertEqual(record.getPhotoCalib(), reader.readPhotoCalib()) 

201 self.assertEqual(record.getDetector(), reader.readDetector()) 

202 self.checkMultiPlaneReader( 

203 reader, exposureIn, fileName, dtypesOut, 

204 compare=lambda a, b: self.assertMaskedImagesEqual(a.maskedImage, b.maskedImage) 

205 ) 

206 

207 def testMultiPlaneFitsReaders(self): 

208 """Run tests for MaskedImageFitsReader and ExposureFitsReader. 

209 """ 

210 metadata = PropertyList() 

211 metadata.add("FIVE", 5) 

212 metadata.add("SIX", 6.0) 

213 wcs = makeSkyWcs(Point2D(2.5, 3.75), SpherePoint(40.0*degrees, 50.0*degrees), 

214 np.array([[1E-5, 0.0], [0.0, -1E-5]])) 

215 defineFilter("test_readers_filter", lambdaEff=470.0) 

216 calib = PhotoCalib(2.5E4) 

217 psf = GaussianPsf(21, 21, 8.0) 

218 polygon = Polygon(Box2D(self.bbox)) 

219 apCorrMap = ApCorrMap() 

220 visitInfo = VisitInfo(exposureTime=5.0) 

221 transmissionCurve = TransmissionCurve.makeIdentity() 

222 coaddInputs = CoaddInputs(ExposureTable.makeMinimalSchema(), ExposureTable.makeMinimalSchema()) 

223 detector = DetectorWrapper().detector 

224 record = coaddInputs.ccds.addNew() 

225 record.setWcs(wcs) 

226 record.setPhotoCalib(calib) 

227 record.setPsf(psf) 

228 record.setValidPolygon(polygon) 

229 record.setApCorrMap(apCorrMap) 

230 record.setVisitInfo(visitInfo) 

231 record.setTransmissionCurve(transmissionCurve) 

232 record.setDetector(detector) 

233 for n, dtypeIn in enumerate(self.dtypes): 

234 with self.subTest(dtypeIn=dtypeIn): 

235 exposureIn = Exposure(self.bbox, dtype=dtypeIn) 

236 shape = exposureIn.image.array.shape 

237 exposureIn.image.array[:, :] = np.random.randint(low=1, high=5, size=shape) 

238 exposureIn.mask.array[:, :] = np.random.randint(low=1, high=5, size=shape) 

239 exposureIn.variance.array[:, :] = np.random.randint(low=1, high=5, size=shape) 

240 exposureIn.setMetadata(metadata) 

241 exposureIn.setWcs(wcs) 

242 exposureIn.setFilter(Filter("test_readers_filter")) 

243 exposureIn.setPhotoCalib(calib) 

244 exposureIn.setPsf(psf) 

245 exposureIn.getInfo().setValidPolygon(polygon) 

246 exposureIn.getInfo().setApCorrMap(apCorrMap) 

247 exposureIn.getInfo().setVisitInfo(visitInfo) 

248 exposureIn.getInfo().setTransmissionCurve(transmissionCurve) 

249 exposureIn.getInfo().setCoaddInputs(coaddInputs) 

250 exposureIn.setDetector(detector) 

251 with lsst.utils.tests.getTempFilePath(".fits") as fileName: 

252 exposureIn.writeFits(fileName) 

253 self.checkMaskedImageFitsReader(exposureIn, fileName, self.dtypes[n:]) 

254 self.checkExposureFitsReader(exposureIn, fileName, self.dtypes[n:]) 

255 

256 

257class TestMemory(lsst.utils.tests.MemoryTestCase): 

258 pass 

259 

260 

261def setup_module(module): 

262 lsst.utils.tests.init() 

263 

264 

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

266 import sys 

267 setup_module(sys.modules[__name__]) 

268 unittest.main()