Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PR: Implement Support for Executing CLF Workflows #1310

Draft
wants to merge 12 commits into
base: develop
Choose a base branch
from
434 changes: 434 additions & 0 deletions colour/io/luts/clf.py

Large diffs are not rendered by default.

5 changes: 4 additions & 1 deletion colour/io/luts/lut.py
Original file line number Diff line number Diff line change
Expand Up @@ -1006,7 +1006,10 @@ def linear_table(
if len(domain) != 2:
return domain
else:
attest(is_numeric(size), "Linear table size must be a numeric!")
attest(
is_numeric(size),
f"Linear table size must be a numeric but is {size} instead!",
)

return np.linspace(domain[0], domain[1], as_int_scalar(size))

Expand Down
Empty file.
126 changes: 126 additions & 0 deletions colour/io/luts/tests/clf_apply/test_asc_cdl.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
# !/usr/bin/env python
"""Define the unit tests for the :mod:`colour.io.clf` module."""
import unittest

__author__ = "Colour Developers"
__copyright__ = "Copyright 2013 Colour Developers"
__license__ = "BSD-3-Clause - https://opensource.org/licenses/BSD-3-Clause"
__maintainer__ = "Colour Developers"
__email__ = "[email protected]"
__status__ = "Production"

import numpy as np

from colour.io.luts.tests.test_clf_common import (
assert_ocio_consistency,
rgb_sample_iter,
)


def assert_snippet_consistency(snippet):
"""
Evaluate the snippet with multiple values anc check that they are the same as the
`ociochecklut` tools output.
"""
for rgb in rgb_sample_iter():
value_rgb = np.array(rgb)
assert_ocio_consistency(
value_rgb, snippet, f"Failed to assert consistency for {rgb}"
)


class TestASC_CDL:
"""
Define test for applying Exponent nodes from a CLF file.
"""

def test_ocio_consistency_fwd(self):
"""
Test that the execution is consistent with `ociochecklut`.
"""

example = """
<ASC_CDL id="cc01234" inBitDepth="16f" outBitDepth="16f" style="Fwd">
<SOPNode>
<Slope>1.000000 1.000000 0.900000</Slope>
<Offset>-0.030000 -0.020000 0.000000</Offset>
<Power>1.2500000 1.000000 1.000000</Power>
</SOPNode>
<SatNode>
<Saturation>1.700000</Saturation>
</SatNode>
</ASC_CDL>
"""
assert_snippet_consistency(example)

def test_ocio_consistency_rev(self):
"""
Test that the execution is consistent with `ociochecklut`.
"""

example = """
<ASC_CDL id="cc01234" inBitDepth="16f" outBitDepth="16f" style="Rev">
<SOPNode>
<Slope>1.000000 1.000000 0.900000</Slope>
<Offset>-0.030000 -0.020000 0.000000</Offset>
<Power>1.2500000 1.000000 1.000000</Power>
</SOPNode>
<SatNode>
<Saturation>1.700000</Saturation>
</SatNode>
</ASC_CDL>
"""
assert_snippet_consistency(example)

def test_ocio_consistency_fwd_no_clamp(self):
"""
Test that the execution is consistent with `ociochecklut`.
"""

example = """
<ASC_CDL id="cc01234" inBitDepth="16f" outBitDepth="16f" style="FwdNoClamp">
<SOPNode>
<Slope>1.000000 1.000000 0.900000</Slope>
<Offset>-0.030000 -0.020000 0.000000</Offset>
<Power>1.2500000 1.000000 1.000000</Power>
</SOPNode>
<SatNode>
<Saturation>1.700000</Saturation>
</SatNode>
</ASC_CDL>
"""
assert_snippet_consistency(example)

def test_ocio_consistency_rev_no_clamp(self):
"""
Test that the execution is consistent with `ociochecklut`.
"""

example = """
<ASC_CDL id="cc01234" inBitDepth="16f" outBitDepth="16f" style="RevNoClamp">
<SOPNode>
<Slope>1.000000 1.000000 0.900000</Slope>
<Offset>-0.030000 -0.020000 0.000000</Offset>
<Power>1.2500000 1.000000 1.000000</Power>
</SOPNode>
<SatNode>
<Saturation>1.700000</Saturation>
</SatNode>
</ASC_CDL>
"""
assert_snippet_consistency(example)

def test_ocio_consistency_default_args(self):
"""
Test that the execution is consistent with `ociochecklut`.
"""

example = """
<ASC_CDL id="cc01234" inBitDepth="16f" outBitDepth="16f" style="Fwd">
</ASC_CDL>
"""
assert_snippet_consistency(example)


if __name__ == "__main__":
unittest.main()
199 changes: 199 additions & 0 deletions colour/io/luts/tests/clf_apply/test_exponent.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
# !/usr/bin/env python
"""Define the unit tests for the :mod:`colour.io.clf` module."""
import unittest

__author__ = "Colour Developers"
__copyright__ = "Copyright 2013 Colour Developers"
__license__ = "BSD-3-Clause - https://opensource.org/licenses/BSD-3-Clause"
__maintainer__ = "Colour Developers"
__email__ = "[email protected]"
__status__ = "Production"

import numpy as np

from colour.io.luts.tests.test_clf_common import (
assert_ocio_consistency,
rgb_sample_iter,
)


def assert_snippet_consistency(snippet):
"""
Evaluate the snippet with multiple values anc check that they are the same as the
`ociochecklut` tools output.
"""
for rgb in rgb_sample_iter():
value_rgb = np.array(rgb)
assert_ocio_consistency(
value_rgb, snippet, f"Failed to assert consistency for {rgb}"
)


# TODO assert correct ranges for exponents and offsets


class TestExponent:
"""
Define test for applying Exponent nodes from a CLF file.
"""

def test_ocio_consistency_fwd(self):
"""
Test that the execution is consistent with `ociochecklut`.
"""

example = """
<Exponent inBitDepth="32f" outBitDepth="32f" style="basicFwd">
<ExponentParams exponent="2.2"/>
</Exponent>
"""
assert_snippet_consistency(example)

def test_ocio_consistency_rev(self):
"""
Test that the execution is consistent with `ociochecklut`.
"""

example = """
<Exponent inBitDepth="32f" outBitDepth="32f" style="basicRev">
<ExponentParams exponent="2.2"/>
</Exponent>
"""
assert_snippet_consistency(example)

def test_ocio_consistency_mirror_fwd(self):
"""
Test that the execution is consistent with `ociochecklut`.
"""

example = """
<Exponent inBitDepth="32f" outBitDepth="32f" style="basicMirrorFwd">
<ExponentParams exponent="2.2"/>
</Exponent>
"""
assert_snippet_consistency(example)

def test_ocio_consistency_basic_mirror_rev(self):
"""
Test that the execution is consistent with `ociochecklut`.
"""

example = """
<Exponent inBitDepth="32f" outBitDepth="32f" style="basicMirrorRev">
<ExponentParams exponent="2.2"/>
</Exponent>
"""
assert_snippet_consistency(example)

def test_ocio_consistency_basic_pass_thru_fwd(self):
"""
Test that the execution is consistent with `ociochecklut`.
"""

example = """
<Exponent inBitDepth="32f" outBitDepth="32f" style="basicPassThruFwd">
<ExponentParams exponent="2.2"/>
</Exponent>
"""
assert_snippet_consistency(example)

def test_ocio_consistency_basic_pass_thru_rev(self):
"""
Test that the execution is consistent with `ociochecklut`.
"""

example = """
<Exponent inBitDepth="32f" outBitDepth="32f" style="basicPassThruRev">
<ExponentParams exponent="2.2"/>
</Exponent>
"""
assert_snippet_consistency(example)

def test_ocio_consistency_mon_curve_fwd(self):
"""
Test that the execution is consistent with `ociochecklut`.
"""

example = """
<Exponent inBitDepth="32f" outBitDepth="32f" style="monCurveFwd">
<ExponentParams exponent="3.0" offset="0.16" />
</Exponent>
"""
assert_snippet_consistency(example)

def test_ocio_consistency_mon_curve_rev(self):
"""
Test that the execution is consistent with `ociochecklut`.
"""

example = """
<Exponent inBitDepth="32f" outBitDepth="32f" style="monCurveRev">
<ExponentParams exponent="3.0" offset="0.16" />
</Exponent>
"""
assert_snippet_consistency(example)

def test_ocio_consistency_mon_curve_rev_2(self):
"""
Test that the execution is consistent with `ociochecklut`.
"""

example = """
<Exponent inBitDepth="32f" outBitDepth="32f" style="monCurveRev">
<ExponentParams exponent="2.2222222222222222" offset="0.099" />
</Exponent>
"""
assert_snippet_consistency(example)

def test_ocio_consistency_mon_curve_mirror_fwd(self):
"""
Test that the execution is consistent with `ociochecklut`.
"""

example = """
<Exponent inBitDepth="32f" outBitDepth="32f" style="monCurveMirrorFwd">
<ExponentParams exponent="3.0" offset="0.16" />
</Exponent>
"""
assert_snippet_consistency(example)

def test_ocio_consistency_mon_curve_mirror_rev(self):
"""
Test that the execution is consistent with `ociochecklut`.
"""

example = """
<Exponent inBitDepth="32f" outBitDepth="32f" style="monCurveMirrorRev">
<ExponentParams exponent="3.0" offset="0.16" />
</Exponent>
"""
assert_snippet_consistency(example)

def test_ocio_consistency_single_channel_application(self):
"""
Test that the execution is consistent with `ociochecklut`.
"""

example = """
<Exponent inBitDepth="32f" outBitDepth="32f" style="monCurveMirrorRev">
<ExponentParams exponent="3.0" offset="0.16" channel="G" />
</Exponent>
"""
assert_snippet_consistency(example)

def test_ocio_consistency_multi_channel_application(self):
"""
Test that the execution is consistent with `ociochecklut`.
"""

example = """
<Exponent inBitDepth="32f" outBitDepth="32f" style="monCurveMirrorRev">
<ExponentParams exponent="3.0" offset="0.16" channel="G" />
<ExponentParams exponent="4.0" offset="0.21" channel="B" />
</Exponent>
"""
assert_snippet_consistency(example)


if __name__ == "__main__":
unittest.main()
55 changes: 55 additions & 0 deletions colour/io/luts/tests/clf_apply/test_helper.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# !/usr/bin/env python
"""Define the unit tests for the :mod:`colour.io.clf` module."""
import unittest

__author__ = "Colour Developers"
__copyright__ = "Copyright 2013 Colour Developers"
__license__ = "BSD-3-Clause - https://opensource.org/licenses/BSD-3-Clause"
__maintainer__ = "Colour Developers"
__email__ = "[email protected]"
__status__ = "Production"

import numpy as np

from colour.io.luts.clf import from_f16_to_uint16, from_uint16_to_f16


class TestHelpers:
"""
Define :func:`colour.io.luts.clf.from_uint16_to_f16` and
:func:`colour.io.luts.clf.from_f16_to_uint16` unit tests methods.
"""

def test_uint16_to_f16(self):
"""
Test :func:`colour.io.luts.clf.from_uint16_to_f16` method.
"""
value = np.array([0, 15360])
output = from_uint16_to_f16(value)
expected = np.array([0, 1.0])
np.testing.assert_almost_equal(output, expected)

def test_f16_to_uint16(self):
"""
Test :func:`colour.io.luts.clf.from_f16_to_uint16` method.
"""
value = np.array([0, 1.0])
output = from_f16_to_uint16(value)
expected = np.array([0, 15360])
np.testing.assert_almost_equal(output, expected)

def test_conversion_reversible(self):
"""
Test :func:`colour.io.luts.clf.from_uint16_to_f16` method with
:func:`colour.io.luts.clf.from_f16_to_uint16`.

"""
for i in range(2**16):
value = np.array([i])
float_value = from_uint16_to_f16(value)
int_value = from_f16_to_uint16(float_value)
np.testing.assert_almost_equal(value, int_value)


if __name__ == "__main__":
unittest.main()
Loading
Loading