Simplify empty "print" statements.
[OpenColorIO-Configs.git] / aces_1.0.0 / python / aces_ocio / aces_config.py
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3
4 """
5 Defines objects creating the *ACES* configuration.
6 """
7
8 from __future__ import division
9
10 import copy
11 import os
12 import shutil
13 import sys
14
15 import PyOpenColorIO as ocio
16 from aces_ocio.colorspaces import aces
17 from aces_ocio.colorspaces import arri
18 from aces_ocio.colorspaces import canon
19 from aces_ocio.colorspaces import general
20 from aces_ocio.colorspaces import gopro
21 from aces_ocio.colorspaces import panasonic
22 from aces_ocio.colorspaces import red
23 from aces_ocio.colorspaces import sony
24 from aces_ocio.process import Process
25
26 from aces_ocio.utilities import (
27     ColorSpace,
28     colorspace_prefixed_name,
29     compact,
30     replace,
31     unpack_default)
32
33 __author__ = 'ACES Developers'
34 __copyright__ = 'Copyright (C) 2014 - 2015 - ACES Developers'
35 __license__ = ''
36 __maintainer__ = 'ACES Developers'
37 __email__ = 'aces@oscars.org'
38 __status__ = 'Production'
39
40 __all__ = ['ACES_OCIO_CTL_DIRECTORY_ENVIRON',
41            'ACES_OCIO_CONFIGURATION_DIRECTORY_ENVIRON',
42            'set_config_default_roles',
43            'write_config',
44            'generate_OCIO_transform',
45            'add_colorspace_alias',
46            'create_config',
47            'generate_LUTs',
48            'generate_baked_LUTs',
49            'create_config_dir',
50            'create_ACES_config',
51            'main']
52
53 ACES_OCIO_CTL_DIRECTORY_ENVIRON = 'ACES_OCIO_CTL_DIRECTORY'
54 ACES_OCIO_CONFIGURATION_DIRECTORY_ENVIRON = 'ACES_OCIO_CONFIGURATION_DIRECTORY'
55
56
57 def set_config_default_roles(config,
58                              color_picking='',
59                              color_timing='',
60                              compositing_log='',
61                              data='',
62                              default='',
63                              matte_paint='',
64                              reference='',
65                              scene_linear='',
66                              texture_paint='',
67                              rendering='',
68                              compositing_linear=''):
69     """
70     Sets given *OCIO* configuration default roles.
71
72     Parameters
73     ----------
74     config : config
75         *OCIO* configuration.
76     color_picking : str or unicode
77         Color picking role title.
78     color_timing : str or unicode
79         Color timing role title.
80     compositing_log : str or unicode
81         Compositing log role title.
82     data : str or unicode
83         Data role title.
84     default : str or unicode
85         Default role title.
86     matte_paint : str or unicode
87         Matte painting role title.
88     reference : str or unicode
89         Reference role title.
90     scene_linear : str or unicode
91         Scene linear role title.
92     texture_paint : str or unicode
93         Texture painting role title.
94
95     Returns
96     -------
97     bool
98          Definition success.
99     """
100
101     if color_picking:
102         config.setRole(ocio.Constants.ROLE_COLOR_PICKING, color_picking)
103     if color_timing:
104         config.setRole(ocio.Constants.ROLE_COLOR_TIMING, color_timing)
105     if compositing_log:
106         config.setRole(ocio.Constants.ROLE_COMPOSITING_LOG, compositing_log)
107     if data:
108         config.setRole(ocio.Constants.ROLE_DATA, data)
109     if default:
110         config.setRole(ocio.Constants.ROLE_DEFAULT, default)
111     if matte_paint:
112         config.setRole(ocio.Constants.ROLE_MATTE_PAINT, matte_paint)
113     if reference:
114         config.setRole(ocio.Constants.ROLE_REFERENCE, reference)
115     if texture_paint:
116         config.setRole(ocio.Constants.ROLE_TEXTURE_PAINT, texture_paint)
117
118     # 'rendering' and 'compositing_linear' roles default to the 'scene_linear'
119     # value if not set explicitly
120     if rendering:
121         config.setRole('rendering', rendering)
122     if compositing_linear:
123         config.setRole('compositing_linear', compositing_linear)
124     if scene_linear:
125         config.setRole(ocio.Constants.ROLE_SCENE_LINEAR, scene_linear)
126         if not rendering:
127             config.setRole('rendering', scene_linear)
128         if not compositing_linear:
129             config.setRole('compositing_linear', scene_linear)
130
131     return True
132
133
134 def write_config(config, config_path, sanity_check=True):
135     """
136     Writes the configuration to given path.
137
138     Parameters
139     ----------
140     parameter : type
141         Parameter description.
142
143     Returns
144     -------
145     type
146          Return value description.
147     """
148
149     if sanity_check:
150         try:
151             config.sanityCheck()
152         except Exception, e:
153             print e
154             print 'Configuration was not written due to a failed Sanity Check'
155             return
156
157     with open(config_path, mode='w') as fp:
158         fp.write(config.serialize())
159
160
161 def generate_OCIO_transform(transforms):
162     """
163     Object description.
164
165     Parameters
166     ----------
167     parameter : type
168         Parameter description.
169
170     Returns
171     -------
172     type
173          Return value description.
174     """
175
176     interpolation_options = {
177         'linear': ocio.Constants.INTERP_LINEAR,
178         'nearest': ocio.Constants.INTERP_NEAREST,
179         'tetrahedral': ocio.Constants.INTERP_TETRAHEDRAL}
180
181     direction_options = {
182         'forward': ocio.Constants.TRANSFORM_DIR_FORWARD,
183         'inverse': ocio.Constants.TRANSFORM_DIR_INVERSE}
184
185     ocio_transforms = []
186
187     for transform in transforms:
188
189         # lutFile transform
190         if transform['type'] == 'lutFile':
191             # Create transforms
192             ocio_transform = ocio.FileTransform()
193
194             if 'path' in transform:
195                 ocio_transform.setSrc(transform['path'])
196
197             if 'cccid' in transform:
198                 ocio_transform.setCCCId(transform['cccid'])
199
200             if 'interpolation' in transform:
201                 ocio_transform.setInterpolation(transform['interpolation'])
202             else:
203                 ocio_transform.setInterpolation(ocio.Constants.INTERP_BEST)
204
205             if 'direction' in transform:
206                 ocio_transform.setDirection(
207                     direction_options[transform['direction']])
208
209             ocio_transforms.append(ocio_transform)
210
211         # matrix transform
212         elif transform['type'] == 'matrix':
213             ocio_transform = ocio.MatrixTransform()
214             # MatrixTransform member variables can't be initialized directly.
215             # Each must be set individually.
216             ocio_transform.setMatrix(transform['matrix'])
217
218             if 'offset' in transform:
219                 ocio_transform.setOffset(transform['offset'])
220
221             if 'direction' in transform:
222                 ocio_transform.setDirection(
223                     direction_options[transform['direction']])
224
225             ocio_transforms.append(ocio_transform)
226
227         # exponent transform
228         elif transform['type'] == 'exponent':
229             ocio_transform = ocio.ExponentTransform()
230
231             if 'value' in transform:
232                 ocio_transform.setValue(transform['value'])
233
234             ocio_transforms.append(ocio_transform)
235
236         # log transform
237         elif transform['type'] == 'log':
238             ocio_transform = ocio.LogTransform()
239
240             if 'base' in transform:
241                 ocio_transform.setBase(transform['base'])
242
243             if 'direction' in transform:
244                 ocio_transform.setDirection(
245                     direction_options[transform['direction']])
246
247             ocio_transforms.append(ocio_transform)
248
249         # color space transform
250         elif transform['type'] == 'colorspace':
251             ocio_transform = ocio.ColorSpaceTransform()
252
253             if 'src' in transform:
254                 ocio_transform.setSrc(transform['src'])
255
256             if 'dst' in transform:
257                 ocio_transform.setDst(transform['dst'])
258
259             if 'direction' in transform:
260                 ocio_transform.setDirection(
261                     direction_options[transform['direction']])
262
263             ocio_transforms.append(ocio_transform)
264
265         # look transform
266         elif transform['type'] == 'look':
267             ocio_transform = ocio.LookTransform()
268             if 'look' in transform:
269                 ocio_transform.setLooks(transform['look'])
270
271             if 'src' in transform:
272                 ocio_transform.setSrc(transform['src'])
273
274             if 'dst' in transform:
275                 ocio_transform.setDst(transform['dst'])
276
277             if 'direction' in transform:
278                 ocio_transform.setDirection(
279                     direction_options[transform['direction']])
280
281             ocio_transforms.append(ocio_transform)
282
283         # unknown type
284         else:
285             print('Ignoring unknown transform type : %s' % transform['type'])
286
287     if len(ocio_transforms) > 1:
288         group_transform = ocio.GroupTransform()
289         for transform in ocio_transforms:
290             group_transform.push_back(transform)
291         transform = group_transform
292     else:
293         transform = ocio_transforms[0]
294
295     return transform
296
297
298 def add_colorspace_aliases(config,
299                            reference_colorspace,
300                            colorspace,
301                            colorspace_alias_names,
302                            family='Aliases'):
303     """
304     Object description.
305
306     Parameters
307     ----------
308     parameter : type
309         Parameter description.
310
311     Returns
312     -------
313     type
314          Return value description.
315     """
316
317     for alias_name in colorspace_alias_names:
318         if alias_name.lower() == colorspace.name.lower():
319             print(
320             'Skipping alias creation for %s, alias %s, because lower cased names match' % (
321                 colorspace.name, alias_name))
322             continue
323
324         print('Adding alias colorspace space %s, alias to %s' % (
325             alias_name, colorspace.name))
326
327         compact_family_name = family
328
329         description = colorspace.description
330         if colorspace.aces_transform_id:
331             description += '\n\nACES Transform ID : %s' % colorspace.aces_transform_id
332
333         ocio_colorspace_alias = ocio.ColorSpace(
334             name=alias_name,
335             bitDepth=colorspace.bit_depth,
336             description=description,
337             equalityGroup=colorspace.equality_group,
338             family=compact_family_name,
339             isData=colorspace.is_data,
340             allocation=colorspace.allocation_type,
341             allocationVars=colorspace.allocation_vars)
342
343         if colorspace.to_reference_transforms:
344             print('\tGenerating To-Reference transforms')
345             ocio_transform = generate_OCIO_transform(
346                 [{'type': 'colorspace',
347                   'src': colorspace.name,
348                   'dst': reference_colorspace.name,
349                   'direction': 'forward'}])
350             ocio_colorspace_alias.setTransform(
351                 ocio_transform,
352                 ocio.Constants.COLORSPACE_DIR_TO_REFERENCE)
353
354         if colorspace.from_reference_transforms:
355             print('\tGenerating From-Reference transforms')
356             ocio_transform = generate_OCIO_transform(
357                 [{'type': 'colorspace',
358                   'src': reference_colorspace.name,
359                   'dst': colorspace.name,
360                   'direction': 'forward'}])
361             ocio_colorspace_alias.setTransform(
362                 ocio_transform,
363                 ocio.Constants.COLORSPACE_DIR_FROM_REFERENCE)
364
365         config.addColorSpace(ocio_colorspace_alias)
366
367
368 def add_look(config,
369              look,
370              prefix,
371              custom_lut_dir,
372              reference_name,
373              config_data,
374              multiple_displays=False):
375     """
376     Object description.
377
378     Parameters
379     ----------
380     parameter : type
381         Parameter description.
382
383     Returns
384     -------
385     type
386          Return value description.
387     """
388
389     look_name, look_colorspace, look_lut, look_cccid = unpack_default(look, 4)
390
391     print('Adding look %s - %s' % (look_name, ', '.join(look)))
392
393     #
394     # Copy look lut
395     #
396     if custom_lut_dir:
397         if not '$' in look_lut:
398             print('Getting ready to copy look lut : %s' % look_lut)
399             shutil.copy2(look_lut, custom_lut_dir)
400             look_lut = os.path.split(look_lut)[1]
401         else:
402             print('Skipping LUT copy because path contains a context variable')
403
404     #
405     # Create OCIO Look
406     #
407     # Look 1
408     print('Adding look to config')
409     lk1 = ocio.Look()
410     lk1.setName(look_name)
411     lk1.setProcessSpace(look_colorspace)
412
413     keys = {'type': 'lutFile',
414             'path': look_lut,
415             'direction': 'forward'}
416     if look_cccid:
417         keys['cccid'] = look_cccid
418
419     ocio_transform = generate_OCIO_transform([keys])
420     lk1.setTransform(ocio_transform)
421
422     # add to config
423     config.addLook(lk1)
424
425     print('Creating aliased colorspace')
426
427     #
428     # Create OCIO colorspace that references that look
429     # - Needed for some implementations that don't process looks well
430     # - Also needed for some implementations that don't expose looks well
431     #
432     look_aliases = ['look_%s' % compact(look_name)]
433     colorspace = ColorSpace(look_name,
434                             aliases=look_aliases,
435                             description='The %s Look colorspace' % look_name,
436                             family='Look')
437
438     colorspace.from_reference_transforms = [{'type': 'look',
439                                              'look': look_name,
440                                              'src': reference_name,
441                                              'dst': reference_name,
442                                              'direction': 'forward'}]
443
444     print('Adding colorspace %s, alias to look %s to config data' % (
445         look_name, look_name))
446
447     # Add this colorspace into the main list of colorspaces
448     config_data['colorSpaces'].append(colorspace)
449
450     print()
451
452
453 def integrate_looks_into_views(config,
454                                looks,
455                                reference_name,
456                                config_data,
457                                multiple_displays=False):
458     """
459     Object description.
460
461     Parameters
462     ----------
463     parameter : type
464         Parameter description.
465
466     Returns
467     -------
468     type
469          Return value description.
470     """
471     look_names = [look[0] for look in looks]
472
473     # Option 1 - Add a 'look' to each Display
474     # - Assumes there is a Display for each ACES Output Transform
475     if multiple_displays:
476         for look_name in look_names:
477             config_data['looks'].append(look_name)
478
479     # Option 2
480     # - Copy each Output Transform colorspace
481     # - For each copy, add a LookTransform at the head of the from_reference
482     #     transform list
483     # - Add these new copied colorspaces for the Displays / Views 
484     else:
485         for display, view_list in config_data['displays'].iteritems():
486             output_colorspace_copy = None
487             look_names_string = ''
488             for view_name, output_colorspace in view_list.iteritems():
489                 if view_name == 'Output Transform':
490
491                     print('Adding new View that incorporates looks')
492
493                     # Make a copy of the output colorspace
494                     output_colorspace_copy = copy.deepcopy(output_colorspace)
495
496                     # for look_name in look_names:
497                     for i in range(len(look_names)):
498                         look_name = look_names[i]
499
500                         # Add the LookTransform to the head of the from_reference transform list
501                         if output_colorspace_copy.from_reference_transforms:
502                             output_colorspace_copy.from_reference_transforms.insert(
503                                 i, {'type': 'look',
504                                     'look': look_name,
505                                     'src': reference_name,
506                                     'dst': reference_name,
507                                     'direction': 'forward'})
508
509                         # Add the LookTransform to the end of the to_reference transform list
510                         if output_colorspace_copy.to_reference_transforms:
511                             inverse_look_name = look_names[
512                                 len(look_names) - 1 - i]
513
514                             output_colorspace_copy.to_reference_transforms.append(
515                                 {'type': 'look',
516                                  'look': inverse_look_name,
517                                  'src': reference_name,
518                                  'dst': reference_name,
519                                  'direction': 'inverse'})
520
521                         if not look_name in config_data['looks']:
522                             config_data['looks'].append(look_name)
523
524                     look_names_string = ', '.join(look_names)
525                     output_colorspace_copy.name = '%s with %s' % (
526                     output_colorspace.name, look_names_string)
527                     output_colorspace_copy.aliases = [
528                         'out_%s' % compact(output_colorspace_copy.name)]
529
530                     print(
531                     'Colorspace that incorporates looks created : %s' % output_colorspace_copy.name)
532
533                     config_data['colorSpaces'].append(output_colorspace_copy)
534
535             if output_colorspace_copy:
536                 print(
537                 'Adding colorspace that incorporates looks into view list')
538
539                 # Change the name of the View
540                 view_list[
541                     'Output Transform with %s' % look_names_string] = output_colorspace_copy
542                 config_data['displays'][display] = view_list
543
544                 # print( 'Display : %s, View List : %s' % (display, ', '.join(view_list)) )
545
546
547 def create_config(config_data,
548                   aliases=False,
549                   prefix=False,
550                   multiple_displays=False,
551                   look_info=[],
552                   custom_lut_dir=None):
553     """
554     Object description.
555
556     Parameters
557     ----------
558     parameter : type
559         Parameter description.
560
561     Returns
562     -------
563     type
564          Return value description.
565     """
566
567     prefixed_names = {}
568     alias_colorspaces = []
569
570     # Creating the *OCIO* configuration.
571     config = ocio.Config()
572
573     # Setting configuration description.
574     config.setDescription('An ACES config generated from python')
575
576     # Setting configuration search path.
577     searchPath = ['luts']
578     if custom_lut_dir:
579         searchPath.append('custom')
580     config.setSearchPath(':'.join(searchPath))
581
582     # Defining the reference colorspace.
583     reference_data = config_data['referenceColorSpace']
584
585     # Adding the color space Family into the name
586     # Helps with applications that present colorspaces as one long list
587     if prefix:
588         prefixed_name = colorspace_prefixed_name(reference_data)
589         prefixed_names[reference_data.name] = prefixed_name
590         reference_data.name = prefixed_name
591
592     print('Adding the reference color space : %s' % reference_data.name)
593
594     reference = ocio.ColorSpace(
595         name=reference_data.name,
596         bitDepth=reference_data.bit_depth,
597         description=reference_data.description,
598         equalityGroup=reference_data.equality_group,
599         family=reference_data.family,
600         isData=reference_data.is_data,
601         allocation=reference_data.allocation_type,
602         allocationVars=reference_data.allocation_vars)
603
604     config.addColorSpace(reference)
605
606     # Add alias
607     if aliases:
608         if reference_data.aliases != []:
609             # add_colorspace_alias(config, reference_data,
610             #                     reference_data, reference_data.aliases)
611             # defer adding alias colorspaces until end. Helps with some applications
612             alias_colorspaces.append(
613                 [reference_data, reference_data, reference_data.aliases])
614
615     print()
616
617     # print( 'color spaces : %s' % [x.name for x in sorted(config_data['colorSpaces'])])
618
619     #
620     # Add Looks and Look colorspaces
621     #
622     if look_info != []:
623         print('Adding looks')
624
625         config_data['looks'] = []
626
627         # Add looks and colorspaces
628         for look in look_info:
629             add_look(config,
630                      look,
631                      prefix,
632                      custom_lut_dir,
633                      reference_data.name,
634                      config_data)
635
636         # Integrate looks with displays, views
637         integrate_looks_into_views(config,
638                                    look_info,
639                                    reference_data.name,
640                                    config_data,
641                                    multiple_displays)
642
643         print()
644
645     print('Adding the regular color spaces')
646
647     # Creating the remaining colorspaces.
648     for colorspace in sorted(config_data['colorSpaces']):
649         # Adding the color space Family into the name
650         # Helps with applications that present colorspaces as one long list
651         if prefix:
652             prefixed_name = colorspace_prefixed_name(colorspace)
653             prefixed_names[colorspace.name] = prefixed_name
654             colorspace.name = prefixed_name
655
656         print('Creating new color space : %s' % colorspace.name)
657
658         description = colorspace.description
659         if colorspace.aces_transform_id:
660             description += '\n\nACES Transform ID : %s' % colorspace.aces_transform_id
661
662         ocio_colorspace = ocio.ColorSpace(
663             name=colorspace.name,
664             bitDepth=colorspace.bit_depth,
665             description=description,
666             equalityGroup=colorspace.equality_group,
667             family=colorspace.family,
668             isData=colorspace.is_data,
669             allocation=colorspace.allocation_type,
670             allocationVars=colorspace.allocation_vars)
671
672         if colorspace.to_reference_transforms:
673             print('\tGenerating To-Reference transforms')
674             ocio_transform = generate_OCIO_transform(
675                 colorspace.to_reference_transforms)
676             ocio_colorspace.setTransform(
677                 ocio_transform,
678                 ocio.Constants.COLORSPACE_DIR_TO_REFERENCE)
679
680         if colorspace.from_reference_transforms:
681             print('\tGenerating From-Reference transforms')
682             ocio_transform = generate_OCIO_transform(
683                 colorspace.from_reference_transforms)
684             ocio_colorspace.setTransform(
685                 ocio_transform,
686                 ocio.Constants.COLORSPACE_DIR_FROM_REFERENCE)
687
688         config.addColorSpace(ocio_colorspace)
689
690         #
691         # Add alias to normal colorspace, using compact name
692         #
693         if aliases:
694             if colorspace.aliases != []:
695                 # add_colorspace_alias(config, reference_data,
696                 #                     colorspace, colorspace.aliases)
697                 # defer adding alias colorspaces until end. Helps with some applications
698                 alias_colorspaces.append(
699                     [reference_data, colorspace, colorspace.aliases])
700
701         print()
702
703     print()
704
705     #
706     # We add roles early so we can create alias colorspaces with the names of the roles
707     # before the rest of the colorspace aliases are added to the config.
708     #
709     print('Setting the roles')
710
711     if prefix:
712         set_config_default_roles(
713             config,
714             color_picking=prefixed_names[
715                 config_data['roles']['color_picking']],
716             color_timing=prefixed_names[config_data['roles']['color_timing']],
717             compositing_log=prefixed_names[
718                 config_data['roles']['compositing_log']],
719             data=prefixed_names[config_data['roles']['data']],
720             default=prefixed_names[config_data['roles']['default']],
721             matte_paint=prefixed_names[config_data['roles']['matte_paint']],
722             reference=prefixed_names[config_data['roles']['reference']],
723             scene_linear=prefixed_names[config_data['roles']['scene_linear']],
724             texture_paint=prefixed_names[
725                 config_data['roles']['texture_paint']])
726
727         # Not allowed for the moment. role names can not overlap with colorspace names.
728         """
729         # Add the aliased colorspaces for each role
730         for role_name, role_colorspace_name in config_data['roles'].iteritems():
731             role_colorspace_prefixed_name = prefixed_names[role_colorspace_name]
732
733             print( 'Finding colorspace : %s' % role_colorspace_prefixed_name )
734             # Find the colorspace pointed to by the role
735             role_colorspaces = [colorspace for colorspace in config_data['colorSpaces'] if colorspace.name == role_colorspace_prefixed_name]
736             role_colorspace = None
737             if len(role_colorspaces) > 0:
738                 role_colorspace = role_colorspaces[0]
739             else:
740                 if reference_data.name == role_colorspace_prefixed_name:
741                     role_colorspace = reference_data
742
743             if role_colorspace:
744                 print( 'Adding an alias colorspace named %s, pointing to %s' % (
745                     role_name, role_colorspace.name))
746
747                 add_colorspace_aliases(config, reference_data, role_colorspace, [role_name], 'Roles')
748         """
749
750     else:
751         set_config_default_roles(
752             config,
753             color_picking=config_data['roles']['color_picking'],
754             color_timing=config_data['roles']['color_timing'],
755             compositing_log=config_data['roles']['compositing_log'],
756             data=config_data['roles']['data'],
757             default=config_data['roles']['default'],
758             matte_paint=config_data['roles']['matte_paint'],
759             reference=config_data['roles']['reference'],
760             scene_linear=config_data['roles']['scene_linear'],
761             texture_paint=config_data['roles']['texture_paint'])
762
763         # Not allowed for the moment. role names can not overlap with colorspace names.
764         """
765         # Add the aliased colorspaces for each role
766         for role_name, role_colorspace_name in config_data['roles'].iteritems():
767             # Find the colorspace pointed to by the role
768             role_colorspaces = [colorspace for colorspace in config_data['colorSpaces'] if colorspace.name == role_colorspace_name]
769             role_colorspace = None
770             if len(role_colorspaces) > 0:
771                 role_colorspace = role_colorspaces[0]
772             else:
773                 if reference_data.name == role_colorspace_name:
774                     role_colorspace = reference_data
775
776             if role_colorspace:
777                 print( 'Adding an alias colorspace named %s, pointing to %s' % (
778                     role_name, role_colorspace.name))
779
780                 add_colorspace_aliases(config, reference_data, role_colorspace, [role_name], 'Roles')
781         """
782
783     print()
784
785     # We add these at the end as some applications use the order of the colorspaces
786     # definitions in the config to order the colorspaces in their selection lists.
787     # Other go alphabetically. This should keep the alias colorspaces out of the way
788     # for the apps that use the order of definition in the config.
789     print('Adding the alias colorspaces')
790     for reference, colorspace, aliases in alias_colorspaces:
791         add_colorspace_aliases(config, reference, colorspace, aliases)
792
793     print()
794
795     print('Adding the diplays and views')
796
797     # Set the color_picking role to be the first Display's Output Transform View
798     default_display_name = config_data['defaultDisplay']
799     default_display_views = config_data['displays'][default_display_name]
800     default_display_colorspace = default_display_views['Output Transform']
801
802     set_config_default_roles(
803         config,
804         color_picking=default_display_colorspace.name)
805
806     # Defining the *views* and *displays*.
807     displays = []
808     views = []
809
810     # Defining a *generic* *display* and *view* setup.
811     if multiple_displays:
812         # Built list of looks to add to Displays
813         looks = config_data['looks'] if ('looks' in config_data) else []
814         looks = ', '.join(looks)
815         print('Creating multiple displays, with looks : %s' % looks)
816
817         # Note: We don't reorder the Displays to put the 'defaultDisplay' first
818         # because OCIO will order them alphabetically when the config is written to disk.
819
820         # Create Displays, Views
821         for display, view_list in config_data['displays'].iteritems():
822             for view_name, colorspace in view_list.iteritems():
823                 config.addDisplay(display, view_name, colorspace.name, looks)
824                 if 'Output Transform' in view_name and looks != '':
825                     # Add normal View, without looks
826                     config.addDisplay(display, view_name, colorspace.name)
827
828                     # Add View with looks
829                     view_name_with_looks = '%s with %s' % (view_name, looks)
830                     config.addDisplay(display, view_name_with_looks,
831                                       colorspace.name, looks)
832                 else:
833                     config.addDisplay(display, view_name, colorspace.name)
834                 if not (view_name in views):
835                     views.append(view_name)
836             displays.append(display)
837
838     # Defining the set of *views* and *displays* useful in a *GUI* context.
839     else:
840         single_display_name = 'ACES'
841         # single_display_name = config_data['roles']['scene_linear']
842         displays.append(single_display_name)
843
844         # Make sure the default display is first
845         display_names = sorted(config_data['displays'])
846         display_names.insert(0, display_names.pop(
847             display_names.index(default_display_name)))
848
849         # Built list of looks to add to Displays
850         looks = config_data['looks'] if ('looks' in config_data) else []
851         look_names = ', '.join(looks)
852
853         displays_views_colorspaces = []
854
855         # Create Displays, Views
856         for display in display_names:
857             view_list = config_data['displays'][display]
858             for view_name, colorspace in view_list.iteritems():
859                 if 'Output Transform' in view_name:
860                     # print( 'Adding view for %s' % colorspace.name )
861
862                     # We use the Display names as the View names in this case
863                     # as there is a single Display that contains all views.
864                     # This works for more applications than not, as of the time of this implementation.
865
866                     # Maya 2016 doesn't like parentheses in View names
867                     display_cleaned = replace(display, {')': '', '(': ''})
868
869                     # If View includes looks
870                     if 'with' in view_name:
871                         # Integrate looks into view name
872                         display_cleaned = '%s with %s' % (
873                         display_cleaned, look_names)
874
875                         viewsWithLooksAtEnd = False
876                         # Storing combo of display, view and colorspace name in a list so we can
877                         # add them to the end of the list
878                         if viewsWithLooksAtEnd:
879                             displays_views_colorspaces.append(
880                                 [single_display_name, display_cleaned,
881                                  colorspace.name])
882
883                         # Or add as normal
884                         else:
885                             config.addDisplay(single_display_name,
886                                               display_cleaned, colorspace.name)
887
888                             # Add to views list
889                             if not (display_cleaned in views):
890                                 views.append(display_cleaned)
891
892                     # A normal View
893                     else:
894                         config.addDisplay(single_display_name, display_cleaned,
895                                           colorspace.name)
896
897                         # Add to views list
898                         if not (display_cleaned in views):
899                             views.append(display_cleaned)
900
901         # Add to config any display, view combinations that were saved for later
902         # This list will be empty unless viewsWithLooksAtEnd is set to True above 
903         for display_view_colorspace in displays_views_colorspaces:
904             single_display_name, display_cleaned, colorspace_name = display_view_colorspace
905
906             # Add to config
907             config.addDisplay(single_display_name, display_cleaned,
908                               colorspace_name)
909
910             # Add to views list
911             if not (display_cleaned in views):
912                 views.append(display_cleaned)
913
914
915         # Works with Nuke Studio and Mari, but not Nuke
916         # single_display_name = 'Utility'
917         # displays.append(single_display_name)
918
919         raw_display_space_name = config_data['roles']['data']
920         log_display_space_name = config_data['roles']['compositing_log']
921
922         # Find the newly-prefixed colorspace names
923         if prefix:
924             # print( prefixed_names )
925             raw_display_space_name = prefixed_names[raw_display_space_name]
926             log_display_space_name = prefixed_names[log_display_space_name]
927
928         config.addDisplay(single_display_name, 'Raw', raw_display_space_name)
929         views.append('Raw')
930         config.addDisplay(single_display_name, 'Log', log_display_space_name)
931         views.append('Log')
932
933     # Setting the active *displays* and *views*.
934     config.setActiveDisplays(','.join(sorted(displays)))
935     config.setActiveViews(','.join(views))
936
937     print()
938
939     # Make sure we didn't create a bad config
940     config.sanityCheck()
941
942     # Reset the colorspace names back to their non-prefixed versions
943     if prefix:
944         # Build the reverse lookup
945         prefixed_names_inverse = {}
946         for original, prefixed in prefixed_names.iteritems():
947             prefixed_names_inverse[prefixed] = original
948
949         # Reset the reference colorspace name
950         reference_data.name = prefixed_names_inverse[reference_data.name]
951
952         # Reset the rest of the colorspace names
953         try:
954             for colorspace in config_data['colorSpaces']:
955                 colorspace.name = prefixed_names_inverse[colorspace.name]
956         except:
957             print('Prefixed names')
958             for original, prefixed in prefixed_names.iteritems():
959                 print('%s, %s' % (original, prefixed))
960
961             print('\n')
962
963             print('Inverse Lookup of Prefixed names')
964             for prefixed, original in prefixed_names_inverse.iteritems():
965                 print('%s, %s' % (prefixed, original))
966             raise
967
968     return config
969
970
971 def generate_LUTs(odt_info,
972                   lmt_info,
973                   shaper_name,
974                   aces_ctl_directory,
975                   lut_directory,
976                   lut_resolution_1d=4096,
977                   lut_resolution_3d=64,
978                   cleanup=True):
979     """
980     Object description.
981
982     Parameters
983     ----------
984     parameter : type
985         Parameter description.
986
987     Returns
988     -------
989     dict
990          Colorspaces and transforms converting between those colorspaces and
991          the reference colorspace, *ACES*.
992     """
993
994     print('generateLUTs - begin')
995     config_data = {}
996
997     # Initialize a few variables
998     config_data['displays'] = {}
999     config_data['colorSpaces'] = []
1000
1001     # -------------------------------------------------------------------------
1002     # *ACES Color Spaces*
1003     # -------------------------------------------------------------------------
1004
1005     # *ACES* colorspaces
1006     (aces_reference,
1007      aces_colorspaces,
1008      aces_displays,
1009      aces_log_display_space,
1010      aces_roles,
1011      aces_default_display) = aces.create_colorspaces(aces_ctl_directory,
1012                                                      lut_directory,
1013                                                      lut_resolution_1d,
1014                                                      lut_resolution_3d,
1015                                                      lmt_info,
1016                                                      odt_info,
1017                                                      shaper_name,
1018                                                      cleanup)
1019
1020     config_data['referenceColorSpace'] = aces_reference
1021     config_data['roles'] = aces_roles
1022
1023     for cs in aces_colorspaces:
1024         config_data['colorSpaces'].append(cs)
1025
1026     for name, data in aces_displays.iteritems():
1027         config_data['displays'][name] = data
1028
1029     config_data['defaultDisplay'] = aces_default_display
1030     config_data['linearDisplaySpace'] = aces_reference
1031     config_data['logDisplaySpace'] = aces_log_display_space
1032
1033     # -------------------------------------------------------------------------
1034     # *Camera Input Transforms*
1035     # -------------------------------------------------------------------------
1036
1037     # *ARRI Log-C* to *ACES*.
1038     arri_colorSpaces = arri.create_colorspaces(lut_directory,
1039                                                lut_resolution_1d)
1040     for cs in arri_colorSpaces:
1041         config_data['colorSpaces'].append(cs)
1042
1043     # *Canon-Log* to *ACES*.
1044     canon_colorspaces = canon.create_colorspaces(lut_directory,
1045                                                  lut_resolution_1d)
1046     for cs in canon_colorspaces:
1047         config_data['colorSpaces'].append(cs)
1048
1049     # *GoPro Protune* to *ACES*.
1050     gopro_colorspaces = gopro.create_colorspaces(lut_directory,
1051                                                  lut_resolution_1d)
1052     for cs in gopro_colorspaces:
1053         config_data['colorSpaces'].append(cs)
1054
1055     # *Panasonic V-Log* to *ACES*.
1056     panasonic_colorSpaces = panasonic.create_colorspaces(lut_directory,
1057                                                          lut_resolution_1d)
1058     for cs in panasonic_colorSpaces:
1059         config_data['colorSpaces'].append(cs)
1060
1061     # *RED* colorspaces to *ACES*.
1062     red_colorspaces = red.create_colorspaces(lut_directory,
1063                                              lut_resolution_1d)
1064     for cs in red_colorspaces:
1065         config_data['colorSpaces'].append(cs)
1066
1067     # *S-Log* to *ACES*.
1068     sony_colorSpaces = sony.create_colorspaces(lut_directory,
1069                                                lut_resolution_1d)
1070     for cs in sony_colorSpaces:
1071         config_data['colorSpaces'].append(cs)
1072
1073     # -------------------------------------------------------------------------
1074     # General Color Spaces
1075     # -------------------------------------------------------------------------
1076     general_colorSpaces = general.create_colorspaces(lut_directory,
1077                                                      lut_resolution_1d,
1078                                                      lut_resolution_3d)
1079     for cs in general_colorSpaces:
1080         config_data['colorSpaces'].append(cs)
1081
1082     # The *Raw* color space
1083     raw = general.create_raw()
1084     config_data['colorSpaces'].append(raw)
1085
1086     # Override certain roles, for now
1087     config_data['roles']['data'] = raw.name
1088     config_data['roles']['reference'] = raw.name
1089     config_data['roles']['texture_paint'] = raw.name
1090
1091     print('generateLUTs - end')
1092     return config_data
1093
1094
1095 def generate_baked_LUTs(odt_info,
1096                         shaper_name,
1097                         baked_directory,
1098                         config_path,
1099                         lut_resolution_1d,
1100                         lut_resolution_3d,
1101                         lut_resolution_shaper=1024,
1102                         prefix=False):
1103     """
1104     Object description.
1105
1106     Parameters
1107     ----------
1108     parameter : type
1109         Parameter description.
1110
1111     Returns
1112     -------
1113     type
1114          Return value description.
1115     """
1116
1117     odt_info_C = dict(odt_info)
1118
1119     # Uncomment if you would like to support the older behavior where ODTs
1120     # that have support for full and legal range output generate a LUT for each.
1121     """
1122     # Create two entries for ODTs that have full and legal range support
1123     for odt_ctl_name, odt_values in odt_info.iteritems():
1124         if odt_values['transformHasFullLegalSwitch']:
1125             odt_name = odt_values['transformUserName']
1126
1127             odt_values_legal = dict(odt_values)
1128             odt_values_legal['transformUserName'] = '%s - Legal' % odt_name
1129             odt_info_C['%s - Legal' % odt_ctl_name] = odt_values_legal
1130
1131             odt_values_full = dict(odt_values)
1132             odt_values_full['transformUserName'] = '%s - Full' % odt_name
1133             odt_info_C['%s - Full' % odt_ctl_name] = odt_values_full
1134
1135             del (odt_info_C[odt_ctl_name])
1136     """
1137
1138     # Generate appropriate LUTs for each ODT
1139     for odt_ctl_name, odt_values in odt_info_C.iteritems():
1140         odt_prefix = odt_values['transformUserNamePrefix']
1141         odt_name = odt_values['transformUserName']
1142
1143         # *Photoshop*
1144         for input_space in ['ACEScc', 'ACESproxy']:
1145             args = ['--iconfig', config_path,
1146                     '-v']
1147             if prefix:
1148                 args += ['--inputspace', 'ACES - %s' % input_space]
1149                 args += ['--outputspace', 'Output - %s' % odt_name]
1150             else:
1151                 args += ['--inputspace', input_space]
1152                 args += ['--outputspace', odt_name]
1153
1154             args += ['--description',
1155                      '%s - %s for %s data' % (odt_prefix,
1156                                               odt_name,
1157                                               input_space)]
1158             if prefix:
1159                 args += ['--shaperspace', 'Utility - %s' % shaper_name,
1160                          '--shapersize', str(lut_resolution_shaper)]
1161             else:
1162                 args += ['--shaperspace', shaper_name,
1163                          '--shapersize', str(lut_resolution_shaper)]
1164             args += ['--cubesize', str(lut_resolution_3d)]
1165             args += ['--format',
1166                      'icc',
1167                      os.path.join(baked_directory,
1168                                   'photoshop',
1169                                   '%s for %s.icc' % (odt_name, input_space))]
1170
1171             bake_lut = Process(description='bake a LUT',
1172                                cmd='ociobakelut',
1173                                args=args)
1174             bake_lut.execute()
1175
1176         # *Flame*, *Lustre*
1177         for input_space in ['ACEScc', 'ACESproxy']:
1178             args = ['--iconfig', config_path,
1179                     '-v']
1180             if prefix:
1181                 args += ['--inputspace', 'ACES - %s' % input_space]
1182                 args += ['--outputspace', 'Output - %s' % odt_name]
1183             else:
1184                 args += ['--inputspace', input_space]
1185                 args += ['--outputspace', odt_name]
1186             args += ['--description',
1187                      '%s - %s for %s data' % (
1188                          odt_prefix, odt_name, input_space)]
1189             if prefix:
1190                 args += ['--shaperspace', 'Utility - %s' % shaper_name,
1191                          '--shapersize', str(lut_resolution_shaper)]
1192             else:
1193                 args += ['--shaperspace', shaper_name,
1194                          '--shapersize', str(lut_resolution_shaper)]
1195             args += ['--cubesize', str(lut_resolution_3d)]
1196
1197             fargs = ['--format',
1198                      'flame',
1199                      os.path.join(
1200                          baked_directory,
1201                          'flame',
1202                          '%s for %s Flame.3dl' % (odt_name, input_space))]
1203             bake_lut = Process(description='bake a LUT',
1204                                cmd='ociobakelut',
1205                                args=(args + fargs))
1206             bake_lut.execute()
1207
1208             largs = ['--format',
1209                      'lustre',
1210                      os.path.join(
1211                          baked_directory,
1212                          'lustre',
1213                          '%s for %s Lustre.3dl' % (odt_name, input_space))]
1214             bake_lut = Process(description='bake a LUT',
1215                                cmd='ociobakelut',
1216                                args=(args + largs))
1217             bake_lut.execute()
1218
1219         # *Maya*, *Houdini*
1220         for input_space in ['ACEScg', 'ACES2065-1']:
1221             args = ['--iconfig', config_path,
1222                     '-v']
1223             if prefix:
1224                 args += ['--inputspace', 'ACES - %s' % input_space]
1225                 args += ['--outputspace', 'Output - %s' % odt_name]
1226             else:
1227                 args += ['--inputspace', input_space]
1228                 args += ['--outputspace', odt_name]
1229             args += ['--description',
1230                      '%s - %s for %s data' % (
1231                          odt_prefix, odt_name, input_space)]
1232             if input_space == 'ACEScg':
1233                 lin_shaper_name = '%s - AP1' % shaper_name
1234             else:
1235                 lin_shaper_name = shaper_name
1236             if prefix:
1237                 lin_shaper_name = 'Utility - %s' % lin_shaper_name
1238             args += ['--shaperspace', lin_shaper_name,
1239                      '--shapersize', str(lut_resolution_shaper)]
1240
1241             args += ['--cubesize', str(lut_resolution_3d)]
1242
1243             margs = ['--format',
1244                      'cinespace',
1245                      os.path.join(
1246                          baked_directory,
1247                          'maya',
1248                          '%s for %s Maya.csp' % (odt_name, input_space))]
1249             bake_lut = Process(description='bake a LUT',
1250                                cmd='ociobakelut',
1251                                args=(args + margs))
1252             bake_lut.execute()
1253
1254             hargs = ['--format',
1255                      'houdini',
1256                      os.path.join(
1257                          baked_directory,
1258                          'houdini',
1259                          '%s for %s Houdini.lut' % (odt_name, input_space))]
1260             bake_lut = Process(description='bake a LUT',
1261                                cmd='ociobakelut',
1262                                args=(args + hargs))
1263             bake_lut.execute()
1264
1265
1266 def create_config_dir(config_directory,
1267                       bake_secondary_LUTs=False,
1268                       custom_lut_dir=None):
1269     """
1270     Object description.
1271
1272     Parameters
1273     ----------
1274     parameter : type
1275         Parameter description.
1276
1277     Returns
1278     -------
1279     type
1280          Return value description.
1281     """
1282
1283     lut_directory = os.path.join(config_directory, 'luts')
1284     dirs = [config_directory, lut_directory]
1285
1286     if bake_secondary_LUTs:
1287         dirs.extend([os.path.join(config_directory, 'baked'),
1288                      os.path.join(config_directory, 'baked', 'flame'),
1289                      os.path.join(config_directory, 'baked', 'photoshop'),
1290                      os.path.join(config_directory, 'baked', 'houdini'),
1291                      os.path.join(config_directory, 'baked', 'lustre'),
1292                      os.path.join(config_directory, 'baked', 'maya')])
1293
1294     if custom_lut_dir:
1295         dirs.append(os.path.join(config_directory, 'custom'))
1296
1297     for d in dirs:
1298         not os.path.exists(d) and os.mkdir(d)
1299
1300     return lut_directory
1301
1302
1303 def create_ACES_config(aces_ctl_directory,
1304                        config_directory,
1305                        lut_resolution_1d=4096,
1306                        lut_resolution_3d=64,
1307                        bake_secondary_LUTs=True,
1308                        multiple_displays=False,
1309                        look_info=[],
1310                        copy_custom_luts=True,
1311                        cleanup=True,
1312                        prefix_colorspaces_with_family_names=True):
1313     """
1314     Creates the ACES configuration.
1315
1316     Parameters
1317     ----------
1318     parameter : type
1319         Parameter description.
1320
1321     Returns
1322     -------
1323     type
1324          Return value description.
1325     """
1326
1327     # Directory for custom LUTs
1328     custom_lut_dir = None
1329     if copy_custom_luts:
1330         custom_lut_dir = os.path.join(config_directory, 'custom')
1331
1332     lut_directory = create_config_dir(config_directory,
1333                                       bake_secondary_LUTs,
1334                                       custom_lut_dir)
1335
1336     odt_info = aces.get_ODTs_info(aces_ctl_directory)
1337     lmt_info = aces.get_LMTs_info(aces_ctl_directory)
1338
1339     shaper_name = 'Output Shaper'
1340     config_data = generate_LUTs(odt_info,
1341                                 lmt_info,
1342                                 shaper_name,
1343                                 aces_ctl_directory,
1344                                 lut_directory,
1345                                 lut_resolution_1d,
1346                                 lut_resolution_3d,
1347                                 cleanup)
1348
1349     print('Creating config - with prefixes, with aliases')
1350     config = create_config(config_data,
1351                            prefix=prefix_colorspaces_with_family_names,
1352                            aliases=True,
1353                            multiple_displays=multiple_displays,
1354                            look_info=look_info,
1355                            custom_lut_dir=custom_lut_dir)
1356     print('\n\n\n')
1357
1358     write_config(config,
1359                  os.path.join(config_directory, 'config.ocio'))
1360
1361     if bake_secondary_LUTs:
1362         generate_baked_LUTs(odt_info,
1363                             shaper_name,
1364                             os.path.join(config_directory, 'baked'),
1365                             os.path.join(config_directory, 'config.ocio'),
1366                             lut_resolution_1d,
1367                             lut_resolution_3d,
1368                             lut_resolution_1d,
1369                             prefix=prefix_colorspaces_with_family_names)
1370
1371     return True
1372
1373
1374 def main():
1375     """
1376     Object description.
1377
1378     Parameters
1379     ----------
1380     parameter : type
1381         Parameter description.
1382
1383     Returns
1384     -------
1385     type
1386          Return value description.
1387     """
1388
1389     import optparse
1390
1391     usage = '%prog [options]\n'
1392     usage += '\n'
1393     usage += 'An OCIO config generation script for ACES 1.0\n'
1394     usage += '\n'
1395     usage += 'Command line examples'
1396     usage += '\n'
1397     usage += 'Create a GUI-friendly ACES 1.0 config with no secondary, baked LUTs : \n'
1398     usage += '\tcreate_aces_config -a /path/to/aces-dev/transforms/ctl --lutResolution1d 1024 --lutResolution3d 33 -c aces_1.0.0 --dontBakeSecondaryLUTs'
1399     usage += '\n'
1400     usage += 'Create a more OCIO-compliant ACES 1.0 config : \n'
1401     usage += '\tcreate_aces_config -a /path/to/aces-dev/transforms/ctl --lutResolution1d 1024 --lutResolution3d 33 -c aces_1.0.0 --createMultipleDisplays'
1402     usage += '\n'
1403     usage += '\n'
1404     usage += 'Adding custom looks'
1405     usage += '\n'
1406     usage += 'Create a GUI-friendly ACES 1.0 config with an ACES-style CDL (will be applied in the ACEScc colorspace): \n'
1407     usage += '\tcreate_aces_config -a /path/to/aces-dev/transforms/ctl --lutResolution1d 1024 --lutResolution3d 33 -c aces_1.0.0 \n\t\t--addACESLookCDL ACESCDLName /path/to/SampleCDL.ccc cc03345'
1408     usage += '\n'
1409     usage += 'Create a GUI-friendly ACES 1.0 config with an general CDL: \n'
1410     usage += '\tcreate_aces_config -a /path/to/aces-dev/transforms/ctl --lutResolution1d 1024 --lutResolution3d 33 -c aces_1.0.0 \n\t\t--addCustomLookCDL CustomCDLName "ACES - ACEScc" /path/to/SampleCDL.ccc cc03345'
1411     usage += '\n'
1412     usage += '\tIn this example, the CDL will be applied in the ACEScc colorspace, but the user could choose other spaces by changing the argument after the name of the look. \n'
1413     usage += '\n'
1414     usage += 'Create a GUI-friendly ACES 1.0 config with an ACES-style LUT (will be applied in the ACEScc colorspace): \n'
1415     usage += '\tcreate_aces_config -a /path/to/aces-dev/transforms/ctl --lutResolution1d 1024 --lutResolution3d 33 -c aces_1.0.0 \n\t\t--addACESLookLUT ACESLUTName /path/to/SampleCDL.ccc cc03345'
1416     usage += '\n'
1417     usage += 'Create a GUI-friendly ACES 1.0 config with an general LUT: \n'
1418     usage += '\tcreate_aces_config -a /path/to/aces-dev/transforms/ctl --lutResolution1d 1024 --lutResolution3d 33 -c aces_1.0.0 \n\t\t--addCustomLookLUT CustomLUTName "ACES - ACEScc" /path/to/SampleCDL.ccc cc03345'
1419     usage += '\n'
1420     usage += '\tIn this example, the LUT will be applied in the ACEScc colorspace, but the user could choose other spaces by changing the argument after the name of the look. \n'
1421     usage += '\n'
1422
1423     look_info = []
1424
1425     def look_info_callback(option, opt_str, value, parser):
1426         print('look_info_callback')
1427         print(option, opt_str, value, parser)
1428         if opt_str == '--addCustomLookCDL':
1429             look_info.append(value)
1430         elif opt_str == '--addCustomLookLUT':
1431             look_info.append(value)
1432         elif opt_str == '--addACESLookCDL':
1433             look_info.append([value[0], 'ACES - ACEScc', value[1], value[2]])
1434         elif opt_str == '--addACESLookLUT':
1435             look_info.append([value[0], 'ACES - ACEScc', value[1]])
1436
1437     p = optparse.OptionParser(description='',
1438                               prog='create_aces_config',
1439                               version='create_aces_config 1.0',
1440                               usage=usage)
1441     p.add_option('--acesCTLDir', '-a', default=os.environ.get(
1442         ACES_OCIO_CTL_DIRECTORY_ENVIRON, None))
1443     p.add_option('--configDir', '-c', default=os.environ.get(
1444         ACES_OCIO_CONFIGURATION_DIRECTORY_ENVIRON, None))
1445     p.add_option('--lutResolution1d', default=4096)
1446     p.add_option('--lutResolution3d', default=64)
1447     p.add_option('--dontBakeSecondaryLUTs', action='store_true', default=False)
1448     p.add_option('--keepTempImages', action='store_true', default=False)
1449
1450     p.add_option('--createMultipleDisplays', action='store_true',
1451                  default=False)
1452
1453     p.add_option('--addCustomLookLUT', '', type='string', nargs=3,
1454                  action='callback', callback=look_info_callback)
1455     p.add_option('--addCustomLookCDL', '', type='string', nargs=4,
1456                  action='callback', callback=look_info_callback)
1457     p.add_option('--addACESLookLUT', '', type='string', nargs=2,
1458                  action='callback', callback=look_info_callback)
1459     p.add_option('--addACESLookCDL', '', type='string', nargs=3,
1460                  action='callback', callback=look_info_callback)
1461     p.add_option('--copyCustomLUTs', action='store_true', default=False)
1462
1463     options, arguments = p.parse_args()
1464
1465     aces_ctl_directory = options.acesCTLDir
1466     config_directory = options.configDir
1467     lut_resolution_1d = int(options.lutResolution1d)
1468     lut_resolution_3d = int(options.lutResolution3d)
1469     bake_secondary_luts = not options.dontBakeSecondaryLUTs
1470     cleanup_temp_images = not options.keepTempImages
1471     multiple_displays = options.createMultipleDisplays
1472     copy_custom_luts = options.copyCustomLUTs
1473
1474     print(look_info)
1475
1476     # TODO: Investigate the following statements.
1477     try:
1478         args_start = sys.argv.index('--') + 1
1479         args = sys.argv[args_start:]
1480     except:
1481         args_start = len(sys.argv) + 1
1482         args = []
1483
1484     print('command line : \n%s\n' % ' '.join(sys.argv))
1485
1486     assert aces_ctl_directory is not None, (
1487         'process: No "{0}" environment variable defined or no "ACES CTL" '
1488         'directory specified'.format(
1489             ACES_OCIO_CTL_DIRECTORY_ENVIRON))
1490
1491     assert config_directory is not None, (
1492         'process: No "{0}" environment variable defined or no configuration '
1493         'directory specified'.format(
1494             ACES_OCIO_CONFIGURATION_DIRECTORY_ENVIRON))
1495
1496     return create_ACES_config(aces_ctl_directory,
1497                               config_directory,
1498                               lut_resolution_1d,
1499                               lut_resolution_3d,
1500                               bake_secondary_luts,
1501                               multiple_displays,
1502                               look_info,
1503                               copy_custom_luts,
1504                               cleanup_temp_images)
1505
1506
1507 if __name__ == '__main__':
1508     main()