From dbc462e253277ce286a040d10ee8f9283fbf9c84 Mon Sep 17 00:00:00 2001 From: Thomas Mansencal Date: Sat, 12 Aug 2023 14:23:04 +1200 Subject: [PATCH] Implement initial support for "AMF" relations. Signed-off-by: Thomas Mansencal --- docs/opencolorio_config_aces.config.rst | 3 +- opencolorio_config_aces/__init__.py | 4 +- .../clf/discover/classify.py | 33 ++- opencolorio_config_aces/config/__init__.py | 6 +- .../config/cg/generate/config.py | 90 ++++---- .../config/reference/__init__.py | 6 +- .../config/reference/discover/__init__.py | 2 + .../config/reference/discover/classify.py | 151 ++++++++++++- .../config/reference/generate/__init__.py | 4 +- .../config/reference/generate/analytical.py | 10 +- .../config/reference/generate/config.py | 205 ++++++++++++------ .../config/studio/generate/config.py | 6 +- 12 files changed, 395 insertions(+), 125 deletions(-) diff --git a/docs/opencolorio_config_aces.config.rst b/docs/opencolorio_config_aces.config.rst index be3aa095..b85a13d4 100644 --- a/docs/opencolorio_config_aces.config.rst +++ b/docs/opencolorio_config_aces.config.rst @@ -70,6 +70,7 @@ Reference Configuration classify_aces_ctl_transforms discover_aces_ctl_transforms filter_ctl_transforms + generate_amf_relations print_aces_taxonomy unclassify_ctl_transforms @@ -100,7 +101,7 @@ Reference Configuration .. autosummary:: :toctree: generated/ - ColorspaceDescriptionStyle + DescriptionStyle version_config_mapping_file generate_config_aces diff --git a/opencolorio_config_aces/__init__.py b/opencolorio_config_aces/__init__.py index 3cd5674b..d1d03893 100644 --- a/opencolorio_config_aces/__init__.py +++ b/opencolorio_config_aces/__init__.py @@ -57,7 +57,7 @@ version_config_mapping_file, ) from .config import ( - ColorspaceDescriptionStyle, + DescriptionStyle, generate_config_aces, ) from .config import generate_config_cg, generate_config_studio @@ -114,7 +114,7 @@ "version_config_mapping_file", ] __all__ += [ - "ColorspaceDescriptionStyle", + "DescriptionStyle", "generate_config_aces", ] __all__ += ["generate_config_cg", "generate_config_studio"] diff --git a/opencolorio_config_aces/clf/discover/classify.py b/opencolorio_config_aces/clf/discover/classify.py index d7dbfb1a..9ba4a2af 100644 --- a/opencolorio_config_aces/clf/discover/classify.py +++ b/opencolorio_config_aces/clf/discover/classify.py @@ -475,6 +475,8 @@ class CLFTransform: *CLF* transform family, e.g. *aces* genus : unicode, optional *CLF* transform genus, e.g. *undefined* + siblings : array_like, optional + *CLF* transform siblings, e.g. inverse transform. Attributes ---------- @@ -497,7 +499,10 @@ class CLFTransform: __ne__ """ - def __init__(self, path, family=None, genus=None): + def __init__(self, path, family=None, genus=None, siblings=None): + if siblings is None: + siblings = [] + self._path = os.path.abspath(os.path.normpath(path)) self._code = None @@ -510,6 +515,7 @@ def __init__(self, path, family=None, genus=None): self._family = family self._genus = genus + self._siblings = siblings self._parse() @@ -692,6 +698,24 @@ def genus(self): return self._genus + @property + def siblings(self): + """ + Getter property for the *CLF* transform siblings, e.g. inverse + transform. + + Returns + ------- + unicode + *CLF* transform siblings. + + Notes + ----- + - This property is read only. + """ + + return self._siblings + def __getattr__(self, item): """ Reimplement the :meth:`object.__getattr__` so that unsuccessful @@ -999,7 +1023,12 @@ def stem(path): clf_transform_pairs[basename][ "inverse_transform" ] = clf_transforms[1] - + clf_transform_pairs[basename]["forward_transform"].siblings.append( + clf_transform_pairs[basename]["inverse_transform"] + ) + clf_transform_pairs[basename]["inverse_transform"].siblings.append( + clf_transform_pairs[basename]["forward_transform"] + ) return clf_transform_pairs diff --git a/opencolorio_config_aces/config/__init__.py b/opencolorio_config_aces/config/__init__.py index 1e871551..b3d08f90 100644 --- a/opencolorio_config_aces/config/__init__.py +++ b/opencolorio_config_aces/config/__init__.py @@ -30,6 +30,7 @@ discover_aces_ctl_transforms, filter_ctl_transforms, filter_nodes, + generate_amf_relations, node_to_ctl_transform, plot_aces_conversion_graph, print_aces_taxonomy, @@ -38,7 +39,7 @@ version_config_mapping_file, ) from .reference import ( - ColorspaceDescriptionStyle, + DescriptionStyle, generate_config_aces, ) from .cg import generate_config_cg @@ -73,6 +74,7 @@ "discover_aces_ctl_transforms", "filter_ctl_transforms", "filter_nodes", + "generate_amf_relations", "node_to_ctl_transform", "plot_aces_conversion_graph", "print_aces_taxonomy", @@ -81,7 +83,7 @@ "version_config_mapping_file", ] __all__ += [ - "ColorspaceDescriptionStyle", + "DescriptionStyle", "generate_config_aces", ] __all__ += ["generate_config_cg"] diff --git a/opencolorio_config_aces/config/cg/generate/config.py b/opencolorio_config_aces/config/cg/generate/config.py index 541795fc..95c802cf 100644 --- a/opencolorio_config_aces/config/cg/generate/config.py +++ b/opencolorio_config_aces/config/cg/generate/config.py @@ -36,7 +36,7 @@ named_transform_factory, ) from opencolorio_config_aces.config.reference import ( - ColorspaceDescriptionStyle, + DescriptionStyle, version_aces_dev, version_config_mapping_file, generate_config_aces, @@ -64,6 +64,7 @@ "URL_EXPORT_TRANSFORMS_MAPPING_FILE_CG", "PATH_TRANSFORMS_MAPPING_FILE_CG", "FILTERED_NAMESPACES", + "DESCRIPTION_CLF_TRANSFORM_ID", "is_reference", "clf_transform_to_colorspace_name", "clf_transform_to_description", @@ -108,6 +109,13 @@ FILTERED_NAMESPACES : tuple """ +DESCRIPTION_CLF_TRANSFORM_ID = "CLFtransformID: {}" +""" +Template for the description of an *CLFtransformID*. + +DESCRIPTION_CLF_TRANSFORM_ID : unicode +""" + def is_reference(name): """ @@ -155,7 +163,7 @@ def clf_transform_to_colorspace_name(clf_transform): def clf_transform_to_description( - clf_transform, describe=ColorspaceDescriptionStyle.LONG_UNION + clf_transform, describe=DescriptionStyle.LONG_UNION ): """ Generate the *OpenColorIO* `Colorspace` or `NamedTransform` description for @@ -176,13 +184,13 @@ def clf_transform_to_description( """ description = None - if describe != ColorspaceDescriptionStyle.NONE: + if describe != DescriptionStyle.NONE: description = [] if describe in ( - ColorspaceDescriptionStyle.OPENCOLORIO, - ColorspaceDescriptionStyle.SHORT, - ColorspaceDescriptionStyle.SHORT_UNION, + DescriptionStyle.OPENCOLORIO, + DescriptionStyle.SHORT, + DescriptionStyle.SHORT_UNION, ): if clf_transform.description is not None: description.append( @@ -191,16 +199,20 @@ def clf_transform_to_description( ) elif describe in ( # noqa: SIM102 - ColorspaceDescriptionStyle.OPENCOLORIO, - ColorspaceDescriptionStyle.LONG, - ColorspaceDescriptionStyle.LONG_UNION, + DescriptionStyle.OPENCOLORIO, + DescriptionStyle.LONG, + DescriptionStyle.LONG_UNION, ): if clf_transform.description is not None: description.append("\n" + clf_transform.description) - description.append( - f"\nCLFtransformID: " - f"{clf_transform.clf_transform_id.clf_transform_id}" + description.extend( + [ + "", + DESCRIPTION_CLF_TRANSFORM_ID.format( + clf_transform.clf_transform_id.clf_transform_id + ), + ] ) description = "\n".join(description).strip() @@ -243,7 +255,7 @@ def clf_transform_to_family( def clf_transform_to_colorspace( clf_transform, - describe=ColorspaceDescriptionStyle.LONG_UNION, + describe=DescriptionStyle.LONG_UNION, signature_only=False, **kwargs, ): @@ -255,7 +267,7 @@ def clf_transform_to_colorspace( clf_transform : CLFTransform *CLF* transform. describe : bool, optional - Whether to use the full *CLF* transform description or just its ID. + *CLF* transform description style. signature_only : bool, optional Whether to return the *OpenColorIO* `Colorspace` signature only, i.e. the arguments for its instantiation. @@ -306,7 +318,7 @@ def clf_transform_to_colorspace( def clf_transform_to_named_transform( clf_transform, - describe=ColorspaceDescriptionStyle.LONG_UNION, + describe=DescriptionStyle.LONG_UNION, signature_only=False, **kwargs, ): @@ -318,7 +330,7 @@ def clf_transform_to_named_transform( clf_transform : CLFTransform *CLF* transform. describe : bool, optional - Whether to use the full *CLF* transform description or just its ID. + *CLF* transform description style. signature_only : bool, optional Whether to return the *OpenColorIO* `NamedTransform` signature only, i.e. the arguments for its instantiation. @@ -369,7 +381,7 @@ def clf_transform_to_named_transform( def style_to_colorspace( style, - describe=ColorspaceDescriptionStyle.LONG_UNION, + describe=DescriptionStyle.LONG_UNION, signature_only=False, scheme="Modern 1", # noqa: ARG001 **kwargs, @@ -383,7 +395,7 @@ def style_to_colorspace( *OpenColorIO* builtin transform style. describe : int, optional Any value from the - :class:`opencolorio_config_aces.ColorspaceDescriptionStyle` enum. + :class:`opencolorio_config_aces.DescriptionStyle` enum. signature_only : bool, optional Whether to return the *OpenColorIO* view `Colorspace` signature only, i.e. the arguments for its instantiation. @@ -407,13 +419,13 @@ def style_to_colorspace( builtin_transform = ocio.BuiltinTransform(style) description = None - if describe != ColorspaceDescriptionStyle.NONE: + if describe != DescriptionStyle.NONE: description = [] if describe in ( - ColorspaceDescriptionStyle.OPENCOLORIO, - ColorspaceDescriptionStyle.SHORT_UNION, - ColorspaceDescriptionStyle.LONG_UNION, + DescriptionStyle.OPENCOLORIO, + DescriptionStyle.SHORT_UNION, + DescriptionStyle.LONG_UNION, ): description.append(builtin_transform.getDescription()) @@ -477,7 +489,7 @@ def style_to_colorspace( def style_to_named_transform( style, - describe=ColorspaceDescriptionStyle.LONG_UNION, + describe=DescriptionStyle.LONG_UNION, signature_only=False, scheme="Modern 1", # noqa: ARG001 **kwargs, @@ -491,7 +503,7 @@ def style_to_named_transform( *OpenColorIO* builtin transform style. describe : int, optional Any value from the - :class:`opencolorio_config_aces.ColorspaceDescriptionStyle` enum. + :class:`opencolorio_config_aces.DescriptionStyle` enum. signature_only : bool, optional Whether to return the *OpenColorIO* view `Colorspace` signature only, i.e. the arguments for its instantiation. @@ -515,13 +527,13 @@ def style_to_named_transform( builtin_transform = ocio.BuiltinTransform(style) description = None - if describe != ColorspaceDescriptionStyle.NONE: + if describe != DescriptionStyle.NONE: description = [] if describe in ( - ColorspaceDescriptionStyle.OPENCOLORIO, - ColorspaceDescriptionStyle.SHORT_UNION, - ColorspaceDescriptionStyle.LONG_UNION, + DescriptionStyle.OPENCOLORIO, + DescriptionStyle.SHORT_UNION, + DescriptionStyle.LONG_UNION, ): description.append(builtin_transform.getDescription()) @@ -723,7 +735,7 @@ def generate_config_cg( config_name=None, profile_version=PROFILE_VERSION_DEFAULT, validate=True, - describe=ColorspaceDescriptionStyle.SHORT_UNION, + describe=DescriptionStyle.SHORT_UNION, config_mapping_file_path=PATH_TRANSFORMS_MAPPING_FILE_CG, scheme="Modern 1", additional_data=False, @@ -768,7 +780,7 @@ def generate_config_cg( Whether to validate the config. describe : int, optional Any value from the - :class:`opencolorio_config_aces.ColorspaceDescriptionStyle` enum. + :class:`opencolorio_config_aces.DescriptionStyle` enum. config_mapping_file_path : unicode, optional Path to the *CSV* mapping file used to describe the transforms mapping. scheme : str, optional @@ -784,12 +796,18 @@ def generate_config_cg( :class:`opencolorio_config_aces.ConfigData` class instance. """ + scheme = validate_method(scheme, ["Legacy", "Modern 1"]) + logger.info( 'Generating "%s" config...', config_name_cg(config_mapping_file_path, profile_version), ) - scheme = validate_method(scheme, ["Legacy", "Modern 1"]) + clf_transforms = unclassify_clf_transforms( + classify_clf_transforms(discover_clf_transforms()) + ) + + logger.debug('Using %s "CLF" transforms...', clf_transforms) if data is None: _config, data = generate_config_aces( @@ -800,16 +818,6 @@ def generate_config_cg( additional_data=True, ) - clf_transforms = unclassify_clf_transforms( - classify_clf_transforms(discover_clf_transforms()) - ) - - logger.debug('Using %s "CLF" transforms...', clf_transforms) - - logger.debug( - 'Using %s "Builtin" transforms...', list(BUILTIN_TRANSFORMS.keys()) - ) - def clf_transform_from_id(clf_transform_id): """ Filter the "CLFTransform" instances matching given "CLFtransformID". diff --git a/opencolorio_config_aces/config/reference/__init__.py b/opencolorio_config_aces/config/reference/__init__.py index adfd8fdb..1e9b6c9b 100644 --- a/opencolorio_config_aces/config/reference/__init__.py +++ b/opencolorio_config_aces/config/reference/__init__.py @@ -7,6 +7,7 @@ classify_aces_ctl_transforms, unclassify_ctl_transforms, filter_ctl_transforms, + generate_amf_relations, print_aces_taxonomy, build_aces_conversion_graph, node_to_ctl_transform, @@ -16,7 +17,7 @@ plot_aces_conversion_graph, ) from .generate import ( - ColorspaceDescriptionStyle, + DescriptionStyle, version_config_mapping_file, generate_config_aces, ) @@ -27,6 +28,7 @@ "classify_aces_ctl_transforms", "unclassify_ctl_transforms", "filter_ctl_transforms", + "generate_amf_relations", "print_aces_taxonomy", "build_aces_conversion_graph", "node_to_ctl_transform", @@ -36,7 +38,7 @@ "plot_aces_conversion_graph", ] __all__ += [ - "ColorspaceDescriptionStyle", + "DescriptionStyle", "version_config_mapping_file", "generate_config_aces", ] diff --git a/opencolorio_config_aces/config/reference/discover/__init__.py b/opencolorio_config_aces/config/reference/discover/__init__.py index 7bdcec42..59709ab8 100644 --- a/opencolorio_config_aces/config/reference/discover/__init__.py +++ b/opencolorio_config_aces/config/reference/discover/__init__.py @@ -7,6 +7,7 @@ classify_aces_ctl_transforms, unclassify_ctl_transforms, filter_ctl_transforms, + generate_amf_relations, print_aces_taxonomy, ) from .graph import ( @@ -24,6 +25,7 @@ "classify_aces_ctl_transforms", "unclassify_ctl_transforms", "filter_ctl_transforms", + "generate_amf_relations", "print_aces_taxonomy", ] __all__ += [ diff --git a/opencolorio_config_aces/config/reference/discover/classify.py b/opencolorio_config_aces/config/reference/discover/classify.py index 72c9f9ad..d4d0a55f 100644 --- a/opencolorio_config_aces/config/reference/discover/classify.py +++ b/opencolorio_config_aces/config/reference/discover/classify.py @@ -12,6 +12,7 @@ - :func:`opencolorio_config_aces.unclassify_ctl_transforms` - :func:`opencolorio_config_aces.filter_ctl_transforms` - :func:`opencolorio_config_aces.print_aces_taxonomy` +- :func:`opencolorio_config_aces.generate_amf_relations` """ import itertools @@ -62,6 +63,8 @@ "unclassify_ctl_transforms", "filter_ctl_transforms", "print_aces_taxonomy", + "RELATIONS_AMF_IMPLICIT", + "generate_amf_relations", ] logger = logging.getLogger(__name__) @@ -698,9 +701,11 @@ class CTLTransform: path : unicode *ACES* *CTL* transform path. family : unicode, optional - *ACES* *CTL* transform family, e.g. *output_transform* + *ACES* *CTL* transform family, e.g. *output_transform*. genus : unicode, optional - *ACES* *CTL* transform genus, e.g. *dcdm* + *ACES* *CTL* transform genus, e.g. *dcdm*. + siblings : array_like, optional + *ACES* *CTL* transform siblings, e.g. inverse transform. Attributes ---------- @@ -722,7 +727,10 @@ class CTLTransform: __ne__ """ - def __init__(self, path, family=None, genus=None): + def __init__(self, path, family=None, genus=None, siblings=None): + if siblings is None: + siblings = [] + self._path = os.path.abspath(os.path.normpath(path)) self._code = None @@ -732,6 +740,7 @@ def __init__(self, path, family=None, genus=None): self._family = family self._genus = genus + self._siblings = siblings self._parse() @@ -861,6 +870,24 @@ def genus(self): return self._genus + @property + def siblings(self): + """ + Getter property for the *ACES* *CTL* transform siblings, e.g. inverse + transform. + + Returns + ------- + unicode + *ACES* *CTL* transform siblings. + + Notes + ----- + - This property is read only. + """ + + return self._siblings + def __getattr__(self, item): """ Reimplement the :meth:`object.__getattr__` so that unsuccessful @@ -1311,6 +1338,9 @@ def classify_aces_ctl_transforms(unclassified_ctl_transforms): pairs["inverse_transform"], family, genus ) + forward_ctl_transform.siblings.append(inverse_ctl_transform) + inverse_ctl_transform.siblings.append(forward_ctl_transform) + ctl_transform = CTLTransformPair( forward_ctl_transform, inverse_ctl_transform ) @@ -1328,7 +1358,7 @@ def classify_aces_ctl_transforms(unclassified_ctl_transforms): def unclassify_ctl_transforms(classified_ctl_transforms): """ - Unclassifie given *ACES* *CTL* transforms. + Unclassify given *ACES* *CTL* transforms. Parameters ---------- @@ -1466,6 +1496,119 @@ def print_aces_taxonomy(): ) +RELATIONS_AMF_IMPLICIT = { + "urn:ampas:aces:transformId:v1.5:" + "ACEScsc.Academy.BMDFilm_WideGamut_Gen5_to_ACES.a1.v1": [ + "urn:ampas:aces:transformId:v1.5:" + "IDT.BlackmagicDesign.BMDFilm_WideGamut_Gen5.a1.v1" + ], + "urn:ampas:aces:transformId:v1.5:" + "ACEScsc.Academy.LogC_EI800_AWG_to_ACES.a1.1.0": [ + "urn:ampas:aces:transformId:v1.5:IDT.ARRI.Alexa-v3-logC-EI800.a1.v2" + ], + "urn:ampas:aces:transformId:v1.5:" + "ACEScsc.Academy.SLog3_SGamut3_to_ACES.a1.1.0": [ + "urn:ampas:aces:transformId:v1.5:IDT.Sony.SLog3_SGamut3.a1.v1" + ], + "urn:ampas:aces:transformId:v1.5:" + "ACEScsc.Academy.SLog3_SGamut3Cine_to_ACES.a1.1.0": [ + "urn:ampas:aces:transformId:v1.5:IDT.Sony.SLog3_SGamut3Cine.a1.v1" + ], + "urn:ampas:aces:transformId:v1.5:" + "ACEScsc.Academy.SLog3_Venice_SGamut3_to_ACES.a1.1.0": [ + "urn:ampas:aces:transformId:v1.5:" + "IDT.Sony.Venice_SLog3_SGamut3.a1.v1" + ], + "urn:ampas:aces:transformId:v1.5:" + "ACEScsc.Academy.SLog3_Venice_SGamut3Cine_to_ACES.a1.1.0": [ + "urn:ampas:aces:transformId:v1.5:" + "IDT.Sony.Venice_SLog3_SGamut3Cine.a1.v1" + ], +} +""" +Implicit *ACES* *AMF* relations. + +Notes +----- +Those are currently hardcoded as there is no trivial way to build a +relationship between an *ACES* *CSC* and an *ACES* *IDT*. + +RELATIONS_AMF_IMPLICIT : dict +""" + + +def generate_amf_relations(ctl_transforms): + """ + Generate the *ACES* *AMF* relations from given *ACES* *CTL* transforms. + + Parameters + ---------- + ctl_transforms : dict or list + *ACES* *CTL* transforms as returned by + :func:`opencolorio_config_aces.classify_aces_ctl_transforms` or + :func:`opencolorio_config_aces.unclassify_aces_ctl_transforms` + definitions. + + Returns + ------- + defaultdict + *ACES* *AMF* relations. + """ + mapping = defaultdict(list) + + if isinstance(ctl_transforms, Mapping): + ctl_transforms = unclassify_ctl_transforms(ctl_transforms) + + # Checking that the explicit "ACEStransformID" do exist. + for aces_transform_id, relations in RELATIONS_AMF_IMPLICIT.items(): + explicit_aces_transform_ids = [aces_transform_id] + explicit_aces_transform_ids.extend(relations) + + for explicit_aces_transform_id in explicit_aces_transform_ids: + filtered_ctl_transforms = filter_ctl_transforms( + ctl_transforms, + [ + lambda x, y=explicit_aces_transform_id: ( + x.aces_transform_id.aces_transform_id == y + ) + ], + ) + + ctl_transform = next(iter(filtered_ctl_transforms), None) + + attest( + ctl_transform is not None, + ( + f'"aces-dev" has no transform with ' + f'"{explicit_aces_transform_id}" "ACEStransformID!' + ), + ) + + for ctl_transform in ctl_transforms: + aces_transform_id = ctl_transform.aces_transform_id.aces_transform_id + + for siblings in [ + ctl_transform.siblings + for ctl_transform in filter_ctl_transforms( + ctl_transforms, + [ + lambda x, y=aces_transform_id: ( + x.aces_transform_id.aces_transform_id == y + ) + ], + ) + ]: + for sibling in siblings: + mapping[aces_transform_id].append( + sibling.aces_transform_id.aces_transform_id + ) + + for aces_transform_id, relations in RELATIONS_AMF_IMPLICIT.items(): + mapping[aces_transform_id].extend(relations) + + return mapping + + if __name__ == "__main__": logging.basicConfig() logging.getLogger().setLevel(logging.INFO) diff --git a/opencolorio_config_aces/config/reference/generate/__init__.py b/opencolorio_config_aces/config/reference/generate/__init__.py index 89f6a76b..a9278e18 100644 --- a/opencolorio_config_aces/config/reference/generate/__init__.py +++ b/opencolorio_config_aces/config/reference/generate/__init__.py @@ -2,13 +2,13 @@ # Copyright Contributors to the OpenColorIO Project. from .config import ( - ColorspaceDescriptionStyle, + DescriptionStyle, version_config_mapping_file, generate_config_aces, ) __all__ = [ - "ColorspaceDescriptionStyle", + "DescriptionStyle", "version_config_mapping_file", "generate_config_aces", ] diff --git a/opencolorio_config_aces/config/reference/generate/analytical.py b/opencolorio_config_aces/config/reference/generate/analytical.py index 254d6cf3..c74b8c18 100644 --- a/opencolorio_config_aces/config/reference/generate/analytical.py +++ b/opencolorio_config_aces/config/reference/generate/analytical.py @@ -27,7 +27,7 @@ SEPARATOR_NODE_NAME_CTL, ) from opencolorio_config_aces.config.reference import ( - ColorspaceDescriptionStyle, + DescriptionStyle, build_aces_conversion_graph, classify_aces_ctl_transforms, conversion_path, @@ -234,7 +234,7 @@ def node_to_colorspace( graph, node, profile_version=PROFILE_VERSION_DEFAULT, - describe=ColorspaceDescriptionStyle.LONG_UNION, + describe=DescriptionStyle.LONG_UNION, ): """ Generate the *OpenColorIO* `Colorspace` for given *aces-dev* conversion @@ -250,7 +250,7 @@ def node_to_colorspace( *OpenColorIO* config profile version. describe : int, optional Any value from the - :class:`opencolorio_config_aces.ColorspaceDescriptionStyle` enum. + :class:`opencolorio_config_aces.DescriptionStyle` enum. Returns ------- @@ -356,7 +356,7 @@ def generate_config_aces( config_name=None, profile_version=PROFILE_VERSION_DEFAULT, validate=True, - describe=ColorspaceDescriptionStyle.LONG_UNION, + describe=DescriptionStyle.LONG_UNION, filterers=None, additional_data=False, ): @@ -381,7 +381,7 @@ def generate_config_aces( Whether to validate the config. describe : int, optional Any value from the - :class:`opencolorio_config_aces.ColorspaceDescriptionStyle` enum. + :class:`opencolorio_config_aces.DescriptionStyle` enum. filterers : array_like, optional List of callables used to filter the *ACES* *CTL* transforms, each callable takes an *ACES* *CTL* transform as argument and returns diff --git a/opencolorio_config_aces/config/reference/generate/config.py b/opencolorio_config_aces/config/reference/generate/config.py index b1fbc9a9..7434b9cf 100644 --- a/opencolorio_config_aces/config/reference/generate/config.py +++ b/opencolorio_config_aces/config/reference/generate/config.py @@ -39,6 +39,8 @@ from opencolorio_config_aces.config.reference import ( classify_aces_ctl_transforms, discover_aces_ctl_transforms, + filter_ctl_transforms, + generate_amf_relations, unclassify_ctl_transforms, version_aces_dev, ) @@ -62,7 +64,8 @@ "COLORSPACE_SCENE_ENCODING_REFERENCE", "COLORSPACE_OUTPUT_ENCODING_REFERENCE", "FAMILY_DISPLAY_REFERENCE", - "ColorspaceDescriptionStyle", + "DESCRIPTION_ACES_TRANSFORM_ID", + "DescriptionStyle", "version_config_mapping_file", "format_optional_prefix", "format_swapped_affix", @@ -125,10 +128,17 @@ FAMILY_DISPLAY_REFERENCE : unicode """ +DESCRIPTION_ACES_TRANSFORM_ID = "ACEStransformID: {}" +""" +Template for the description of an *ACEStransformID*. + +DESCRIPTION_ACES_TRANSFORM_ID : unicode +""" -class ColorspaceDescriptionStyle(Flag): + +class DescriptionStyle(Flag): """ - Enum storing the various *OpenColorIO* `Colorspace` description styles. + Enum storing the various *OpenColorIO* description styles. """ NONE = auto() @@ -364,7 +374,8 @@ def ctl_transform_to_transform_family(ctl_transform, analytical=True): def ctl_transform_to_description( ctl_transform, - describe=ColorspaceDescriptionStyle.LONG_UNION, + describe=DescriptionStyle.LONG_UNION, + amf_relations=None, factory=colorspace_factory, **kwargs, ): @@ -377,8 +388,11 @@ def ctl_transform_to_description( ctl_transform : CTLTransform *ACES* *CTL* transform to generate the *OpenColorIO* `Colorspace` for. describe : bool, optional - Whether to use the full *ACES* *CTL* transform description or just the - first line. + *ACES* *CTL* transform description style. Any value from the + :class:`opencolorio_config_aces.DescriptionStyle` enum. + amf_relations : mapping, optional + *ACES* *AMF* relations used to extend the *ACES* *CTL* transform + description. factory : callable, optional Factory used to adjust the code paths because of slight difference of signature between the *OpenColorIO* `Colorspace` and `Look`. @@ -395,14 +409,17 @@ def ctl_transform_to_description( *OpenColorIO* `Colorspace` or `Look` description. """ + if amf_relations is None: + amf_relations = {} + description = None - if describe != ColorspaceDescriptionStyle.NONE: + if describe != DescriptionStyle.NONE: description = [] if describe in ( - ColorspaceDescriptionStyle.OPENCOLORIO, - ColorspaceDescriptionStyle.SHORT_UNION, - ColorspaceDescriptionStyle.LONG_UNION, + DescriptionStyle.OPENCOLORIO, + DescriptionStyle.SHORT_UNION, + DescriptionStyle.LONG_UNION, ): forward, inverse = ( [ @@ -425,10 +442,10 @@ def ctl_transform_to_description( description.append(transform.getDescription()) if describe in ( - ColorspaceDescriptionStyle.ACES, - ColorspaceDescriptionStyle.ACES | ColorspaceDescriptionStyle.SHORT, - ColorspaceDescriptionStyle.SHORT_UNION, - ColorspaceDescriptionStyle.LONG_UNION, + DescriptionStyle.ACES, + DescriptionStyle.ACES | DescriptionStyle.SHORT, + DescriptionStyle.SHORT_UNION, + DescriptionStyle.LONG_UNION, ): if len(description) > 0: description.append("") @@ -438,18 +455,30 @@ def ctl_transform_to_description( ) if describe in ( - ColorspaceDescriptionStyle.ACES, - ColorspaceDescriptionStyle.ACES - | ColorspaceDescriptionStyle.SHORT, - ColorspaceDescriptionStyle.SHORT_UNION, + DescriptionStyle.ACES, + DescriptionStyle.ACES | DescriptionStyle.SHORT, + DescriptionStyle.SHORT_UNION, ): - description.append(f"ACEStransformID: {aces_transform_id}") + description.append( + DESCRIPTION_ACES_TRANSFORM_ID.format(aces_transform_id) + ) else: description.append("CTL Transform") description.append(f'{"=" * len(description[-1])}\n') description.append(f"{ctl_transform.description}\n") - description.append(f"ACEStransformID: {aces_transform_id}") + description.append( + DESCRIPTION_ACES_TRANSFORM_ID.format(aces_transform_id) + ) + + description.extend( + [ + DESCRIPTION_ACES_TRANSFORM_ID.format(amf_aces_transform_id) + for amf_aces_transform_id in amf_relations.get( + aces_transform_id, [] + ) + ] + ) description = "\n".join(description) @@ -458,7 +487,8 @@ def ctl_transform_to_description( def ctl_transform_to_colorspace( ctl_transform, - describe=ColorspaceDescriptionStyle.LONG_UNION, + describe=DescriptionStyle.LONG_UNION, + amf_relations=None, analytical=True, signature_only=False, scheme="Modern 1", @@ -473,8 +503,11 @@ def ctl_transform_to_colorspace( ctl_transform : CTLTransform *ACES* *CTL* transform to generate the *OpenColorIO* `Colorspace` for. describe : bool, optional - Whether to use the full *ACES* *CTL* transform description or just the - first line. + *ACES* *CTL* transform description style. Any value from the + :class:`opencolorio_config_aces.DescriptionStyle` enum. + amf_relations : mapping, optional + *ACES* *AMF* relations used to extend the *OpenColorIO* `Colorspace` + description. analytical : bool, optional Whether to generate the *OpenColorIO* transform family that analytically matches the given *ACES* *CTL* transform, i.e. true to @@ -501,7 +534,7 @@ def ctl_transform_to_colorspace( name = ctl_transform_to_colorspace_name(ctl_transform) family = ctl_transform_to_transform_family(ctl_transform, analytical) description = ctl_transform_to_description( - ctl_transform, describe, colorspace_factory, **kwargs + ctl_transform, describe, amf_relations, colorspace_factory, **kwargs ) signature = { @@ -529,7 +562,8 @@ def ctl_transform_to_colorspace( def ctl_transform_to_look( ctl_transform, - describe=ColorspaceDescriptionStyle.LONG_UNION, + describe=DescriptionStyle.LONG_UNION, + amf_relations=None, analytical=True, signature_only=False, scheme="Modern 1", @@ -544,8 +578,11 @@ def ctl_transform_to_look( ctl_transform : CTLTransform *ACES* *CTL* transform to generate the *OpenColorIO* `Look` for. describe : bool, optional - Whether to use the full *ACES* *CTL* transform description or just the - first line. + *ACES* *CTL* transform description style. Any value from the + :class:`opencolorio_config_aces.DescriptionStyle` enum. + amf_relations : mapping, optional + *ACES* *AMF* relations used to extend the *OpenColorIO* `Look` + description. analytical : bool, optional Whether to generate the *OpenColorIO* transform family that analytically matches the given *ACES* *CTL* transform, i.e. true to @@ -572,7 +609,7 @@ def ctl_transform_to_look( name = ctl_transform_to_look_name(ctl_transform) family = ctl_transform_to_transform_family(ctl_transform, analytical) description = ctl_transform_to_description( - ctl_transform, describe, look_factory, **kwargs + ctl_transform, describe, amf_relations, look_factory, **kwargs ) signature = { @@ -594,7 +631,8 @@ def ctl_transform_to_look( def style_to_view_transform( style, ctl_transforms, - describe=ColorspaceDescriptionStyle.LONG_UNION, + describe=DescriptionStyle.LONG_UNION, + amf_relations=None, signature_only=False, scheme="Modern 1", **kwargs, @@ -610,8 +648,11 @@ def style_to_view_transform( Array of :class:`opencolorio_config_aces.config.reference.CTLTransform` class instances corresponding to the given style. describe : int, optional - Any value from the - :class:`opencolorio_config_aces.ColorspaceDescriptionStyle` enum. + Any value from the :class:`opencolorio_config_aces.DescriptionStyle` + enum. + amf_relations : mapping, optional + *ACES* *AMF* relations used to extend the *OpenColorIO* `ViewTransform` + description. signature_only : bool, optional Whether to return the *OpenColorIO* `ViewTransform` signature only, i.e. the arguments for its instantiation. @@ -635,21 +676,21 @@ class instances corresponding to the given style. builtin_transform = ocio.BuiltinTransform(style) description = None - if describe != ColorspaceDescriptionStyle.NONE: + if describe != DescriptionStyle.NONE: description = [] if describe in ( - ColorspaceDescriptionStyle.OPENCOLORIO, - ColorspaceDescriptionStyle.SHORT_UNION, - ColorspaceDescriptionStyle.LONG_UNION, + DescriptionStyle.OPENCOLORIO, + DescriptionStyle.SHORT_UNION, + DescriptionStyle.LONG_UNION, ): description.append(builtin_transform.getDescription()) if describe in ( - ColorspaceDescriptionStyle.ACES, - ColorspaceDescriptionStyle.ACES | ColorspaceDescriptionStyle.SHORT, - ColorspaceDescriptionStyle.SHORT_UNION, - ColorspaceDescriptionStyle.LONG_UNION, + DescriptionStyle.ACES, + DescriptionStyle.ACES | DescriptionStyle.SHORT, + DescriptionStyle.SHORT_UNION, + DescriptionStyle.LONG_UNION, ): aces_transform_ids, aces_descriptions = zip( *[ @@ -665,9 +706,8 @@ class instances corresponding to the given style. description.append("") if describe in ( - ColorspaceDescriptionStyle.ACES - | ColorspaceDescriptionStyle.SHORT, - ColorspaceDescriptionStyle.SHORT_UNION, + DescriptionStyle.ACES | DescriptionStyle.SHORT, + DescriptionStyle.SHORT_UNION, ): description.extend( [ @@ -696,6 +736,18 @@ class instances corresponding to the given style. ) ) + for aces_transform_id in aces_transform_ids: + description.extend( + [ + DESCRIPTION_ACES_TRANSFORM_ID.format( + amf_aces_transform_id + ) + for amf_aces_transform_id in amf_relations.get( + aces_transform_id, [] + ) + ] + ) + description = "\n".join(description) version = style.split(SEPARATOR_COLORSPACE_NAME)[-1].split("_")[-1] @@ -724,7 +776,8 @@ class instances corresponding to the given style. def style_to_display_colorspace( style, - describe=ColorspaceDescriptionStyle.OPENCOLORIO, + describe=DescriptionStyle.OPENCOLORIO, + amf_relations=None, signature_only=False, scheme="Modern 1", **kwargs, @@ -738,8 +791,11 @@ def style_to_display_colorspace( style : unicode *OpenColorIO* builtin transform style describe : int, optional - Any value from the - :class:`opencolorio_config_aces.ColorspaceDescriptionStyle` enum. + Any value from the :class:`opencolorio_config_aces.DescriptionStyle` + enum. + amf_relations : mapping, optional + *ACES* *AMF* relations used to extend the *OpenColorIO* display + `Colorspace` description. signature_only : bool, optional Whether to return the *OpenColorIO* display `Colorspace` signature only, i.e. the arguments for its instantiation. @@ -765,16 +821,26 @@ def style_to_display_colorspace( builtin_transform = ocio.BuiltinTransform(style) description = None - if describe != ColorspaceDescriptionStyle.NONE: + if describe != DescriptionStyle.NONE: description = [] if describe in ( - ColorspaceDescriptionStyle.OPENCOLORIO, - ColorspaceDescriptionStyle.SHORT_UNION, - ColorspaceDescriptionStyle.LONG_UNION, + DescriptionStyle.OPENCOLORIO, + DescriptionStyle.SHORT_UNION, + DescriptionStyle.LONG_UNION, ): description.append(builtin_transform.getDescription()) + if len(description) > 0: + description.append("") + + description.extend( + [ + DESCRIPTION_ACES_TRANSFORM_ID.format(amf_aces_transform_id) + for amf_aces_transform_id in amf_relations.get(style, []) + ] + ) + description = "\n".join(description) signature = { @@ -971,7 +1037,7 @@ def generate_config_aces( config_name=None, profile_version=PROFILE_VERSION_DEFAULT, validate=True, - describe=ColorspaceDescriptionStyle.SHORT_UNION, + describe=DescriptionStyle.SHORT_UNION, config_mapping_file_path=PATH_TRANSFORMS_MAPPING_FILE_REFERENCE, analytical=True, scheme="Modern 1", @@ -1002,7 +1068,7 @@ def generate_config_aces( Whether to validate the config. describe : int, optional Any value from the - :class:`opencolorio_config_aces.ColorspaceDescriptionStyle` enum. + :class:`opencolorio_config_aces.DescriptionStyle` enum. config_mapping_file_path : unicode, optional Path to the *CSV* mapping file used by the *Mapping* method. analytical : bool, optional @@ -1027,16 +1093,17 @@ def generate_config_aces( config_name_aces(config_mapping_file_path, profile_version), ) + logger.debug( + 'Using %s "Builtin" transforms...', list(BUILTIN_TRANSFORMS.keys()) + ) + ctl_transforms = unclassify_ctl_transforms( classify_aces_ctl_transforms(discover_aces_ctl_transforms()) ) + amf_relations = generate_amf_relations(ctl_transforms) logger.debug('Using %s "CTL" transforms...', ctl_transforms) - logger.debug( - 'Using %s "Builtin" transforms...', list(BUILTIN_TRANSFORMS.keys()) - ) - logger.info( 'Parsing "%s" config mapping file...', config_mapping_file_path ) @@ -1103,12 +1170,14 @@ def generate_config_aces( # "ACEStransformID", if it does not exist, there is a critical # mismatch in the mapping with *aces-dev*. aces_transform_id = transform_data["aces_transform_id"] - filtered_ctl_transforms = [ - ctl_transform - for ctl_transform in ctl_transforms - if ctl_transform.aces_transform_id.aces_transform_id - == aces_transform_id - ] + filtered_ctl_transforms = filter_ctl_transforms( + ctl_transforms, + [ + lambda x, y=aces_transform_id: ( + x.aces_transform_id.aces_transform_id == y + ) + ], + ) ctl_transform = next(iter(filtered_ctl_transforms), None) @@ -1124,6 +1193,15 @@ def generate_config_aces( transform_data["ctl_transform"] = ctl_transform + # Extending the "AMF" relations. + amf_relations[style].extend( + [ctl_transform.aces_transform_id.aces_transform_id] + + [ + sibling.aces_transform_id.aces_transform_id + for sibling in ctl_transform.siblings + ] + ) + config_mapping[transform_data["builtin_transform_style"]].append( transform_data ) @@ -1190,6 +1268,7 @@ def generate_config_aces( for transform_data in transforms_data ], describe, + amf_relations, signature_only=True, scheme=scheme, ) @@ -1205,6 +1284,8 @@ def generate_config_aces( display = style_to_display_colorspace( display_style, + describe, + amf_relations, signature_only=True, scheme=scheme, encoding=transform_data.get("encoding"), @@ -1242,6 +1323,7 @@ def generate_config_aces( look = ctl_transform_to_look( ctl_transform, describe, + amf_relations, analytical=analytical, signature_only=True, scheme=scheme, @@ -1262,6 +1344,7 @@ def generate_config_aces( colorspace = ctl_transform_to_colorspace( ctl_transform, describe, + amf_relations, analytical=analytical, signature_only=True, scheme=scheme, diff --git a/opencolorio_config_aces/config/studio/generate/config.py b/opencolorio_config_aces/config/studio/generate/config.py index e5ae1b50..3d44fc14 100644 --- a/opencolorio_config_aces/config/studio/generate/config.py +++ b/opencolorio_config_aces/config/studio/generate/config.py @@ -19,7 +19,7 @@ generate_config, ) from opencolorio_config_aces.config.reference import ( - ColorspaceDescriptionStyle, + DescriptionStyle, ) from opencolorio_config_aces.config.cg import ( generate_config_cg, @@ -172,7 +172,7 @@ def generate_config_studio( config_name=None, profile_version=PROFILE_VERSION_DEFAULT, validate=True, - describe=ColorspaceDescriptionStyle.SHORT_UNION, + describe=DescriptionStyle.SHORT_UNION, config_mapping_file_path=PATH_TRANSFORMS_MAPPING_FILE_STUDIO, scheme="Modern 1", additional_data=False, @@ -209,7 +209,7 @@ def generate_config_studio( Whether to validate the config. describe : int, optional Any value from the - :class:`opencolorio_config_aces.ColorspaceDescriptionStyle` enum. + :class:`opencolorio_config_aces.DescriptionStyle` enum. config_mapping_file_path : unicode, optional Path to the *CSV* mapping file used to describe the transforms mapping. scheme : str, optional