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

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

# 

# LSST Data Management System 

# Copyright 2008-2017 LSST Corporation. 

# 

# This product includes software developed by the 

# LSST Project (http://www.lsst.org/). 

# 

# This program is free software: you can redistribute it and/or modify 

# it under the terms of the GNU General Public License as published by 

# the Free Software Foundation, either version 3 of the License, or 

# (at your option) any later version. 

# 

# This program is distributed in the hope that it will be useful, 

# but WITHOUT ANY WARRANTY; without even the implied warranty of 

# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 

# GNU General Public License for more details. 

# 

# You should have received a copy of the LSST License Statement and 

# the GNU General Public License along with this program. If not, 

# see <http://www.lsstcorp.org/LegalNotices/>. 

# 

 

import unittest 

import os 

 

import numpy as np 

 

import lsst.utils.tests 

import lsst.afw.geom 

import lsst.afw.geom.ellipses as el 

import lsst.shapelet.tractor 

import lsst.shapelet.tests 

import lsst.afw.image 

 

# These parameters match those used to generate the check images; see 

# tests/data/generate.py 

GALAXY_RADIUS = 8.0 

PSF_SIGMA = 2.0 

E1 = 0.3 

E2 = -0.2 

PROFILES = [ 

("exp", 9, 8), 

("dev", 9, 8), 

] 

 

CHECK_COMPONENT_IMAGES = False 

 

 

class ProfileTestCase(lsst.shapelet.tests.ShapeletTestCase): 

 

def testRadii(self): 

"""Check RadialProfile definitions of moments and half-light radii. 

""" 

s = np.linspace(-20.0, 20.0, 1000) 

x, y = np.meshgrid(s, s) 

r = (x**2 + y**2)**0.5 

dxdy = (s[1] - s[0])**2 

for name in ["gaussian", "exp", "ser2", "luv", "lux"]: 

profile = lsst.shapelet.RadialProfile.get(name) 

z = profile.evaluate(r) * dxdy 

# lux and luv don't use the true half-light radius; instead they use the half-light radius 

# of the exp and dev profiles they approximate 

if not name.startswith("lu"): 

self.assertFloatsAlmostEqual(z[r < 1].sum(), 0.5*z.sum(), rtol=0.01) 

# lhs of this comparison is the moments radius (using a sum approximation to the integral) 

self.assertFloatsAlmostEqual(((z*x**2).sum() / z.sum())**0.5, 

profile.getMomentsRadiusFactor(), rtol=0.01) 

 

def testGaussian(self): 

"""Test that the Gaussian profile's shapelet 'approximation' is actually exact. 

""" 

profile = lsst.shapelet.RadialProfile.get("gaussian") 

r = np.linspace(0.0, 4.0, 100) 

z1 = profile.evaluate(r) 

basis = profile.getBasis(1) 

z2 = lsst.shapelet.tractor.evaluateRadial(basis, r, sbNormalize=True)[0, :] 

self.assertFloatsAlmostEqual(z1, z2, rtol=1E-8) 

 

def testShapeletApproximations(self): 

psf0 = lsst.shapelet.ShapeletFunction(0, lsst.shapelet.HERMITE, PSF_SIGMA) 

psf0.getCoefficients()[:] = 1.0 / lsst.shapelet.ShapeletFunction.FLUX_FACTOR 

psf = lsst.shapelet.MultiShapeletFunction() 

psf.addComponent(psf0) 

psf.normalize() 

ellipse = el.Separable[el.Distortion, el.DeterminantRadius](E1, E2, GALAXY_RADIUS) 

for name, nComponents, maxRadius in PROFILES: 

# check1 is the multi-Gaussian approximation, as convolved and evaluated by GalSim, 

check1 = lsst.afw.image.ImageD(os.path.join("tests", "data", name + "-approx.fits")).getArray() 

xc = check1.shape[1] // 2 

yc = check1.shape[0] // 2 

xb = np.arange(check1.shape[1], dtype=float) - xc 

yb = np.arange(check1.shape[0], dtype=float) - yc 

xg, yg = np.meshgrid(xb, yb) 

 

basis = lsst.shapelet.RadialProfile.get(name).getBasis(nComponents, maxRadius) 

builder = lsst.shapelet.MatrixBuilderD.Factory(xg.ravel(), yg.ravel(), basis, psf)() 

image1 = np.zeros(check1.shape, dtype=float) 

matrix = image1.reshape(check1.size, 1) 

builder(matrix, el.Ellipse(ellipse)) 

self.assertFloatsAlmostEqual(check1, image1, plotOnFailure=False, rtol=5E-5, relTo=check1.max()) 

msf = basis.makeFunction(el.Ellipse(ellipse, lsst.afw.geom.Point2D(xc, yc)), 

np.array([1.0], dtype=float)) 

msf = msf.convolve(psf) 

image2 = np.zeros(check1.shape, dtype=float) 

msf.evaluate().addToImage(lsst.afw.image.ImageD(image2, False)) 

self.assertFloatsAlmostEqual(check1, image2, plotOnFailure=False, rtol=5E-5, relTo=check1.max()) 

 

if name == 'exp': 

# check2 is the exact profile, again by GalSim. 

# We only check exp against the exact profile. The other approximations are less 

# accurate, and we only really need to test one. The real measure of whether these 

# profiles are good enough is more complicated than what we can do in a unit test. 

check2 = lsst.afw.image.ImageD( 

os.path.join("tests", "data", name + "-exact.fits") 

).getArray() 

self.assertFloatsAlmostEqual(check2, image1, plotOnFailure=False, 

rtol=1E-3, relTo=check2.max()) 

 

if CHECK_COMPONENT_IMAGES: 

# This was once useful for debugging test failures, and may be again, but it's 

# redundant with the above and requires putting more check images in git, so 

# it's disabled by default. 

for n, sf in enumerate(msf.getComponents()): 

check = lsst.afw.image.ImageD( 

os.path.join("tests", "data", "%s-approx-%0d.fits" % (name, n)) 

).getArray() 

image = np.zeros(check1.shape, dtype=float) 

sf.evaluate().addToImage(lsst.afw.image.ImageD(image, False)) 

self.assertFloatsAlmostEqual(check, image, plotOnFailure=False, 

rtol=5E-5, relTo=check1.max()) 

 

 

class MemoryTester(lsst.utils.tests.MemoryTestCase): 

pass 

 

 

def setup_module(module): 

lsst.utils.tests.init() 

 

 

141 ↛ 142line 141 didn't jump to line 142, because the condition on line 141 was never trueif __name__ == "__main__": 

lsst.utils.tests.init() 

unittest.main()