Coverage for colour/models/tests/test_ipt.py: 100%
91 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.ipt` module."""
3from __future__ import annotations
5from itertools import product
7import numpy as np
9from colour.constants import TOLERANCE_ABSOLUTE_TESTS
10from colour.models import IPT_hue_angle, IPT_to_XYZ, XYZ_to_IPT
11from colour.utilities import domain_range_scale, ignore_numpy_errors
13__author__ = "Colour Developers"
14__copyright__ = "Copyright 2013 Colour Developers"
15__license__ = "BSD-3-Clause - https://opensource.org/licenses/BSD-3-Clause"
16__maintainer__ = "Colour Developers"
17__email__ = "colour-developers@colour-science.org"
18__status__ = "Production"
20__all__ = [
21 "TestXYZ_to_IPT",
22 "TestIPT_to_XYZ",
23 "TestIPTHueAngle",
24]
27class TestXYZ_to_IPT:
28 """Define :func:`colour.models.ipt.XYZ_to_IPT` definition unit tests methods."""
30 def test_XYZ_to_IPT(self) -> None:
31 """Test :func:`colour.models.ipt.XYZ_to_IPT` definition."""
33 np.testing.assert_allclose(
34 XYZ_to_IPT(np.array([0.20654008, 0.12197225, 0.05136952])),
35 np.array([0.38426191, 0.38487306, 0.18886838]),
36 atol=TOLERANCE_ABSOLUTE_TESTS,
37 )
39 np.testing.assert_allclose(
40 XYZ_to_IPT(np.array([0.14222010, 0.23042768, 0.10495772])),
41 np.array([0.49437481, -0.19251742, 0.18080304]),
42 atol=TOLERANCE_ABSOLUTE_TESTS,
43 )
45 np.testing.assert_allclose(
46 XYZ_to_IPT(np.array([0.07818780, 0.06157201, 0.28099326])),
47 np.array([0.35167774, -0.07525627, -0.30921279]),
48 atol=TOLERANCE_ABSOLUTE_TESTS,
49 )
51 def test_n_dimensional_XYZ_to_IPT(self) -> None:
52 """
53 Test :func:`colour.models.ipt.XYZ_to_IPT` definition n-dimensional
54 support.
55 """
57 XYZ = np.array([0.20654008, 0.12197225, 0.05136952])
58 IPT = XYZ_to_IPT(XYZ)
60 XYZ = np.tile(XYZ, (6, 1))
61 IPT = np.tile(IPT, (6, 1))
62 np.testing.assert_allclose(XYZ_to_IPT(XYZ), IPT, atol=TOLERANCE_ABSOLUTE_TESTS)
64 XYZ = np.reshape(XYZ, (2, 3, 3))
65 IPT = np.reshape(IPT, (2, 3, 3))
66 np.testing.assert_allclose(XYZ_to_IPT(XYZ), IPT, atol=TOLERANCE_ABSOLUTE_TESTS)
68 def test_domain_range_scale_XYZ_to_IPT(self) -> None:
69 """
70 Test :func:`colour.models.ipt.XYZ_to_IPT` definition domain and
71 range scale support.
72 """
74 XYZ = np.array([0.20654008, 0.12197225, 0.05136952])
75 IPT = XYZ_to_IPT(XYZ)
77 d_r = (("reference", 1), ("1", 1), ("100", 100))
78 for scale, factor in d_r:
79 with domain_range_scale(scale):
80 np.testing.assert_allclose(
81 XYZ_to_IPT(XYZ * factor),
82 IPT * factor,
83 atol=TOLERANCE_ABSOLUTE_TESTS,
84 )
86 @ignore_numpy_errors
87 def test_nan_XYZ_to_IPT(self) -> None:
88 """Test :func:`colour.models.ipt.XYZ_to_IPT` definition nan support."""
90 cases = [-1.0, 0.0, 1.0, -np.inf, np.inf, np.nan]
91 cases = np.array(list(set(product(cases, repeat=3))))
92 XYZ_to_IPT(cases)
95class TestIPT_to_XYZ:
96 """
97 Define :func:`colour.models.ipt.IPT_to_XYZ` definition unit tests
98 methods.
99 """
101 def test_IPT_to_XYZ(self) -> None:
102 """Test :func:`colour.models.ipt.IPT_to_XYZ` definition."""
104 np.testing.assert_allclose(
105 IPT_to_XYZ(np.array([0.38426191, 0.38487306, 0.18886838])),
106 np.array([0.20654008, 0.12197225, 0.05136952]),
107 atol=TOLERANCE_ABSOLUTE_TESTS,
108 )
110 np.testing.assert_allclose(
111 IPT_to_XYZ(np.array([0.49437481, -0.19251742, 0.18080304])),
112 np.array([0.14222010, 0.23042768, 0.10495772]),
113 atol=TOLERANCE_ABSOLUTE_TESTS,
114 )
116 np.testing.assert_allclose(
117 IPT_to_XYZ(np.array([0.35167774, -0.07525627, -0.30921279])),
118 np.array([0.07818780, 0.06157201, 0.28099326]),
119 atol=TOLERANCE_ABSOLUTE_TESTS,
120 )
122 def test_n_dimensional_IPT_to_XYZ(self) -> None:
123 """
124 Test :func:`colour.models.ipt.IPT_to_XYZ` definition n-dimensional
125 support.
126 """
128 IPT = np.array([0.38426191, 0.38487306, 0.18886838])
129 XYZ = IPT_to_XYZ(IPT)
131 IPT = np.tile(IPT, (6, 1))
132 XYZ = np.tile(XYZ, (6, 1))
133 np.testing.assert_allclose(IPT_to_XYZ(IPT), XYZ, atol=TOLERANCE_ABSOLUTE_TESTS)
135 IPT = np.reshape(IPT, (2, 3, 3))
136 XYZ = np.reshape(XYZ, (2, 3, 3))
137 np.testing.assert_allclose(IPT_to_XYZ(IPT), XYZ, atol=TOLERANCE_ABSOLUTE_TESTS)
139 def test_domain_range_scale_IPT_to_XYZ(self) -> None:
140 """
141 Test :func:`colour.models.ipt.IPT_to_XYZ` definition domain and
142 range scale support.
143 """
145 IPT = np.array([0.38426191, 0.38487306, 0.18886838])
146 XYZ = IPT_to_XYZ(IPT)
148 d_r = (("reference", 1), ("1", 1), ("100", 100))
149 for scale, factor in d_r:
150 with domain_range_scale(scale):
151 np.testing.assert_allclose(
152 IPT_to_XYZ(IPT * factor),
153 XYZ * factor,
154 atol=TOLERANCE_ABSOLUTE_TESTS,
155 )
157 @ignore_numpy_errors
158 def test_nan_IPT_to_XYZ(self) -> None:
159 """Test :func:`colour.models.ipt.IPT_to_XYZ` definition nan support."""
161 cases = [-1.0, 0.0, 1.0, -np.inf, np.inf, np.nan]
162 cases = np.array(list(set(product(cases, repeat=3))))
163 IPT_to_XYZ(cases)
166class TestIPTHueAngle:
167 """
168 Define :func:`colour.models.ipt.IPT_hue_angle` definition unit tests
169 methods.
170 """
172 def test_IPT_hue_angle(self) -> None:
173 """Test :func:`colour.models.ipt.IPT_hue_angle` definition."""
175 np.testing.assert_allclose(
176 IPT_hue_angle(np.array([0.38426191, 0.38487306, 0.18886838])),
177 26.138526939899490,
178 atol=TOLERANCE_ABSOLUTE_TESTS,
179 )
181 np.testing.assert_allclose(
182 IPT_hue_angle(np.array([0.49437481, -0.19251742, 0.18080304])),
183 136.797287973958500,
184 atol=TOLERANCE_ABSOLUTE_TESTS,
185 )
187 np.testing.assert_allclose(
188 IPT_hue_angle(np.array([0.35167774, -0.07525627, -0.30921279])),
189 256.321284526533300,
190 atol=TOLERANCE_ABSOLUTE_TESTS,
191 )
193 def test_n_dimensional_IPT_hue_angle(self) -> None:
194 """
195 Test :func:`colour.models.ipt.IPT_hue_angle` definition n-dimensional
196 support.
197 """
199 IPT = np.array([0.38426191, 0.38487306, 0.18886838])
200 hue = IPT_hue_angle(IPT)
202 IPT = np.tile(IPT, (6, 1))
203 hue = np.tile(hue, 6)
204 np.testing.assert_allclose(
205 IPT_hue_angle(IPT), hue, atol=TOLERANCE_ABSOLUTE_TESTS
206 )
208 IPT = np.reshape(IPT, (2, 3, 3))
209 hue = np.reshape(hue, (2, 3))
210 np.testing.assert_allclose(
211 IPT_hue_angle(IPT), hue, atol=TOLERANCE_ABSOLUTE_TESTS
212 )
214 def test_domain_range_scale_IPT_hue_angle(self) -> None:
215 """
216 Test :func:`colour.models.ipt.IPT_hue_angle` definition domain and
217 range scale support.
218 """
220 IPT = np.array([0.38426191, 0.38487306, 0.18886838])
221 hue = IPT_hue_angle(IPT)
223 d_r = (("reference", 1, 1), ("1", 1, 1 / 360), ("100", 100, 1 / 3.6))
224 for scale, factor_a, factor_b in d_r:
225 with domain_range_scale(scale):
226 np.testing.assert_allclose(
227 IPT_hue_angle(IPT * factor_a),
228 hue * factor_b,
229 atol=TOLERANCE_ABSOLUTE_TESTS,
230 )
232 @ignore_numpy_errors
233 def test_nan_IPT_hue_angle(self) -> None:
234 """Test :func:`colour.models.ipt.IPT_hue_angle` definition nan support."""
236 cases = [-1.0, 0.0, 1.0, -np.inf, np.inf, np.nan]
237 cases = np.array(list(set(product(cases, repeat=3))))
238 IPT_hue_angle(cases)