# colour.LUT3D¶

class colour.LUT3D(table: Optional[ArrayLike] = None, name: Optional[str] = None, domain: Optional[ArrayLike] = None, size: Optional[IntegerOrArrayLike] = None, comments: Optional[Sequence] = None)[source]

Bases: colour.io.luts.lut.AbstractLUT

Define the base class for a 3D LUT.

Parameters
• table (Optional[ArrayLike]) – Underlying LUT table.

• name (Optional[str]) – LUT name.

• domain (Optional[ArrayLike]) – LUT domain, also used to define the instantiation time default table domain.

• size (Optional[IntegerOrArrayLike]) – Size of the instantiation time default table, default to 33.

Methods

Examples

Instantiating a unity LUT with a table with 16x16x16x3 elements:

>>> print(LUT3D(size=16))
LUT3D - Unity 16
----------------

Dimensions : 3
Domain     : [[ 0.  0.  0.]
[ 1.  1.  1.]]
Size       : (16, 16, 16, 3)


Instantiating a LUT using a custom table with 16x16x16x3 elements:

>>> print(LUT3D(LUT3D.linear_table(16) ** (1 / 2.2)))
LUT3D - ...
--------...

Dimensions : 3
Domain     : [[ 0.  0.  0.]
[ 1.  1.  1.]]
Size       : (16, 16, 16, 3)


Instantiating a LUT using a custom table with 16x16x16x3 elements, custom name, custom domain and comments:

>>> from colour.algebra import spow
>>> domain = np.array([[-0.1, -0.2, -0.4], [1.5, 3.0, 6.0]])
>>> print(LUT3D(
...     spow(LUT3D.linear_table(16), 1 / 2.2),
...     'My LUT',
...     domain,
...     comments=['A first comment.', 'A second comment.']))
LUT3D - My LUT
--------------

Dimensions : 3
Domain     : [[-0.1 -0.2 -0.4]
[ 1.5  3.   6. ]]
Size       : (16, 16, 16, 3)
Comment 01 : A first comment.
Comment 02 : A second comment.

__init__(table: Optional[ArrayLike] = None, name: Optional[str] = None, domain: Optional[ArrayLike] = None, size: Optional[IntegerOrArrayLike] = None, comments: Optional[Sequence] = None)[source]
Parameters
• table (Optional[ArrayLike]) –

• name (Optional[str]) –

• domain (Optional[ArrayLike]) –

• size (Optional[IntegerOrArrayLike]) –

is_domain_explicit() bool[source]

Return whether the LUT domain is explicit (or implicit).

An implicit domain is defined by its shape only:

[[0 0 0]
[1 1 1]]


While an explicit domain defines every single discrete samples:

[[0.0 0.0 0.0]
[0.1 0.1 0.1]
[0.2 0.2 0.2]
[0.3 0.3 0.3]
[0.4 0.4 0.4]
[0.8 0.8 0.8]
[1.0 1.0 1.0]]

Returns

Is LUT domain explicit.

Return type

bool

Examples

>>> LUT3D().is_domain_explicit()
False
>>> domain = np.array([[-0.1, -0.2, -0.4],
...                    [0.7, 1.4, 6.0],
...                    [1.5, 3.0, np.nan]])
>>> LUT3D(domain=domain).is_domain_explicit()
True

static linear_table(size: Optional[IntegerOrArrayLike] = None, domain: Optional[ArrayLike] = None) NDArray[source]

Return a linear table, the number of output samples $$n$$ is equal to size**3 * 3 or size[0] * size[1] * size[2] * 3.

Parameters
• size (Optional[IntegerOrArrayLike]) – Expected table size, default to 33.

• domain (Optional[ArrayLike]) – Domain of the table.

Returns

Linear table with size**3 * 3 or size[0] * size[1] * size[2] * 3 samples.

Return type

numpy.ndarray

Examples

>>> LUT3D.linear_table(
...     3, np.array([[-0.1, -0.2, -0.4], [1.5, 3.0, 6.0]]))
array([[[[-0.1, -0.2, -0.4],
[-0.1, -0.2,  2.8],
[-0.1, -0.2,  6. ]],

[[-0.1,  1.4, -0.4],
[-0.1,  1.4,  2.8],
[-0.1,  1.4,  6. ]],

[[-0.1,  3. , -0.4],
[-0.1,  3. ,  2.8],
[-0.1,  3. ,  6. ]]],

[[[ 0.7, -0.2, -0.4],
[ 0.7, -0.2,  2.8],
[ 0.7, -0.2,  6. ]],

[[ 0.7,  1.4, -0.4],
[ 0.7,  1.4,  2.8],
[ 0.7,  1.4,  6. ]],

[[ 0.7,  3. , -0.4],
[ 0.7,  3. ,  2.8],
[ 0.7,  3. ,  6. ]]],

[[[ 1.5, -0.2, -0.4],
[ 1.5, -0.2,  2.8],
[ 1.5, -0.2,  6. ]],

[[ 1.5,  1.4, -0.4],
[ 1.5,  1.4,  2.8],
[ 1.5,  1.4,  6. ]],

[[ 1.5,  3. , -0.4],
[ 1.5,  3. ,  2.8],
[ 1.5,  3. ,  6. ]]]])
>>> LUT3D.linear_table(
...     np.array([3, 3, 2]),
...     np.array([[-0.1, -0.2, -0.4], [1.5, 3.0, 6.0]]))
array([[[[-0.1, -0.2, -0.4],
[-0.1, -0.2,  6. ]],

[[-0.1,  1.4, -0.4],
[-0.1,  1.4,  6. ]],

[[-0.1,  3. , -0.4],
[-0.1,  3. ,  6. ]]],

[[[ 0.7, -0.2, -0.4],
[ 0.7, -0.2,  6. ]],

[[ 0.7,  1.4, -0.4],
[ 0.7,  1.4,  6. ]],

[[ 0.7,  3. , -0.4],
[ 0.7,  3. ,  6. ]]],

[[[ 1.5, -0.2, -0.4],
[ 1.5, -0.2,  6. ]],

[[ 1.5,  1.4, -0.4],
[ 1.5,  1.4,  6. ]],

[[ 1.5,  3. , -0.4],
[ 1.5,  3. ,  6. ]]]])
>>> domain = np.array([[-0.1, -0.2, -0.4],
...                    [0.7, 1.4, 6.0],
...                    [1.5, 3.0, np.nan]])
>>> LUT3D.linear_table(domain=domain)
array([[[[-0.1, -0.2, -0.4],
[-0.1, -0.2,  6. ]],

[[-0.1,  1.4, -0.4],
[-0.1,  1.4,  6. ]],

[[-0.1,  3. , -0.4],
[-0.1,  3. ,  6. ]]],

[[[ 0.7, -0.2, -0.4],
[ 0.7, -0.2,  6. ]],

[[ 0.7,  1.4, -0.4],
[ 0.7,  1.4,  6. ]],

[[ 0.7,  3. , -0.4],
[ 0.7,  3. ,  6. ]]],

[[[ 1.5, -0.2, -0.4],
[ 1.5, -0.2,  6. ]],

[[ 1.5,  1.4, -0.4],
[ 1.5,  1.4,  6. ]],

[[ 1.5,  3. , -0.4],
[ 1.5,  3. ,  6. ]]]])

invert(**kwargs: Any) [source]

Compute and returns an inverse copy of the LUT.

Parameters
• extrapolate – Whether to extrapolate the LUT when computing its inverse. Extrapolation is performed by reflecting the LUT cube along its 8 faces. Note that the domain is extended beyond [0, 1], thus the LUT might not be handled properly in other software.

• interpolator – Interpolator class type or object to use as interpolating function.

• query_size – Number of points to query in the KDTree, their mean is computed, resulting in a smoother result.

• size – Size of the inverse LUT. With the given implementation, it is good practise to double the size of the inverse LUT to provide a smoother result. If size is not given, $$2^{\sqrt{size_{LUT}} + 1} + 1$$ will be used instead.

• kwargs (Any) –

Returns

Inverse LUT class instance.

Return type

colour.LUT3D

Examples

>>> LUT = LUT3D()
>>> print(LUT)
LUT3D - Unity 33
----------------

Dimensions : 3
Domain     : [[ 0.  0.  0.]
[ 1.  1.  1.]]
Size       : (33, 33, 33, 3)
>>> print(LUT.invert())
LUT3D - Unity 33 - Inverse
--------------------------

Dimensions : 3
Domain     : [[ 0.  0.  0.]
[ 1.  1.  1.]]
Size       : (108, 108, 108, 3)

apply(RGB: ArrayLike, **kwargs: Any) [source]

Apply the LUT to given RGB colourspace array using given method.

Parameters
• RGB (ArrayLike) – RGB colourspace array to apply the LUT onto.

• direction – Whether the LUT should be applied in the forward or inverse direction.

• extrapolate – Whether to extrapolate the LUT when computing its inverse. Extrapolation is performed by reflecting the LUT cube along its 8 faces.

• interpolator – Interpolator object to use as interpolating function.

• interpolator_kwargs – Arguments to use when calling the interpolating function.

• query_size – Number of points to query in the KDTree, their mean is computed, resulting in a smoother result.

• size – Size of the inverse LUT. With the given implementation, it is good practise to double the size of the inverse LUT to provide a smoother result. If size is not given, $$2^{\sqrt{size_{LUT}} + 1} + 1$$ will be used instead.

• kwargs (Any) –

Returns

Interpolated RGB colourspace array.

Return type

numpy.ndarray

Examples

>>> LUT = LUT3D(LUT3D.linear_table() ** (1 / 2.2))
>>> RGB = np.array([0.18, 0.18, 0.18])
>>> LUT.apply(RGB)
array([ 0.4583277...,  0.4583277...,  0.4583277...])
>>> LUT.apply(LUT.apply(RGB), direction='Inverse')
...
array([ 0.1781995...,  0.1809414...,  0.1809513...])
>>> from colour.algebra import spow
>>> domain = np.array([[-0.1, -0.2, -0.4],
...                    [0.3, 1.4, 6.0],
...                    [0.7, 3.0, np.nan],
...                    [1.1, np.nan, np.nan],
...                    [1.5, np.nan, np.nan]])
>>> table = spow(LUT3D.linear_table(domain=domain), 1 / 2.2)
>>> LUT = LUT3D(table, domain=domain)
>>> RGB = np.array([0.18, 0.18, 0.18])
>>> LUT.apply(RGB)
array([ 0.2996370..., -0.0901332..., -0.3949770...])

convert(cls: Type[colour.io.luts.lut.AbstractLUT], force_conversion: bool = False, **kwargs: Any) colour.io.luts.lut.AbstractLUT[source]

Convert the LUT to given cls class instance.

Parameters
• cls (Type[colour.io.luts.lut.AbstractLUT]) – LUT class instance.

• force_conversion (bool) – Whether to force the conversion as it might be destructive.

• interpolator – Interpolator class type to use as interpolating function.

• interpolator_kwargs – Arguments to use when instantiating the interpolating function.

• size – Expected table size in case of a downcast from a LUT3D class instance.

• kwargs (Any) –

Returns

Converted LUT class instance.

Return type

Warning

Some conversions are destructive and raise a ValueError exception by default.

Raises

ValueError – If the conversion is destructive.

Parameters
• cls (Type[colour.io.luts.lut.AbstractLUT]) –

• force_conversion (bool) –

• kwargs (Any) –

Return type

colour.io.luts.lut.AbstractLUT

Examples

>>> LUT = LUT3D()
>>> print(LUT.convert(LUT1D, force_conversion=True))
LUT1D - Unity 33 - Converted 3D to 1D
-------------------------------------

Dimensions : 1
Domain     : [ 0.  1.]
Size       : (10,)
>>> print(LUT.convert(LUT3x1D, force_conversion=True))
LUT3x1D - Unity 33 - Converted 3D to 3x1D
-----------------------------------------

Dimensions : 2
Domain     : [[ 0.  0.  0.]
[ 1.  1.  1.]]
Size       : (10, 3)
>>> print(LUT.convert(LUT3D))
LUT3D - Unity 33 - Converted 3D to 3D
-------------------------------------

Dimensions : 3
Domain     : [[ 0.  0.  0.]
[ 1.  1.  1.]]
Size       : (33, 33, 33, 3)