Coverage for tests/test_projection.py: 26%
61 statements
« prev ^ index » next coverage.py v6.5.0, created at 2023-02-22 03:33 -0800
« prev ^ index » next coverage.py v6.5.0, created at 2023-02-22 03:33 -0800
1#
2# LSST Data Management System
3# Copyright 2008-2017 LSST Corporation.
4#
5# This product includes software developed by the
6# LSST Project (http://www.lsst.org/).
7#
8# This program is free software: you can redistribute it and/or modify
9# it under the terms of the GNU General Public License as published by
10# the Free Software Foundation, either version 3 of the License, or
11# (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU General Public License for more details.
17#
18# You should have received a copy of the LSST License Statement and
19# the GNU General Public License along with this program. If not,
20# see <http://www.lsstcorp.org/LegalNotices/>.
21#
23import unittest
25import numpy as np
27import lsst.geom
28import lsst.utils.tests
29import lsst.pex.exceptions
30import lsst.afw.geom.ellipses
31import lsst.shapelet.tests
32import lsst.afw.image
35class ProjectionTestCase(lsst.shapelet.tests.ShapeletTestCase):
37 def setUp(self):
38 np.random.seed(500)
39 self.ghp = lsst.shapelet.GaussHermiteProjection(16)
41 def testRotation(self):
42 order = 4
43 size = lsst.shapelet.computeSize(order)
44 nPoints = 100
45 unitCircle = lsst.afw.geom.ellipses.Ellipse(lsst.afw.geom.ellipses.Quadrupole(1.0, 1.0, 0.0))
46 # This matrix should represent a pure rotation in shapelet space, which can be done exactly.
47 inputTransform = lsst.geom.LinearTransform.makeRotation(0.0*lsst.geom.radians)
48 outputTransform = lsst.geom.LinearTransform.makeRotation(np.pi/3*lsst.geom.radians)
49 m = self.ghp.compute(inputTransform, order, outputTransform, order)
50 # If we apply a rotation by np.pi/3 six times, we should get back where we started with.
51 self.assertFloatsAlmostEqual(np.linalg.matrix_power(m, 6),
52 np.identity(size), rtol=1E-14, atol=1E-14)
53 # Now we test that we get the same result (up to round-off error) for a bunch of test points.
54 inputTestPoints = np.random.randn(2, nPoints)
55 outputTestPoints = np.dot(outputTransform.getMatrix(), inputTestPoints)
56 inputBuilder = lsst.shapelet.MatrixBuilderD.Factory(inputTestPoints[0, :],
57 inputTestPoints[1, :], order)()
58 outputBuilder = lsst.shapelet.MatrixBuilderD.Factory(outputTestPoints[0, :],
59 outputTestPoints[1, :], order)()
60 inputBasis = inputBuilder(unitCircle)
61 outputBasis = outputBuilder(unitCircle)
62 self.assertFloatsAlmostEqual(np.dot(outputBasis, m), inputBasis, rtol=1E-13)
64 def testPerturbation(self):
65 inputEllipse = lsst.afw.geom.ellipses.Quadrupole(2.0, 2.0, 0.0)
66 outputEllipse = lsst.afw.geom.ellipses.Quadrupole(2.01, 2.0, 0.02)
67 inputShapelet = lsst.shapelet.ShapeletFunction(2, lsst.shapelet.HERMITE,
68 lsst.afw.geom.ellipses.Ellipse(inputEllipse))
69 outputShapelet = lsst.shapelet.ShapeletFunction(8, lsst.shapelet.HERMITE,
70 lsst.afw.geom.ellipses.Ellipse(outputEllipse))
71 m = self.ghp.compute(inputEllipse, inputShapelet.getOrder(),
72 outputEllipse, outputShapelet.getOrder())
73 x = np.random.randn(50)
74 y = np.random.randn(50)
75 for i, nx, ny in lsst.shapelet.HermiteIndexGenerator(2):
76 inputShapelet.getCoefficients()[:] = 0.0
77 inputShapelet.getCoefficients()[i] = 1.0
78 outputShapelet.getCoefficients()[:] = np.dot(m, inputShapelet.getCoefficients())
79 inputEv = inputShapelet.evaluate()
80 outputEv = outputShapelet.evaluate()
81 inputZ = np.array([inputEv(px, py) for px, py in zip(x, y)])
82 outputZ = np.array([outputEv(px, py) for px, py in zip(x, y)])
83 # tolerances here aren't rigorous, because we're testing an approximation without
84 # computing how good it should be; it's mostly just a regression/sanity test
85 self.assertFloatsAlmostEqual(inputZ, outputZ, rtol=5E-3)
87 def testConvolution0(self):
88 """Test that the specialization for zeroth-order convolution produces the same tensor
89 as the general case, which is tested more rigorously elsewhere."""
90 psf = self.makeRandomShapeletFunction(order=4)
91 ellipse1 = lsst.afw.geom.ellipses.Ellipse(lsst.afw.geom.ellipses.Quadrupole(2.0, 3.0, 1.0))
92 ellipse2 = lsst.afw.geom.ellipses.Ellipse(ellipse1)
93 ghcN = lsst.shapelet.GaussHermiteConvolution(1, psf)
94 ghc0 = lsst.shapelet.GaussHermiteConvolution(0, psf)
95 rN = ghcN.evaluate(ellipse1)
96 r0 = ghc0.evaluate(ellipse2)
97 self.assertFloatsAlmostEqual(rN[:15, 0], r0[:15, 0], rtol=1E-14)
100class MemoryTester(lsst.utils.tests.MemoryTestCase):
101 pass
104def setup_module(module):
105 lsst.utils.tests.init()
108if __name__ == "__main__": 108 ↛ 109line 108 didn't jump to line 109, because the condition on line 108 was never true
109 lsst.utils.tests.init()
110 unittest.main()