Coverage for models/tests/test_sucs.py: 100%
169 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.models.sucs` module."""
3from __future__ import annotations
5from itertools import product
7import numpy as np
9from colour.constants import TOLERANCE_ABSOLUTE_TESTS
10from colour.models import (
11 XYZ_to_sUCS,
12 sUCS_chroma,
13 sUCS_hue_angle,
14 sUCS_Iab_to_sUCS_ICh,
15 sUCS_ICh_to_sUCS_Iab,
16 sUCS_to_XYZ,
17)
18from colour.utilities import domain_range_scale, ignore_numpy_errors
20__author__ = "UltraMo114(Molin Li), Colour Developers"
21__copyright__ = "Copyright 2013 Colour Developers"
22__license__ = "BSD-3-Clause - https://opensource.org/licenses/BSD-3-Clause"
23__maintainer__ = "Colour Developers"
24__email__ = "colour-developers@colour-science.org"
25__status__ = "Production"
27__all__ = [
28 "TestXYZ_to_sUCS",
29 "TestsUCS_to_XYZ",
30 "TestsUCSChroma",
31 "TestsUCSHueAngle",
32 "TestsUCS_Iab_to_sUCS_ICh",
33 "TestsUCS_ICh_to_sUCS_Iab",
34]
37class TestXYZ_to_sUCS:
38 """Define :func:`colour.models.sucs.XYZ_to_sUCS` definition unit tests methods."""
40 def test_XYZ_to_sUCS(self) -> None:
41 """Test :func:`colour.models.sucs.XYZ_to_sUCS` definition."""
43 np.testing.assert_allclose(
44 XYZ_to_sUCS(np.array([0.20654008, 0.12197225, 0.05136952])),
45 np.array([42.62923653, 36.97646831, 14.12301358]),
46 atol=TOLERANCE_ABSOLUTE_TESTS,
47 )
49 np.testing.assert_allclose(
50 XYZ_to_sUCS(np.array([0.14222010, 0.23042768, 0.10495772])),
51 np.array([51.93649255, -18.89245582, 15.76112395]),
52 atol=TOLERANCE_ABSOLUTE_TESTS,
53 )
55 np.testing.assert_allclose(
56 XYZ_to_sUCS(np.array([0.07818780, 0.06157201, 0.28099326])),
57 np.array([29.79456846, -6.83806757, -25.33884097]),
58 atol=TOLERANCE_ABSOLUTE_TESTS,
59 )
61 def test_n_dimensional_XYZ_to_sUCS(self) -> None:
62 """
63 Test :func:`colour.models.sucs.XYZ_to_sUCS` definition n-dimensional
64 support.
65 """
67 XYZ = np.array([0.20654008, 0.12197225, 0.05136952])
68 Iab = XYZ_to_sUCS(XYZ)
70 XYZ = np.tile(XYZ, (6, 1))
71 Iab = np.tile(Iab, (6, 1))
72 np.testing.assert_allclose(XYZ_to_sUCS(XYZ), Iab, atol=TOLERANCE_ABSOLUTE_TESTS)
74 XYZ = np.reshape(XYZ, (2, 3, 3))
75 Iab = np.reshape(Iab, (2, 3, 3))
76 np.testing.assert_allclose(XYZ_to_sUCS(XYZ), Iab, atol=TOLERANCE_ABSOLUTE_TESTS)
78 def test_domain_range_scale_XYZ_to_sUCS(self) -> None:
79 """
80 Test :func:`colour.models.sucs.XYZ_to_sUCS` definition domain and
81 range scale support.
82 """
84 XYZ = np.array([0.20654008, 0.12197225, 0.05136952])
85 Iab = XYZ_to_sUCS(XYZ)
87 d_r = (("reference", 1, 1), ("1", 1, 0.01), ("100", 100, 1))
88 for scale, factor_a, factor_b in d_r:
89 with domain_range_scale(scale):
90 np.testing.assert_allclose(
91 XYZ_to_sUCS(XYZ * factor_a),
92 Iab * factor_b,
93 atol=TOLERANCE_ABSOLUTE_TESTS,
94 )
96 @ignore_numpy_errors
97 def test_nan_XYZ_to_sUCS(self) -> None:
98 """Test :func:`colour.models.sucs.XYZ_to_sUCS` definition nan support."""
100 cases = [-1.0, 0.0, 1.0, -np.inf, np.inf, np.nan]
101 cases = np.array(list(set(product(cases, repeat=3))))
102 XYZ_to_sUCS(cases)
105class TestsUCS_to_XYZ:
106 """
107 Define :func:`colour.models.sucs.sUCS_to_XYZ` definition unit tests
108 methods.
109 """
111 def test_sUCS_to_XYZ(self) -> None:
112 """Test :func:`colour.models.sucs.sUCS_to_XYZ` definition."""
114 np.testing.assert_allclose(
115 sUCS_to_XYZ(np.array([42.62923653, 36.97646831, 14.12301358])),
116 np.array([0.20654008, 0.12197225, 0.05136952]),
117 atol=TOLERANCE_ABSOLUTE_TESTS,
118 )
120 np.testing.assert_allclose(
121 sUCS_to_XYZ(np.array([51.93649255, -18.89245582, 15.76112395])),
122 np.array([0.14222010, 0.23042768, 0.10495772]),
123 atol=TOLERANCE_ABSOLUTE_TESTS,
124 )
126 np.testing.assert_allclose(
127 sUCS_to_XYZ(np.array([29.79456846, -6.83806757, -25.33884097])),
128 np.array([0.07818780, 0.06157201, 0.28099326]),
129 atol=TOLERANCE_ABSOLUTE_TESTS,
130 )
132 def test_n_dimensional_sUCS_to_XYZ(self) -> None:
133 """
134 Test :func:`colour.models.sucs.sUCS_to_XYZ` definition n-dimensional
135 support.
136 """
138 Iab = np.array([42.62923653, 36.97646831, 14.12301358])
139 XYZ = sUCS_to_XYZ(Iab)
141 Iab = np.tile(Iab, (6, 1))
142 XYZ = np.tile(XYZ, (6, 1))
143 np.testing.assert_allclose(sUCS_to_XYZ(Iab), XYZ, atol=TOLERANCE_ABSOLUTE_TESTS)
145 Iab = np.reshape(Iab, (2, 3, 3))
146 XYZ = np.reshape(XYZ, (2, 3, 3))
147 np.testing.assert_allclose(sUCS_to_XYZ(Iab), XYZ, atol=TOLERANCE_ABSOLUTE_TESTS)
149 def test_domain_range_scale_sUCS_to_XYZ(self) -> None:
150 """
151 Test :func:`colour.models.sucs.sUCS_to_XYZ` definition domain and
152 range scale support.
153 """
155 Iab = np.array([42.62923653, 36.97646831, 14.12301358])
156 XYZ = sUCS_to_XYZ(Iab)
158 d_r = (("reference", 1, 1), ("1", 0.01, 1), ("100", 1, 100))
159 for scale, factor_a, factor_b in d_r:
160 with domain_range_scale(scale):
161 np.testing.assert_allclose(
162 sUCS_to_XYZ(Iab * factor_a),
163 XYZ * factor_b,
164 atol=TOLERANCE_ABSOLUTE_TESTS,
165 )
167 @ignore_numpy_errors
168 def test_nan_sUCS_to_XYZ(self) -> None:
169 """Test :func:`colour.models.sucs.sUCS_to_XYZ` definition nan support."""
171 cases = [-1.0, 0.0, 1.0, -np.inf, np.inf, np.nan]
172 cases = np.array(list(set(product(cases, repeat=3))))
173 sUCS_to_XYZ(cases)
176class TestsUCSChroma:
177 """
178 Define :func:`colour.models.sucs.sUCS_chroma` definition unit tests
179 methods.
180 """
182 def test_sUCS_hue_angle(self) -> None:
183 """Test :func:`colour.models.sucs.sUCS_chroma` definition."""
185 np.testing.assert_allclose(
186 sUCS_chroma(np.array([42.62923653, 36.97646831, 14.12301358])),
187 40.420511061137226,
188 atol=TOLERANCE_ABSOLUTE_TESTS,
189 )
191 np.testing.assert_allclose(
192 sUCS_chroma(np.array([51.93649255, -18.89245582, 15.76112395])),
193 29.437831501432590,
194 atol=TOLERANCE_ABSOLUTE_TESTS,
195 )
197 np.testing.assert_allclose(
198 sUCS_chroma(np.array([29.79456846, -6.83806757, -25.33884097])),
199 30.800979756091614,
200 atol=TOLERANCE_ABSOLUTE_TESTS,
201 )
203 def test_n_dimensional_sUCS_hue_angle(self) -> None:
204 """
205 Test :func:`colour.models.sucs.sUCS_chroma` definition n-dimensional
206 support.
207 """
209 Iab = np.array([42.62923653, 36.97646831, 14.12301358])
210 C = sUCS_chroma(Iab)
212 Iab = np.tile(Iab, (6, 1))
213 C = np.tile(C, 6)
214 np.testing.assert_allclose(sUCS_chroma(Iab), C, atol=TOLERANCE_ABSOLUTE_TESTS)
216 Iab = np.reshape(Iab, (2, 3, 3))
217 C = np.reshape(C, (2, 3))
218 np.testing.assert_allclose(sUCS_chroma(Iab), C, atol=TOLERANCE_ABSOLUTE_TESTS)
220 def test_domain_range_scale_sUCS_chroma(self) -> None:
221 """
222 Test :func:`colour.models.sucs.sUCS_chroma` definition domain and
223 range scale support.
224 """
226 Iab = np.array([42.62923653, 36.97646831, 14.12301358])
227 C = sUCS_chroma(Iab)
229 d_r = (("reference", 1, 1), ("1", 0.01, 0.01), ("100", 1, 1))
230 for scale, factor_a, factor_b in d_r:
231 with domain_range_scale(scale):
232 np.testing.assert_allclose(
233 sUCS_chroma(Iab * factor_a),
234 C * factor_b,
235 atol=TOLERANCE_ABSOLUTE_TESTS,
236 )
238 @ignore_numpy_errors
239 def test_nan_sUCS_hue_angle(self) -> None:
240 """Test :func:`colour.models.sucs.sUCS_chroma` definition nan support."""
242 cases = [-1.0, 0.0, 1.0, -np.inf, np.inf, np.nan]
243 cases = np.array(list(set(product(cases, repeat=3))))
244 sUCS_chroma(cases)
247class TestsUCSHueAngle:
248 """
249 Define :func:`colour.models.sucs.sUCS_hue_angle` definition unit tests
250 methods.
251 """
253 def test_sUCS_hue_angle(self) -> None:
254 """Test :func:`colour.models.sucs.sUCS_hue_angle` definition."""
256 np.testing.assert_allclose(
257 sUCS_hue_angle(np.array([42.62923653, 36.97646831, 14.12301358])),
258 20.904156072136217,
259 atol=TOLERANCE_ABSOLUTE_TESTS,
260 )
262 np.testing.assert_allclose(
263 sUCS_hue_angle(np.array([51.93649255, -18.89245582, 15.76112395])),
264 140.163281067124470,
265 atol=TOLERANCE_ABSOLUTE_TESTS,
266 )
268 np.testing.assert_allclose(
269 sUCS_hue_angle(np.array([29.79456846, -6.83806757, -25.33884097])),
270 254.897631851863850,
271 atol=TOLERANCE_ABSOLUTE_TESTS,
272 )
274 def test_n_dimensional_sUCS_hue_angle(self) -> None:
275 """
276 Test :func:`colour.models.sucs.sUCS_hue_angle` definition n-dimensional
277 support.
278 """
280 Iab = np.array([42.62923653, 36.97646831, 14.12301358])
281 hue = sUCS_hue_angle(Iab)
283 Iab = np.tile(Iab, (6, 1))
284 hue = np.tile(hue, 6)
285 np.testing.assert_allclose(
286 sUCS_hue_angle(Iab), hue, atol=TOLERANCE_ABSOLUTE_TESTS
287 )
289 Iab = np.reshape(Iab, (2, 3, 3))
290 hue = np.reshape(hue, (2, 3))
291 np.testing.assert_allclose(
292 sUCS_hue_angle(Iab), hue, atol=TOLERANCE_ABSOLUTE_TESTS
293 )
295 def test_domain_range_scale_sUCS_hue_angle(self) -> None:
296 """
297 Test :func:`colour.models.sucs.sUCS_hue_angle` definition domain and
298 range scale support.
299 """
301 Iab = np.array([42.62923653, 36.97646831, 14.12301358])
302 hue = sUCS_hue_angle(Iab)
304 d_r = (("reference", 1, 1), ("1", 1, 1 / 360), ("100", 100, 1 / 3.6))
305 for scale, factor_a, factor_b in d_r:
306 with domain_range_scale(scale):
307 np.testing.assert_allclose(
308 sUCS_hue_angle(Iab * factor_a),
309 hue * factor_b,
310 atol=TOLERANCE_ABSOLUTE_TESTS,
311 )
313 @ignore_numpy_errors
314 def test_nan_sUCS_hue_angle(self) -> None:
315 """Test :func:`colour.models.sucs.sUCS_hue_angle` definition nan support."""
317 cases = [-1.0, 0.0, 1.0, -np.inf, np.inf, np.nan]
318 cases = np.array(list(set(product(cases, repeat=3))))
319 sUCS_hue_angle(cases)
322class TestsUCS_Iab_to_sUCS_ICh:
323 """
324 Define :func:`colour.models.sucs.sUCS_Iab_to_sUCS_ICh` definition unit tests
325 methods.
326 """
328 def test_sUCS_Iab_to_sUCS_ICh(self) -> None:
329 """Test :func:`colour.models.sucs.sUCS_Iab_to_sUCS_ICh` definition."""
331 np.testing.assert_allclose(
332 sUCS_Iab_to_sUCS_ICh(np.array([42.62923653, 36.97646831, 14.12301358])),
333 np.array([42.62923653, 40.42051106, 20.90415607]),
334 atol=TOLERANCE_ABSOLUTE_TESTS,
335 )
337 np.testing.assert_allclose(
338 sUCS_Iab_to_sUCS_ICh(np.array([51.93649255, -18.89245582, 15.76112395])),
339 np.array([51.93649255, 29.43783150, 140.16328107]),
340 atol=TOLERANCE_ABSOLUTE_TESTS,
341 )
343 np.testing.assert_allclose(
344 sUCS_Iab_to_sUCS_ICh(np.array([29.79456846, -6.83806757, -25.33884097])),
345 np.array([29.79456846, 30.80097976, 254.89763185]),
346 atol=TOLERANCE_ABSOLUTE_TESTS,
347 )
349 def test_n_dimensional_sUCS_Iab_to_sUCS_ICh(self) -> None:
350 """
351 Test :func:`colour.models.sucs.sUCS_Iab_to_sUCS_ICh` definition
352 n-dimensional support.
353 """
355 Iab = np.array([42.62923653, 36.97646831, 14.12301358])
356 ICh = sUCS_Iab_to_sUCS_ICh(Iab)
358 Iab = np.tile(Iab, (6, 1))
359 ICh = np.tile(ICh, (6, 1))
360 np.testing.assert_allclose(
361 sUCS_Iab_to_sUCS_ICh(Iab), ICh, atol=TOLERANCE_ABSOLUTE_TESTS
362 )
364 Iab = np.reshape(Iab, (2, 3, 3))
365 ICh = np.reshape(ICh, (2, 3, 3))
366 np.testing.assert_allclose(
367 sUCS_Iab_to_sUCS_ICh(Iab), ICh, atol=TOLERANCE_ABSOLUTE_TESTS
368 )
370 def test_domain_range_scale_sUCS_Iab_to_sUCS_ICh(self) -> None:
371 """
372 Test :func:`colour.models.sucs.sUCS_Iab_to_sUCS_ICh` definition domain
373 and range scale support.
374 """
376 Iab = np.array([42.62923653, 36.97646831, 14.12301358])
377 ICh = sUCS_Iab_to_sUCS_ICh(Iab)
379 d_r = (
380 ("reference", 1, 1),
381 ("1", 0.01, np.array([0.01, 0.01, 1 / 360])),
382 ("100", 1, np.array([1, 1, 100 / 360])),
383 )
384 for scale, factor_a, factor_b in d_r:
385 with domain_range_scale(scale):
386 np.testing.assert_allclose(
387 sUCS_Iab_to_sUCS_ICh(Iab * factor_a),
388 ICh * factor_b,
389 atol=TOLERANCE_ABSOLUTE_TESTS,
390 )
392 @ignore_numpy_errors
393 def test_nan_sUCS_Iab_to_sUCS_ICh(self) -> None:
394 """
395 Test :func:`colour.models.sucs.sUCS_Iab_to_sUCS_ICh` definition nan support.
396 """
398 cases = [-1.0, 0.0, 1.0, -np.inf, np.inf, np.nan]
399 cases = np.array(list(set(product(cases, repeat=3))))
400 sUCS_Iab_to_sUCS_ICh(cases)
403class TestsUCS_ICh_to_sUCS_Iab:
404 """
405 Define :func:`colour.models.sucs.sUCS_ICh_to_sUCS_Iab` definition unit tests
406 methods.
407 """
409 def test_sUCS_ICh_to_sUCS_Iab(self) -> None:
410 """Test :func:`colour.models.sucs.sUCS_ICh_to_sUCS_Iab` definition."""
412 np.testing.assert_allclose(
413 sUCS_ICh_to_sUCS_Iab(np.array([42.62923653, 40.42051106, 20.90415607])),
414 np.array([42.62923653, 36.97646831, 14.12301358]),
415 atol=TOLERANCE_ABSOLUTE_TESTS,
416 )
418 np.testing.assert_allclose(
419 sUCS_ICh_to_sUCS_Iab(np.array([51.93649255, 29.43783150, 140.16328107])),
420 np.array([51.93649255, -18.89245582, 15.76112395]),
421 atol=TOLERANCE_ABSOLUTE_TESTS,
422 )
424 np.testing.assert_allclose(
425 sUCS_ICh_to_sUCS_Iab(np.array([29.79456846, 30.80097976, 254.89763185])),
426 np.array([29.79456846, -6.83806757, -25.33884097]),
427 atol=TOLERANCE_ABSOLUTE_TESTS,
428 )
430 def test_n_dimensional_sUCS_ICh_to_sUCS_Iab(self) -> None:
431 """
432 Test :func:`colour.models.sucs.sUCS_ICh_to_sUCS_Iab` definition
433 n-dimensional support.
434 """
436 ICh = np.array([42.62923653, 40.42051106, 20.90415607])
437 Iab = sUCS_ICh_to_sUCS_Iab(ICh)
439 ICh = np.tile(ICh, (6, 1))
440 Iab = np.tile(Iab, (6, 1))
441 np.testing.assert_allclose(
442 sUCS_ICh_to_sUCS_Iab(ICh), Iab, atol=TOLERANCE_ABSOLUTE_TESTS
443 )
445 ICh = np.reshape(ICh, (2, 3, 3))
446 Iab = np.reshape(Iab, (2, 3, 3))
447 np.testing.assert_allclose(
448 sUCS_ICh_to_sUCS_Iab(ICh), Iab, atol=TOLERANCE_ABSOLUTE_TESTS
449 )
451 def test_domain_range_scale_sUCS_ICh_to_sUCS_Iab(self) -> None:
452 """
453 Test :func:`colour.models.sucs.sUCS_ICh_to_sUCS_Iab` definition domain
454 and range scale support.
455 """
457 ICh = np.array([42.62923653, 40.42051106, 20.90415607])
458 Iab = sUCS_ICh_to_sUCS_Iab(ICh)
460 d_r = (
461 ("reference", 1, 1),
462 ("1", np.array([0.01, 0.01, 1 / 360]), 0.01),
463 ("100", np.array([1, 1, 100 / 360]), 1),
464 )
465 for scale, factor_a, factor_b in d_r:
466 with domain_range_scale(scale):
467 np.testing.assert_allclose(
468 sUCS_ICh_to_sUCS_Iab(ICh * factor_a),
469 Iab * factor_b,
470 atol=TOLERANCE_ABSOLUTE_TESTS,
471 )
473 @ignore_numpy_errors
474 def test_nan_sUCS_ICh_to_sUCS_Iab(self) -> None:
475 """
476 Test :func:`colour.models.sucs.sUCS_ICh_to_sUCS_Iab` definition nan support.
477 """
479 cases = [-1.0, 0.0, 1.0, -np.inf, np.inf, np.nan]
480 cases = np.array(list(set(product(cases, repeat=3))))
481 sUCS_ICh_to_sUCS_Iab(cases)