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