Coverage for tests / test_plotting_limits.py: 32%

112 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-04-28 08:31 +0000

1# This file is part of utils. 

2# 

3# Developed for the LSST Data Management System. 

4# This product includes software developed by the LSST Project 

5# (https://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 program is free software: you can redistribute it and/or modify 

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

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

12# (at your option) any later version. 

13# 

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

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

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

17# GNU General Public License for more details. 

18# 

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

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

21 

22import unittest 

23 

24import numpy as np 

25 

26from lsst.utils.plotting.limits import calculate_safe_plotting_limits, make_calculate_safe_plotting_limits 

27 

28 

29class PlottingLimitsClosureTestCase(unittest.TestCase): 

30 """Tests for `make_calculate_safe_plotting_limits` function.""" 

31 

32 xs = np.linspace(0, 10, 10000) 

33 series1 = np.sin(xs + 3.1415 / 2) + 0.75 # min=-0.24999, max=1.74999 

34 series1_min = min(series1) 

35 series1_max = max(series1) 

36 

37 series2 = np.sin(xs) + 1.2 # min=0.2, max=2.19999 

38 series2_min = min(series2) 

39 series2_max = max(series2) 

40 

41 outliers = series1[:] 

42 outliers[1000] = 20 

43 outliers[2000] = -1000 

44 

45 def testSingleSeries(self): 

46 """Test that a single series works and the outliers exclusion works.""" 

47 # Deliberately test the bounds are the same when using the series 

48 # itself, and the copy with the outlier values, i.e. using 

49 # self.series1_min/max inside the loop despite changing the series we 

50 # loop over is the intent here, not a bug. 

51 for series in [self.series1, self.outliers]: 

52 ymin, ymax = make_calculate_safe_plotting_limits()(series) 

53 self.assertLess(ymin, self.series1_min) 

54 self.assertGreater(ymin, self.series1_min - 1) 

55 self.assertLess(ymax, self.series1_max + 1) 

56 self.assertGreater(ymax, self.series1_max) 

57 

58 def testMultipleSeries(self): 

59 """Test that passing multiple several series in works wrt outliers.""" 

60 calculate_safe_plotting_limits_accumulator = make_calculate_safe_plotting_limits() 

61 _, _ = calculate_safe_plotting_limits_accumulator(self.series1) 

62 ymin, ymax = calculate_safe_plotting_limits_accumulator(self.outliers) 

63 

64 self.assertLess(ymin, self.series1_min) 

65 self.assertGreater(ymin, self.series1_min - 1) 

66 self.assertLess(ymax, self.series1_max + 1) 

67 self.assertGreater(ymax, self.series1_max) 

68 

69 def testMultipleSeriesCommonRange(self): 

70 """Test that passing multiple several series in works wrt outliers.""" 

71 calculate_safe_plotting_limits_accumulator = make_calculate_safe_plotting_limits() 

72 _, _ = calculate_safe_plotting_limits_accumulator(self.series1) 

73 ymin, ymax = calculate_safe_plotting_limits_accumulator(self.series2) 

74 # lower bound less than the lowest of the two 

75 self.assertLess(ymin, min(self.series1_min, self.series2_min)) 

76 # lower bound less than the lowest of the two, but not by much 

77 self.assertGreater(ymin, min(self.series1_min, self.series2_min) - 1) 

78 # upper bound greater than the highest of the two 

79 self.assertGreater(ymax, max(self.series1_max, self.series2_max)) 

80 # upper bound greater than the highest of the two, but not by much 

81 self.assertLess(ymax, max(self.series1_max, self.series2_max) + 1) 

82 

83 def testSymmetric(self): 

84 """Test that the symmetric option works.""" 

85 calc = make_calculate_safe_plotting_limits(symmetric_around_zero=True) 

86 _, _ = calc(self.series1) 

87 ymin, ymax = calc(self.outliers) 

88 

89 self.assertEqual(ymin, -ymax) 

90 self.assertGreater(ymax, self.series1_max) 

91 self.assertLess(ymin, self.series1_min) 

92 

93 def testConstantExtra(self): 

94 """Test that the constantExtra option works.""" 

95 calc = make_calculate_safe_plotting_limits(constant_extra=0) 

96 _, _ = calc(self.series1) 

97 strictMin, strictMax = calc(self.outliers) 

98 

99 self.assertAlmostEqual(strictMin, self.series1_min, places=4) 

100 self.assertAlmostEqual(strictMax, self.series1_max, places=4) 

101 

102 for extra in [-2.123, -1, 0, 1, 1.5, 23]: 

103 calc = make_calculate_safe_plotting_limits(constant_extra=extra) 

104 _, _ = calc(self.series1) 

105 ymin, ymax = calc(self.outliers) 

106 

107 self.assertAlmostEqual(ymin, self.series1_min - extra, places=4) 

108 self.assertAlmostEqual(ymax, self.series1_max + extra, places=4) 

109 

110 def testSeriesOfSeries(self): 

111 """Test that we can pass a list of series to the accumulator in one.""" 

112 calculate_safe_plotting_limits_accumulator = make_calculate_safe_plotting_limits() 

113 ymin, ymax = calculate_safe_plotting_limits_accumulator([self.series1, self.outliers]) 

114 

115 self.assertLess(ymin, self.series1_min) 

116 self.assertGreater(ymin, self.series1_min - 1) 

117 self.assertLess(ymax, self.series1_max + 1) 

118 self.assertGreater(ymax, self.series1_max) 

119 

120 def testRaises(self): 

121 with self.assertRaises(TypeError): 

122 make_calculate_safe_plotting_limits()(1.234) 

123 

124 

125class PlottingLimitsTestCase(unittest.TestCase): 

126 """Tests for `calculate_safe_plotting_limits` function.""" 

127 

128 xs = np.linspace(0, 10, 10000) 

129 series1 = np.sin(xs + 3.1415 / 2) + 0.75 # min=-0.24999, max=1.74999 

130 series1_min = min(series1) 

131 series1_max = max(series1) 

132 

133 series2 = np.sin(xs) + 1.2 # min=0.2, max=2.19999 

134 series2_min = min(series2) 

135 series2_max = max(series2) 

136 

137 outliers = series1[:] 

138 outliers[1000] = 20 

139 outliers[2000] = -1000 

140 

141 def testSingleSeries(self): 

142 """Test that a single series works and the outliers exclusion works.""" 

143 # Deliberately test the bounds are the same when using the series 

144 # itself, and the copy with the outlier values, i.e. using 

145 # self.series1_min/max inside the loop despite changing the series we 

146 # loop over is the intent here, not a bug. 

147 for series in [self.series1, self.outliers]: 

148 ymin, ymax = calculate_safe_plotting_limits(series) 

149 self.assertLess(ymin, self.series1_min) 

150 self.assertGreater(ymin, self.series1_min - 1) 

151 self.assertLess(ymax, self.series1_max + 1) 

152 self.assertGreater(ymax, self.series1_max) 

153 

154 def testMultipleSeries(self): 

155 """Test that passing multiple several series in works wrt outliers.""" 

156 ymin, ymax = calculate_safe_plotting_limits([self.series1, self.outliers]) 

157 self.assertLess(ymin, self.series1_min) 

158 self.assertGreater(ymin, self.series1_min - 1) 

159 self.assertLess(ymax, self.series1_max + 1) 

160 self.assertGreater(ymax, self.series1_max) 

161 

162 def testMultipleSeriesCommonRange(self): 

163 """Test that passing multiple several series in works wrt outliers.""" 

164 ymin, ymax = calculate_safe_plotting_limits([self.series1, self.series2]) 

165 # lower bound less than the lowest of the two 

166 self.assertLess(ymin, min(self.series1_min, self.series2_min)) 

167 # lower bound less than the lowest of the two, but not by much 

168 self.assertGreater(ymin, min(self.series1_min, self.series2_min) - 1) 

169 # upper bound greater than the highest of the two 

170 self.assertGreater(ymax, max(self.series1_max, self.series2_max)) 

171 # upper bound greater than the highest of the two, but not by much 

172 self.assertLess(ymax, max(self.series1_max, self.series2_max) + 1) 

173 

174 def testSymmetric(self): 

175 """Test that the symmetric option works.""" 

176 ymin, ymax = calculate_safe_plotting_limits([self.series1, self.outliers], symmetric_around_zero=True) 

177 self.assertEqual(ymin, -ymax) 

178 self.assertGreater(ymax, self.series1_max) 

179 self.assertLess(ymin, self.series1_min) 

180 

181 def testConstantExtra(self): 

182 """Test that the constantExtra option works.""" 

183 strictMin, strictMax = calculate_safe_plotting_limits([self.series1, self.outliers], constant_extra=0) 

184 self.assertAlmostEqual(strictMin, self.series1_min, places=4) 

185 self.assertAlmostEqual(strictMax, self.series1_max, places=4) 

186 

187 for extra in [-2.123, -1, 0, 1, 1.5, 23]: 

188 ymin, ymax = calculate_safe_plotting_limits([self.series1, self.outliers], constant_extra=extra) 

189 self.assertAlmostEqual(ymin, self.series1_min - extra, places=4) 

190 self.assertAlmostEqual(ymax, self.series1_max + extra, places=4) 

191 

192 def testRaises(self): 

193 with self.assertRaises(TypeError): 

194 calculate_safe_plotting_limits(1.234) 

195 

196 

197if __name__ == "__main__": 

198 unittest.main()