Coverage for colour/models/rgb/tests/test_derivation.py: 100%
109 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"""Define the unit tests for the :mod:`colour.models.rgb.derivation` module."""
3from __future__ import annotations
5import contextlib
6import re
7from itertools import product
9import numpy as np
10from numpy.linalg import LinAlgError
12from colour.constants import TOLERANCE_ABSOLUTE_TESTS
13from colour.models import (
14 RGB_luminance,
15 RGB_luminance_equation,
16 chromatically_adapted_primaries,
17 normalised_primary_matrix,
18 primaries_whitepoint,
19)
20from colour.models.rgb.derivation import xy_to_z
21from colour.utilities import ignore_numpy_errors
23__author__ = "Colour Developers"
24__copyright__ = "Copyright 2013 Colour Developers"
25__license__ = "BSD-3-Clause - https://opensource.org/licenses/BSD-3-Clause"
26__maintainer__ = "Colour Developers"
27__email__ = "colour-developers@colour-science.org"
28__status__ = "Production"
30__all__ = [
31 "Testxy_to_z",
32 "TestNormalisedPrimaryMatrix",
33 "TestChromaticallyAdaptedPrimaries",
34 "TestPrimariesWhitepoint",
35 "TestRGBLuminanceEquation",
36 "TestRGBLuminance",
37]
40class Testxy_to_z:
41 """
42 Define :func:`colour.models.rgb.derivation.xy_to_z` definition unit
43 tests methods.
44 """
46 def test_xy_to_z(self) -> None:
47 """Test :func:`colour.models.rgb.derivation.xy_to_z` definition."""
49 np.testing.assert_allclose(
50 xy_to_z(np.array([0.2500, 0.2500])),
51 0.50000000,
52 atol=TOLERANCE_ABSOLUTE_TESTS,
53 )
55 np.testing.assert_allclose(
56 xy_to_z(np.array([0.0001, -0.0770])),
57 1.07690000,
58 atol=TOLERANCE_ABSOLUTE_TESTS,
59 )
61 np.testing.assert_allclose(
62 xy_to_z(np.array([0.0000, 1.0000])),
63 0.00000000,
64 atol=TOLERANCE_ABSOLUTE_TESTS,
65 )
67 def test_n_dimensional_xy_to_z(self) -> None:
68 """
69 Test :func:`colour.models.rgb.derivation.xy_to_z` definition
70 n-dimensional arrays support.
71 """
73 xy = np.array([0.25, 0.25])
74 z = xy_to_z(xy)
76 xy = np.tile(xy, (6, 1))
77 z = np.tile(
78 z,
79 6,
80 )
81 np.testing.assert_allclose(xy_to_z(xy), z, atol=TOLERANCE_ABSOLUTE_TESTS)
83 xy = np.reshape(xy, (2, 3, 2))
84 z = np.reshape(z, (2, 3))
85 np.testing.assert_allclose(xy_to_z(xy), z, atol=TOLERANCE_ABSOLUTE_TESTS)
87 @ignore_numpy_errors
88 def test_nan_xy_to_z(self) -> None:
89 """
90 Test :func:`colour.models.rgb.derivation.xy_to_z` definition nan
91 support.
92 """
94 cases = [-1.0, 0.0, 1.0, -np.inf, np.inf, np.nan]
95 cases = np.array(list(set(product(cases, repeat=2))))
96 xy_to_z(cases)
99class TestNormalisedPrimaryMatrix:
100 """
101 Define :func:`colour.models.rgb.derivation.normalised_primary_matrix`
102 definition unit tests methods.
103 """
105 def test_normalised_primary_matrix(self) -> None:
106 """
107 Test :func:`colour.models.rgb.derivation.normalised_primary_matrix`
108 definition.
109 """
111 np.testing.assert_allclose(
112 normalised_primary_matrix(
113 np.array([0.73470, 0.26530, 0.00000, 1.00000, 0.00010, -0.07700]),
114 np.array([0.32168, 0.33767]),
115 ),
116 np.array(
117 [
118 [0.95255240, 0.00000000, 0.00009368],
119 [0.34396645, 0.72816610, -0.07213255],
120 [0.00000000, 0.00000000, 1.00882518],
121 ]
122 ),
123 atol=TOLERANCE_ABSOLUTE_TESTS,
124 )
126 np.testing.assert_allclose(
127 normalised_primary_matrix(
128 np.array([0.640, 0.330, 0.300, 0.600, 0.150, 0.060]),
129 np.array([0.3127, 0.3290]),
130 ),
131 np.array(
132 [
133 [0.41239080, 0.35758434, 0.18048079],
134 [0.21263901, 0.71516868, 0.07219232],
135 [0.01933082, 0.11919478, 0.95053215],
136 ]
137 ),
138 atol=TOLERANCE_ABSOLUTE_TESTS,
139 )
141 @ignore_numpy_errors
142 def test_nan_normalised_primary_matrix(self) -> None:
143 """
144 Test :func:`colour.models.rgb.derivation.normalised_primary_matrix`
145 definition nan support.
146 """
148 cases = [-1.0, 0.0, 1.0, -np.inf, np.inf, np.nan]
149 cases = np.array(list(set(product(cases, repeat=2))))
150 for case in cases:
151 P = np.array(np.vstack([case, case, case]))
152 W = case
153 with contextlib.suppress(LinAlgError):
154 normalised_primary_matrix(P, W)
157class TestChromaticallyAdaptedPrimaries:
158 """
159 Define :func:`colour.models.rgb.derivation.\
160chromatically_adapted_primaries` definition unit tests methods.
161 """
163 def test_chromatically_adapted_primaries(self) -> None:
164 """
165 Test :func:`colour.models.rgb.derivation.\
166chromatically_adapted_primaries` definition.
167 """
169 np.testing.assert_allclose(
170 chromatically_adapted_primaries(
171 np.array([0.73470, 0.26530, 0.00000, 1.00000, 0.00010, -0.07700]),
172 np.array([0.32168, 0.33767]),
173 np.array([0.34570, 0.35850]),
174 ),
175 np.array(
176 [
177 [0.73431182, 0.26694964],
178 [0.02211963, 0.98038009],
179 [-0.05880375, -0.12573056],
180 ]
181 ),
182 atol=TOLERANCE_ABSOLUTE_TESTS,
183 )
185 np.testing.assert_allclose(
186 chromatically_adapted_primaries(
187 np.array([0.640, 0.330, 0.300, 0.600, 0.150, 0.060]),
188 np.array([0.31270, 0.32900]),
189 np.array([0.34570, 0.35850]),
190 ),
191 np.array(
192 [
193 [0.64922534, 0.33062196],
194 [0.32425276, 0.60237128],
195 [0.15236177, 0.06118676],
196 ]
197 ),
198 atol=TOLERANCE_ABSOLUTE_TESTS,
199 )
201 np.testing.assert_allclose(
202 chromatically_adapted_primaries(
203 np.array([0.640, 0.330, 0.300, 0.600, 0.150, 0.060]),
204 np.array([0.31270, 0.32900]),
205 np.array([0.34570, 0.35850]),
206 "Bradford",
207 ),
208 np.array(
209 [
210 [0.64844144, 0.33085331],
211 [0.32119518, 0.59784434],
212 [0.15589322, 0.06604921],
213 ]
214 ),
215 atol=TOLERANCE_ABSOLUTE_TESTS,
216 )
218 @ignore_numpy_errors
219 def test_nan_chromatically_adapted_primaries(self) -> None:
220 """
221 Test :func:`colour.models.rgb.derivation.\
222chromatically_adapted_primaries` definition nan support.
223 """
225 cases = [-1.0, 0.0, 1.0, -np.inf, np.inf, np.nan]
226 cases = np.array(list(set(product(cases, repeat=2))))
227 for case in cases:
228 P = np.array(np.vstack([case, case, case]))
229 W = case
230 chromatically_adapted_primaries(P, W, W)
233class TestPrimariesWhitepoint:
234 """
235 Define :func:`colour.models.rgb.derivation.primaries_whitepoint`
236 definition unit tests methods.
237 """
239 def test_primaries_whitepoint(self) -> None:
240 """
241 Test :func:`colour.models.rgb.derivation.primaries_whitepoint`
242 definition.
243 """
245 P, W = primaries_whitepoint(
246 np.array(
247 [
248 [0.95255240, 0.00000000, 0.00009368],
249 [0.34396645, 0.72816610, -0.07213255],
250 [0.00000000, 0.00000000, 1.00882518],
251 ]
252 )
253 )
254 np.testing.assert_allclose(
255 P,
256 np.array(
257 [
258 [0.73470, 0.26530],
259 [0.00000, 1.00000],
260 [0.00010, -0.07700],
261 ]
262 ),
263 atol=TOLERANCE_ABSOLUTE_TESTS,
264 )
265 np.testing.assert_allclose(
266 W, np.array([0.32168, 0.33767]), atol=TOLERANCE_ABSOLUTE_TESTS
267 )
269 P, W = primaries_whitepoint(
270 np.array(
271 [
272 [0.41240000, 0.35760000, 0.18050000],
273 [0.21260000, 0.71520000, 0.07220000],
274 [0.01930000, 0.11920000, 0.95050000],
275 ]
276 )
277 )
278 np.testing.assert_allclose(
279 P,
280 np.array(
281 [
282 [0.64007450, 0.32997051],
283 [0.30000000, 0.60000000],
284 [0.15001662, 0.06000665],
285 ]
286 ),
287 atol=TOLERANCE_ABSOLUTE_TESTS,
288 )
289 np.testing.assert_allclose(
290 W,
291 np.array([0.31271591, 0.32900148]),
292 atol=TOLERANCE_ABSOLUTE_TESTS,
293 )
295 @ignore_numpy_errors
296 def test_nan_primaries_whitepoint(self) -> None:
297 """
298 Test :func:`colour.models.rgb.derivation.primaries_whitepoint`
299 definition nan support.
300 """
302 cases = [-1.0, 0.0, 1.0, -np.inf, np.inf, np.nan]
303 cases = np.array(list(set(product(cases, repeat=3))))
304 for case in cases:
305 M = np.array(np.vstack([case, case, case]))
306 primaries_whitepoint(M)
309class TestRGBLuminanceEquation:
310 """
311 Define :func:`colour.models.rgb.derivation.RGB_luminance_equation`
312 definition unit tests methods.
313 """
315 def test_RGB_luminance_equation(self) -> None:
316 """
317 Test :func:`colour.models.rgb.derivation.RGB_luminance_equation`
318 definition.
319 """
321 assert isinstance(
322 RGB_luminance_equation(
323 np.array([0.73470, 0.26530, 0.00000, 1.00000, 0.00010, -0.07700]),
324 np.array([0.32168, 0.33767]),
325 ),
326 str,
327 )
329 # TODO: Simplify that monster.
330 pattern = (
331 "Y\\s?=\\s?[-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?."
332 "\\(R\\)\\s?[+-]\\s?[-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?."
333 "\\(G\\)\\s?[+-]\\s?[-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?."
334 "\\(B\\)"
335 )
336 P = np.array([0.73470, 0.26530, 0.00000, 1.00000, 0.00010, -0.07700])
337 assert re.match(
338 pattern,
339 RGB_luminance_equation(P, np.array([0.32168, 0.33767])),
340 )
343class TestRGBLuminance:
344 """
345 Define :func:`colour.models.rgb.derivation.RGB_luminance` definition
346 unit tests methods.
347 """
349 def test_RGB_luminance(self) -> None:
350 """
351 Test :func:`colour.models.rgb.derivation.RGB_luminance`
352 definition.
353 """
355 np.testing.assert_allclose(
356 RGB_luminance(
357 np.array([0.18, 0.18, 0.18]),
358 np.array([0.73470, 0.26530, 0.00000, 1.00000, 0.00010, -0.07700]),
359 np.array([0.32168, 0.33767]),
360 ),
361 0.18000000,
362 atol=TOLERANCE_ABSOLUTE_TESTS,
363 )
365 np.testing.assert_allclose(
366 RGB_luminance(
367 np.array([0.21959402, 0.06986677, 0.04703877]),
368 np.array([0.73470, 0.26530, 0.00000, 1.00000, 0.00010, -0.07700]),
369 np.array([0.32168, 0.33767]),
370 ),
371 0.123014562384318,
372 atol=TOLERANCE_ABSOLUTE_TESTS,
373 )
375 np.testing.assert_allclose(
376 RGB_luminance(
377 np.array([0.45620519, 0.03081071, 0.04091952]),
378 np.array([0.6400, 0.3300, 0.3000, 0.6000, 0.1500, 0.0600]),
379 np.array([0.31270, 0.32900]),
380 ),
381 0.121995947729870,
382 atol=TOLERANCE_ABSOLUTE_TESTS,
383 )
385 def test_n_dimensional_RGB_luminance(self) -> None:
386 """
387 Test :func:`colour.models.rgb.derivation.RGB_luminance` definition
388 n_dimensional arrays support.
389 """
391 RGB = (np.array([0.18, 0.18, 0.18]),)
392 P = (np.array([0.73470, 0.26530, 0.00000, 1.00000, 0.00010, -0.07700]),)
393 W = np.array([0.32168, 0.33767])
394 Y = RGB_luminance(RGB, P, W)
396 RGB = np.tile(RGB, (6, 1))
397 Y = np.tile(Y, 6)
398 np.testing.assert_allclose(
399 RGB_luminance(RGB, P, W), Y, atol=TOLERANCE_ABSOLUTE_TESTS
400 )
402 RGB = np.reshape(RGB, (2, 3, 3))
403 Y = np.reshape(Y, (2, 3))
404 np.testing.assert_allclose(
405 RGB_luminance(RGB, P, W), Y, atol=TOLERANCE_ABSOLUTE_TESTS
406 )
408 @ignore_numpy_errors
409 def test_nan_RGB_luminance(self) -> None:
410 """
411 Test :func:`colour.models.rgb.derivation.RGB_luminance`
412 definition nan support.
413 """
415 cases = [-1.0, 0.0, 1.0, -np.inf, np.inf, np.nan]
416 cases = np.array(list(set(product(cases, repeat=3))))
417 for case in cases:
418 RGB = case
419 P = np.array(np.vstack([case[0:2], case[0:2], case[0:2]]))
420 W = case[0:2]
421 with contextlib.suppress(LinAlgError):
422 RGB_luminance(RGB, P, W)