Coverage for io/luts/tests/test_cinespace_csp.py: 100%
83 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.io.luts.cinespace_csp` module."""
3from __future__ import annotations
5import os
6import shutil
7import tempfile
9import numpy as np
10import pytest
12from colour.constants import TOLERANCE_ABSOLUTE_TESTS
13from colour.hints import cast
14from colour.io import (
15 LUT1D,
16 LUT3D,
17 LUT3x1D,
18 LUTSequence,
19 read_LUT_Cinespace,
20 write_LUT_Cinespace,
21)
22from colour.utilities import tstack
24__author__ = "Colour Developers"
25__copyright__ = "Copyright 2013 Colour Developers"
26__license__ = "BSD-3-Clause - https://opensource.org/licenses/BSD-3-Clause"
27__maintainer__ = "Colour Developers"
28__email__ = "colour-developers@colour-science.org"
29__status__ = "Production"
31__all__ = [
32 "ROOT_LUTS",
33 "TestReadLUTCinespace",
34 "TestWriteLUTCinespace",
35]
37ROOT_LUTS: str = os.path.join(os.path.dirname(__file__), "resources", "cinespace")
40class TestReadLUTCinespace:
41 """
42 Define :func:`colour.io.luts.cinespace_csp.read_LUT_Cinespace` definition
43 unit tests methods.
44 """
46 def test_read_LUT_Cinespace(self) -> None:
47 """
48 Test :func:`colour.io.luts.cinespace_csp.read_LUT_Cinespace`
49 definition.
50 """
52 LUT_1 = cast(
53 "LUT3x1D",
54 read_LUT_Cinespace(os.path.join(ROOT_LUTS, "ACES_Proxy_10_to_ACES.csp")),
55 )
57 np.testing.assert_allclose(
58 LUT_1.table,
59 np.array(
60 [
61 [4.88300000e-04, 4.88300000e-04, 4.88300000e-04],
62 [7.71400000e-04, 7.71400000e-04, 7.71400000e-04],
63 [1.21900000e-03, 1.21900000e-03, 1.21900000e-03],
64 [1.92600000e-03, 1.92600000e-03, 1.92600000e-03],
65 [3.04400000e-03, 3.04400000e-03, 3.04400000e-03],
66 [4.80900000e-03, 4.80900000e-03, 4.80900000e-03],
67 [7.59900000e-03, 7.59900000e-03, 7.59900000e-03],
68 [1.20100000e-02, 1.20100000e-02, 1.20100000e-02],
69 [1.89700000e-02, 1.89700000e-02, 1.89700000e-02],
70 [2.99800000e-02, 2.99800000e-02, 2.99800000e-02],
71 [4.73700000e-02, 4.73700000e-02, 4.73700000e-02],
72 [7.48400000e-02, 7.48400000e-02, 7.48400000e-02],
73 [1.18300000e-01, 1.18300000e-01, 1.18300000e-01],
74 [1.86900000e-01, 1.86900000e-01, 1.86900000e-01],
75 [2.95200000e-01, 2.95200000e-01, 2.95200000e-01],
76 [4.66500000e-01, 4.66500000e-01, 4.66500000e-01],
77 [7.37100000e-01, 7.37100000e-01, 7.37100000e-01],
78 [1.16500000e00, 1.16500000e00, 1.16500000e00],
79 [1.84000000e00, 1.84000000e00, 1.84000000e00],
80 [2.90800000e00, 2.90800000e00, 2.90800000e00],
81 [4.59500000e00, 4.59500000e00, 4.59500000e00],
82 [7.26000000e00, 7.26000000e00, 7.26000000e00],
83 [1.14700000e01, 1.14700000e01, 1.14700000e01],
84 [1.81300000e01, 1.81300000e01, 1.81300000e01],
85 [2.86400000e01, 2.86400000e01, 2.86400000e01],
86 [4.52500000e01, 4.52500000e01, 4.52500000e01],
87 [7.15100000e01, 7.15100000e01, 7.15100000e01],
88 [1.13000000e02, 1.13000000e02, 1.13000000e02],
89 [1.78500000e02, 1.78500000e02, 1.78500000e02],
90 [2.82100000e02, 2.82100000e02, 2.82100000e02],
91 [4.45700000e02, 4.45700000e02, 4.45700000e02],
92 [7.04300000e02, 7.04300000e02, 7.04300000e02],
93 ]
94 ),
95 atol=TOLERANCE_ABSOLUTE_TESTS,
96 )
97 assert LUT_1.name == "ACES Proxy 10 to ACES"
98 assert LUT_1.dimensions == 2
99 np.testing.assert_array_equal(LUT_1.domain, np.array([[0, 0, 0], [1, 1, 1]]))
100 assert LUT_1.size == 32
101 assert LUT_1.comments == []
103 LUT_2 = cast("LUT3x1D", read_LUT_Cinespace(os.path.join(ROOT_LUTS, "Demo.csp")))
104 assert LUT_2.comments == ["Comments are ignored by most parsers"]
105 np.testing.assert_array_equal(LUT_2.domain, np.array([[0, 0, 0], [1, 2, 3]]))
107 LUT_3 = cast(
108 "LUT3D",
109 read_LUT_Cinespace(os.path.join(ROOT_LUTS, "Three_Dimensional_Table.csp")),
110 )
111 assert LUT_3.dimensions == 3
112 assert LUT_3.size == 2
114 LUT_4 = cast(
115 "LUTSequence",
116 read_LUT_Cinespace(os.path.join(ROOT_LUTS, "Explicit_Domain.csp")),
117 )
118 assert LUT_4[0].is_domain_explicit() is True
119 assert LUT_4[1].table.shape == (2, 3, 4, 3)
121 LUT_5 = cast(
122 "LUTSequence",
123 read_LUT_Cinespace(
124 os.path.join(ROOT_LUTS, "Uncommon_3x1D_With_Pre_Lut.csp")
125 ),
126 )
127 assert isinstance(LUT_5[0], LUT3x1D)
128 assert isinstance(LUT_5[1], LUT3x1D)
131class TestWriteLUTCinespace:
132 """
133 Define :func:`colour.io.luts.cinespace_csp.write_LUT_Cinespace` definition
134 unit tests methods.
135 """
137 def setup_method(self) -> None:
138 """Initialise the common tests attributes."""
140 self._temporary_directory = tempfile.mkdtemp()
142 def teardown_method(self) -> None:
143 """After tests actions."""
145 shutil.rmtree(self._temporary_directory)
147 def test_write_LUT_Cinespace(self) -> None:
148 """
149 Test :func:`colour.io.luts.cinespace_csp.write_LUT_Cinespace`
150 definition.
151 """
153 LUT_1_r = read_LUT_Cinespace(
154 os.path.join(ROOT_LUTS, "ACES_Proxy_10_to_ACES.csp")
155 )
156 write_LUT_Cinespace(
157 LUT_1_r,
158 os.path.join(self._temporary_directory, "ACES_Proxy_10_to_ACES.csp"),
159 )
160 LUT_1_t = read_LUT_Cinespace(
161 os.path.join(self._temporary_directory, "ACES_Proxy_10_to_ACES.csp")
162 )
163 assert LUT_1_r == LUT_1_t
164 assert LUT_1_r == LUT_1_t
166 LUT_2_r = cast(
167 "LUT3x1D", read_LUT_Cinespace(os.path.join(ROOT_LUTS, "Demo.csp"))
168 )
169 write_LUT_Cinespace(
170 LUT_2_r, os.path.join(self._temporary_directory, "Demo.csp")
171 )
172 LUT_2_t = cast(
173 "LUT3x1D",
174 read_LUT_Cinespace(os.path.join(self._temporary_directory, "Demo.csp")),
175 )
176 assert LUT_2_r == LUT_2_t
177 assert LUT_2_r.comments == LUT_2_t.comments
179 LUT_3_r = cast(
180 "LUT3D",
181 read_LUT_Cinespace(os.path.join(ROOT_LUTS, "Three_Dimensional_Table.csp")),
182 )
183 write_LUT_Cinespace(
184 LUT_3_r,
185 os.path.join(self._temporary_directory, "Three_Dimensional_Table.csp"),
186 )
187 LUT_3_t = cast(
188 "LUT3D",
189 read_LUT_Cinespace(
190 os.path.join(self._temporary_directory, "Three_Dimensional_Table.csp")
191 ),
192 )
193 assert LUT_3_r == LUT_3_t
195 domain = tstack(
196 (
197 np.array([0.0, 0.1, 0.2, 0.4, 0.8, 1.2]),
198 np.array([-0.1, 0.5, 1.0, np.nan, np.nan, np.nan]),
199 np.array([-1.0, -0.5, 0.0, 0.5, 1.0, np.nan]),
200 )
201 )
202 LUT_4_t = LUT3x1D(domain=domain, table=domain * 2, name="Ragged Domain")
203 write_LUT_Cinespace(
204 LUT_4_t,
205 os.path.join(self._temporary_directory, "Ragged_Domain.csp"),
206 )
207 LUT_4_r = cast(
208 "LUT3x1D", read_LUT_Cinespace(os.path.join(ROOT_LUTS, "Ragged_Domain.csp"))
209 )
210 np.testing.assert_allclose(
211 LUT_4_t.domain, LUT_4_r.domain, atol=TOLERANCE_ABSOLUTE_TESTS
212 )
213 np.testing.assert_allclose(LUT_4_t.table, LUT_4_r.table, atol=5e-5)
215 LUT_5_r = cast(
216 "LUTSequence",
217 read_LUT_Cinespace(
218 os.path.join(ROOT_LUTS, "Three_Dimensional_Table_With_Shaper.csp")
219 ),
220 )
221 LUT_5_r.sequence[0] = LUT_5_r.sequence[0].convert( # pyright: ignore
222 LUT1D, force_conversion=True
223 )
224 write_LUT_Cinespace(
225 LUT_5_r,
226 os.path.join(
227 self._temporary_directory,
228 "Three_Dimensional_Table_With_Shaper.csp",
229 ),
230 )
231 LUT_5_r = cast(
232 "LUTSequence",
233 read_LUT_Cinespace(
234 os.path.join(ROOT_LUTS, "Three_Dimensional_Table_With_Shaper.csp")
235 ),
236 )
237 LUT_5_t = cast(
238 "LUTSequence",
239 read_LUT_Cinespace(
240 os.path.join(
241 self._temporary_directory,
242 "Three_Dimensional_Table_With_Shaper.csp",
243 )
244 ),
245 )
246 assert LUT_5_r == LUT_5_t
248 LUT_6_r = cast(
249 "LUTSequence",
250 read_LUT_Cinespace(
251 os.path.join(ROOT_LUTS, "Three_Dimensional_Table_With_Shaper.csp")
252 ),
253 )
254 LUT_6_r.sequence[0] = LUT_6_r.sequence[0].convert( # pyright: ignore
255 LUT3x1D, force_conversion=True
256 )
257 write_LUT_Cinespace(
258 LUT_6_r,
259 os.path.join(
260 self._temporary_directory,
261 "Three_Dimensional_Table_With_Shaper.csp",
262 ),
263 )
264 LUT_6_r = cast(
265 "LUTSequence",
266 read_LUT_Cinespace(
267 os.path.join(ROOT_LUTS, "Three_Dimensional_Table_With_Shaper.csp")
268 ),
269 )
270 LUT_6_t = cast(
271 "LUTSequence",
272 read_LUT_Cinespace(
273 os.path.join(
274 self._temporary_directory,
275 "Three_Dimensional_Table_With_Shaper.csp",
276 )
277 ),
278 )
279 assert LUT_6_r == LUT_6_t
281 LUT_7_r = cast(
282 "LUT3x1D",
283 read_LUT_Cinespace(os.path.join(ROOT_LUTS, "ACES_Proxy_10_to_ACES.csp")),
284 )
285 write_LUT_Cinespace(
286 cast("LUT1D", LUT_7_r.convert(LUT1D, force_conversion=True)),
287 os.path.join(self._temporary_directory, "ACES_Proxy_10_to_ACES.csp"),
288 )
289 LUT_7_t = cast(
290 "LUT3x1D",
291 read_LUT_Cinespace(
292 os.path.join(self._temporary_directory, "ACES_Proxy_10_to_ACES.csp")
293 ),
294 )
295 assert LUT_7_r == LUT_7_t
297 def test_raise_exception_write_LUT_Cinespace(self) -> None:
298 """
299 Test :func:`colour.io.luts.cinespace_csp.write_LUT_Cinespace`
300 definition raised exception.
301 """
303 pytest.raises(TypeError, write_LUT_Cinespace, object(), "")