Coverage for appearance/tests/test_llab.py: 100%
125 statements
« prev ^ index » next coverage.py v7.11.0, created at 2025-11-16 22:49 +1300
« 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.appearance.kim2009` module."""
3from __future__ import annotations
5from itertools import product
7import numpy as np
8import pytest
10from colour.appearance import (
11 MEDIA_PARAMETERS_KIM2009,
12 VIEWING_CONDITIONS_KIM2009,
13 CAM_Specification_Kim2009,
14 InductionFactors_Kim2009,
15 Kim2009_to_XYZ,
16 MediaParameters_Kim2009,
17 XYZ_to_Kim2009,
18)
19from colour.constants import TOLERANCE_ABSOLUTE_TESTS
20from colour.utilities import (
21 as_float_array,
22 domain_range_scale,
23 ignore_numpy_errors,
24 tsplit,
25)
27__author__ = "Colour Developers"
28__copyright__ = "Copyright 2013 Colour Developers"
29__license__ = "BSD-3-Clause - https://opensource.org/licenses/BSD-3-Clause"
30__maintainer__ = "Colour Developers"
31__email__ = "colour-developers@colour-science.org"
32__status__ = "Production"
34__all__ = [
35 "TestXYZ_to_Kim2009",
36 "TestKim2009_to_XYZ",
37]
40class TestXYZ_to_Kim2009:
41 """
42 Define :func:`colour.appearance.kim2009.XYZ_to_Kim2009` definition unit
43 tests methods.
44 """
46 def test_XYZ_to_Kim2009(self) -> None:
47 """Test :func:`colour.appearance.kim2009.XYZ_to_Kim2009` definition."""
49 XYZ = np.array([19.01, 20.00, 21.78])
50 XYZ_w = np.array([95.05, 100.00, 108.88])
51 L_a = 318.31
52 media = MEDIA_PARAMETERS_KIM2009["CRT Displays"]
53 surround = VIEWING_CONDITIONS_KIM2009["Average"]
54 np.testing.assert_allclose(
55 XYZ_to_Kim2009(XYZ, XYZ_w, L_a, media, surround),
56 np.array(
57 [
58 28.86190898,
59 0.55924559,
60 219.04806678,
61 9.38377973,
62 52.71388839,
63 0.46417384,
64 278.06028246,
65 np.nan,
66 ]
67 ),
68 atol=TOLERANCE_ABSOLUTE_TESTS,
69 )
71 XYZ = np.array([57.06, 43.06, 31.96])
72 L_a = 31.83
73 np.testing.assert_allclose(
74 XYZ_to_Kim2009(XYZ, XYZ_w, L_a, media, surround),
75 np.array(
76 [
77 70.15940419,
78 57.89295872,
79 21.27017200,
80 61.23630434,
81 128.14034598,
82 48.05115573,
83 1.41841443,
84 np.nan,
85 ]
86 ),
87 atol=TOLERANCE_ABSOLUTE_TESTS,
88 )
90 XYZ = np.array([3.53, 6.56, 2.14])
91 XYZ_w = np.array([109.85, 100.00, 35.58])
92 L_a = 318.31
93 np.testing.assert_allclose(
94 XYZ_to_Kim2009(XYZ, XYZ_w, L_a, media, surround),
95 np.array(
96 [
97 -4.83430022,
98 37.42013921,
99 177.12166057,
100 np.nan,
101 -8.82944930,
102 31.05871555,
103 220.36270343,
104 np.nan,
105 ]
106 ),
107 atol=TOLERANCE_ABSOLUTE_TESTS,
108 )
110 XYZ = np.array([19.01, 20.00, 21.78])
111 L_a = 31.83
112 np.testing.assert_allclose(
113 XYZ_to_Kim2009(XYZ, XYZ_w, L_a, media, surround),
114 np.array(
115 [
116 47.20460719,
117 56.35723637,
118 241.04877377,
119 73.65830083,
120 86.21530880,
121 46.77650619,
122 301.77516676,
123 np.nan,
124 ]
125 ),
126 atol=TOLERANCE_ABSOLUTE_TESTS,
127 )
129 def test_n_dimensional_XYZ_to_Kim2009(self) -> None:
130 """
131 Test :func:`colour.appearance.kim2009.XYZ_to_Kim2009` definition
132 n-dimensional support.
133 """
135 XYZ = np.array([19.01, 20.00, 21.78])
136 XYZ_w = np.array([95.05, 100.00, 108.88])
137 L_a = 318.31
138 media = MEDIA_PARAMETERS_KIM2009["CRT Displays"]
139 surround = VIEWING_CONDITIONS_KIM2009["Average"]
140 specification = XYZ_to_Kim2009(XYZ, XYZ_w, L_a, media, surround)
142 XYZ = np.tile(XYZ, (6, 1))
143 specification = np.tile(specification, (6, 1))
144 np.testing.assert_allclose(
145 XYZ_to_Kim2009(XYZ, XYZ_w, L_a, media, surround),
146 specification,
147 atol=TOLERANCE_ABSOLUTE_TESTS,
148 )
150 XYZ_w = np.tile(XYZ_w, (6, 1))
151 np.testing.assert_allclose(
152 XYZ_to_Kim2009(XYZ, XYZ_w, L_a, media, surround),
153 specification,
154 atol=TOLERANCE_ABSOLUTE_TESTS,
155 )
157 XYZ = np.reshape(XYZ, (2, 3, 3))
158 XYZ_w = np.reshape(XYZ_w, (2, 3, 3))
159 specification = np.reshape(specification, (2, 3, 8))
160 np.testing.assert_allclose(
161 XYZ_to_Kim2009(XYZ, XYZ_w, L_a, media, surround),
162 specification,
163 atol=TOLERANCE_ABSOLUTE_TESTS,
164 )
166 @ignore_numpy_errors
167 def test_domain_range_scale_XYZ_to_Kim2009(self) -> None:
168 """
169 Test :func:`colour.appearance.kim2009.XYZ_to_Kim2009` definition
170 domain and range scale support.
171 """
173 XYZ = np.array([19.01, 20.00, 21.78])
174 XYZ_w = np.array([95.05, 100.00, 108.88])
175 L_a = 318.31
176 media = MEDIA_PARAMETERS_KIM2009["CRT Displays"]
177 surround = VIEWING_CONDITIONS_KIM2009["Average"]
178 specification = XYZ_to_Kim2009(XYZ, XYZ_w, L_a, media, surround)
180 d_r = (
181 ("reference", 1, 1),
182 (
183 "1",
184 0.01,
185 np.array(
186 [
187 1 / 100,
188 1 / 100,
189 1 / 360,
190 1 / 100,
191 1 / 100,
192 1 / 100,
193 1 / 400,
194 np.nan,
195 ]
196 ),
197 ),
198 (
199 "100",
200 1,
201 np.array([1, 1, 100 / 360, 1, 1, 1, 100 / 400, np.nan]),
202 ),
203 )
204 for scale, factor_a, factor_b in d_r:
205 with domain_range_scale(scale):
206 np.testing.assert_allclose(
207 XYZ_to_Kim2009(
208 XYZ * factor_a, XYZ_w * factor_a, L_a, media, surround
209 ),
210 as_float_array(specification) * factor_b,
211 atol=TOLERANCE_ABSOLUTE_TESTS,
212 )
214 @ignore_numpy_errors
215 def test_nan_XYZ_to_Kim2009(self) -> None:
216 """
217 Test :func:`colour.appearance.kim2009.XYZ_to_Kim2009` definition
218 nan support.
219 """
221 cases = [-1.0, 0.0, 1.0, -np.inf, np.inf, np.nan]
222 cases = np.array(list(set(product(cases, repeat=3))))
223 media = MediaParameters_Kim2009(cases[0, 0])
224 surround = InductionFactors_Kim2009(cases[0, 0], cases[0, 0], cases[0, 0])
225 XYZ_to_Kim2009(cases, cases, cases[0, 0], media, surround)
228class TestKim2009_to_XYZ:
229 """
230 Define :func:`colour.appearance.kim2009.Kim2009_to_XYZ` definition unit
231 tests methods.
232 """
234 def test_Kim2009_to_XYZ(self) -> None:
235 """Test :func:`colour.appearance.kim2009.Kim2009_to_XYZ` definition."""
237 specification = CAM_Specification_Kim2009(
238 28.86190898,
239 0.55924559,
240 219.04806678,
241 9.38377973,
242 52.71388839,
243 0.46417384,
244 278.06028246,
245 np.nan,
246 )
247 XYZ_w = np.array([95.05, 100.00, 108.88])
248 L_a = 318.31
249 media = MEDIA_PARAMETERS_KIM2009["CRT Displays"]
250 surround = VIEWING_CONDITIONS_KIM2009["Average"]
251 np.testing.assert_allclose(
252 Kim2009_to_XYZ(specification, XYZ_w, L_a, media, surround),
253 np.array([19.01, 20.00, 21.78]),
254 atol=0.01,
255 )
257 specification = CAM_Specification_Kim2009(
258 70.15940419,
259 57.89295872,
260 21.27017200,
261 61.23630434,
262 128.14034598,
263 48.05115573,
264 1.41841443,
265 np.nan,
266 )
267 L_a = 31.83
268 np.testing.assert_allclose(
269 Kim2009_to_XYZ(specification, XYZ_w, L_a, media, surround),
270 np.array([57.06, 43.06, 31.96]),
271 atol=0.01,
272 )
274 specification = CAM_Specification_Kim2009(
275 -4.83430022,
276 37.42013921,
277 177.12166057,
278 np.nan,
279 -8.82944930,
280 31.05871555,
281 220.36270343,
282 np.nan,
283 )
284 XYZ_w = np.array([109.85, 100.00, 35.58])
285 L_a = 318.31
286 np.testing.assert_allclose(
287 Kim2009_to_XYZ(specification, XYZ_w, L_a, media, surround),
288 np.array([3.53, 6.56, 2.14]),
289 atol=0.01,
290 )
292 specification = CAM_Specification_Kim2009(
293 47.20460719,
294 56.35723637,
295 241.04877377,
296 73.65830083,
297 86.21530880,
298 46.77650619,
299 301.77516676,
300 np.nan,
301 )
302 L_a = 31.83
303 np.testing.assert_allclose(
304 Kim2009_to_XYZ(specification, XYZ_w, L_a, media, surround),
305 np.array([19.01, 20.00, 21.78]),
306 atol=0.01,
307 )
309 def test_n_dimensional_Kim2009_to_XYZ(self) -> None:
310 """
311 Test :func:`colour.appearance.kim2009.Kim2009_to_XYZ` definition
312 n-dimensional support.
313 """
315 XYZ = np.array([19.01, 20.00, 21.78])
316 XYZ_w = np.array([95.05, 100.00, 108.88])
317 L_a = 318.31
318 media = MEDIA_PARAMETERS_KIM2009["CRT Displays"]
319 surround = VIEWING_CONDITIONS_KIM2009["Average"]
320 specification = XYZ_to_Kim2009(XYZ, XYZ_w, L_a, media, surround)
321 XYZ = Kim2009_to_XYZ(specification, XYZ_w, L_a, media, surround)
323 specification = CAM_Specification_Kim2009(
324 *np.transpose(np.tile(tsplit(specification), (6, 1))).tolist()
325 )
326 XYZ = np.tile(XYZ, (6, 1))
327 np.testing.assert_allclose(
328 Kim2009_to_XYZ(specification, XYZ_w, L_a, media, surround),
329 XYZ,
330 atol=TOLERANCE_ABSOLUTE_TESTS,
331 )
333 XYZ_w = np.tile(XYZ_w, (6, 1))
334 np.testing.assert_allclose(
335 Kim2009_to_XYZ(specification, XYZ_w, L_a, media, surround),
336 XYZ,
337 atol=TOLERANCE_ABSOLUTE_TESTS,
338 )
340 specification = CAM_Specification_Kim2009(
341 *tsplit(np.reshape(specification, (2, 3, 8))).tolist()
342 )
343 XYZ_w = np.reshape(XYZ_w, (2, 3, 3))
344 XYZ = np.reshape(XYZ, (2, 3, 3))
345 np.testing.assert_allclose(
346 Kim2009_to_XYZ(specification, XYZ_w, L_a, media, surround),
347 XYZ,
348 atol=TOLERANCE_ABSOLUTE_TESTS,
349 )
351 @ignore_numpy_errors
352 def test_domain_range_scale_Kim2009_to_XYZ(self) -> None:
353 """
354 Test :func:`colour.appearance.kim2009.Kim2009_to_XYZ` definition
355 domain and range scale support.
356 """
358 XYZ_i = np.array([19.01, 20.00, 21.78])
359 XYZ_w = np.array([95.05, 100.00, 108.88])
360 L_a = 318.31
361 media = MEDIA_PARAMETERS_KIM2009["CRT Displays"]
362 surround = VIEWING_CONDITIONS_KIM2009["Average"]
363 specification = XYZ_to_Kim2009(XYZ_i, XYZ_w, L_a, media, surround)
364 XYZ = Kim2009_to_XYZ(specification, XYZ_w, L_a, media, surround)
366 d_r = (
367 ("reference", 1, 1),
368 (
369 "1",
370 np.array(
371 [
372 1 / 100,
373 1 / 100,
374 1 / 360,
375 1 / 100,
376 1 / 100,
377 1 / 100,
378 1 / 400,
379 np.nan,
380 ]
381 ),
382 0.01,
383 ),
384 (
385 "100",
386 np.array([1, 1, 100 / 360, 1, 1, 1, 100 / 400, np.nan]),
387 1,
388 ),
389 )
390 for scale, factor_a, factor_b in d_r:
391 with domain_range_scale(scale):
392 np.testing.assert_allclose(
393 Kim2009_to_XYZ(
394 specification * factor_a,
395 XYZ_w * factor_b,
396 L_a,
397 media,
398 surround,
399 ),
400 XYZ * factor_b,
401 atol=TOLERANCE_ABSOLUTE_TESTS,
402 )
404 @ignore_numpy_errors
405 def test_raise_exception_Kim2009_to_XYZ(self) -> None:
406 """
407 Test :func:`colour.appearance.kim2009.Kim2009_to_XYZ` definition
408 raised exception.
409 """
411 pytest.raises(
412 ValueError,
413 Kim2009_to_XYZ,
414 CAM_Specification_Kim2009(
415 41.731091132513917,
416 None,
417 219.04843265831178,
418 ),
419 np.array([95.05, 100.00, 108.88]),
420 318.31,
421 20.0,
422 VIEWING_CONDITIONS_KIM2009["Average"],
423 )
425 @ignore_numpy_errors
426 def test_nan_Kim2009_to_XYZ(self) -> None:
427 """
428 Test :func:`colour.appearance.kim2009.Kim2009_to_XYZ` definition nan
429 support.
430 """
432 cases = [-1.0, 0.0, 1.0, -np.inf, np.inf, np.nan]
433 cases = np.array(list(set(product(cases, repeat=3))))
434 media = MediaParameters_Kim2009(cases[0, 0])
435 surround = InductionFactors_Kim2009(cases[0, 0], cases[0, 0], cases[0, 0])
436 Kim2009_to_XYZ(
437 CAM_Specification_Kim2009(
438 cases[..., 0], cases[..., 0], cases[..., 0], M=50
439 ),
440 cases,
441 cases[0, 0],
442 media,
443 surround,
444 )