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

104 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.hunter_rdab` module.""" 

2 

3from __future__ import annotations 

4 

5from itertools import product 

6 

7import numpy as np 

8 

9from colour.colorimetry import TVS_ILLUMINANTS_HUNTERLAB 

10from colour.constants import TOLERANCE_ABSOLUTE_TESTS 

11from colour.models import Hunter_Rdab_to_XYZ, XYZ_to_Hunter_Rdab 

12from colour.utilities import domain_range_scale, ignore_numpy_errors 

13 

14__author__ = "Colour Developers" 

15__copyright__ = "Copyright 2013 Colour Developers" 

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

17__maintainer__ = "Colour Developers" 

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

19__status__ = "Production" 

20 

21__all__ = [ 

22 "TestXYZ_to_Hunter_Rdab", 

23 "TestHunter_Rdab_to_XYZ", 

24] 

25 

26 

27class TestXYZ_to_Hunter_Rdab: 

28 """ 

29 Define :func:`colour.models.hunter_rdab.XYZ_to_Hunter_Rdab` definition 

30 unit tests methods. 

31 """ 

32 

33 def test_XYZ_to_Hunter_Rdab(self) -> None: 

34 """Test :func:`colour.models.hunter_rdab.XYZ_to_Hunter_Rdab` definition.""" 

35 

36 np.testing.assert_allclose( 

37 XYZ_to_Hunter_Rdab(np.array([0.20654008, 0.12197225, 0.05136952]) * 100), 

38 np.array([12.19722500, 57.12537874, 17.46241341]), 

39 atol=TOLERANCE_ABSOLUTE_TESTS, 

40 ) 

41 

42 np.testing.assert_allclose( 

43 XYZ_to_Hunter_Rdab(np.array([0.14222010, 0.23042768, 0.10495772]) * 100), 

44 np.array([23.04276800, -32.40057474, 20.96542183]), 

45 atol=TOLERANCE_ABSOLUTE_TESTS, 

46 ) 

47 

48 np.testing.assert_allclose( 

49 XYZ_to_Hunter_Rdab(np.array([0.07818780, 0.06157201, 0.28099326]) * 100), 

50 np.array([6.15720100, 18.13400284, -67.14408607]), 

51 atol=TOLERANCE_ABSOLUTE_TESTS, 

52 ) 

53 

54 h_i = TVS_ILLUMINANTS_HUNTERLAB["CIE 1931 2 Degree Standard Observer"] 

55 A = h_i["A"] 

56 np.testing.assert_allclose( 

57 XYZ_to_Hunter_Rdab( 

58 np.array([0.20654008, 0.12197225, 0.05136952]) * 100, 

59 A.XYZ_n, 

60 A.K_ab, 

61 ), 

62 np.array([12.19722500, 42.53572838, -3.00653110]), 

63 atol=TOLERANCE_ABSOLUTE_TESTS, 

64 ) 

65 

66 D65 = h_i["D65"] 

67 np.testing.assert_allclose( 

68 XYZ_to_Hunter_Rdab( 

69 np.array([0.20654008, 0.12197225, 0.05136952]) * 100, 

70 D65.XYZ_n, 

71 D65.K_ab, 

72 ), 

73 np.array([12.19722500, 57.12537874, 17.46241341]), 

74 atol=TOLERANCE_ABSOLUTE_TESTS, 

75 ) 

76 

77 np.testing.assert_allclose( 

78 XYZ_to_Hunter_Rdab( 

79 np.array([0.20654008, 0.12197225, 0.05136952]) * 100, 

80 D65.XYZ_n, 

81 K_ab=None, 

82 ), 

83 np.array([12.19722500, 57.11906384, 17.45962317]), 

84 atol=TOLERANCE_ABSOLUTE_TESTS, 

85 ) 

86 

87 def test_n_dimensional_XYZ_to_Hunter_Rdab(self) -> None: 

88 """ 

89 Test :func:`colour.models.hunter_rdab.XYZ_to_Hunter_Rdab` definition 

90 n-dimensional support. 

91 """ 

92 

93 h_i = TVS_ILLUMINANTS_HUNTERLAB["CIE 1931 2 Degree Standard Observer"] 

94 D65 = h_i["D65"] 

95 

96 XYZ = np.array([0.20654008, 0.12197225, 0.05136952]) * 100 

97 XYZ_n = D65.XYZ_n 

98 K_ab = D65.K_ab 

99 R_d_ab = XYZ_to_Hunter_Rdab(XYZ, XYZ_n, K_ab) 

100 

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

102 R_d_ab = np.tile(R_d_ab, (6, 1)) 

103 np.testing.assert_allclose( 

104 XYZ_to_Hunter_Rdab(XYZ, XYZ_n, K_ab), 

105 R_d_ab, 

106 atol=TOLERANCE_ABSOLUTE_TESTS, 

107 ) 

108 

109 XYZ_n = np.tile(XYZ_n, (6, 1)) 

110 K_ab = np.tile(K_ab, (6, 1)) 

111 np.testing.assert_allclose( 

112 XYZ_to_Hunter_Rdab(XYZ, XYZ_n, K_ab), 

113 R_d_ab, 

114 atol=TOLERANCE_ABSOLUTE_TESTS, 

115 ) 

116 

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

118 XYZ_n = np.reshape(XYZ_n, (2, 3, 3)) 

119 K_ab = np.reshape(K_ab, (2, 3, 2)) 

120 R_d_ab = np.reshape(R_d_ab, (2, 3, 3)) 

121 np.testing.assert_allclose( 

122 XYZ_to_Hunter_Rdab(XYZ, XYZ_n, K_ab), 

123 R_d_ab, 

124 atol=TOLERANCE_ABSOLUTE_TESTS, 

125 ) 

126 

127 def test_domain_range_scale_XYZ_to_Hunter_Rdab(self) -> None: 

128 """ 

129 Test :func:`colour.models.hunter_lab.XYZ_to_Hunter_Rdab` definition 

130 domain and range scale support. 

131 """ 

132 

133 h_i = TVS_ILLUMINANTS_HUNTERLAB["CIE 1931 2 Degree Standard Observer"] 

134 D65 = h_i["D65"] 

135 

136 XYZ = np.array([0.20654008, 0.12197225, 0.05136952]) * 100 

137 XYZ_n = D65.XYZ_n 

138 K_ab = D65.K_ab 

139 R_d_ab = XYZ_to_Hunter_Rdab(XYZ, XYZ_n, K_ab) 

140 

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

142 for scale, factor in d_r: 

143 with domain_range_scale(scale): 

144 np.testing.assert_allclose( 

145 XYZ_to_Hunter_Rdab(XYZ * factor, XYZ_n * factor, K_ab), 

146 R_d_ab * factor, 

147 atol=TOLERANCE_ABSOLUTE_TESTS, 

148 ) 

149 

150 @ignore_numpy_errors 

151 def test_nan_XYZ_to_Hunter_Rdab(self) -> None: 

152 """ 

153 Test :func:`colour.models.hunter_rdab.XYZ_to_Hunter_Rdab` definition 

154 nan support. 

155 """ 

156 

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

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

159 XYZ_to_Hunter_Rdab(cases, cases, cases[..., 0:2]) 

160 

161 

162class TestHunter_Rdab_to_XYZ: 

163 """ 

164 Define :func:`colour.models.hunter_rdab.Hunter_Rdab_to_XYZ` definition 

165 unit tests methods. 

166 """ 

167 

168 def test_Hunter_Rdab_to_XYZ(self) -> None: 

169 """Test :func:`colour.models.hunter_rdab.Hunter_Rdab_to_XYZ` definition.""" 

170 

171 np.testing.assert_allclose( 

172 Hunter_Rdab_to_XYZ(np.array([12.19722500, 57.12537874, 17.46241341])), 

173 np.array([0.20654008, 0.12197225, 0.05136952]) * 100, 

174 atol=TOLERANCE_ABSOLUTE_TESTS, 

175 ) 

176 

177 np.testing.assert_allclose( 

178 Hunter_Rdab_to_XYZ(np.array([23.04276800, -32.40057474, 20.96542183])), 

179 np.array([0.14222010, 0.23042768, 0.10495772]) * 100, 

180 atol=TOLERANCE_ABSOLUTE_TESTS, 

181 ) 

182 

183 np.testing.assert_allclose( 

184 Hunter_Rdab_to_XYZ(np.array([6.15720100, 18.13400284, -67.14408607])), 

185 np.array([0.07818780, 0.06157201, 0.28099326]) * 100, 

186 atol=TOLERANCE_ABSOLUTE_TESTS, 

187 ) 

188 

189 h_i = TVS_ILLUMINANTS_HUNTERLAB["CIE 1931 2 Degree Standard Observer"] 

190 A = h_i["A"] 

191 np.testing.assert_allclose( 

192 Hunter_Rdab_to_XYZ( 

193 np.array([12.19722500, 42.53572838, -3.00653110]), 

194 A.XYZ_n, 

195 A.K_ab, 

196 ), 

197 np.array([0.20654008, 0.12197225, 0.05136952]) * 100, 

198 atol=TOLERANCE_ABSOLUTE_TESTS, 

199 ) 

200 

201 D65 = h_i["D65"] 

202 np.testing.assert_allclose( 

203 Hunter_Rdab_to_XYZ( 

204 np.array([12.19722500, 57.12537874, 17.46241341]), 

205 D65.XYZ_n, 

206 D65.K_ab, 

207 ), 

208 np.array([0.20654008, 0.12197225, 0.05136952]) * 100, 

209 atol=TOLERANCE_ABSOLUTE_TESTS, 

210 ) 

211 

212 np.testing.assert_allclose( 

213 Hunter_Rdab_to_XYZ( 

214 np.array([12.19722500, 57.11906384, 17.45962317]), 

215 D65.XYZ_n, 

216 K_ab=None, 

217 ), 

218 np.array([0.20654008, 0.12197225, 0.05136952]) * 100, 

219 atol=TOLERANCE_ABSOLUTE_TESTS, 

220 ) 

221 

222 def test_n_dimensional_Hunter_Rdab_to_XYZ(self) -> None: 

223 """ 

224 Test :func:`colour.models.hunter_rdab.Hunter_Rdab_to_XYZ` definition 

225 n-dimensional support. 

226 """ 

227 

228 h_i = TVS_ILLUMINANTS_HUNTERLAB["CIE 1931 2 Degree Standard Observer"] 

229 D65 = h_i["D65"] 

230 

231 R_d_ab = np.array([12.19722500, 57.12537874, 17.46241341]) 

232 XYZ_n = D65.XYZ_n 

233 K_ab = D65.K_ab 

234 XYZ = Hunter_Rdab_to_XYZ(R_d_ab, XYZ_n, K_ab) 

235 

236 R_d_ab = np.tile(R_d_ab, (6, 1)) 

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

238 np.testing.assert_allclose( 

239 Hunter_Rdab_to_XYZ(R_d_ab, XYZ_n, K_ab), 

240 XYZ, 

241 atol=TOLERANCE_ABSOLUTE_TESTS, 

242 ) 

243 

244 K_ab = np.tile(K_ab, (6, 1)) 

245 XYZ_n = np.tile(XYZ_n, (6, 1)) 

246 np.testing.assert_allclose( 

247 Hunter_Rdab_to_XYZ(R_d_ab, XYZ_n, K_ab), 

248 XYZ, 

249 atol=TOLERANCE_ABSOLUTE_TESTS, 

250 ) 

251 

252 R_d_ab = np.reshape(R_d_ab, (2, 3, 3)) 

253 XYZ_n = np.reshape(XYZ_n, (2, 3, 3)) 

254 K_ab = np.reshape(K_ab, (2, 3, 2)) 

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

256 np.testing.assert_allclose( 

257 Hunter_Rdab_to_XYZ(R_d_ab, XYZ_n, K_ab), 

258 XYZ, 

259 atol=TOLERANCE_ABSOLUTE_TESTS, 

260 ) 

261 

262 def test_domain_range_scale_Hunter_Rdab_to_XYZ(self) -> None: 

263 """ 

264 Test :func:`colour.models.hunter_lab.Hunter_Rdab_to_XYZ` definition 

265 domain and range scale support. 

266 """ 

267 

268 h_i = TVS_ILLUMINANTS_HUNTERLAB["CIE 1931 2 Degree Standard Observer"] 

269 D65 = h_i["D65"] 

270 

271 R_d_ab = np.array([12.19722500, 57.12537874, 17.46241341]) 

272 XYZ_n = D65.XYZ_n 

273 K_ab = D65.K_ab 

274 XYZ = Hunter_Rdab_to_XYZ(R_d_ab, XYZ_n, K_ab) 

275 

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

277 for scale, factor in d_r: 

278 with domain_range_scale(scale): 

279 np.testing.assert_allclose( 

280 Hunter_Rdab_to_XYZ(R_d_ab * factor, XYZ_n * factor, K_ab), 

281 XYZ * factor, 

282 atol=TOLERANCE_ABSOLUTE_TESTS, 

283 ) 

284 

285 @ignore_numpy_errors 

286 def test_nan_Hunter_Rdab_to_XYZ(self) -> None: 

287 """ 

288 Test :func:`colour.models.hunter_rdab.Hunter_Rdab_to_XYZ` definition 

289 nan support. 

290 """ 

291 

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

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

294 Hunter_Rdab_to_XYZ(cases, cases, cases[..., 0:2])