Coverage for tests/test_chebyshev.py: 26%

64 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2023-06-09 04:04 -0700

1# See COPYRIGHT file at the top of the source tree. 

2# 

3# This file is part of fgcmcal. 

4# 

5# Developed for the LSST Data Management System. 

6# This product includes software developed by the LSST Project 

7# (https://www.lsst.org). 

8# See the COPYRIGHT file at the top-level directory of this distribution 

9# for details of code ownership. 

10# 

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

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

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

14# (at your option) any later version. 

15# 

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

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

18# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 

19# GNU General Public License for more details. 

20# 

21# You should have received a copy of the GNU General Public License 

22# along with this program. If not, see <https://www.gnu.org/licenses/>. 

23"""Test the fgcm and fgcmcal (stack) chebyshev polynomial code. 

24 

25Run small tests to ensure that the two chebyshev implementations are 

26equivalent. The fgcm chebyshev polynomial code 

27(`fgcm.fgcmUtilities.Cheb2dField`) was developed independently of the stack 

28`lsst.afw.math.ChebyshevBoundedField`, so as to avoid dependencies. 

29""" 

30 

31import unittest 

32import numpy as np 

33 

34import lsst.afw.math as afwMath 

35import lsst.geom 

36 

37import matplotlib 

38matplotlib.use("Agg") 

39 

40import fgcm # noqa: E402 

41 

42 

43class FgcmChebyshevTest(lsst.utils.tests.TestCase): 

44 """ 

45 Test the fgcm and fgcmcal (stack) chebyshev polynomial code. 

46 """ 

47 def setUp(self): 

48 """ 

49 Set up test class. 

50 """ 

51 self.xSize = 2000 

52 self.ySize = 4000 

53 self.nStar = 1000 

54 

55 self.order = 2 

56 self.pars = np.zeros((self.order + 1, self.order + 1)) 

57 self.pars[0, 0] = 1.0 

58 self.pars[0, 1] = 3e-3 

59 self.pars[0, 2] = 1e-5 

60 self.pars[1, 0] = 5e-3 

61 self.pars[1, 1] = 7e-6 

62 self.pars[1, 2] = 0.0 

63 self.pars[2, 0] = 3e-5 

64 self.pars[2, 1] = 0.0 

65 self.pars[2, 2] = 0.0 

66 

67 self.order2 = 1 

68 self.pars2 = np.zeros((self.order2 + 1, self.order2 + 1)) 

69 self.pars2[0, 0] = 0.98 

70 self.pars2[0, 1] = 5e-3 

71 self.pars2[1, 0] = 2e-2 

72 

73 def test_chebyshev_evaluate(self, seed=1000): 

74 """ 

75 Test the evaluation of chebyshev polynomials. 

76 

77 Parameters 

78 ---------- 

79 seed: `int`, optional 

80 Numpy random seed 

81 """ 

82 # Set numpy seed for stability 

83 np.random.seed(seed=seed) 

84 

85 xPos = self.xSize * np.random.rand(self.nStar) 

86 yPos = self.ySize * np.random.rand(self.nStar) 

87 

88 bbox = lsst.geom.Box2I(lsst.geom.Point2I(0, 0), 

89 lsst.geom.Point2I(self.xSize - 1, self.ySize - 1)) 

90 

91 # Compute the chebyshev values using the fgcm code 

92 fgcmField = fgcm.fgcmUtilities.Cheb2dField(self.xSize, self.ySize, 

93 self.pars) 

94 fgcmValues = fgcmField.evaluate(xPos, yPos) 

95 

96 # Compute the chebyshev values using the afw code 

97 field = afwMath.ChebyshevBoundedField(bbox, self.pars) 

98 fieldValues = field.evaluate(xPos, yPos) 

99 

100 self.assertFloatsAlmostEqual(fieldValues, fgcmValues, rtol=1e-14) 

101 

102 def test_chebyshev_fit(self, seed=1000): 

103 """ 

104 Test the fitting of chebyshev polynomials. 

105 

106 Parameters 

107 ---------- 

108 seed: `int`, optional 

109 Numpy random seed 

110 """ 

111 # Set numpy seed for stability 

112 np.random.seed(seed=seed) 

113 

114 # Generate some points to fit 

115 xPos = self.xSize * np.random.rand(self.nStar) 

116 yPos = self.ySize * np.random.rand(self.nStar) 

117 fgcmField = fgcm.fgcmUtilities.Cheb2dField(self.xSize, self.ySize, 

118 self.pars) 

119 fgcmValues = fgcmField.evaluate(xPos, yPos) 

120 

121 # Fit the points using the fgcm code 

122 fgcmField = fgcm.fgcmUtilities.Cheb2dField.fit(self.xSize, self.ySize, 

123 self.order, xPos, yPos, 

124 fgcmValues) 

125 

126 # Fit the points using the afw code 

127 bbox = lsst.geom.Box2I(lsst.geom.Point2I(0, 0), 

128 lsst.geom.Point2I(self.xSize - 1, self.ySize - 1)) 

129 

130 ctrl = afwMath.ChebyshevBoundedFieldControl() 

131 ctrl.orderX = self.order 

132 ctrl.orderY = self.order 

133 ctrl.triangular = True 

134 field = afwMath.ChebyshevBoundedField.fit(bbox, xPos, yPos, 

135 fgcmValues, ctrl) 

136 

137 # Compare the fit parameters 

138 # The tolerance here must be looser than the application, I believe 

139 # because of rounding errors in the fit implementations. But the 

140 # good news is that a tolerance of 1e-9 in parameters in these 

141 # tests yields a recovered tolerance of < 1e-14. 

142 self.assertFloatsAlmostEqual(fgcmField.pars, field.getCoefficients(), 

143 rtol=1e-9) 

144 

145 # And compare the input and output 

146 fgcmValues2 = fgcmField.evaluate(xPos, yPos) 

147 fieldValues2 = field.evaluate(xPos, yPos) 

148 

149 self.assertFloatsAlmostEqual(fgcmValues, fgcmValues2, rtol=1e-14) 

150 self.assertFloatsAlmostEqual(fgcmValues2, fieldValues2, rtol=1e-14) 

151 

152 

153class TestMemory(lsst.utils.tests.MemoryTestCase): 

154 pass 

155 

156 

157def setup_module(module): 

158 lsst.utils.tests.init() 

159 

160 

161if __name__ == "__main__": 161 ↛ 162line 161 didn't jump to line 162, because the condition on line 161 was never true

162 lsst.utils.tests.init() 

163 unittest.main()