Coverage for tests/test_gaussianPsf.py: 31%
77 statements
« prev ^ index » next coverage.py v6.4.4, created at 2022-09-20 02:20 -0700
« prev ^ index » next coverage.py v6.4.4, created at 2022-09-20 02:20 -0700
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# (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/>.
22import unittest
24import numpy as np
26import lsst.utils.tests
27import lsst.pex.exceptions
28import lsst.geom
29import lsst.afw.table
30import lsst.afw.fits
31import lsst.afw.image
32import lsst.afw.detection
35def makeGaussianImage(bbox, sigma, xc=0.0, yc=0.0):
36 image = lsst.afw.image.ImageD(bbox)
37 array = image.getArray()
38 for yi, yv in enumerate(range(bbox.getBeginY(), bbox.getEndY())):
39 for xi, xv in enumerate(range(bbox.getBeginX(), bbox.getEndX())):
40 array[yi, xi] = np.exp(-0.5*((xv - xc)**2 + (yv - yc)**2)/sigma**2)
41 array /= array.sum()
42 return image
45def computeNaiveApertureFlux(image, radius, xc=0.0, yc=0.0):
46 bbox = image.getBBox()
47 array = image.getArray()
48 s = 0.0
49 for yi, yv in enumerate(range(bbox.getBeginY(), bbox.getEndY())):
50 for xi, xv in enumerate(range(bbox.getBeginX(), bbox.getEndX())):
51 if (xv - xc)**2 + (yv - yc)**2 < radius**2:
52 s += array[yi, xi]
53 return s
56class GaussianPsfTestCase(lsst.utils.tests.TestCase):
58 def setUp(self):
59 self.kernelSize = 51
60 self.psf = lsst.afw.detection.GaussianPsf(
61 self.kernelSize, self.kernelSize, 4.0)
63 def tearDown(self):
64 del self.psf
66 def testKernelImage(self):
67 image = self.psf.computeKernelImage(self.psf.getAveragePosition())
68 check = makeGaussianImage(image.getBBox(), self.psf.getSigma())
69 self.assertFloatsAlmostEqual(image.getArray(), check.getArray())
70 self.assertFloatsAlmostEqual(image.getArray().sum(), 1.0, atol=1E-14)
72 def testOffsetImage(self):
73 image = self.psf.computeImage(lsst.geom.Point2D(0.25, 0.25))
74 check = makeGaussianImage(
75 image.getBBox(), self.psf.getSigma(), 0.25, 0.25)
76 self.assertFloatsAlmostEqual(image.getArray(), check.getArray(), atol=1E-4, rtol=1E-4,
77 plotOnFailure=True)
79 def testApertureFlux(self):
80 image = self.psf.computeKernelImage(lsst.geom.Point2D(0.0, 0.0))
81 # test aperture implementation is very crude; can only test to about 10%
82 self.assertFloatsAlmostEqual(self.psf.computeApertureFlux(5.0), computeNaiveApertureFlux(image, 5.0),
83 rtol=0.1)
84 self.assertFloatsAlmostEqual(self.psf.computeApertureFlux(7.0), computeNaiveApertureFlux(image, 7.0),
85 rtol=0.1)
87 def testShape(self):
88 self.assertFloatsAlmostEqual(
89 self.psf.computeShape(self.psf.getAveragePosition()).getDeterminantRadius(), 4.0)
91 def testPersistence(self):
92 with lsst.utils.tests.getTempFilePath(".fits") as filename:
93 self.psf.writeFits(filename)
94 psf = lsst.afw.detection.GaussianPsf.readFits(filename)
95 self.assertEqual(self.psf.getSigma(), psf.getSigma())
96 self.assertEqual(self.psf.getDimensions(), psf.getDimensions())
98 def testBBox(self):
100 self.assertEqual(self.psf.computeKernelImage(self.psf.getAveragePosition()).getBBox(),
101 self.psf.computeBBox(self.psf.getAveragePosition()))
103 self.assertEqual(self.psf.computeBBox().getWidth(), self.kernelSize)
105 # Test interface. GaussianPsf does not vary spatially
106 self.assertEqual(self.psf.computeKernelImage(lsst.geom.Point2D(0.0, 0.0)).getBBox(),
107 self.psf.computeBBox(lsst.geom.Point2D(0.0, 0.0)))
109 self.assertEqual(self.psf.computeImage(self.psf.getAveragePosition()).getBBox(),
110 self.psf.computeImageBBox(self.psf.getAveragePosition()))
112 def testResized(self):
113 for pad in [0, -10, 10]:
114 newLen = self.kernelSize - pad
115 resizedPsf = self.psf.resized(newLen, newLen)
116 newBBox = resizedPsf.computeBBox(resizedPsf.getAveragePosition())
117 self.assertEqual(newBBox.getWidth(), newLen)
118 self.assertEqual(newBBox.getHeight(), newLen)
119 self.assertEqual(resizedPsf.getSigma(), self.psf.getSigma())
121 image = resizedPsf.computeKernelImage(resizedPsf.getAveragePosition())
122 check = makeGaussianImage(newBBox, self.psf.getSigma())
123 self.assertFloatsAlmostEqual(image.getArray(), check.getArray())
124 # tolerance same as in self.testKernelImage
125 self.assertFloatsAlmostEqual(image.getArray().sum(), 1.0, atol=1E-14)
128class MemoryTester(lsst.utils.tests.MemoryTestCase):
129 pass
132def setup_module(module):
133 lsst.utils.tests.init()
136if __name__ == "__main__": 136 ↛ 137line 136 didn't jump to line 137, because the condition on line 136 was never true
137 lsst.utils.tests.init()
138 unittest.main()