Coverage for models/tests/test_cie_lab.py: 100%

81 statements  

« prev     ^ index     » next       coverage.py v7.11.0, created at 2025-11-16 22:49 +1300

1"""Define the unit tests for the :mod:`colour.models.cie_lab` module.""" 

2 

3from __future__ import annotations 

4 

5from itertools import product 

6 

7import numpy as np 

8 

9from colour.constants import TOLERANCE_ABSOLUTE_TESTS 

10from colour.models import Lab_to_XYZ, XYZ_to_Lab 

11from colour.utilities import domain_range_scale, ignore_numpy_errors 

12 

13__author__ = "Colour Developers" 

14__copyright__ = "Copyright 2013 Colour Developers" 

15__license__ = "BSD-3-Clause - https://opensource.org/licenses/BSD-3-Clause" 

16__maintainer__ = "Colour Developers" 

17__email__ = "colour-developers@colour-science.org" 

18__status__ = "Production" 

19 

20__all__ = [ 

21 "TestXYZ_to_Lab", 

22 "TestLab_to_XYZ", 

23] 

24 

25 

26class TestXYZ_to_Lab: 

27 """ 

28 Define :func:`colour.models.cie_lab.XYZ_to_Lab` definition unit tests 

29 methods. 

30 """ 

31 

32 def test_XYZ_to_Lab(self) -> None: 

33 """Test :func:`colour.models.cie_lab.XYZ_to_Lab` definition.""" 

34 

35 np.testing.assert_allclose( 

36 XYZ_to_Lab(np.array([0.20654008, 0.12197225, 0.05136952])), 

37 np.array([41.52787529, 52.63858304, 26.92317922]), 

38 atol=TOLERANCE_ABSOLUTE_TESTS, 

39 ) 

40 

41 np.testing.assert_allclose( 

42 XYZ_to_Lab(np.array([0.14222010, 0.23042768, 0.10495772])), 

43 np.array([55.11636304, -41.08791787, 30.91825778]), 

44 atol=TOLERANCE_ABSOLUTE_TESTS, 

45 ) 

46 

47 np.testing.assert_allclose( 

48 XYZ_to_Lab(np.array([0.07818780, 0.06157201, 0.28099326])), 

49 np.array([29.80565520, 20.01830466, -48.34913874]), 

50 atol=TOLERANCE_ABSOLUTE_TESTS, 

51 ) 

52 

53 np.testing.assert_allclose( 

54 XYZ_to_Lab( 

55 np.array([0.20654008, 0.12197225, 0.05136952]), 

56 np.array([0.44757, 0.40745]), 

57 ), 

58 np.array([41.52787529, 38.48089305, -5.73295122]), 

59 atol=TOLERANCE_ABSOLUTE_TESTS, 

60 ) 

61 

62 np.testing.assert_allclose( 

63 XYZ_to_Lab( 

64 np.array([0.20654008, 0.12197225, 0.05136952]), 

65 np.array([0.34570, 0.35850]), 

66 ), 

67 np.array([41.52787529, 51.19354174, 19.91843098]), 

68 atol=TOLERANCE_ABSOLUTE_TESTS, 

69 ) 

70 

71 np.testing.assert_allclose( 

72 XYZ_to_Lab( 

73 np.array([0.20654008, 0.12197225, 0.05136952]), 

74 np.array([0.34570, 0.35850, 1.00000]), 

75 ), 

76 np.array([41.52787529, 51.19354174, 19.91843098]), 

77 atol=TOLERANCE_ABSOLUTE_TESTS, 

78 ) 

79 

80 def test_n_dimensional_XYZ_to_Lab(self) -> None: 

81 """ 

82 Test :func:`colour.models.cie_lab.XYZ_to_Lab` definition n-dimensional 

83 support. 

84 """ 

85 

86 XYZ = np.array([0.20654008, 0.12197225, 0.05136952]) 

87 illuminant = np.array([0.31270, 0.32900]) 

88 Lab = XYZ_to_Lab(XYZ, illuminant) 

89 

90 XYZ = np.tile(XYZ, (6, 1)) 

91 Lab = np.tile(Lab, (6, 1)) 

92 np.testing.assert_allclose( 

93 XYZ_to_Lab(XYZ, illuminant), Lab, atol=TOLERANCE_ABSOLUTE_TESTS 

94 ) 

95 

96 illuminant = np.tile(illuminant, (6, 1)) 

97 np.testing.assert_allclose( 

98 XYZ_to_Lab(XYZ, illuminant), Lab, atol=TOLERANCE_ABSOLUTE_TESTS 

99 ) 

100 

101 XYZ = np.reshape(XYZ, (2, 3, 3)) 

102 illuminant = np.reshape(illuminant, (2, 3, 2)) 

103 Lab = np.reshape(Lab, (2, 3, 3)) 

104 np.testing.assert_allclose( 

105 XYZ_to_Lab(XYZ, illuminant), Lab, atol=TOLERANCE_ABSOLUTE_TESTS 

106 ) 

107 

108 def test_domain_range_scale_XYZ_to_Lab(self) -> None: 

109 """ 

110 Test :func:`colour.models.cie_lab.XYZ_to_Lab` definition 

111 domain and range scale support. 

112 """ 

113 

114 XYZ = np.array([0.20654008, 0.12197225, 0.05136952]) 

115 illuminant = np.array([0.31270, 0.32900]) 

116 Lab = XYZ_to_Lab(XYZ, illuminant) 

117 

118 d_r = (("reference", 1, 1), ("1", 1, 0.01), ("100", 100, 1)) 

119 for scale, factor_a, factor_b in d_r: 

120 with domain_range_scale(scale): 

121 np.testing.assert_allclose( 

122 XYZ_to_Lab(XYZ * factor_a, illuminant), 

123 Lab * factor_b, 

124 atol=TOLERANCE_ABSOLUTE_TESTS, 

125 ) 

126 

127 @ignore_numpy_errors 

128 def test_nan_XYZ_to_Lab(self) -> None: 

129 """Test :func:`colour.models.cie_lab.XYZ_to_Lab` definition nan support.""" 

130 

131 cases = [-1.0, 0.0, 1.0, -np.inf, np.inf, np.nan] 

132 cases = np.array(list(set(product(cases, repeat=3)))) 

133 XYZ_to_Lab(cases, cases[..., 0:2]) 

134 

135 

136class TestLab_to_XYZ: 

137 """ 

138 Define :func:`colour.models.cie_lab.Lab_to_XYZ` definition unit tests 

139 methods. 

140 """ 

141 

142 def test_Lab_to_XYZ(self) -> None: 

143 """Test :func:`colour.models.cie_lab.Lab_to_XYZ` definition.""" 

144 

145 np.testing.assert_allclose( 

146 Lab_to_XYZ(np.array([41.52787529, 52.63858304, 26.92317922])), 

147 np.array([0.20654008, 0.12197225, 0.05136952]), 

148 atol=TOLERANCE_ABSOLUTE_TESTS, 

149 ) 

150 

151 np.testing.assert_allclose( 

152 Lab_to_XYZ(np.array([55.11636304, -41.08791787, 30.91825778])), 

153 np.array([0.14222010, 0.23042768, 0.10495772]), 

154 atol=TOLERANCE_ABSOLUTE_TESTS, 

155 ) 

156 

157 np.testing.assert_allclose( 

158 Lab_to_XYZ(np.array([29.80565520, 20.01830466, -48.34913874])), 

159 np.array([0.07818780, 0.06157201, 0.28099326]), 

160 atol=TOLERANCE_ABSOLUTE_TESTS, 

161 ) 

162 

163 np.testing.assert_allclose( 

164 Lab_to_XYZ( 

165 np.array([41.52787529, 38.48089305, -5.73295122]), 

166 np.array([0.44757, 0.40745]), 

167 ), 

168 np.array([0.20654008, 0.12197225, 0.05136952]), 

169 atol=TOLERANCE_ABSOLUTE_TESTS, 

170 ) 

171 

172 np.testing.assert_allclose( 

173 Lab_to_XYZ( 

174 np.array([41.52787529, 51.19354174, 19.91843098]), 

175 np.array([0.34570, 0.35850]), 

176 ), 

177 np.array([0.20654008, 0.12197225, 0.05136952]), 

178 atol=TOLERANCE_ABSOLUTE_TESTS, 

179 ) 

180 

181 np.testing.assert_allclose( 

182 Lab_to_XYZ( 

183 np.array([41.52787529, 51.19354174, 19.91843098]), 

184 np.array([0.34570, 0.35850, 1.00000]), 

185 ), 

186 np.array([0.20654008, 0.12197225, 0.05136952]), 

187 atol=TOLERANCE_ABSOLUTE_TESTS, 

188 ) 

189 

190 def test_n_dimensional_Lab_to_XYZ(self) -> None: 

191 """ 

192 Test :func:`colour.models.cie_lab.Lab_to_XYZ` definition n-dimensional 

193 support. 

194 """ 

195 

196 Lab = np.array([41.52787529, 52.63858304, 26.92317922]) 

197 illuminant = np.array([0.31270, 0.32900]) 

198 XYZ = Lab_to_XYZ(Lab, illuminant) 

199 

200 Lab = np.tile(Lab, (6, 1)) 

201 XYZ = np.tile(XYZ, (6, 1)) 

202 np.testing.assert_allclose( 

203 Lab_to_XYZ(Lab, illuminant), XYZ, atol=TOLERANCE_ABSOLUTE_TESTS 

204 ) 

205 

206 illuminant = np.tile(illuminant, (6, 1)) 

207 np.testing.assert_allclose( 

208 Lab_to_XYZ(Lab, illuminant), XYZ, atol=TOLERANCE_ABSOLUTE_TESTS 

209 ) 

210 

211 Lab = np.reshape(Lab, (2, 3, 3)) 

212 illuminant = np.reshape(illuminant, (2, 3, 2)) 

213 XYZ = np.reshape(XYZ, (2, 3, 3)) 

214 np.testing.assert_allclose( 

215 Lab_to_XYZ(Lab, illuminant), XYZ, atol=TOLERANCE_ABSOLUTE_TESTS 

216 ) 

217 

218 def test_domain_range_scale_Lab_to_XYZ(self) -> None: 

219 """ 

220 Test :func:`colour.models.cie_lab.Lab_to_XYZ` definition 

221 domain and range scale support. 

222 """ 

223 

224 Lab = np.array([41.52787529, 52.63858304, 26.92317922]) 

225 illuminant = np.array([0.31270, 0.32900]) 

226 XYZ = Lab_to_XYZ(Lab, illuminant) 

227 

228 d_r = (("reference", 1, 1), ("1", 0.01, 1), ("100", 1, 100)) 

229 for scale, factor_a, factor_b in d_r: 

230 with domain_range_scale(scale): 

231 np.testing.assert_allclose( 

232 Lab_to_XYZ(Lab * factor_a, illuminant), 

233 XYZ * factor_b, 

234 atol=TOLERANCE_ABSOLUTE_TESTS, 

235 ) 

236 

237 @ignore_numpy_errors 

238 def test_nan_Lab_to_XYZ(self) -> None: 

239 """Test :func:`colour.models.cie_lab.Lab_to_XYZ` definition nan support.""" 

240 

241 cases = [-1.0, 0.0, 1.0, -np.inf, np.inf, np.nan] 

242 cases = np.array(list(set(product(cases, repeat=3)))) 

243 Lab_to_XYZ(cases, cases[..., 0:2])