Coverage for difference/tests/test_delta_e.py: 100%

235 statements  

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

1""" 

2Define the unit tests for the :mod:`colour.difference.delta_e` module. 

3 

4References 

5---------- 

6- :cite:`Sharma2005b` : Sharma, G., Wu, W., & Dalal, E. N. (2005). The 

7 CIEDE2000 color-difference formula: Implementation notes, supplementary 

8 test data, and mathematical observations. Color Research & Application, 

9 30(1), 21-30. doi:10.1002/col.20070 

10""" 

11 

12from __future__ import annotations 

13 

14from itertools import product 

15 

16import numpy as np 

17 

18from colour.algebra import euclidean_distance 

19from colour.constants import TOLERANCE_ABSOLUTE_TESTS 

20from colour.difference import ( 

21 delta_E_CIE1976, 

22 delta_E_CIE1994, 

23 delta_E_CIE2000, 

24 delta_E_CMC, 

25 delta_E_HyAB, 

26 delta_E_HyCH, 

27 delta_E_ITP, 

28) 

29from colour.difference.delta_e import intermediate_attributes_CIE2000 

30from colour.utilities import domain_range_scale, ignore_numpy_errors 

31 

32__author__ = "Colour Developers" 

33__copyright__ = "Copyright 2013 Colour Developers" 

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

35__maintainer__ = "Colour Developers" 

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

37__status__ = "Production" 

38 

39__all__ = [ 

40 "TestDelta_E_CIE1976", 

41 "TestDelta_E_CIE1994", 

42 "TestDelta_E_CIE2000", 

43 "TestDelta_E_CMC", 

44 "TestDelta_E_ITP", 

45 "TestDelta_E_HyAB", 

46 "TestDelta_E_HyCH", 

47] 

48 

49 

50class TestDelta_E_CIE1976: 

51 """ 

52 Define :func:`colour.difference.delta_e.delta_E_CIE1976` definition unit 

53 tests methods. 

54 

55 Notes 

56 ----- 

57 - :func:`colour.difference.delta_e.delta_E_CIE1976` definition is a 

58 wrapper around :func:`colour.algebra.geometry.euclidean_distance` 

59 definition, thus unit tests are not entirely implemented. 

60 """ 

61 

62 def test_delta_E_CIE1976(self) -> None: 

63 """Test :func:`colour.difference.delta_e.delta_E_CIE1976` definition.""" 

64 

65 Lab_1 = np.array([48.99183622, -0.10561667, 400.65619925]) 

66 Lab_2 = np.array([50.65907324, -0.11671910, 402.82235718]) 

67 Lab_1 = np.reshape(np.tile(Lab_1, (6, 1)), (2, 3, 3)) 

68 Lab_2 = np.reshape(np.tile(Lab_2, (6, 1)), (2, 3, 3)) 

69 

70 np.testing.assert_allclose( 

71 delta_E_CIE1976(Lab_1, Lab_2), 

72 euclidean_distance(Lab_1, Lab_2), 

73 atol=TOLERANCE_ABSOLUTE_TESTS, 

74 ) 

75 

76 def test_n_dimensional_delta_E_CIE1976(self) -> None: 

77 """ 

78 Test :func:`colour.difference.delta_e.delta_E_CIE1976` definition 

79 n-dimensional arrays support. 

80 """ 

81 

82 def test_domain_range_scale_delta_E_CIE1976(self) -> None: 

83 """ 

84 Test :func:`colour.difference.delta_e.delta_E_CIE1976` definition 

85 domain and range scale support. 

86 """ 

87 

88 Lab_1 = np.array([48.99183622, -0.10561667, 400.65619925]) 

89 Lab_2 = np.array([50.65907324, -0.11671910, 402.82235718]) 

90 

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

92 for scale, factor in d_r: 

93 with domain_range_scale(scale): 

94 np.testing.assert_allclose( 

95 delta_E_CIE1976(Lab_1 * factor, Lab_2 * factor), 

96 euclidean_distance(Lab_1, Lab_2), 

97 atol=TOLERANCE_ABSOLUTE_TESTS, 

98 ) 

99 

100 @ignore_numpy_errors 

101 def test_nan_delta_E_CIE1976(self) -> None: 

102 """ 

103 Test :func:`colour.difference.delta_e.delta_E_CIE1976` definition nan 

104 support. 

105 """ 

106 

107 

108class TestDelta_E_CIE1994: 

109 """ 

110 Define :func:`colour.difference.delta_e.delta_E_CIE1994` definition unit 

111 tests methods. 

112 """ 

113 

114 def test_delta_E_CIE1994(self) -> None: 

115 """Test :func:`colour.difference.delta_e.delta_E_CIE1994` definition.""" 

116 

117 np.testing.assert_allclose( 

118 delta_E_CIE1994( 

119 np.array([48.99183622, -0.10561667, 400.65619925]), 

120 np.array([50.65907324, -0.11671910, 402.82235718]), 

121 ), 

122 1.671119130541200, 

123 atol=TOLERANCE_ABSOLUTE_TESTS, 

124 ) 

125 

126 np.testing.assert_allclose( 

127 delta_E_CIE1994( 

128 np.array([100.00000000, 21.57210357, 272.22819350]), 

129 np.array([100.00000000, 426.67945353, 72.39590835]), 

130 ), 

131 83.779225500887094, 

132 atol=TOLERANCE_ABSOLUTE_TESTS, 

133 ) 

134 

135 np.testing.assert_allclose( 

136 delta_E_CIE1994( 

137 np.array([100.00000000, 21.57210357, 272.22819350]), 

138 np.array([100.00000000, 74.05216981, 276.45318193]), 

139 ), 

140 10.053931954553839, 

141 atol=TOLERANCE_ABSOLUTE_TESTS, 

142 ) 

143 

144 np.testing.assert_allclose( 

145 delta_E_CIE1994( 

146 np.array([100.00000000, 21.57210357, 272.22819350]), 

147 np.array([100.00000000, 426.67945353, 72.39590835]), 

148 textiles=True, 

149 ), 

150 88.335553057506502, 

151 atol=TOLERANCE_ABSOLUTE_TESTS, 

152 ) 

153 

154 np.testing.assert_allclose( 

155 delta_E_CIE1994( 

156 np.array([100.00000000, 21.57210357, 272.22819350]), 

157 np.array([100.00000000, 74.05216981, 276.45318193]), 

158 textiles=True, 

159 ), 

160 10.612657890048272, 

161 atol=TOLERANCE_ABSOLUTE_TESTS, 

162 ) 

163 

164 np.testing.assert_allclose( 

165 delta_E_CIE1994( 

166 np.array([100.00000000, 21.57210357, 272.22819350]), 

167 np.array([100.00000000, 8.32281957, -73.58297716]), 

168 textiles=True, 

169 ), 

170 60.368687261063329, 

171 atol=TOLERANCE_ABSOLUTE_TESTS, 

172 ) 

173 

174 def test_n_dimensional_delta_E_CIE1994(self) -> None: 

175 """ 

176 Test :func:`colour.difference.delta_e.delta_E_CIE1994` definition 

177 n-dimensional arrays support. 

178 """ 

179 

180 Lab_1 = np.array([48.99183622, -0.10561667, 400.65619925]) 

181 Lab_2 = np.array([50.65907324, -0.11671910, 402.82235718]) 

182 delta_E = delta_E_CIE1994(Lab_1, Lab_2) 

183 

184 Lab_1 = np.tile(Lab_1, (6, 1)) 

185 Lab_2 = np.tile(Lab_2, (6, 1)) 

186 delta_E = np.tile(delta_E, 6) 

187 np.testing.assert_allclose( 

188 delta_E_CIE1994(Lab_1, Lab_2), 

189 delta_E, 

190 atol=TOLERANCE_ABSOLUTE_TESTS, 

191 ) 

192 

193 Lab_1 = np.reshape(Lab_1, (2, 3, 3)) 

194 Lab_2 = np.reshape(Lab_2, (2, 3, 3)) 

195 delta_E = np.reshape(delta_E, (2, 3)) 

196 np.testing.assert_allclose( 

197 delta_E_CIE1994(Lab_1, Lab_2), 

198 delta_E, 

199 atol=TOLERANCE_ABSOLUTE_TESTS, 

200 ) 

201 

202 def test_domain_range_scale_delta_E_CIE1994(self) -> None: 

203 """ 

204 Test :func:`colour.difference.delta_e.delta_E_CIE1994` definition 

205 domain and range scale support. 

206 """ 

207 

208 Lab_1 = np.array([48.99183622, -0.10561667, 400.65619925]) 

209 Lab_2 = np.array([50.65907324, -0.11671910, 402.82235718]) 

210 delta_E = delta_E_CIE1994(Lab_1, Lab_2) 

211 

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

213 for scale, factor in d_r: 

214 with domain_range_scale(scale): 

215 np.testing.assert_allclose( 

216 delta_E_CIE1994(Lab_1 * factor, Lab_2 * factor), 

217 delta_E, 

218 atol=TOLERANCE_ABSOLUTE_TESTS, 

219 ) 

220 

221 @ignore_numpy_errors 

222 def test_nan_delta_E_CIE1994(self) -> None: 

223 """ 

224 Test :func:`colour.difference.delta_e.delta_E_CIE1994` definition nan 

225 support. 

226 """ 

227 

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

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

230 delta_E_CIE1994(cases, cases) 

231 

232 

233class TestIntermediateAttributes_CIE2000: 

234 """ 

235 Define :func:`colour.difference.delta_e.intermediate_attributes_CIE2000` 

236 definition unit tests methods. 

237 """ 

238 

239 def test_intermediate_attributes_CIE2000(self) -> None: 

240 """ 

241 Test :func:`colour.difference.delta_e.intermediate_attributes_CIE2000` 

242 definition. 

243 """ 

244 

245 np.testing.assert_allclose( 

246 intermediate_attributes_CIE2000( 

247 np.array([48.99183622, -0.10561667, 400.65619925]), 

248 np.array([50.65907324, -0.11671910, 402.82235718]), 

249 ), 

250 np.array( 

251 [ 

252 1.00010211, 

253 19.07826821, 

254 4.72266955, 

255 1.66723702, 

256 2.16616092, 

257 0.01050306, 

258 -0.00000000, 

259 ] 

260 ), 

261 atol=TOLERANCE_ABSOLUTE_TESTS, 

262 ) 

263 

264 

265class TestDelta_E_CIE2000: 

266 """ 

267 Define :func:`colour.difference.delta_e.delta_E_CIE2000` definition unit 

268 tests methods. 

269 """ 

270 

271 def test_delta_E_CIE2000(self) -> None: 

272 """Test :func:`colour.difference.delta_e.delta_E_CIE2000` definition.""" 

273 

274 np.testing.assert_allclose( 

275 delta_E_CIE2000( 

276 np.array([48.99183622, -0.10561667, 400.65619925]), 

277 np.array([50.65907324, -0.11671910, 402.82235718]), 

278 ), 

279 1.670930327213592, 

280 atol=TOLERANCE_ABSOLUTE_TESTS, 

281 ) 

282 

283 np.testing.assert_allclose( 

284 delta_E_CIE2000( 

285 np.array([100.00000000, 21.57210357, 272.22819350]), 

286 np.array([100.00000000, 426.67945353, 72.39590835]), 

287 ), 

288 94.03564903, 

289 atol=TOLERANCE_ABSOLUTE_TESTS, 

290 ) 

291 

292 np.testing.assert_allclose( 

293 delta_E_CIE2000( 

294 np.array([100.00000000, 21.57210357, 272.22819350]), 

295 np.array([100.00000000, 74.05216981, 276.45318193]), 

296 ), 

297 14.87906419, 

298 atol=TOLERANCE_ABSOLUTE_TESTS, 

299 ) 

300 

301 np.testing.assert_allclose( 

302 delta_E_CIE2000( 

303 np.array([100.00000000, 21.57210357, 272.22819350]), 

304 np.array([50.00000000, 426.67945353, 72.39590835]), 

305 textiles=True, 

306 ), 

307 95.79205352, 

308 atol=TOLERANCE_ABSOLUTE_TESTS, 

309 ) 

310 

311 np.testing.assert_allclose( 

312 delta_E_CIE2000( 

313 np.array([100.00000000, 21.57210357, 272.22819350]), 

314 np.array([50.00000000, 74.05216981, 276.45318193]), 

315 textiles=True, 

316 ), 

317 23.55420943, 

318 atol=TOLERANCE_ABSOLUTE_TESTS, 

319 ) 

320 

321 np.testing.assert_allclose( 

322 delta_E_CIE2000( 

323 np.array([100.00000000, 21.57210357, 272.22819350]), 

324 np.array([50.00000000, 8.32281957, -73.58297716]), 

325 textiles=True, 

326 ), 

327 70.63213819, 

328 atol=TOLERANCE_ABSOLUTE_TESTS, 

329 ) 

330 

331 def test_n_dimensional_delta_E_CIE2000(self) -> None: 

332 """ 

333 Test :func:`colour.difference.delta_e.delta_E_CIE2000` definition 

334 n-dimensional arrays support. 

335 """ 

336 

337 Lab_1 = np.array([48.99183622, -0.10561667, 400.65619925]) 

338 Lab_2 = np.array([50.65907324, -0.11671910, 402.82235718]) 

339 delta_E = delta_E_CIE2000(Lab_1, Lab_2) 

340 

341 Lab_1 = np.tile(Lab_1, (6, 1)) 

342 Lab_2 = np.tile(Lab_2, (6, 1)) 

343 delta_E = np.tile(delta_E, 6) 

344 np.testing.assert_allclose( 

345 delta_E_CIE2000(Lab_1, Lab_2), 

346 delta_E, 

347 atol=TOLERANCE_ABSOLUTE_TESTS, 

348 ) 

349 

350 Lab_1 = np.reshape(Lab_1, (2, 3, 3)) 

351 Lab_2 = np.reshape(Lab_2, (2, 3, 3)) 

352 delta_E = np.reshape(delta_E, (2, 3)) 

353 np.testing.assert_allclose( 

354 delta_E_CIE2000(Lab_1, Lab_2), 

355 delta_E, 

356 atol=TOLERANCE_ABSOLUTE_TESTS, 

357 ) 

358 

359 def test_domain_range_scale_delta_E_CIE2000(self) -> None: 

360 """ 

361 Test :func:`colour.difference.delta_e.delta_E_CIE2000` definition 

362 domain and range scale support. 

363 """ 

364 

365 Lab_1 = np.array([48.99183622, -0.10561667, 400.65619925]) 

366 Lab_2 = np.array([50.65907324, -0.11671910, 402.82235718]) 

367 delta_E = delta_E_CIE2000(Lab_1, Lab_2) 

368 

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

370 for scale, factor in d_r: 

371 with domain_range_scale(scale): 

372 np.testing.assert_allclose( 

373 delta_E_CIE2000(Lab_1 * factor, Lab_2 * factor), 

374 delta_E, 

375 atol=TOLERANCE_ABSOLUTE_TESTS, 

376 ) 

377 

378 @ignore_numpy_errors 

379 def test_nan_delta_E_CIE2000(self) -> None: 

380 """ 

381 Test :func:`colour.difference.delta_e.delta_E_CIE2000` definition nan 

382 support. 

383 """ 

384 

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

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

387 delta_E_CIE2000(cases, cases) 

388 

389 def test_delta_E_CIE2000_Sharma2004(self) -> None: 

390 """ 

391 Test :func:`colour.difference.delta_e.delta_E_CIE2000` definition 

392 using Sharma (2004) dataset. 

393 

394 References 

395 ---------- 

396 :cite:`Sharma2005b` 

397 """ 

398 

399 # NOTE: The 14th test case is excluded as "Numpy" 1.24.0 introduced 

400 # numerical differences between "Linux" and "macOS / Windows" with the 

401 # "np.arctan2" definition : 

402 # 

403 # | Ubuntu | macOS / Windows | 

404 # C_1_ab | 2.490000200803205 | 2.490000200803205 | 

405 # C_2_ab | 2.490000200803205 | 2.490000200803205 | 

406 # C_bar_ab | 2.490000200803205 | 2.490000200803205 | 

407 # C_bar_ab_7 | 593.465770158617033 | 593.465770158617033 | 

408 # G | 0.499844088629080 | 0.499844088629080 | 

409 # a_p_1 | -0.001499844088629 | -0.001499844088629 | 

410 # a_p_2 | 0.001499844088629 | 0.001499844088629 | 

411 # C_p_1 | 2.490000451713271 | 2.490000451713271 | 

412 # C_p_2 | 2.490000451713271 | 2.490000451713271 | 

413 # h_p_1 | 90.034511938077543 | 90.034511938077557 | <-- 

414 # h_p_2 | 270.034511938077571 | 270.034511938077571 | 

415 # delta_L_p | 0.000000000000000 | 0.000000000000000 | 

416 # delta_C_p | 0.000000000000000 | 0.000000000000000 | 

417 # h_p_2_s_1 | 180.000000000000028 | 180.000000000000000 | <-- 

418 # C_p_1_m_2 | 6.200102249532291 | 6.200102249532291 | 

419 # delta_h_p | -179.999999999999972 | 180.000000000000000 | <-- 

420 # delta_H_p | -4.980000903426540 | 4.980000903426541 | <-- 

421 # L_bar_p | 50.000000000000000 | 50.000000000000000 | 

422 # C_bar_p | 2.490000451713271 | 2.490000451713271 | 

423 # a_h_p_1_s_2 | 180.000000000000028 | 180.000000000000000 | <-- 

424 # h_p_1_a_2 | 360.069023876155143 | 360.069023876155143 | 

425 # h_bar_p | 0.034511938077571 | 180.034511938077571 | 

426 # T | 1.319683185432364 | 0.977862082189372 | <-- 

427 # delta_theta | 0.000000000000000 | 0.000016235458767 | <-- 

428 # C_bar_p_7 | 593.466188771459770 | 593.466188771459770 | 

429 # R_C | 0.000623645703630 | 0.000623645703630 | 

430 # L_bar_p_2 | 0.000000000000000 | 0.000000000000000 | 

431 # S_L | 1.000000000000000 | 1.000000000000000 | 

432 # S_C | 1.112050020327097 | 1.112050020327097 | 

433 # S_H | 1.049290175917675 | 1.036523155395472 | <-- 

434 # R_T | -0.000000000000000 | -0.000000000353435 | <-- 

435 # d_E | 4.746066453039259 | 4.804524508211768 | <-- 

436 

437 Lab_1 = np.array( 

438 [ 

439 [50.0000, 2.6772, -79.7751], 

440 [50.0000, 3.1571, -77.2803], 

441 [50.0000, 2.8361, -74.0200], 

442 [50.0000, -1.3802, -84.2814], 

443 [50.0000, -1.1848, -84.8006], 

444 [50.0000, -0.9009, -85.5211], 

445 [50.0000, 0.0000, 0.0000], 

446 [50.0000, -1.0000, 2.0000], 

447 [50.0000, 2.4900, -0.0010], 

448 [50.0000, 2.4900, -0.0010], 

449 [50.0000, 2.4900, -0.0010], 

450 [50.0000, 2.4900, -0.0010], 

451 [50.0000, -0.0010, 2.4900], 

452 # [50.0000, -0.0010, 2.4900], 

453 [50.0000, -0.0010, 2.4900], 

454 [50.0000, 2.5000, 0.0000], 

455 [50.0000, 2.5000, 0.0000], 

456 [50.0000, 2.5000, 0.0000], 

457 [50.0000, 2.5000, 0.0000], 

458 [50.0000, 2.5000, 0.0000], 

459 [50.0000, 2.5000, 0.0000], 

460 [50.0000, 2.5000, 0.0000], 

461 [50.0000, 2.5000, 0.0000], 

462 [50.0000, 2.5000, 0.0000], 

463 [60.2574, -34.0099, 36.2677], 

464 [63.0109, -31.0961, -5.8663], 

465 [61.2901, 3.7196, -5.3901], 

466 [35.0831, -44.1164, 3.7933], 

467 [22.7233, 20.0904, -46.6940], 

468 [36.4612, 47.8580, 18.3852], 

469 [90.8027, -2.0831, 1.4410], 

470 [90.9257, -0.5406, -0.9208], 

471 [6.7747, -0.2908, -2.4247], 

472 [2.0776, 0.0795, -1.1350], 

473 ] 

474 ) 

475 

476 Lab_2 = np.array( 

477 [ 

478 [50.0000, 0.0000, -82.7485], 

479 [50.0000, 0.0000, -82.7485], 

480 [50.0000, 0.0000, -82.7485], 

481 [50.0000, 0.0000, -82.7485], 

482 [50.0000, 0.0000, -82.7485], 

483 [50.0000, 0.0000, -82.7485], 

484 [50.0000, -1.0000, 2.0000], 

485 [50.0000, 0.0000, 0.0000], 

486 [50.0000, -2.4900, 0.0009], 

487 [50.0000, -2.4900, 0.0010], 

488 [50.0000, -2.4900, 0.0011], 

489 [50.0000, -2.4900, 0.0012], 

490 [50.0000, 0.0009, -2.4900], 

491 # [50.0000, 0.0010, -2.4900], 

492 [50.0000, 0.0011, -2.4900], 

493 [50.0000, 0.0000, -2.5000], 

494 [73.0000, 25.0000, -18.0000], 

495 [61.0000, -5.0000, 29.0000], 

496 [56.0000, -27.0000, -3.0000], 

497 [58.0000, 24.0000, 15.0000], 

498 [50.0000, 3.1736, 0.5854], 

499 [50.0000, 3.2972, 0.0000], 

500 [50.0000, 1.8634, 0.5757], 

501 [50.0000, 3.2592, 0.3350], 

502 [60.4626, -34.1751, 39.4387], 

503 [62.8187, -29.7946, -4.0864], 

504 [61.4292, 2.2480, -4.9620], 

505 [35.0232, -40.0716, 1.5901], 

506 [23.0331, 14.9730, -42.5619], 

507 [36.2715, 50.5065, 21.2231], 

508 [91.1528, -1.6435, 0.0447], 

509 [88.6381, -0.8985, -0.7239], 

510 [5.8714, -0.0985, -2.2286], 

511 [0.9033, -0.0636, -0.5514], 

512 ] 

513 ) 

514 

515 d_E = np.array( 

516 [ 

517 2.0425, 

518 2.8615, 

519 3.4412, 

520 1.0000, 

521 1.0000, 

522 1.0000, 

523 2.3669, 

524 2.3669, 

525 7.1792, 

526 7.1792, 

527 7.2195, 

528 7.2195, 

529 4.8045, 

530 # 4.8045, 

531 4.7461, 

532 4.3065, 

533 27.1492, 

534 22.8977, 

535 31.9030, 

536 19.4535, 

537 1.0000, 

538 1.0000, 

539 1.0000, 

540 1.0000, 

541 1.2644, 

542 1.2630, 

543 1.8731, 

544 1.8645, 

545 2.0373, 

546 1.4146, 

547 1.4441, 

548 1.5381, 

549 0.6377, 

550 0.9082, 

551 ] 

552 ) 

553 

554 np.testing.assert_allclose(delta_E_CIE2000(Lab_1, Lab_2), d_E, atol=1e-4) 

555 

556 

557class TestDelta_E_CMC: 

558 """ 

559 Define :func:`colour.difference.delta_e.delta_E_CMC` definition unit tests 

560 methods. 

561 """ 

562 

563 def test_delta_E_CMC(self) -> None: 

564 """Test :func:`colour.difference.delta_e.delta_E_CMC` definition.""" 

565 

566 np.testing.assert_allclose( 

567 delta_E_CMC( 

568 np.array([48.99183622, -0.10561667, 400.65619925]), 

569 np.array([50.65907324, -0.11671910, 402.82235718]), 

570 ), 

571 0.899699975683419, 

572 atol=TOLERANCE_ABSOLUTE_TESTS, 

573 ) 

574 

575 np.testing.assert_allclose( 

576 delta_E_CMC( 

577 np.array([100.00000000, 21.57210357, 272.22819350]), 

578 np.array([100.00000000, 426.67945353, 72.39590835]), 

579 ), 

580 172.70477129, 

581 atol=TOLERANCE_ABSOLUTE_TESTS, 

582 ) 

583 

584 np.testing.assert_allclose( 

585 delta_E_CMC( 

586 np.array([100.00000000, 21.57210357, 272.22819350]), 

587 np.array([100.00000000, 74.05216981, 276.45318193]), 

588 ), 

589 20.59732717, 

590 atol=TOLERANCE_ABSOLUTE_TESTS, 

591 ) 

592 

593 np.testing.assert_allclose( 

594 delta_E_CMC( 

595 np.array([100.00000000, 21.57210357, 272.22819350]), 

596 np.array([100.00000000, 426.67945353, 72.39590835]), 

597 l=1, 

598 ), 

599 172.70477129, 

600 atol=TOLERANCE_ABSOLUTE_TESTS, 

601 ) 

602 

603 np.testing.assert_allclose( 

604 delta_E_CMC( 

605 np.array([100.00000000, 21.57210357, 272.22819350]), 

606 np.array([100.00000000, 74.05216981, 276.45318193]), 

607 l=1, 

608 ), 

609 20.59732717, 

610 atol=TOLERANCE_ABSOLUTE_TESTS, 

611 ) 

612 

613 np.testing.assert_allclose( 

614 delta_E_CMC( 

615 np.array([100.00000000, 21.57210357, 272.22819350]), 

616 np.array([100.00000000, 8.32281957, -73.58297716]), 

617 l=1, 

618 ), 

619 121.71841479, 

620 atol=TOLERANCE_ABSOLUTE_TESTS, 

621 ) 

622 

623 def test_n_dimensional_delta_E_CMC(self) -> None: 

624 """ 

625 Test :func:`colour.difference.delta_e.delta_E_CMC` definition 

626 n-dimensional arrays support. 

627 """ 

628 

629 Lab_1 = np.array([48.99183622, -0.10561667, 400.65619925]) 

630 Lab_2 = np.array([50.65907324, -0.11671910, 402.82235718]) 

631 delta_E = delta_E_CMC(Lab_1, Lab_2) 

632 

633 Lab_1 = np.tile(Lab_1, (6, 1)) 

634 Lab_2 = np.tile(Lab_2, (6, 1)) 

635 delta_E = np.tile(delta_E, 6) 

636 np.testing.assert_allclose( 

637 delta_E_CMC(Lab_1, Lab_2), delta_E, atol=TOLERANCE_ABSOLUTE_TESTS 

638 ) 

639 

640 Lab_1 = np.reshape(Lab_1, (2, 3, 3)) 

641 Lab_2 = np.reshape(Lab_2, (2, 3, 3)) 

642 delta_E = np.reshape(delta_E, (2, 3)) 

643 np.testing.assert_allclose( 

644 delta_E_CMC(Lab_1, Lab_2), delta_E, atol=TOLERANCE_ABSOLUTE_TESTS 

645 ) 

646 

647 def test_domain_range_scale_delta_E_CMC(self) -> None: 

648 """ 

649 Test :func:`colour.difference.delta_e.delta_E_CMC` definition 

650 domain and range scale support. 

651 """ 

652 

653 Lab_1 = np.array([48.99183622, -0.10561667, 400.65619925]) 

654 Lab_2 = np.array([50.65907324, -0.11671910, 402.82235718]) 

655 delta_E = delta_E_CMC(Lab_1, Lab_2) 

656 

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

658 for scale, factor in d_r: 

659 with domain_range_scale(scale): 

660 np.testing.assert_allclose( 

661 delta_E_CMC(Lab_1 * factor, Lab_2 * factor), 

662 delta_E, 

663 atol=TOLERANCE_ABSOLUTE_TESTS, 

664 ) 

665 

666 @ignore_numpy_errors 

667 def test_nan_delta_E_CMC(self) -> None: 

668 """ 

669 Test :func:`colour.difference.delta_e.delta_E_CMC` definition nan 

670 support. 

671 """ 

672 

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

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

675 delta_E_CMC(cases, cases) 

676 

677 

678class TestDelta_E_ITP: 

679 """ 

680 Define :func:`colour.difference.delta_e.delta_E_ITP` definition unit tests 

681 methods. 

682 """ 

683 

684 def test_delta_E_ITP(self) -> None: 

685 """Test :func:`colour.difference.delta_e.delta_E_ITP` definition.""" 

686 

687 np.testing.assert_allclose( 

688 delta_E_ITP( 

689 # RGB: (110, 82, 69), Dark Skin 

690 np.array([0.4885468072, -0.04739350675, 0.07475401302]), 

691 np.array([0.4899203231, -0.04567508203, 0.07361341775]), 

692 ), 

693 1.426572247, 

694 atol=TOLERANCE_ABSOLUTE_TESTS, 

695 ) 

696 

697 np.testing.assert_allclose( 

698 delta_E_ITP( 

699 # RGB: (110, 82, 69), 100% White 

700 np.array([0.7538438727, 0, -6.25e-16]), 

701 np.array([0.7538912244, 0.001930922514, -0.0003599955951]), 

702 ), 

703 0.7426668055, 

704 atol=TOLERANCE_ABSOLUTE_TESTS, 

705 ) 

706 

707 np.testing.assert_allclose( 

708 delta_E_ITP( 

709 # RGB: (0, 0, 0), 100% Black 

710 np.array([0.1596179061, 0, -1.21e-16]), 

711 np.array([0.1603575152, 0.02881444889, -0.009908665843]), 

712 ), 

713 12.60096264, 

714 atol=TOLERANCE_ABSOLUTE_TESTS, 

715 ) 

716 

717 np.testing.assert_allclose( 

718 delta_E_ITP( 

719 # RGB: (255, 0, 0), 100% Red 

720 np.array([0.5965650331, -0.2083210482, 0.3699729716]), 

721 np.array([0.596263079, -0.1629742033, 0.3617767026]), 

722 ), 

723 17.36012552, 

724 atol=TOLERANCE_ABSOLUTE_TESTS, 

725 ) 

726 

727 np.testing.assert_allclose( 

728 delta_E_ITP( 

729 # RGB: (0, 255, 0), 100% Green 

730 np.array([0.7055787513, -0.4063731514, -0.07278767382]), 

731 np.array([0.7046946082, -0.3771037586, -0.07141626753]), 

732 ), 

733 10.60227327, 

734 atol=TOLERANCE_ABSOLUTE_TESTS, 

735 ) 

736 

737 np.testing.assert_allclose( 

738 delta_E_ITP( 

739 # RGB: (255, 0, 0), 100% Blue 

740 np.array([0.5180652611, 0.2932420978, -0.1873112695]), 

741 np.array([0.5167090868, 0.298191609, -0.1824609953]), 

742 ), 

743 4.040270489, 

744 atol=TOLERANCE_ABSOLUTE_TESTS, 

745 ) 

746 

747 np.testing.assert_allclose( 

748 delta_E_ITP( 

749 # RGB: (0, 255, 255), 100% Cyan 

750 np.array([0.7223275939, -0.01290632441, -0.1139004748]), 

751 np.array([0.7215329274, -0.007863821961, -0.1106683944]), 

752 ), 

753 3.00633812, 

754 atol=TOLERANCE_ABSOLUTE_TESTS, 

755 ) 

756 

757 np.testing.assert_allclose( 

758 delta_E_ITP( 

759 # RGB: (255, 0, 255), 100% Magenta 

760 np.array([0.6401125212, 0.280225698, 0.1665590804]), 

761 np.array([0.640473651, 0.2819981563, 0.1654050172]), 

762 ), 

763 1.07944277, 

764 atol=TOLERANCE_ABSOLUTE_TESTS, 

765 ) 

766 

767 np.testing.assert_allclose( 

768 delta_E_ITP( 

769 # RGB: (255, 255, 0), 100% Yellow 

770 np.array([0.7413041405, -0.3638807621, 0.04959414794]), 

771 np.array([0.7412815181, -0.3299076141, 0.04545287368]), 

772 ), 

773 12.5885645, 

774 atol=TOLERANCE_ABSOLUTE_TESTS, 

775 ) 

776 

777 def test_n_dimensional_delta_E_ITP(self) -> None: 

778 """ 

779 Test :func:`colour.difference.delta_e.delta_E_ITP` definition 

780 n-dimensional arrays support. 

781 """ 

782 

783 ICtCp_1 = np.array([0.4885468072, -0.04739350675, 0.07475401302]) 

784 ICtCp_2 = np.array([0.4899203231, -0.04567508203, 0.07361341775]) 

785 delta_E = delta_E_ITP(ICtCp_1, ICtCp_2) 

786 

787 ICtCp_1 = np.tile(ICtCp_1, (6, 1)) 

788 ICtCp_2 = np.tile(ICtCp_2, (6, 1)) 

789 delta_E = np.tile(delta_E, 6) 

790 np.testing.assert_allclose( 

791 delta_E_ITP(ICtCp_1, ICtCp_2), delta_E, atol=TOLERANCE_ABSOLUTE_TESTS 

792 ) 

793 

794 ICtCp_1 = np.reshape(ICtCp_1, (2, 3, 3)) 

795 ICtCp_2 = np.reshape(ICtCp_2, (2, 3, 3)) 

796 delta_E = np.reshape(delta_E, (2, 3)) 

797 np.testing.assert_allclose( 

798 delta_E_ITP(ICtCp_1, ICtCp_2), delta_E, atol=TOLERANCE_ABSOLUTE_TESTS 

799 ) 

800 

801 def test_domain_range_scale_delta_E_ITP(self) -> None: 

802 """ 

803 Test :func:`colour.difference.delta_e.delta_E_ITP` definition domain 

804 and range scale support. 

805 """ 

806 

807 ICtCp_1 = np.array([0.4885468072, -0.04739350675, 0.07475401302]) 

808 ICtCp_2 = np.array([0.4899203231, -0.04567508203, 0.07361341775]) 

809 delta_E = delta_E_ITP(ICtCp_1, ICtCp_2) 

810 

811 d_r = (("reference", 1), ("1", 1), ("100", 1)) 

812 for scale, factor in d_r: 

813 with domain_range_scale(scale): 

814 np.testing.assert_allclose( 

815 delta_E_ITP(ICtCp_1 * factor, ICtCp_2 * factor), 

816 delta_E, 

817 atol=TOLERANCE_ABSOLUTE_TESTS, 

818 ) 

819 

820 @ignore_numpy_errors 

821 def test_nan_delta_E_ITP(self) -> None: 

822 """ 

823 Test :func:`colour.difference.delta_e.delta_E_ITP` definition nan 

824 support. 

825 """ 

826 

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

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

829 delta_E_ITP(cases, cases) 

830 

831 

832class TestDelta_E_HyAB: 

833 """ 

834 Define :func:`colour.difference.delta_e.delta_E_HyAB` definition unit 

835 tests methods. 

836 """ 

837 

838 def test_delta_E_HyAB(self) -> None: 

839 """Test :func:`colour.difference.delta_e.delta_E_HyAB` definition.""" 

840 

841 np.testing.assert_allclose( 

842 delta_E_HyAB( 

843 np.array([39.91531343, 51.16658481, 146.12933781]), 

844 np.array([53.12207516, -39.92365056, 249.54831278]), 

845 ), 

846 151.021548177635900, 

847 atol=TOLERANCE_ABSOLUTE_TESTS, 

848 ) 

849 

850 np.testing.assert_allclose( 

851 delta_E_HyAB( 

852 np.array([39.91531343, 51.16658481, 146.12933781]), 

853 np.array([28.52234779, 19.46628874, 472.06042624]), 

854 ), 

855 338.862022462305200, 

856 atol=TOLERANCE_ABSOLUTE_TESTS, 

857 ) 

858 

859 np.testing.assert_allclose( 

860 delta_E_HyAB( 

861 np.array([48.99183622, -0.10561667, 400.65619925]), 

862 np.array([50.65907324, -0.11671910, 402.82235718]), 

863 ), 

864 3.833423402021121, 

865 atol=TOLERANCE_ABSOLUTE_TESTS, 

866 ) 

867 

868 def test_n_dimensional_delta_E_HyAB(self) -> None: 

869 """ 

870 Test :func:`colour.difference.delta_e.delta_E_HyAB` definition 

871 n-dimensional arrays support. 

872 """ 

873 

874 Lab_1 = (np.array([39.91531343, 51.16658481, 146.12933781]),) 

875 Lab_2 = (np.array([53.12207516, -39.92365056, 249.54831278]),) 

876 delta_E = delta_E_HyAB(Lab_1, Lab_2) 

877 

878 Lab_1 = np.tile(Lab_1, (6, 1)) 

879 Lab_2 = np.tile(Lab_2, (6, 1)) 

880 delta_E = np.tile(delta_E, 6) 

881 np.testing.assert_allclose( 

882 delta_E_HyAB(Lab_1, Lab_2), 

883 delta_E, 

884 atol=TOLERANCE_ABSOLUTE_TESTS, 

885 ) 

886 

887 Lab_1 = np.reshape(Lab_1, (2, 3, 3)) 

888 Lab_2 = np.reshape(Lab_2, (2, 3, 3)) 

889 delta_E = np.reshape(delta_E, (2, 3)) 

890 np.testing.assert_allclose( 

891 delta_E_HyAB(Lab_1, Lab_2), 

892 delta_E, 

893 atol=TOLERANCE_ABSOLUTE_TESTS, 

894 ) 

895 

896 def test_domain_range_scale_delta_E_HyAB(self) -> None: 

897 """ 

898 Test :func:`colour.difference.delta_e.delta_E_HyAB` definition 

899 domain and range scale support. 

900 """ 

901 

902 Lab_1 = np.array([39.91531343, 51.16658481, 146.12933781]) 

903 Lab_2 = np.array([53.12207516, -39.92365056, 249.54831278]) 

904 delta_E = delta_E_HyAB(Lab_1, Lab_2) 

905 

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

907 for scale, factor in d_r: 

908 with domain_range_scale(scale): 

909 np.testing.assert_allclose( 

910 delta_E_HyAB(Lab_1 * factor, Lab_2 * factor), 

911 delta_E, 

912 atol=TOLERANCE_ABSOLUTE_TESTS, 

913 ) 

914 

915 @ignore_numpy_errors 

916 def test_nan_delta_E_HyAB(self) -> None: 

917 """ 

918 Test :func:`colour.difference.delta_e.delta_E_HyAB` definition nan 

919 support. 

920 """ 

921 

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

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

924 delta_E_HyAB(cases, cases) 

925 

926 

927class TestDelta_E_HyCH: 

928 """ 

929 Define :func:`colour.difference.delta_e.delta_E_HyCH` definition unit 

930 tests methods. 

931 """ 

932 

933 def test_delta_E_HyCH(self) -> None: 

934 """Test :func:`colour.difference.delta_e.delta_E_HyCH` definition.""" 

935 

936 np.testing.assert_allclose( 

937 delta_E_HyCH( 

938 np.array([39.91531343, 51.16658481, 146.12933781]), 

939 np.array([53.12207516, -39.92365056, 249.54831278]), 

940 ), 

941 48.664279419760369, 

942 atol=TOLERANCE_ABSOLUTE_TESTS, 

943 ) 

944 

945 np.testing.assert_allclose( 

946 delta_E_HyCH( 

947 np.array([39.91531343, 51.16658481, 146.12933781]), 

948 np.array([28.52234779, 19.46628874, 472.06042624]), 

949 ), 

950 39.260928157999118, 

951 atol=TOLERANCE_ABSOLUTE_TESTS, 

952 ) 

953 

954 np.testing.assert_allclose( 

955 delta_E_HyCH( 

956 np.array([48.99183622, -0.10561667, 400.65619925]), 

957 np.array([50.65907324, -0.11671910, 402.82235718]), 

958 ), 

959 1.7806293290163562, 

960 atol=TOLERANCE_ABSOLUTE_TESTS, 

961 ) 

962 

963 def test_n_dimensional_delta_E_HyCH(self) -> None: 

964 """ 

965 Test :func:`colour.difference.delta_e.delta_E_HyCH` definition 

966 n-dimensional arrays support. 

967 """ 

968 

969 Lab_1 = (np.array([39.91531343, 51.16658481, 146.12933781]),) 

970 Lab_2 = (np.array([53.12207516, -39.92365056, 249.54831278]),) 

971 delta_E = delta_E_HyCH(Lab_1, Lab_2) 

972 

973 Lab_1 = np.tile(Lab_1, (6, 1)) 

974 Lab_2 = np.tile(Lab_2, (6, 1)) 

975 delta_E = np.tile(delta_E, 6) 

976 np.testing.assert_allclose( 

977 delta_E_HyCH(Lab_1, Lab_2), 

978 delta_E, 

979 atol=TOLERANCE_ABSOLUTE_TESTS, 

980 ) 

981 

982 Lab_1 = np.reshape(Lab_1, (2, 3, 3)) 

983 Lab_2 = np.reshape(Lab_2, (2, 3, 3)) 

984 delta_E = np.reshape(delta_E, (2, 3)) 

985 np.testing.assert_allclose( 

986 delta_E_HyCH(Lab_1, Lab_2), 

987 delta_E, 

988 atol=TOLERANCE_ABSOLUTE_TESTS, 

989 ) 

990 

991 def test_domain_range_scale_delta_E_HyCH(self) -> None: 

992 """ 

993 Test :func:`colour.difference.delta_e.delta_E_HyCH` definition 

994 domain and range scale support. 

995 """ 

996 

997 Lab_1 = np.array([39.91531343, 51.16658481, 146.12933781]) 

998 Lab_2 = np.array([53.12207516, -39.92365056, 249.54831278]) 

999 delta_E = delta_E_HyCH(Lab_1, Lab_2) 

1000 

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

1002 for scale, factor in d_r: 

1003 with domain_range_scale(scale): 

1004 np.testing.assert_allclose( 

1005 delta_E_HyCH(Lab_1 * factor, Lab_2 * factor), 

1006 delta_E, 

1007 atol=TOLERANCE_ABSOLUTE_TESTS, 

1008 ) 

1009 

1010 @ignore_numpy_errors 

1011 def test_nan_delta_E_HyCH(self) -> None: 

1012 """ 

1013 Test :func:`colour.difference.delta_e.delta_E_HyCH` definition nan 

1014 support. 

1015 """ 

1016 

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

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

1019 delta_E_HyCH(cases, cases)