Coverage for colour/difference/tests/test_delta_e.py: 100%
235 statements
« prev ^ index » next coverage.py v7.11.0, created at 2025-11-15 19:01 +1300
« prev ^ index » next coverage.py v7.11.0, created at 2025-11-15 19:01 +1300
1"""
2Define the unit tests for the :mod:`colour.difference.delta_e` module.
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"""
12from __future__ import annotations
14from itertools import product
16import numpy as np
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
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"
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]
50class TestDelta_E_CIE1976:
51 """
52 Define :func:`colour.difference.delta_e.delta_E_CIE1976` definition unit
53 tests methods.
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 """
62 def test_delta_E_CIE1976(self) -> None:
63 """Test :func:`colour.difference.delta_e.delta_E_CIE1976` definition."""
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))
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 )
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 """
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 """
88 Lab_1 = np.array([48.99183622, -0.10561667, 400.65619925])
89 Lab_2 = np.array([50.65907324, -0.11671910, 402.82235718])
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 )
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 """
108class TestDelta_E_CIE1994:
109 """
110 Define :func:`colour.difference.delta_e.delta_E_CIE1994` definition unit
111 tests methods.
112 """
114 def test_delta_E_CIE1994(self) -> None:
115 """Test :func:`colour.difference.delta_e.delta_E_CIE1994` definition."""
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 )
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 )
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 )
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 )
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 )
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 )
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 """
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)
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 )
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 )
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 """
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)
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 )
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 """
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)
233class TestIntermediateAttributes_CIE2000:
234 """
235 Define :func:`colour.difference.delta_e.intermediate_attributes_CIE2000`
236 definition unit tests methods.
237 """
239 def test_intermediate_attributes_CIE2000(self) -> None:
240 """
241 Test :func:`colour.difference.delta_e.intermediate_attributes_CIE2000`
242 definition.
243 """
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 )
265class TestDelta_E_CIE2000:
266 """
267 Define :func:`colour.difference.delta_e.delta_E_CIE2000` definition unit
268 tests methods.
269 """
271 def test_delta_E_CIE2000(self) -> None:
272 """Test :func:`colour.difference.delta_e.delta_E_CIE2000` definition."""
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 )
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 )
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 )
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 )
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 )
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 )
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 """
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)
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 )
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 )
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 """
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)
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 )
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 """
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)
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.
394 References
395 ----------
396 :cite:`Sharma2005b`
397 """
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 | <--
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 )
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 )
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 )
554 np.testing.assert_allclose(delta_E_CIE2000(Lab_1, Lab_2), d_E, atol=1e-4)
557class TestDelta_E_CMC:
558 """
559 Define :func:`colour.difference.delta_e.delta_E_CMC` definition unit tests
560 methods.
561 """
563 def test_delta_E_CMC(self) -> None:
564 """Test :func:`colour.difference.delta_e.delta_E_CMC` definition."""
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 )
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 )
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 )
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 )
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 )
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 )
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 """
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)
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 )
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 )
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 """
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)
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 )
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 """
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)
678class TestDelta_E_ITP:
679 """
680 Define :func:`colour.difference.delta_e.delta_E_ITP` definition unit tests
681 methods.
682 """
684 def test_delta_E_ITP(self) -> None:
685 """Test :func:`colour.difference.delta_e.delta_E_ITP` definition."""
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 )
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 )
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 )
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 )
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 )
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 )
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 )
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 )
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 )
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 """
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)
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 )
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 )
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 """
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)
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 )
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 """
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)
832class TestDelta_E_HyAB:
833 """
834 Define :func:`colour.difference.delta_e.delta_E_HyAB` definition unit
835 tests methods.
836 """
838 def test_delta_E_HyAB(self) -> None:
839 """Test :func:`colour.difference.delta_e.delta_E_HyAB` definition."""
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 )
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 )
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 )
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 """
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)
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 )
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 )
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 """
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)
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 )
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 """
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)
927class TestDelta_E_HyCH:
928 """
929 Define :func:`colour.difference.delta_e.delta_E_HyCH` definition unit
930 tests methods.
931 """
933 def test_delta_E_HyCH(self) -> None:
934 """Test :func:`colour.difference.delta_e.delta_E_HyCH` definition."""
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 )
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 )
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 )
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 """
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)
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 )
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 )
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 """
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)
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 )
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 """
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)