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 os 

25import numpy as np 

26 

27import lsst.utils.tests 

28from lsst.daf.base import PropertyList 

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

30from lsst.afw.geom import makeSkyWcs, Polygon 

31from lsst.afw.table import ExposureTable 

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

33 ImageFitsReader, MaskFitsReader, MaskedImageFitsReader, ExposureFitsReader, 

34 Filter, FilterLabel, PhotoCalib, ApCorrMap, VisitInfo, TransmissionCurve, 

35 CoaddInputs) 

36from lsst.afw.image.utils import defineFilter 

37from lsst.afw.detection import GaussianPsf 

38from lsst.afw.cameraGeom.testUtils import DetectorWrapper 

39 

40TESTDIR = os.path.abspath(os.path.dirname(__file__)) 

41 

42 

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

44 

45 def setUp(self): 

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

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

48 self.args = [ 

49 (), 

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

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

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

53 ] 

54 

55 def testImageFitsReader(self): 

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

57 with self.subTest(dtypeIn=dtypeIn): 

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

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

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

61 imageIn.writeFits(fileName) 

62 reader = ImageFitsReader(fileName) 

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

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

65 self.assertEqual(reader.fileName, fileName) 

66 for args in self.args: 

67 with self.subTest(args=args): 

68 array1 = reader.readArray(*args) 

69 image1 = reader.read(*args) 

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

71 self.assertEqual(dtypeIn, array1.dtype) 

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

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

74 self.assertImagesEqual(subIn, image1) 

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

76 for args in self.args: 

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

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

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

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

81 self.assertEqual(dtype2, array2.dtype) 

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

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

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

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

86 

87 def testMaskFitsReader(self): 

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

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

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

91 maskIn.writeFits(fileName) 

92 reader = MaskFitsReader(fileName) 

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

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

95 self.assertEqual(reader.fileName, fileName) 

96 for args in self.args: 

97 with self.subTest(args=args): 

98 array = reader.readArray(*args) 

99 mask = reader.read(*args) 

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

101 self.assertEqual(MaskPixel, array.dtype) 

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

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

104 self.assertImagesEqual(subIn, mask) 

105 

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

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

108 

109 Parameters 

110 ---------- 

111 reader : `MaskedImageFitsReader` or `ExposureFitsReader` instance 

112 Reader object to test. 

113 objectIn : `MaskedImage` or `Exposure` 

114 Object originally saved, to compare against. 

115 fileName : `str` 

116 Name of the file the reader is reading. 

117 dtypesOut : sequence of `numpy.dype` 

118 Compatible image pixel types to try to read in. 

119 compare : callable 

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

121 asserts if they are not equal. 

122 """ 

123 dtypeIn = objectIn.image.dtype 

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

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

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

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

128 self.assertEqual(reader.fileName, fileName) 

129 for args in self.args: 

130 with self.subTest(args=args): 

131 object1 = reader.read(*args) 

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

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

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

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

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

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

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

139 compare(subIn, object1) 

140 for dtype2 in dtypesOut: 

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

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

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

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

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

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

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

148 self.assertImagesEqual(image2, object2.image) 

149 compare(subIn, object2) 

150 

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

152 """Test MaskedImageFitsReader. 

153 

154 Parameters 

155 ---------- 

156 exposureIn : `Exposure` 

157 Object originally saved, to compare against. 

158 fileName : `str` 

159 Name of the file the reader is reading. 

160 dtypesOut : sequence of `numpy.dype` 

161 Compatible image pixel types to try to read in. 

162 """ 

163 reader = MaskedImageFitsReader(fileName) 

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

165 compare=self.assertMaskedImagesEqual) 

166 

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

168 """Test ExposureFitsReader. 

169 

170 Parameters 

171 ---------- 

172 exposureIn : `Exposure` 

173 Object originally saved, to compare against. 

174 fileName : `str` 

175 Name of the file the reader is reading. 

176 dtypesOut : sequence of `numpy.dype` 

177 Compatible image pixel types to try to read in. 

178 """ 

179 reader = ExposureFitsReader(fileName) 

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

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

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

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

184 maxDiffPix=0, maxDiffSky=0*degrees) 

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

186 self.assertEqual(exposureIn.getFilterLabel(), reader.readFilterLabel()) 

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

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

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

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

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

192 reader.readVisitInfo().getExposureTime()) 

193 point = Point2D(2.3, 3.1) 

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

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

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

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

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

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

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

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

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

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

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

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

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

207 self.checkMultiPlaneReader( 

208 reader, exposureIn, fileName, dtypesOut, 

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

210 ) 

211 

212 def testCompressedSinglePlaneExposureFitsReader(self): 

213 """Test that a compressed single plane image can be read as exposure. 

214 """ 

215 uncompressed_file = os.path.join(TESTDIR, "data", "ticketdm26260.fits") 

216 compressed_file = os.path.join(TESTDIR, "data", "ticketdm26260.fits.fz") 

217 uncompressed = ExposureFitsReader(uncompressed_file).read() 

218 compressed = ExposureFitsReader(compressed_file).read() 

219 

220 self.assertMaskedImagesEqual(uncompressed.maskedImage, compressed.maskedImage) 

221 

222 def testMultiPlaneFitsReaders(self): 

223 """Run tests for MaskedImageFitsReader and ExposureFitsReader. 

224 """ 

225 metadata = PropertyList() 

226 metadata.add("FIVE", 5) 

227 metadata.add("SIX", 6.0) 

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

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

230 defineFilter("test_readers_filter", lambdaEff=470.0) 

231 calib = PhotoCalib(2.5E4) 

232 psf = GaussianPsf(21, 21, 8.0) 

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

234 apCorrMap = ApCorrMap() 

235 visitInfo = VisitInfo(exposureTime=5.0) 

236 transmissionCurve = TransmissionCurve.makeIdentity() 

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

238 detector = DetectorWrapper().detector 

239 record = coaddInputs.ccds.addNew() 

240 record.setWcs(wcs) 

241 record.setPhotoCalib(calib) 

242 record.setPsf(psf) 

243 record.setValidPolygon(polygon) 

244 record.setApCorrMap(apCorrMap) 

245 record.setVisitInfo(visitInfo) 

246 record.setTransmissionCurve(transmissionCurve) 

247 record.setDetector(detector) 

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

249 with self.subTest(dtypeIn=dtypeIn): 

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

251 shape = exposureIn.image.array.shape 

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

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

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

255 exposureIn.setMetadata(metadata) 

256 exposureIn.setWcs(wcs) 

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

258 exposureIn.setFilterLabel(FilterLabel(physical="test_readers_filter")) 

259 exposureIn.setPhotoCalib(calib) 

260 exposureIn.setPsf(psf) 

261 exposureIn.getInfo().setValidPolygon(polygon) 

262 exposureIn.getInfo().setApCorrMap(apCorrMap) 

263 exposureIn.getInfo().setVisitInfo(visitInfo) 

264 exposureIn.getInfo().setTransmissionCurve(transmissionCurve) 

265 exposureIn.getInfo().setCoaddInputs(coaddInputs) 

266 exposureIn.setDetector(detector) 

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

268 exposureIn.writeFits(fileName) 

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

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

271 

272 

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

274 pass 

275 

276 

277def setup_module(module): 

278 lsst.utils.tests.init() 

279 

280 

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

282 import sys 

283 setup_module(sys.modules[__name__]) 

284 unittest.main()