lsst.shapelet  14.0-1-ge6e5c2d+57
tests.py
Go to the documentation of this file.
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 #
22 
23 """
24 Test utility code for shapelets library; here so it can be used
25 in multiple test scripts and tests in downstream packages.
26 """
27 from __future__ import absolute_import, division, print_function
28 from builtins import zip
29 from builtins import range
30 
31 import numpy
32 try:
33  import scipy.ndimage
34 except ImportError:
35  scipy = None
36 
37 import lsst.utils.tests
38 import lsst.afw.geom
40 
41 
43 
44  @staticmethod
45  def makeUnitVector(i, n):
46  v = numpy.zeros(n, dtype=float)
47  v[i] = 1.0
48  return v
49 
50  @staticmethod
51  def makeImage(function, x, y):
52  z = numpy.zeros((y.size, x.size), dtype=float)
53  e = function.evaluate()
54  for i, py in enumerate(y):
55  for j, px in enumerate(x):
56  z[i, j] = e(float(px), float(py))
57  return z
58 
59  @staticmethod
60  def makeRandomShapeletFunction(order=2, zeroCenter=False, ellipse=None, scale=1.0):
61  center = lsst.afw.geom.Point2D()
62  if not zeroCenter:
63  center = lsst.afw.geom.Point2D(numpy.random.randn(), numpy.random.randn())
64  if ellipse is None:
67  float(numpy.random.uniform(low=1, high=2)),
68  float(numpy.random.uniform(low=1, high=2)),
69  float(numpy.random.uniform(low=0, high=numpy.pi))
70  ),
71  center
72  )
73  coefficients = numpy.random.randn(lsst.shapelet.computeSize(order))
74  result = lsst.shapelet.ShapeletFunction(order, lsst.shapelet.HERMITE, coefficients)
75  result.setEllipse(ellipse)
76  result.getEllipse().scale(scale)
77  return result
78 
79  @staticmethod
80  def makeRandomMultiShapeletFunction(nComponents=3, ellipse=None):
81  components = []
82  for n in range(nComponents):
83  components.append(ShapeletTestCase.makeRandomShapeletFunction(ellipse=ellipse))
84  return lsst.shapelet.MultiShapeletFunction(components)
85 
86  def compareShapeletFunctions(self, a, b, rtolEllipse=1E-13, rtolCoeff=1E-13,
87  atolEllipse=1E-14, atolCoeff=1E-14):
88  self.assertEqual(a.getOrder(), b.getOrder())
89  self.assertEqual(a.getBasisType(), b.getBasisType())
90  self.assertFloatsAlmostEqual(a.getEllipse().getParameterVector(),
91  b.getEllipse().getParameterVector(),
92  rtol=rtolEllipse, atol=atolEllipse)
93  self.assertFloatsAlmostEqual(a.getCoefficients(), b.getCoefficients(),
94  rtol=rtolCoeff, atol=atolCoeff)
95 
97  keep = []
98  for s in msf.getComponents():
99  if not numpy.allclose(s.getCoefficients(), 0.0):
100  params = tuple(s.getEllipse().getParameterVector()) + tuple(s.getCoefficients())
101  keep.append((params, s))
103  keep.sort(key=lambda t: t[0])
104  for params, s in keep:
105  msf.addComponent(s)
106  return msf
107 
108  def compareMultiShapeletFunctions(self, a, b, simplify=True, rtolEllipse=1E-13, rtolCoeff=1E-13,
109  atolEllipse=1E-14, atolCoeff=1E-14):
110  if simplify:
113  self.assertEqual(len(a.getComponents()), len(b.getComponents()))
114  for sa, sb in zip(a.getComponents(), b.getComponents()):
115  self.compareShapeletFunctions(sa, sb, rtolEllipse=rtolEllipse, rtolCoeff=rtolCoeff,
116  atolEllipse=atolEllipse, atolCoeff=atolCoeff)
117 
118  def checkMoments(self, function, x, y, z):
119  gx, gy = numpy.meshgrid(x, y)
120  m = z.sum()
121  dipole = lsst.afw.geom.Point2D((gx * z).sum() / m, (gy * z).sum() / m)
122  gx -= dipole.getX()
123  gy -= dipole.getY()
125  (gx**2 * z).sum() / m,
126  (gy**2 * z).sum() / m,
127  (gx * gy * z).sum() / m
128  )
129  imageMoments = lsst.afw.geom.ellipses.Ellipse(quadrupole, dipole)
130  shapeletMoments = function.evaluate().computeMoments()
131  self.assertFloatsAlmostEqual(imageMoments.getCenter().getX(),
132  shapeletMoments.getCenter().getX(), rtol=1E-3)
133  self.assertFloatsAlmostEqual(imageMoments.getCenter().getY(),
134  shapeletMoments.getCenter().getY(), rtol=1E-3)
135  self.assertFloatsAlmostEqual(imageMoments.getCore().getIxx(),
136  shapeletMoments.getCore().getIxx(), rtol=1E-3)
137  self.assertFloatsAlmostEqual(imageMoments.getCore().getIyy(),
138  shapeletMoments.getCore().getIyy(), rtol=1E-3)
139  self.assertFloatsAlmostEqual(imageMoments.getCore().getIxy(),
140  shapeletMoments.getCore().getIxy(), rtol=1E-3)
141  integral = numpy.trapz(numpy.trapz(z, gx, axis=1), y, axis=0)
142  self.assertFloatsAlmostEqual(integral, function.evaluate().integrate(), rtol=1E-3)
143 
144  def checkConvolution(self, f1, f2):
146  i1 = lsst.afw.image.ImageD(bbox)
147  f1.evaluate().addToImage(i1)
148  self.assertFloatsAlmostEqual(i1.getArray().sum(), f1.evaluate().integrate(), rtol=1E-3)
149  i2 = lsst.afw.image.ImageD(bbox)
150  f2.evaluate().addToImage(i2)
151  self.assertFloatsAlmostEqual(i2.getArray().sum(), f2.evaluate().integrate(), rtol=1E-3)
152  fc1 = f1.convolve(f2)
153  fc2 = f2.convolve(f1)
154  ic1 = lsst.afw.image.ImageD(bbox)
155  fc1.evaluate().addToImage(ic1)
156  ic2 = lsst.afw.image.ImageD(bbox)
157  fc2.evaluate().addToImage(ic2)
158  self.assertFloatsAlmostEqual(ic1.getArray(), ic2.getArray())
159  out = lsst.afw.image.ImageD(bbox)
160  if scipy is None:
161  print("Skipping convolution test; scipy could not be imported.")
162  return
163  # I'm using scipy.ndimage to convolve test images, because I can't figure
164  # out how to make afw do it (afw can convolve images with kernels, but two similarly-sized
165  # are apparently another matter; if I try to make a FixedKernel from one of the images,
166  # I can't even make the operation commutative, let alone correct.
167  scipy.ndimage.convolve(i1.getArray(), i2.getArray(), output=out.getArray(),
168  mode="constant", cval=0.0)
169  self.assertFloatsAlmostEqual(out.getArray(), ic1.getArray(), rtol=1E-4, atol=1E-5)
170  self.assertFloatsAlmostEqual(out.getArray(), ic2.getArray(), rtol=1E-4, atol=1E-5)
171  return fc1, fc2
def makeRandomMultiShapeletFunction(nComponents=3, ellipse=None)
Definition: tests.py:80
def makeImage(function, x, y)
Definition: tests.py:51
def checkMoments(self, function, x, y, z)
Definition: tests.py:118
int computeSize(int order)
Return the size of the coefficient vector for the given order.
Definition: constants.h:97
def makeRandomShapeletFunction(order=2, zeroCenter=False, ellipse=None, scale=1.0)
Definition: tests.py:60
A multi-scale shapelet function.
def simplifyMultiShapeletFunction(self, msf)
Definition: tests.py:96
def compareMultiShapeletFunctions(self, a, b, simplify=True, rtolEllipse=1E-13, rtolCoeff=1E-13, atolEllipse=1E-14, atolCoeff=1E-14)
Definition: tests.py:109
def checkConvolution(self, f1, f2)
Definition: tests.py:144
A 2-d function defined by an expansion onto a Gauss-Laguerre or Gauss-Hermite basis.
def compareShapeletFunctions(self, a, b, rtolEllipse=1E-13, rtolCoeff=1E-13, atolEllipse=1E-14, atolCoeff=1E-14)
Definition: tests.py:87