Coverage for models/tests/test_hunter_lab.py: 100%
123 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.hunter_lab` module."""
3from __future__ import annotations
5from itertools import product
7import numpy as np
9from colour.colorimetry import TVS_ILLUMINANTS_HUNTERLAB
10from colour.constants import TOLERANCE_ABSOLUTE_TESTS
11from colour.models import (
12 Hunter_Lab_to_XYZ,
13 XYZ_to_Hunter_Lab,
14 XYZ_to_K_ab_HunterLab1966,
15)
16from colour.utilities import domain_range_scale, ignore_numpy_errors
18__author__ = "Colour Developers"
19__copyright__ = "Copyright 2013 Colour Developers"
20__license__ = "BSD-3-Clause - https://opensource.org/licenses/BSD-3-Clause"
21__maintainer__ = "Colour Developers"
22__email__ = "colour-developers@colour-science.org"
23__status__ = "Production"
25__all__ = [
26 "TestXYZ_to_K_ab_HunterLab1966",
27 "TestXYZ_to_Hunter_Lab",
28 "TestHunter_Lab_to_XYZ",
29]
32class TestXYZ_to_K_ab_HunterLab1966:
33 """
34 Define :func:`colour.models.hunter_lab.XYZ_to_K_ab_HunterLab1966`
35 definition unit tests methods.
36 """
38 def test_XYZ_to_K_ab_HunterLab1966(self) -> None:
39 """
40 Test :func:`colour.models.hunter_lab.XYZ_to_K_ab_HunterLab1966`
41 definition.
42 """
44 np.testing.assert_allclose(
45 XYZ_to_K_ab_HunterLab1966(
46 np.array([0.20654008, 0.12197225, 0.05136952]) * 100
47 ),
48 np.array([80.32152090, 14.59816495]),
49 atol=TOLERANCE_ABSOLUTE_TESTS,
50 )
52 np.testing.assert_allclose(
53 XYZ_to_K_ab_HunterLab1966(
54 np.array([0.14222010, 0.23042768, 0.10495772]) * 100
55 ),
56 np.array([66.65154834, 20.86664881]),
57 atol=TOLERANCE_ABSOLUTE_TESTS,
58 )
60 np.testing.assert_allclose(
61 XYZ_to_K_ab_HunterLab1966(
62 np.array([0.07818780, 0.06157201, 0.28099326]) * 100
63 ),
64 np.array([49.41960269, 34.14235426]),
65 atol=TOLERANCE_ABSOLUTE_TESTS,
66 )
68 def test_n_dimensional_XYZ_to_K_ab_HunterLab1966(self) -> None:
69 """
70 Test :func:`colour.models.hunter_lab.XYZ_to_K_ab_HunterLab1966`
71 definition n-dimensional support.
72 """
74 XYZ = np.array([0.20654008, 0.12197225, 0.05136952]) * 100
75 K_ab = XYZ_to_K_ab_HunterLab1966(XYZ)
77 XYZ = np.tile(XYZ, (6, 1))
78 K_ab = np.tile(K_ab, (6, 1))
79 np.testing.assert_allclose(
80 XYZ_to_K_ab_HunterLab1966(XYZ), K_ab, atol=TOLERANCE_ABSOLUTE_TESTS
81 )
83 XYZ = np.reshape(XYZ, (2, 3, 3))
84 K_ab = np.reshape(K_ab, (2, 3, 2))
85 np.testing.assert_allclose(
86 XYZ_to_K_ab_HunterLab1966(XYZ), K_ab, atol=TOLERANCE_ABSOLUTE_TESTS
87 )
89 @ignore_numpy_errors
90 def test_nan_XYZ_to_K_ab_HunterLab1966(self) -> None:
91 """
92 Test :func:`colour.models.hunter_lab.XYZ_to_K_ab_HunterLab1966`
93 definition nan support.
94 """
96 cases = [-1.0, 0.0, 1.0, -np.inf, np.inf, np.nan]
97 cases = np.array(list(set(product(cases, repeat=3))))
98 XYZ_to_K_ab_HunterLab1966(cases)
101class TestXYZ_to_Hunter_Lab:
102 """
103 Define :func:`colour.models.hunter_lab.XYZ_to_Hunter_Lab` definition unit
104 tests methods.
105 """
107 def test_XYZ_to_Hunter_Lab(self) -> None:
108 """Test :func:`colour.models.hunter_lab.XYZ_to_Hunter_Lab` definition."""
110 np.testing.assert_allclose(
111 XYZ_to_Hunter_Lab(np.array([0.20654008, 0.12197225, 0.05136952]) * 100),
112 np.array([34.92452577, 47.06189858, 14.38615107]),
113 atol=TOLERANCE_ABSOLUTE_TESTS,
114 )
116 np.testing.assert_allclose(
117 XYZ_to_Hunter_Lab(np.array([0.14222010, 0.23042768, 0.10495772]) * 100),
118 np.array([48.00288325, -28.98551622, 18.75564181]),
119 atol=TOLERANCE_ABSOLUTE_TESTS,
120 )
122 np.testing.assert_allclose(
123 XYZ_to_Hunter_Lab(np.array([0.07818780, 0.06157201, 0.28099326]) * 100),
124 np.array([24.81370791, 14.38300039, -53.25539126]),
125 atol=TOLERANCE_ABSOLUTE_TESTS,
126 )
128 h_i = TVS_ILLUMINANTS_HUNTERLAB["CIE 1931 2 Degree Standard Observer"]
129 A = h_i["A"]
130 np.testing.assert_allclose(
131 XYZ_to_Hunter_Lab(
132 np.array([0.20654008, 0.12197225, 0.05136952]) * 100,
133 A.XYZ_n,
134 A.K_ab,
135 ),
136 np.array([34.92452577, 35.04243086, -2.47688619]),
137 atol=TOLERANCE_ABSOLUTE_TESTS,
138 )
140 D65 = h_i["D65"]
141 np.testing.assert_allclose(
142 XYZ_to_Hunter_Lab(
143 np.array([0.20654008, 0.12197225, 0.05136952]) * 100,
144 D65.XYZ_n,
145 D65.K_ab,
146 ),
147 np.array([34.92452577, 47.06189858, 14.38615107]),
148 atol=TOLERANCE_ABSOLUTE_TESTS,
149 )
151 np.testing.assert_allclose(
152 XYZ_to_Hunter_Lab(
153 np.array([0.20654008, 0.12197225, 0.05136952]) * 100,
154 D65.XYZ_n,
155 K_ab=None,
156 ),
157 np.array([34.92452577, 47.05669614, 14.38385238]),
158 atol=TOLERANCE_ABSOLUTE_TESTS,
159 )
161 def test_n_dimensional_XYZ_to_Hunter_Lab(self) -> None:
162 """
163 Test :func:`colour.models.hunter_lab.XYZ_to_Hunter_Lab` definition
164 n-dimensional support.
165 """
167 h_i = TVS_ILLUMINANTS_HUNTERLAB["CIE 1931 2 Degree Standard Observer"]
168 D65 = h_i["D65"]
170 XYZ = np.array([0.20654008, 0.12197225, 0.05136952]) * 100
171 XYZ_n = D65.XYZ_n
172 K_ab = D65.K_ab
173 Lab = XYZ_to_Hunter_Lab(XYZ, XYZ_n, K_ab)
175 XYZ = np.tile(XYZ, (6, 1))
176 Lab = np.tile(Lab, (6, 1))
177 np.testing.assert_allclose(
178 XYZ_to_Hunter_Lab(XYZ, XYZ_n, K_ab),
179 Lab,
180 atol=TOLERANCE_ABSOLUTE_TESTS,
181 )
183 XYZ_n = np.tile(XYZ_n, (6, 1))
184 K_ab = np.tile(K_ab, (6, 1))
185 np.testing.assert_allclose(
186 XYZ_to_Hunter_Lab(XYZ, XYZ_n, K_ab),
187 Lab,
188 atol=TOLERANCE_ABSOLUTE_TESTS,
189 )
191 XYZ = np.reshape(XYZ, (2, 3, 3))
192 XYZ_n = np.reshape(XYZ_n, (2, 3, 3))
193 K_ab = np.reshape(K_ab, (2, 3, 2))
194 Lab = np.reshape(Lab, (2, 3, 3))
195 np.testing.assert_allclose(
196 XYZ_to_Hunter_Lab(XYZ, XYZ_n, K_ab),
197 Lab,
198 atol=TOLERANCE_ABSOLUTE_TESTS,
199 )
201 def test_domain_range_scale_XYZ_to_Hunter_Lab(self) -> None:
202 """
203 Test :func:`colour.models.hunter_lab.XYZ_to_Hunter_Lab` definition
204 domain and range scale support.
205 """
207 h_i = TVS_ILLUMINANTS_HUNTERLAB["CIE 1931 2 Degree Standard Observer"]
208 D65 = h_i["D65"]
210 XYZ = np.array([0.20654008, 0.12197225, 0.05136952]) * 100
211 XYZ_n = D65.XYZ_n
212 K_ab = D65.K_ab
213 Lab = XYZ_to_Hunter_Lab(XYZ, XYZ_n, K_ab)
215 d_r = (("reference", 1), ("1", 0.01), ("100", 1))
216 for scale, factor in d_r:
217 with domain_range_scale(scale):
218 np.testing.assert_allclose(
219 XYZ_to_Hunter_Lab(XYZ * factor, XYZ_n * factor, K_ab),
220 Lab * factor,
221 atol=TOLERANCE_ABSOLUTE_TESTS,
222 )
224 @ignore_numpy_errors
225 def test_nan_XYZ_to_Hunter_Lab(self) -> None:
226 """
227 Test :func:`colour.models.hunter_lab.XYZ_to_Hunter_Lab` definition nan
228 support.
229 """
231 cases = [-1.0, 0.0, 1.0, -np.inf, np.inf, np.nan]
232 cases = np.array(list(set(product(cases, repeat=3))))
233 XYZ_to_Hunter_Lab(cases, cases, cases[..., 0:2])
236class TestHunter_Lab_to_XYZ:
237 """
238 Define :func:`colour.models.hunter_lab.Hunter_Lab_to_XYZ` definition unit
239 tests methods.
240 """
242 def test_Hunter_Lab_to_XYZ(self) -> None:
243 """Test :func:`colour.models.hunter_lab.Hunter_Lab_to_XYZ` definition."""
245 np.testing.assert_allclose(
246 Hunter_Lab_to_XYZ(np.array([34.92452577, 47.06189858, 14.38615107])),
247 np.array([20.65400800, 12.19722500, 5.13695200]),
248 atol=TOLERANCE_ABSOLUTE_TESTS,
249 )
251 np.testing.assert_allclose(
252 Hunter_Lab_to_XYZ(np.array([48.00288325, -28.98551622, 18.75564181])),
253 np.array([14.22201000, 23.04276800, 10.49577200]),
254 atol=TOLERANCE_ABSOLUTE_TESTS,
255 )
257 np.testing.assert_allclose(
258 Hunter_Lab_to_XYZ(np.array([24.81370791, 14.38300039, -53.25539126])),
259 np.array([7.81878000, 6.15720100, 28.09932601]),
260 atol=TOLERANCE_ABSOLUTE_TESTS,
261 )
263 h_i = TVS_ILLUMINANTS_HUNTERLAB["CIE 1931 2 Degree Standard Observer"]
264 A = h_i["A"]
265 np.testing.assert_allclose(
266 Hunter_Lab_to_XYZ(
267 np.array([34.92452577, 35.04243086, -2.47688619]),
268 A.XYZ_n,
269 A.K_ab,
270 ),
271 np.array([20.65400800, 12.19722500, 5.13695200]),
272 atol=TOLERANCE_ABSOLUTE_TESTS,
273 )
275 D65 = h_i["D65"]
276 np.testing.assert_allclose(
277 Hunter_Lab_to_XYZ(
278 np.array([34.92452577, 47.06189858, 14.38615107]),
279 D65.XYZ_n,
280 D65.K_ab,
281 ),
282 np.array([20.65400800, 12.19722500, 5.13695200]),
283 atol=TOLERANCE_ABSOLUTE_TESTS,
284 )
286 np.testing.assert_allclose(
287 Hunter_Lab_to_XYZ(
288 np.array([34.92452577, 47.05669614, 14.38385238]),
289 D65.XYZ_n,
290 K_ab=None,
291 ),
292 np.array([20.65400800, 12.19722500, 5.13695200]),
293 atol=TOLERANCE_ABSOLUTE_TESTS,
294 )
296 def test_n_dimensional_Hunter_Lab_to_XYZ(self) -> None:
297 """
298 Test :func:`colour.models.hunter_lab.Hunter_Lab_to_XYZ` definition
299 n-dimensional support.
300 """
302 h_i = TVS_ILLUMINANTS_HUNTERLAB["CIE 1931 2 Degree Standard Observer"]
303 D65 = h_i["D65"]
305 Lab = np.array([34.92452577, 47.06189858, 14.38615107])
306 XYZ_n = D65.XYZ_n
307 K_ab = D65.K_ab
308 XYZ = Hunter_Lab_to_XYZ(Lab, XYZ_n, K_ab)
310 Lab = np.tile(Lab, (6, 1))
311 XYZ = np.tile(XYZ, (6, 1))
312 np.testing.assert_allclose(
313 Hunter_Lab_to_XYZ(Lab, XYZ_n, K_ab),
314 XYZ,
315 atol=TOLERANCE_ABSOLUTE_TESTS,
316 )
318 K_ab = np.tile(K_ab, (6, 1))
319 XYZ_n = np.tile(XYZ_n, (6, 1))
320 np.testing.assert_allclose(
321 Hunter_Lab_to_XYZ(Lab, XYZ_n, K_ab),
322 XYZ,
323 atol=TOLERANCE_ABSOLUTE_TESTS,
324 )
326 Lab = np.reshape(Lab, (2, 3, 3))
327 XYZ_n = np.reshape(XYZ_n, (2, 3, 3))
328 K_ab = np.reshape(K_ab, (2, 3, 2))
329 XYZ = np.reshape(XYZ, (2, 3, 3))
330 np.testing.assert_allclose(
331 Hunter_Lab_to_XYZ(Lab, XYZ_n, K_ab),
332 XYZ,
333 atol=TOLERANCE_ABSOLUTE_TESTS,
334 )
336 def test_domain_range_scale_Hunter_Lab_to_XYZ(self) -> None:
337 """
338 Test :func:`colour.models.hunter_lab.Hunter_Lab_to_XYZ` definition
339 domain and range scale support.
340 """
342 h_i = TVS_ILLUMINANTS_HUNTERLAB["CIE 1931 2 Degree Standard Observer"]
343 D65 = h_i["D65"]
345 Lab = np.array([34.92452577, 47.06189858, 14.38615107])
346 XYZ_n = D65.XYZ_n
347 K_ab = D65.K_ab
348 XYZ = Hunter_Lab_to_XYZ(Lab, XYZ_n, K_ab)
350 d_r = (("reference", 1), ("1", 0.01), ("100", 1))
351 for scale, factor in d_r:
352 with domain_range_scale(scale):
353 np.testing.assert_allclose(
354 Hunter_Lab_to_XYZ(Lab * factor, XYZ_n * factor, K_ab),
355 XYZ * factor,
356 atol=TOLERANCE_ABSOLUTE_TESTS,
357 )
359 @ignore_numpy_errors
360 def test_nan_Hunter_Lab_to_XYZ(self) -> None:
361 """
362 Test :func:`colour.models.hunter_lab.Hunter_Lab_to_XYZ` definition
363 nan support.
364 """
366 cases = [-1.0, 0.0, 1.0, -np.inf, np.inf, np.nan]
367 cases = np.array(list(set(product(cases, repeat=3))))
368 Hunter_Lab_to_XYZ(cases, cases, cases[..., 0:2])