Coverage for tests/test_readers.py : 13%

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/>.
22import unittest
24import os
25import numpy as np
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, PhotoCalib, ApCorrMap, VisitInfo, TransmissionCurve, CoaddInputs)
35from lsst.afw.image.utils import defineFilter
36from lsst.afw.detection import GaussianPsf
37from lsst.afw.cameraGeom.testUtils import DetectorWrapper
39TESTDIR = os.path.abspath(os.path.dirname(__file__))
42class FitsReaderTestCase(lsst.utils.tests.TestCase):
44 def setUp(self):
45 self.dtypes = [np.dtype(t) for t in (np.uint16, np.int32, np.float32, np.float64)]
46 self.bbox = Box2I(Point2I(2, 1), Extent2I(5, 7))
47 self.args = [
48 (),
49 (Box2I(Point2I(3, 4), Extent2I(2, 1)),),
50 (Box2I(Point2I(3, 4), Extent2I(2, 1)), PARENT),
51 (Box2I(Point2I(1, 0), Extent2I(3, 2)), LOCAL),
52 ]
54 def testImageFitsReader(self):
55 for n, dtypeIn in enumerate(self.dtypes):
56 with self.subTest(dtypeIn=dtypeIn):
57 imageIn = Image(self.bbox, dtype=dtypeIn)
58 imageIn.array[:, :] = np.random.randint(low=1, high=5, size=imageIn.array.shape)
59 with lsst.utils.tests.getTempFilePath(".fits") as fileName:
60 imageIn.writeFits(fileName)
61 reader = ImageFitsReader(fileName)
62 self.assertEqual(reader.readBBox(), self.bbox)
63 self.assertEqual(reader.readDType(), dtypeIn)
64 self.assertEqual(reader.fileName, fileName)
65 for args in self.args:
66 with self.subTest(args=args):
67 array1 = reader.readArray(*args)
68 image1 = reader.read(*args)
69 subIn = imageIn.subset(*args) if args else imageIn
70 self.assertEqual(dtypeIn, array1.dtype)
71 self.assertTrue(np.all(subIn.array == array1))
72 self.assertEqual(subIn.getXY0(), reader.readXY0(*args))
73 self.assertImagesEqual(subIn, image1)
74 for dtype2 in self.dtypes[n:]:
75 for args in self.args:
76 with self.subTest(dtype2=dtype2, args=args):
77 subIn = imageIn.subset(*args) if args else imageIn
78 array2 = reader.readArray(*args, dtype=dtype2)
79 image2 = reader.read(*args, dtype=dtype2)
80 self.assertEqual(dtype2, array2.dtype)
81 self.assertTrue(np.all(subIn.array == array2))
82 self.assertEqual(subIn.getXY0(), reader.readXY0(*args))
83 self.assertEqual(subIn.getBBox(), image2.getBBox())
84 self.assertTrue(np.all(image2.array == array2))
86 def testMaskFitsReader(self):
87 maskIn = Mask(self.bbox, dtype=MaskPixel)
88 maskIn.array[:, :] = np.random.randint(low=1, high=5, size=maskIn.array.shape)
89 with lsst.utils.tests.getTempFilePath(".fits") as fileName:
90 maskIn.writeFits(fileName)
91 reader = MaskFitsReader(fileName)
92 self.assertEqual(reader.readBBox(), self.bbox)
93 self.assertEqual(reader.readDType(), MaskPixel)
94 self.assertEqual(reader.fileName, fileName)
95 for args in self.args:
96 with self.subTest(args=args):
97 array = reader.readArray(*args)
98 mask = reader.read(*args)
99 subIn = maskIn.subset(*args) if args else maskIn
100 self.assertEqual(MaskPixel, array.dtype)
101 self.assertTrue(np.all(subIn.array == array))
102 self.assertEqual(subIn.getXY0(), reader.readXY0(*args))
103 self.assertImagesEqual(subIn, mask)
105 def checkMultiPlaneReader(self, reader, objectIn, fileName, dtypesOut, compare):
106 """Test operations common to MaskedImageFitsReader and ExposureFitsReader.
108 Parameters
109 ----------
110 reader : `MaskedImageFitsReader` or `ExposureFitsReader` instance
111 Reader object to test.
112 objectIn : `MaskedImage` or `Exposure`
113 Object originally saved, to compare against.
114 fileName : `str`
115 Name of the file the reader is reading.
116 dtypesOut : sequence of `numpy.dype`
117 Compatible image pixel types to try to read in.
118 compare : callable
119 Callable that compares objects of the same type as objectIn and
120 asserts if they are not equal.
121 """
122 dtypeIn = objectIn.image.dtype
123 self.assertEqual(reader.readBBox(), self.bbox)
124 self.assertEqual(reader.readImageDType(), dtypeIn)
125 self.assertEqual(reader.readMaskDType(), MaskPixel)
126 self.assertEqual(reader.readVarianceDType(), VariancePixel)
127 self.assertEqual(reader.fileName, fileName)
128 for args in self.args:
129 with self.subTest(args=args):
130 object1 = reader.read(*args)
131 subIn = objectIn.subset(*args) if args else objectIn
132 self.assertEqual(object1.image.array.dtype, dtypeIn)
133 self.assertEqual(object1.mask.array.dtype, MaskPixel)
134 self.assertEqual(object1.variance.array.dtype, VariancePixel)
135 self.assertImagesEqual(subIn.image, reader.readImage(*args))
136 self.assertImagesEqual(subIn.mask, reader.readMask(*args))
137 self.assertImagesEqual(subIn.variance, reader.readVariance(*args))
138 compare(subIn, object1)
139 for dtype2 in dtypesOut:
140 with self.subTest(dtype2=dtype2, args=args):
141 object2 = reader.read(*args, dtype=dtype2)
142 image2 = reader.readImage(*args, dtype=dtype2)
143 self.assertEqual(object2.image.array.dtype, dtype2)
144 self.assertEqual(object2.mask.array.dtype, MaskPixel)
145 self.assertEqual(object2.variance.array.dtype, VariancePixel)
146 self.assertImagesEqual(subIn.image, Image(image2, deep=True, dtype=dtypeIn))
147 self.assertImagesEqual(image2, object2.image)
148 compare(subIn, object2)
150 def checkMaskedImageFitsReader(self, exposureIn, fileName, dtypesOut):
151 """Test MaskedImageFitsReader.
153 Parameters
154 ----------
155 exposureIn : `Exposure`
156 Object originally saved, to compare against.
157 fileName : `str`
158 Name of the file the reader is reading.
159 dtypesOut : sequence of `numpy.dype`
160 Compatible image pixel types to try to read in.
161 """
162 reader = MaskedImageFitsReader(fileName)
163 self.checkMultiPlaneReader(reader, exposureIn.maskedImage, fileName, dtypesOut,
164 compare=self.assertMaskedImagesEqual)
166 def checkExposureFitsReader(self, exposureIn, fileName, dtypesOut):
167 """Test ExposureFitsReader.
169 Parameters
170 ----------
171 exposureIn : `Exposure`
172 Object originally saved, to compare against.
173 fileName : `str`
174 Name of the file the reader is reading.
175 dtypesOut : sequence of `numpy.dype`
176 Compatible image pixel types to try to read in.
177 """
178 reader = ExposureFitsReader(fileName)
179 self.assertIn('EXPINFO_V', reader.readMetadata().toDict(), "metadata is automatically versioned")
180 reader.readMetadata().remove('EXPINFO_V')
181 self.assertEqual(exposureIn.getMetadata().toDict(), reader.readMetadata().toDict())
182 self.assertWcsAlmostEqualOverBBox(exposureIn.getWcs(), reader.readWcs(), self.bbox,
183 maxDiffPix=0, maxDiffSky=0*degrees)
184 self.assertEqual(exposureIn.getFilter(), reader.readFilter())
185 self.assertEqual(exposureIn.getPhotoCalib(), reader.readPhotoCalib())
186 self.assertImagesEqual(exposureIn.getPsf().computeImage(), reader.readPsf().computeImage())
187 self.assertEqual(exposureIn.getInfo().getValidPolygon(), reader.readValidPolygon())
188 self.assertCountEqual(exposureIn.getInfo().getApCorrMap(), reader.readApCorrMap())
189 self.assertEqual(exposureIn.getInfo().getVisitInfo().getExposureTime(),
190 reader.readVisitInfo().getExposureTime())
191 point = Point2D(2.3, 3.1)
192 wavelengths = np.linspace(4000, 5000, 5)
193 self.assertFloatsEqual(exposureIn.getInfo().getTransmissionCurve().sampleAt(point, wavelengths),
194 reader.readTransmissionCurve().sampleAt(point, wavelengths))
195 # Because we persisted the same instances, we should get back the same
196 # instances for *archive* components, and hence equality comparisons
197 # should work even if it just amounts to C++ pointer equality.
198 record = reader.readCoaddInputs().ccds[0]
199 self.assertEqual(record.getWcs(), reader.readWcs())
200 self.assertEqual(record.getPsf(), reader.readPsf())
201 self.assertEqual(record.getValidPolygon(), reader.readValidPolygon())
202 self.assertEqual(record.getApCorrMap(), reader.readApCorrMap())
203 self.assertEqual(record.getPhotoCalib(), reader.readPhotoCalib())
204 self.assertEqual(record.getDetector(), reader.readDetector())
205 self.checkMultiPlaneReader(
206 reader, exposureIn, fileName, dtypesOut,
207 compare=lambda a, b: self.assertMaskedImagesEqual(a.maskedImage, b.maskedImage)
208 )
210 def testCompressedSinglePlaneExposureFitsReader(self):
211 """Test that a compressed single plane image can be read as exposure.
212 """
213 uncompressed_file = os.path.join(TESTDIR, "data", "ticketdm26260.fits")
214 compressed_file = os.path.join(TESTDIR, "data", "ticketdm26260.fits.fz")
215 uncompressed = ExposureFitsReader(uncompressed_file).read()
216 compressed = ExposureFitsReader(compressed_file).read()
218 self.assertMaskedImagesEqual(uncompressed.maskedImage, compressed.maskedImage)
220 def testMultiPlaneFitsReaders(self):
221 """Run tests for MaskedImageFitsReader and ExposureFitsReader.
222 """
223 metadata = PropertyList()
224 metadata.add("FIVE", 5)
225 metadata.add("SIX", 6.0)
226 wcs = makeSkyWcs(Point2D(2.5, 3.75), SpherePoint(40.0*degrees, 50.0*degrees),
227 np.array([[1E-5, 0.0], [0.0, -1E-5]]))
228 defineFilter("test_readers_filter", lambdaEff=470.0)
229 calib = PhotoCalib(2.5E4)
230 psf = GaussianPsf(21, 21, 8.0)
231 polygon = Polygon(Box2D(self.bbox))
232 apCorrMap = ApCorrMap()
233 visitInfo = VisitInfo(exposureTime=5.0)
234 transmissionCurve = TransmissionCurve.makeIdentity()
235 coaddInputs = CoaddInputs(ExposureTable.makeMinimalSchema(), ExposureTable.makeMinimalSchema())
236 detector = DetectorWrapper().detector
237 record = coaddInputs.ccds.addNew()
238 record.setWcs(wcs)
239 record.setPhotoCalib(calib)
240 record.setPsf(psf)
241 record.setValidPolygon(polygon)
242 record.setApCorrMap(apCorrMap)
243 record.setVisitInfo(visitInfo)
244 record.setTransmissionCurve(transmissionCurve)
245 record.setDetector(detector)
246 for n, dtypeIn in enumerate(self.dtypes):
247 with self.subTest(dtypeIn=dtypeIn):
248 exposureIn = Exposure(self.bbox, dtype=dtypeIn)
249 shape = exposureIn.image.array.shape
250 exposureIn.image.array[:, :] = np.random.randint(low=1, high=5, size=shape)
251 exposureIn.mask.array[:, :] = np.random.randint(low=1, high=5, size=shape)
252 exposureIn.variance.array[:, :] = np.random.randint(low=1, high=5, size=shape)
253 exposureIn.setMetadata(metadata)
254 exposureIn.setWcs(wcs)
255 exposureIn.setFilter(Filter("test_readers_filter"))
256 exposureIn.setPhotoCalib(calib)
257 exposureIn.setPsf(psf)
258 exposureIn.getInfo().setValidPolygon(polygon)
259 exposureIn.getInfo().setApCorrMap(apCorrMap)
260 exposureIn.getInfo().setVisitInfo(visitInfo)
261 exposureIn.getInfo().setTransmissionCurve(transmissionCurve)
262 exposureIn.getInfo().setCoaddInputs(coaddInputs)
263 exposureIn.setDetector(detector)
264 with lsst.utils.tests.getTempFilePath(".fits") as fileName:
265 exposureIn.writeFits(fileName)
266 self.checkMaskedImageFitsReader(exposureIn, fileName, self.dtypes[n:])
267 self.checkExposureFitsReader(exposureIn, fileName, self.dtypes[n:])
270class TestMemory(lsst.utils.tests.MemoryTestCase):
271 pass
274def setup_module(module):
275 lsst.utils.tests.init()
278if __name__ == "__main__": 278 ↛ 279line 278 didn't jump to line 279, because the condition on line 278 was never true
279 import sys
280 setup_module(sys.modules[__name__])
281 unittest.main()