Added documentation for individual functions
[OpenColorIO-Configs.git] / aces_1.0.0 / python / aces_ocio / generate_config.py
index f16cd29..4f01818 100755 (executable)
@@ -75,23 +75,27 @@ def set_config_roles(config,
     config : Config
         *OCIO* configuration.
     color_picking : str or unicode, optional
-        Color picking role title.
+        Color Picking role title.
     color_timing : str or unicode, optional
-        Color timing role title.
+        Color Timing role title.
     compositing_log : str or unicode, optional
-        Compositing log role title.
+        Compositing Log role title.
     data : str or unicode, optional
         Data role title.
     default : str or unicode, optional
         Default role title.
     matte_paint : str or unicode, optional
-        Matte painting role title.
+        Matte Painting role title.
     reference : str or unicode, optional
         Reference role title.
     scene_linear : str or unicode, optional
-        Scene linear role title.
+        Scene Linear role title.
     texture_paint : str or unicode, optional
-        Texture painting role title.
+        Texture Painting role title.
+    rendering : str or unicode, optional
+        Rendering role title.
+    compositing_linear : str or unicode, optional
+        Compositing Linear role title.
     Returns
     -------
     bool
@@ -427,17 +431,26 @@ def add_looks_to_views(looks,
                        config_data,
                        multiple_displays=False):
     """
-    Object description.
+    Integrates a set of looks into the *OCIO* config's Displays and Views
 
     Parameters
     ----------
-    parameter : type
-        Parameter description.
+    looks : array of str or unicode
+        Names of looks
+    reference_name : str or unicode
+        The name of the *OCIO* reference colorspace
+    config_data : dict
+        Colorspaces and transforms converting between those colorspaces and
+        the reference colorspace, *ACES*.
+    multiple_displays : bool
+        If true, looks are added to the config_data looks list
+        If false, looks are integrated directly into the list of displays and 
+        views. This may be necessary due to limitations of some applications' 
+        currently implementation of OCIO, ex. Maya 2016.
 
     Returns
     -------
-    type
-         Return value description.
+    None
     """
     look_names = [look[0] for look in looks]
 
@@ -522,17 +535,30 @@ def create_config(config_data,
                   look_info=None,
                   custom_lut_dir=None):
     """
-    Object description.
+    Create the *OCIO* config based on the configuration data
 
     Parameters
     ----------
-    parameter : type
-        Parameter description.
+    config_data : dict
+        Colorspaces and transforms converting between those colorspaces and
+        the reference colorspace, *ACES*, along with other data needed to 
+        generate a complete *OCIO* configuration
+    aliases : bool, optional
+        Whether or not to include Alias colorspaces 
+    prefix : bool, optional
+        Whether or not to prefix the colorspace names with their Family names
+    multiple_displays : bool, optional
+        Whether to create a single display named *ACES* with Views for each
+        Output Transform or multiple displays, one for each Output Transform
+    look_info : array of str or unicode, optional
+        Paths and names for look data
+    custom_lut_dir : str or unicode, optional
+        Directory to use for storing custom look files
 
     Returns
     -------
-    type
-         Return value description.
+    *OCIO* config
+         The constructed OCIO configuration
     """
 
     if look_info is None:
@@ -685,18 +711,16 @@ def create_config(config_data,
             matte_paint=prefixed_names[config_data['roles']['matte_paint']],
             reference=prefixed_names[config_data['roles']['reference']],
             scene_linear=prefixed_names[config_data['roles']['scene_linear']],
+            compositing_linear=prefixed_names[config_data['roles']['scene_linear']],
+            rendering=prefixed_names[config_data['roles']['scene_linear']],
             texture_paint=prefixed_names[
                 config_data['roles']['texture_paint']])
 
-        # TODO: Pending code path reactivation.
-        # Not allowed at the moment as role names can not overlap
-        # with colorspace names.
-        """
         # Add the aliased colorspaces for each role
         for role_name, role_colorspace_name in config_data['roles'].iteritems():
             role_colorspace_prefixed_name = prefixed_names[role_colorspace_name]
 
-            print( 'Finding colorspace : %s' % role_colorspace_prefixed_name )
+            #print( 'Finding colorspace : %s' % role_colorspace_prefixed_name )
             # Find the colorspace pointed to by the role
             role_colorspaces = [colorspace
                 for colorspace in config_data['colorSpaces']
@@ -709,12 +733,18 @@ def create_config(config_data,
                     role_colorspace = reference_data
 
             if role_colorspace:
-                print( 'Adding an alias colorspace named %s, pointing to %s' % (
-                    role_name, role_colorspace.name))
+                # The alias colorspace shouldn't match the role name exactly
+                role_name_alias1 = "role_%s" % role_name
+                role_name_alias2 = "Role - %s" % role_name
+
+                print( 'Adding a role colorspace named %s, pointing to %s' % (
+                    role_name_alias2, role_colorspace.name))
+
+                alias_colorspaces.append(
+                (reference_data, role_colorspace, [role_name_alias1]))
 
                 add_colorspace_aliases(
-                config, reference_data, role_colorspace, [role_name], 'Roles')
-        """
+                config, reference_data, role_colorspace, [role_name_alias2], 'Roles')
 
     else:
         set_config_roles(
@@ -727,12 +757,10 @@ def create_config(config_data,
             matte_paint=config_data['roles']['matte_paint'],
             reference=config_data['roles']['reference'],
             scene_linear=config_data['roles']['scene_linear'],
+            compositing_linear=config_data['roles']['scene_linear'],
+            rendering=config_data['roles']['scene_linear'],
             texture_paint=config_data['roles']['texture_paint'])
 
-        # TODO: Pending code path reactivation.
-        # Not allowed at the moment as role names can not overlap
-        # with colorspace names.
-        """
         # Add the aliased colorspaces for each role
         for role_name, role_colorspace_name in config_data['roles'].iteritems():
             # Find the colorspace pointed to by the role
@@ -747,12 +775,18 @@ def create_config(config_data,
                     role_colorspace = reference_data
 
             if role_colorspace:
-                print('Adding an alias colorspace named %s, pointing to %s' % (
-                    role_name, role_colorspace.name))
+                # The alias colorspace shouldn't match the role name exactly
+                role_name_alias1 = "role_%s" % role_name
+                role_name_alias2 = "Role - %s" % role_name
+
+                print('Adding a role colorspace named %s, pointing to %s' % (
+                    role_name_alias2, role_colorspace.name))
+
+                alias_colorspaces.append(
+                (reference_data, role_colorspace, [role_name_alias1]))
 
                 add_colorspace_aliases(
-                config, reference_data, role_colorspace, [role_name], 'Roles')
-        """
+                config, reference_data, role_colorspace, [role_name_alias2], 'Roles')
 
     print('')
 
@@ -776,10 +810,6 @@ def create_config(config_data,
     default_display_views = config_data['displays'][default_display_name]
     default_display_colorspace = default_display_views['Output Transform']
 
-    set_config_roles(
-        config,
-        color_picking=default_display_colorspace.name)
-
     # Defining *Displays* and *Views*.
     displays, views = [], []
 
@@ -938,18 +968,34 @@ def create_config_data(odt_info,
                        lut_resolution_3d=64,
                        cleanup=True):
     """
-    Object description.
+    Create the *ACES* LUTs and data structures needed for later *OCIO* 
+    configuration generation
 
     Parameters
     ----------
-    parameter : type
-        Parameter description.
+    odt_info : array of dicts of str or unicode
+        Descriptions of the *ACES* Output Transforms
+    lmt_info : array of dicts of str or unicode
+        Descriptions of the *ACES* Look Transforms
+    shaper_name : str or unicode
+        The name of the Shaper function to use when generating LUTs. 
+        Options: Log2, DolbyPQ
+    aces_ctl_directory : str or unicode
+        The path to the aces 'transforms/ctl/utilities'
+    lut_directory : str or unicode
+        The path to use when writing LUTs
+    lut_resolution_1d : int, optional
+        The resolution of generated 1D LUTs
+    lut_resolution_3d : int, optional
+        The resolution of generated 3D LUTs
+    cleanup : bool
+        Whether or not to clean up the intermediate images 
 
     Returns
     -------
     dict
-         Colorspaces and transforms converting between those colorspaces and
-         the reference colorspace, *ACES*.
+         Colorspaces, LUT paths and transforms converting between those 
+         colorspaces and the reference colorspace, *ACES*.
     """
 
     print('create_config_data - begin')
@@ -1091,17 +1137,31 @@ def generate_baked_LUTs(odt_info,
                         lut_resolution_shaper=1024,
                         prefix=False):
     """
-    Object description.
+    Generate baked representations of the transforms from the *ACES* *OCIO*
+    configuration
 
     Parameters
     ----------
-    parameter : type
-        Parameter description.
+    odt_info : array of dicts of str or unicode
+        Descriptions of the *ACES* Output Transforms
+    shaper_name : str or unicode
+        The name of the Shaper function to use when generating LUTs. 
+        Options: Log2, DolbyPQ
+    baked_directory : str or unicode
+        The path to use when writing baked LUTs
+    config_path : str or unicode
+        The path to the *OCIO* configuration
+    lut_resolution_3d : int, optional
+        The resolution of generated 3D LUTs
+    lut_resolution_shaper : int, optional
+        The resolution of shaper used as part of some 3D LUTs
+    prefix : bool, optional
+        Whether or not colorspace names will use their Family names as prefixes
+        in the *OCIO* config
 
     Returns
     -------
-    type
-         Return value description.
+    None
     """
 
     odt_info_C = dict(odt_info)
@@ -1129,6 +1189,15 @@ def generate_baked_LUTs(odt_info,
         odt_prefix = odt_values['transformUserNamePrefix']
         odt_name = odt_values['transformUserName']
 
+        if odt_name in ['P3-D60 PQ (1000 nits)']:
+            odt_shaper = shaper_name.replace("48 nits", "1000 nits")
+        elif odt_name in ['P3-D60 PQ (2000 nits)']:
+            odt_shaper = shaper_name.replace("48 nits", "2000 nits")
+        elif odt_name in ['P3-D60 PQ (4000 nits)']:
+            odt_shaper = shaper_name.replace("48 nits", "4000 nits")
+        else:
+            odt_shaper = shaper_name
+
         # *Photoshop*
         for input_space in ['ACEScc', 'ACESproxy']:
             args = ['--iconfig', config_path,
@@ -1145,10 +1214,10 @@ def generate_baked_LUTs(odt_info,
                                               odt_name,
                                               input_space)]
             if prefix:
-                args += ['--shaperspace', 'Utility - %s' % shaper_name,
+                args += ['--shaperspace', 'Utility - %s' % odt_shaper,
                          '--shapersize', str(lut_resolution_shaper)]
             else:
-                args += ['--shaperspace', shaper_name,
+                args += ['--shaperspace', odt_shaper,
                          '--shapersize', str(lut_resolution_shaper)]
             args += ['--cubesize', str(lut_resolution_3d)]
             args += ['--format',
@@ -1176,10 +1245,10 @@ def generate_baked_LUTs(odt_info,
                      '%s - %s for %s data' % (
                          odt_prefix, odt_name, input_space)]
             if prefix:
-                args += ['--shaperspace', 'Utility - %s' % shaper_name,
+                args += ['--shaperspace', 'Utility - %s' % odt_shaper,
                          '--shapersize', str(lut_resolution_shaper)]
             else:
-                args += ['--shaperspace', shaper_name,
+                args += ['--shaperspace', odt_shaper,
                          '--shapersize', str(lut_resolution_shaper)]
             args += ['--cubesize', str(lut_resolution_3d)]
 
@@ -1219,9 +1288,9 @@ def generate_baked_LUTs(odt_info,
                      '%s - %s for %s data' % (
                          odt_prefix, odt_name, input_space)]
             if input_space == 'ACEScg':
-                lin_shaper_name = '%s - AP1' % shaper_name
+                lin_shaper_name = '%s - AP1' % odt_shaper
             else:
-                lin_shaper_name = shaper_name
+                lin_shaper_name = odt_shaper
             if prefix:
                 lin_shaper_name = 'Utility - %s' % lin_shaper_name
             args += ['--shaperspace', lin_shaper_name,
@@ -1256,17 +1325,20 @@ def generate_config_directory(config_directory,
                               bake_secondary_luts=False,
                               custom_lut_dir=None):
     """
-    Object description.
+    Create the directories needed for configuration generation
 
     Parameters
     ----------
-    parameter : type
-        Parameter description.
+    config_directory : str or unicode
+        The base config directory
+    bake_secondary_luts : bool, optional
+        Whether or not to create directories for baked LUTs
+    custom_lut_dir : bool, optional
+        Whether or not to create directories for custom Look LUTs
 
     Returns
     -------
-    type
-         Return value description.
+    None
     """
 
     lut_directory = os.path.join(config_directory, 'luts')
@@ -1298,19 +1370,44 @@ def generate_config(aces_ctl_directory,
                     look_info=None,
                     copy_custom_luts=True,
                     cleanup=True,
-                    prefix_colorspaces_with_family_names=True):
+                    prefix_colorspaces_with_family_names=True,
+                    shaper_base_name='Log2'):
     """
     Creates the ACES configuration.
 
     Parameters
     ----------
-    parameter : type
-        Parameter description.
+    aces_ctl_directory : str or unicode
+        The path to the aces 'transforms/ctl/utilities'
+    config_directory : str or unicode
+        The directory that will hold the generated configuration and LUTs
+    lut_resolution_1d : int, optional
+        The resolution of generated 1D LUTs
+    lut_resolution_3d : int, optional
+        The resolution of generated 3D LUTs
+    bake_secondary_luts : bool, optional
+        Whether or not to create directories for baked LUTs
+    multiple_displays : bool, optional
+        Whether to create a single display named *ACES* with Views for each
+        Output Transform or multiple displays, one for each Output Transform
+    look_info : array of str or unicode, optional
+        Paths and names for look data
+    copy_custom_luts : bool, optional
+        Whether to reference custom look LUTs directly or to copy them into a 
+        directory within the generated configuration
+    cleanup : bool, optional
+        Whether or not to clean up the intermediate images 
+    prefix_colorspaces_with_family_names : bool, optional
+        Whether or not colorspace names will use their Family names as prefixes
+        in the *OCIO* config
+    shaper_base_name : str or unicode
+        The name of the Shaper function to use when generating LUTs. 
+        Options: Log2, DolbyPQ
 
     Returns
     -------
-    type
-         Return value description.
+    bool
+         Success or failure of configuration generation process
     """
 
     if look_info is None:
@@ -1323,11 +1420,14 @@ def generate_config(aces_ctl_directory,
     lut_directory = generate_config_directory(config_directory,
                                               bake_secondary_luts,
                                               custom_lut_dir)
-
     odt_info = aces.get_ODTs_info(aces_ctl_directory)
     lmt_info = aces.get_LMTs_info(aces_ctl_directory)
 
-    shaper_name = 'Output Shaper'
+    if shaper_base_name == 'DolbyPQ':
+        shaper_name = 'Dolby PQ 48 nits Shaper'
+    else:
+        shaper_name = 'Log2 48 nits Shaper'
+
     config_data = create_config_data(odt_info,
                                      lmt_info,
                                      shaper_name,
@@ -1363,17 +1463,16 @@ def generate_config(aces_ctl_directory,
 
 def main():
     """
-    Object description.
+    A simple main that allows the user to exercise the various functions
+    defined in this file
 
     Parameters
     ----------
-    parameter : type
-        Parameter description.
+    None
 
     Returns
     -------
-    type
-         Return value description.
+    None
     """
 
     import optparse
@@ -1432,7 +1531,13 @@ def main():
               'ACEScc colorspace, but the user could choose other spaces '
               'by changing the argument after the name of the look. \n')
     usage += '\n'
-
+    usage += ('Create a GUI-friendly ACES 1.0 config using the Dolby PQ '
+              'transfer function as the shaper: \n')
+    usage += ('\tcreate_aces_config -a /path/to/aces-dev/transforms/ctl '
+              '--lutResolution1d 1024 --lutResolution3d 33 -c aces_1.0.0 '
+              '--shaper DolbyPQ')
+    usage += '\n'
     look_info = []
 
     def look_info_callback(option, opt_str, value, parser):
@@ -1473,6 +1578,8 @@ def main():
                  action='callback', callback=look_info_callback)
     p.add_option('--copyCustomLUTs', action='store_true', default=False)
 
+    p.add_option('--shaper', '-s', default='Log2')
+
     options, arguments = p.parse_args()
 
     aces_ctl_directory = options.acesCTLDir
@@ -1483,6 +1590,8 @@ def main():
     cleanup_temp_images = not options.keepTempImages
     multiple_displays = options.createMultipleDisplays
     copy_custom_luts = options.copyCustomLUTs
+    shaper_base_name = options.shaper
+    prefix = True
 
     print(look_info)
 
@@ -1506,7 +1615,9 @@ def main():
                            multiple_displays,
                            look_info,
                            copy_custom_luts,
-                           cleanup_temp_images)
+                           cleanup_temp_images,
+                           prefix,
+                           shaper_base_name)
 
 
 if __name__ == '__main__':