Coverage for tests/test_Circle.py: 19%

120 statements  

« prev     ^ index     » next       coverage.py v7.5.0, created at 2024-05-02 03:12 -0700

1# This file is part of sphgeom. 

2# 

3# Developed for the LSST Data Management System. 

4# This product includes software developed by the LSST Project 

5# (http://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 software is dual licensed under the GNU General Public License and also 

10# under a 3-clause BSD license. Recipients may choose which of these licenses 

11# to use; please see the files gpl-3.0.txt and/or bsd_license.txt, 

12# respectively. If you choose the GPL option then the following text applies 

13# (but note that there is still no warranty even if you opt for BSD instead): 

14# 

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

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

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

18# (at your option) any later version. 

19# 

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

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

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

23# GNU General Public License for more details. 

24# 

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

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

27 

28import pickle 

29 

30try: 

31 import yaml 

32except ImportError: 

33 yaml = None 

34 

35import math 

36import unittest 

37 

38import numpy as np 

39from lsst.sphgeom import CONTAINS, DISJOINT, Angle, Circle, Region, UnitVector3d 

40 

41 

42class CircleTestCase(unittest.TestCase): 

43 """Test Circle.""" 

44 

45 def setUp(self): 

46 np.random.seed(1) 

47 

48 def test_construction(self): 

49 self.assertTrue(Circle.empty().isEmpty()) 

50 self.assertTrue(Circle().isEmpty()) 

51 self.assertTrue(Circle.full().isFull()) 

52 c = Circle(UnitVector3d.X()) 

53 self.assertEqual(c.getOpeningAngle(), Angle(0)) 

54 self.assertEqual(c.getSquaredChordLength(), 0) 

55 c = Circle(UnitVector3d.Z(), 2.0) 

56 self.assertTrue(c.contains(UnitVector3d.Z())) 

57 c = Circle(UnitVector3d.Z(), Angle(math.pi)) 

58 self.assertTrue(c.isFull()) 

59 d = c.clone() 

60 self.assertEqual(c, d) 

61 self.assertNotEqual(id(c), id(d)) 

62 e = Circle(d) 

63 self.assertEqual(d, e) 

64 

65 def test_comparison_operators(self): 

66 c = Circle(UnitVector3d.X(), 4.0) 

67 d = Circle(UnitVector3d.Y(), 4.0) 

68 self.assertEqual(c, d) 

69 self.assertTrue(c.isFull()) 

70 self.assertNotEqual(c, Circle(UnitVector3d.Z())) 

71 

72 def test_center_and_dimensions(self): 

73 c = Circle(UnitVector3d.X(), 1) 

74 self.assertEqual(c.getCenter(), UnitVector3d.X()) 

75 self.assertEqual(c.getSquaredChordLength(), 1) 

76 self.assertAlmostEqual(c.getOpeningAngle().asRadians(), math.pi / 3) 

77 

78 def test_relationships(self): 

79 c = Circle(UnitVector3d.X(), Angle.fromDegrees(0.1)) 

80 d = Circle(UnitVector3d(1, 1, 1), Angle(math.pi / 2)) 

81 e = Circle(-UnitVector3d.X()) 

82 self.assertTrue(c.contains(UnitVector3d.X())) 

83 self.assertTrue(UnitVector3d.X() in c) 

84 self.assertTrue(d.contains(c)) 

85 self.assertTrue(c.isWithin(d)) 

86 self.assertTrue(c.intersects(d)) 

87 self.assertTrue(c.intersects(UnitVector3d.X())) 

88 self.assertTrue(e.isDisjointFrom(d)) 

89 self.assertEqual(d.relate(c), CONTAINS) 

90 self.assertEqual(e.relate(d), DISJOINT) 

91 

92 def test_vectorized_contains(self): 

93 b = Circle(UnitVector3d(*np.random.randn(3)), Angle(0.4 * math.pi)) 

94 x = np.random.rand(5, 3) 

95 y = np.random.rand(5, 3) 

96 z = np.random.rand(5, 3) 

97 c = b.contains(x, y, z) 

98 lon = np.arctan2(y, x) 

99 lat = np.arctan2(z, np.hypot(x, y)) 

100 c2 = b.contains(lon, lat) 

101 for i in range(x.shape[0]): 

102 for j in range(x.shape[1]): 

103 u = UnitVector3d(x[i, j], y[i, j], z[i, j]) 

104 self.assertEqual(c[i, j], b.contains(u)) 

105 self.assertEqual(c2[i, j], b.contains(u)) 

106 # test with non-contiguous memory 

107 c3 = b.contains(x[::2], y[::2], z[::2]) 

108 c4 = b.contains(lon[::2], lat[::2]) 

109 for i in range(x.shape[0], 2): 

110 for j in range(x.shape[1]): 

111 u = UnitVector3d(x[i, j], y[i, j], z[i, j]) 

112 self.assertEqual(c3[i // 2, j], b.contains(u)) 

113 self.assertEqual(c4[i // 2, j], b.contains(u)) 

114 

115 def test_expanding_and_clipping(self): 

116 a = Circle.empty() 

117 b = ( 

118 a.expandedTo(UnitVector3d.X()) 

119 .expandedTo(Circle(UnitVector3d.Y(), 1)) 

120 .clippedTo(Circle(UnitVector3d(1, 1, 0), 1)) 

121 .clippedTo(UnitVector3d.Y()) 

122 ) 

123 a.expandTo(UnitVector3d.X()) 

124 a.expandTo(Circle(UnitVector3d.Y(), 1)) 

125 a.clipTo(Circle(UnitVector3d(1, 1, 0), 1)) 

126 a.clipTo(UnitVector3d.Y()) 

127 self.assertEqual(a, b) 

128 self.assertEqual(a, Circle(UnitVector3d.Y())) 

129 a.clipTo(UnitVector3d.Z()) 

130 self.assertTrue(a.isEmpty()) 

131 

132 def test_dilation_and_erosion(self): 

133 a = Angle(math.pi / 2) 

134 c = Circle(UnitVector3d.X()) 

135 d = c.dilatedBy(a).erodedBy(a) 

136 c.dilateBy(a).erodeBy(a) 

137 self.assertEqual(c, d) 

138 self.assertEqual(c, Circle(UnitVector3d.X())) 

139 

140 def test_complement(self): 

141 c = Circle(UnitVector3d.X(), 2.0) 

142 d = c.complemented() 

143 c.complement() 

144 self.assertEqual(c, d) 

145 self.assertEqual(c.getCenter(), -UnitVector3d.X()) 

146 self.assertEqual(c.getSquaredChordLength(), 2.0) 

147 

148 def test_area(self): 

149 c = Circle(UnitVector3d(1, 1, 1), 2.0) 

150 self.assertAlmostEqual(c.getArea(), 2 * math.pi) 

151 

152 def test_codec(self): 

153 c = Circle(UnitVector3d.Y(), 1.0) 

154 s = c.encode() 

155 self.assertEqual(Circle.decode(s), c) 

156 self.assertEqual(Region.decode(s), c) 

157 

158 def test_string(self): 

159 c = Circle(UnitVector3d.Z(), Angle(1.0)) 

160 self.assertEqual(str(c), "Circle([0.0, 0.0, 1.0], 1.0)") 

161 self.assertEqual(repr(c), "Circle(UnitVector3d(0.0, 0.0, 1.0), Angle(1.0))") 

162 self.assertEqual(c, eval(repr(c), {"Angle": Angle, "Circle": Circle, "UnitVector3d": UnitVector3d})) 

163 

164 def test_pickle(self): 

165 a = Circle(UnitVector3d(1, -1, 1), 1.0) 

166 b = pickle.loads(pickle.dumps(a, pickle.HIGHEST_PROTOCOL)) 

167 self.assertEqual(a, b) 

168 

169 @unittest.skipIf(not yaml, "YAML module can not be imported") 

170 def test_yaml(self): 

171 a = Circle(UnitVector3d(1, -1, 1), 1.0) 

172 b = yaml.safe_load(yaml.dump(a)) 

173 self.assertEqual(a, b) 

174 

175 

176if __name__ == "__main__": 

177 unittest.main()