Roles now have some assignments
[OpenColorIO-Configs.git] / aces_1.0.0 / python / aces_ocio / create_aces_colorspaces.py
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3
4 """
5 Implements support for *ACES* colorspaces conversions and transfer functions.
6 """
7
8 from __future__ import division
9
10 import math
11 import numpy
12 import os
13 import pprint
14 import string
15 import shutil
16
17 import PyOpenColorIO as ocio
18
19 from aces_ocio.generate_lut import (
20     generate_1d_LUT_from_CTL,
21     generate_3d_LUT_from_CTL,
22     write_SPI_1d)
23 from aces_ocio.utilities import (
24     ColorSpace,
25     mat44_from_mat33,
26     sanitize,
27     compact)
28
29
30 __author__ = 'ACES Developers'
31 __copyright__ = 'Copyright (C) 2014 - 2015 - ACES Developers'
32 __license__ = ''
33 __maintainer__ = 'ACES Developers'
34 __email__ = 'aces@oscars.org'
35 __status__ = 'Production'
36
37 __all__ = ['ACES_AP1_TO_AP0',
38            'ACES_AP0_TO_XYZ',
39            'create_ACES',
40            'create_ACEScc',
41            'create_ACESproxy',
42            'create_ACEScg',
43            'create_ADX',
44            'create_ACES_LMT',
45            'create_ACES_RRT_plus_ODT',
46            'create_generic_log',
47            'create_LMTs',
48            'create_ODTs',
49            'get_transform_info',
50            'get_ODTs_info',
51            'get_LMTs_info',
52            'create_colorspaces']
53
54 # Matrix converting *ACES AP1* primaries to *ACES AP0*.
55 ACES_AP1_TO_AP0 = [0.6954522414, 0.1406786965, 0.1638690622,
56                    0.0447945634, 0.8596711185, 0.0955343182,
57                    -0.0055258826, 0.0040252103, 1.0015006723]
58
59 # Matrix converting *ACES AP0* primaries to *ACES AP1*.
60 ACES_AP0_TO_AP1 = [1.4514393161, -0.2365107469, -0.2149285693,
61                    -0.0765537734, 1.1762296998, -0.0996759264,
62                    0.0083161484, -0.0060324498, 0.9977163014]
63
64 # Matrix converting *ACES AP0* primaries to *XYZ*.
65 ACES_AP0_TO_XYZ = [0.9525523959, 0.0000000000, 0.0000936786,
66                    0.3439664498, 0.7281660966, -0.0721325464,
67                    0.0000000000, 0.0000000000, 1.0088251844]
68
69 # Matrix converting *ACES AP0* primaries to *XYZ*.
70 ACES_XYZ_TO_AP0 = [1.0498110175, 0.0000000000, -0.0000974845,
71                    -0.4959030231, 1.3733130458, 0.0982400361,
72                    0.0000000000, 0.0000000000, 0.9912520182]
73
74
75 def create_ACES():
76     """
77     Object description.
78
79     Parameters
80     ----------
81     parameter : type
82         Parameter description.
83
84     Returns
85     -------
86     type
87          Return value description.
88     """
89
90     # Defining the reference colorspace.
91     aces2065_1 = ColorSpace('ACES2065-1')
92     aces2065_1.description = (
93         'The Academy Color Encoding System reference color space')
94     aces2065_1.equality_group = ''
95     aces2065_1.aliases = ["lin_ap0", "aces"]
96     aces2065_1.family = 'ACES'
97     aces2065_1.is_data = False
98     aces2065_1.allocation_type = ocio.Constants.ALLOCATION_LG2
99     aces2065_1.allocation_vars = [-8, 5, 0.00390625]
100
101     return aces2065_1
102
103
104 def create_ACEScc(aces_ctl_directory,
105                   lut_directory,
106                   lut_resolution_1d,
107                   cleanup,
108                   name='ACEScc',
109                   min_value=0,
110                   max_value=1,
111                   input_scale=1):
112     """
113     Creates the *ACEScc* colorspace.
114
115     Parameters
116     ----------
117     parameter : type
118         Parameter description.
119
120     Returns
121     -------
122     Colorspace
123          *ACEScc* colorspace.
124     """
125
126     cs = ColorSpace(name)
127     cs.description = 'The %s color space' % name
128     cs.aliases = ["acescc_ap1"]
129     cs.equality_group = ''
130     cs.family = 'ACES'
131     cs.is_data = False
132     cs.allocation_type = ocio.Constants.ALLOCATION_UNIFORM
133     cs.allocation_vars = [min_value, max_value]
134
135     ctls = [os.path.join(aces_ctl_directory,
136                          'ACEScc',
137                          'ACEScsc.ACEScc_to_ACES.a1.0.0.ctl')]
138     lut = '%s_to_linear.spi1d' % name
139
140     lut = sanitize(lut)
141
142     generate_1d_LUT_from_CTL(
143         os.path.join(lut_directory, lut),
144         ctls,
145         lut_resolution_1d,
146         'float',
147         input_scale,
148         1,
149         {'transferFunctionOnly':1},
150         cleanup,
151         aces_ctl_directory,
152         min_value,
153         max_value,
154         1)
155
156     cs.to_reference_transforms = []
157     cs.to_reference_transforms.append({
158         'type': 'lutFile',
159         'path': lut,
160         'interpolation': 'linear',
161         'direction': 'forward'})
162
163     # *AP1* primaries to *AP0* primaries.
164     cs.to_reference_transforms.append({
165         'type': 'matrix',
166         'matrix': mat44_from_mat33(ACES_AP1_TO_AP0),
167         'direction': 'forward'})
168
169     cs.from_reference_transforms = []
170     return cs
171
172
173 def create_ACESproxy(aces_ctl_directory,
174                      lut_directory,
175                      lut_resolution_1d,
176                      cleanup,
177                      name='ACESproxy'):
178     """
179     Creates the *ACESproxy* colorspace.
180
181     Parameters
182     ----------
183     parameter : type
184         Parameter description.
185
186     Returns
187     -------
188     Colorspace
189          *ACESproxy* colorspace.
190     """
191
192     cs = ColorSpace(name)
193     cs.description = 'The %s color space' % name
194     cs.aliases = ["acesproxy_ap1"]
195     cs.equality_group = ''
196     cs.family = 'ACES'
197     cs.is_data = False
198
199     ctls = [os.path.join(aces_ctl_directory,
200                          'ACESproxy',
201                          'ACEScsc.ACESproxy10i_to_ACES.a1.0.0.ctl'),
202                           # This transform gets back to the *AP1* primaries.
203                           # Useful as the 1d LUT is only covering the transfer function.
204                           # The primaries switch is covered by the matrix below:
205                           os.path.join(aces_ctl_directory,
206                                        'ACEScg',
207                                        'ACEScsc.ACES_to_ACEScg.a1.0.0.ctl')]
208     lut = '%s_to_linear.spi1d' % name
209
210     lut = sanitize(lut)
211
212     generate_1d_LUT_from_CTL(
213         os.path.join(lut_directory, lut),
214         ctls,
215         lut_resolution_1d,
216         'uint16',
217         64,
218         1,
219         {},
220         cleanup,
221         aces_ctl_directory,
222         0,
223         1,
224         1)
225
226     cs.to_reference_transforms = []
227     cs.to_reference_transforms.append({
228         'type': 'lutFile',
229         'path': lut,
230         'interpolation': 'linear',
231         'direction': 'forward'})
232
233     # *AP1* primaries to *AP0* primaries.
234     cs.to_reference_transforms.append({
235         'type': 'matrix',
236         'matrix': mat44_from_mat33(ACES_AP1_TO_AP0),
237         'direction': 'forward'})
238
239     cs.from_reference_transforms = []
240     return cs
241
242
243 # -------------------------------------------------------------------------
244 # *ACEScg*
245 # -------------------------------------------------------------------------
246 def create_ACEScg(aces_ctl_directory,
247                   lut_directory,
248                   lut_resolution_1d,
249                   cleanup,
250                   name='ACEScg'):
251     """
252     Creates the *ACEScg* colorspace.
253
254     Parameters
255     ----------
256     parameter : type
257         Parameter description.
258
259     Returns
260     -------
261     Colorspace
262          *ACEScg* colorspace.
263     """
264
265     cs = ColorSpace(name)
266     cs.description = 'The %s color space' % name
267     cs.aliases = ["lin_ap1"]
268     cs.equality_group = ''
269     cs.family = 'ACES'
270     cs.is_data = False
271     cs.allocation_type = ocio.Constants.ALLOCATION_LG2
272     cs.allocation_vars = [-8, 5, 0.00390625]
273
274     cs.to_reference_transforms = []
275
276     # *AP1* primaries to *AP0* primaries.
277     cs.to_reference_transforms.append({
278         'type': 'matrix',
279         'matrix': mat44_from_mat33(ACES_AP1_TO_AP0),
280         'direction': 'forward'})
281
282     cs.from_reference_transforms = []
283     return cs
284
285
286 # -------------------------------------------------------------------------
287 # *ADX*
288 # -------------------------------------------------------------------------
289 def create_ADX(lut_directory,
290                lut_resolution_1d,
291                bit_depth=10,
292                name='ADX'):
293     """
294     Creates the *ADX* colorspace.
295
296     Parameters
297     ----------
298     parameter : type
299         Parameter description.
300
301     Returns
302     -------
303     Colorspace
304          *ADX* colorspace.
305     """
306
307     name = '%s%s' % (name, bit_depth)
308     cs = ColorSpace(name)
309     cs.description = '%s color space - used for film scans' % name
310     cs.aliases = ["adx%s" % str(bit_depth)]
311     cs.equality_group = ''
312     cs.family = 'ADX'
313     cs.is_data = False
314
315     if bit_depth == 10:
316         cs.bit_depth = ocio.Constants.BIT_DEPTH_UINT10
317         ADX_to_CDD = [1023 / 500, 0, 0, 0,
318                       0, 1023 / 500, 0, 0,
319                       0, 0, 1023 / 500, 0,
320                       0, 0, 0, 1]
321         offset = [-95 / 500, -95 / 500, -95 / 500, 0]
322     elif bit_depth == 16:
323         cs.bit_depth = ocio.Constants.BIT_DEPTH_UINT16
324         ADX_to_CDD = [65535 / 8000, 0, 0, 0,
325                       0, 65535 / 8000, 0, 0,
326                       0, 0, 65535 / 8000, 0,
327                       0, 0, 0, 1]
328         offset = [-1520 / 8000, -1520 / 8000, -1520 / 8000, 0]
329
330     cs.to_reference_transforms = []
331
332     # Converting from *ADX* to *Channel-Dependent Density*.
333     cs.to_reference_transforms.append({
334         'type': 'matrix',
335         'matrix': ADX_to_CDD,
336         'offset': offset,
337         'direction': 'forward'})
338
339     # Convert from Channel-Dependent Density to Channel-Independent Density
340     cs.to_reference_transforms.append({
341         'type': 'matrix',
342         'matrix': [0.75573, 0.22197, 0.02230, 0,
343                    0.05901, 0.96928, -0.02829, 0,
344                    0.16134, 0.07406, 0.76460, 0,
345                    0, 0, 0, 1],
346         'direction': 'forward'})
347
348     # Copied from *Alex Fry*'s *adx_cid_to_rle.py*
349     def create_CID_to_RLE_LUT():
350
351         def interpolate_1D(x, xp, fp):
352             return numpy.interp(x, xp, fp)
353
354         LUT_1D_xp = [-0.190000000000000,
355                      0.010000000000000,
356                      0.028000000000000,
357                      0.054000000000000,
358                      0.095000000000000,
359                      0.145000000000000,
360                      0.220000000000000,
361                      0.300000000000000,
362                      0.400000000000000,
363                      0.500000000000000,
364                      0.600000000000000]
365
366         LUT_1D_fp = [-6.000000000000000,
367                      -2.721718645000000,
368                      -2.521718645000000,
369                      -2.321718645000000,
370                      -2.121718645000000,
371                      -1.921718645000000,
372                      -1.721718645000000,
373                      -1.521718645000000,
374                      -1.321718645000000,
375                      -1.121718645000000,
376                      -0.926545676714876]
377
378         REF_PT = ((7120 - 1520) / 8000 * (100 / 55) -
379                   math.log(0.18, 10))
380
381         def cid_to_rle(x):
382             if x <= 0.6:
383                 return interpolate_1D(x, LUT_1D_xp, LUT_1D_fp)
384             return (100 / 55) * x - REF_PT
385
386         def fit(value, from_min, from_max, to_min, to_max):
387             if from_min == from_max:
388                 raise ValueError('from_min == from_max')
389             return (value - from_min) / (from_max - from_min) * (
390                 to_max - to_min) + to_min
391
392         num_samples = 2 ** 12
393         domain = (-0.19, 3)
394         data = []
395         for i in xrange(num_samples):
396             x = i / (num_samples - 1)
397             x = fit(x, 0, 1, domain[0], domain[1])
398             data.append(cid_to_rle(x))
399
400         lut = 'ADX_CID_to_RLE.spi1d'
401         write_SPI_1d(os.path.join(lut_directory, lut),
402                      domain[0],
403                      domain[1],
404                      data,
405                      num_samples, 1)
406
407         return lut
408
409     # Converting *Channel Independent Density* values to
410     # *Relative Log Exposure* values.
411     lut = create_CID_to_RLE_LUT()
412     cs.to_reference_transforms.append({
413         'type': 'lutFile',
414         'path': lut,
415         'interpolation': 'linear',
416         'direction': 'forward'})
417
418     # Converting *Relative Log Exposure* values to
419     # *Relative Exposure* values.
420     cs.to_reference_transforms.append({
421         'type': 'log',
422         'base': 10,
423         'direction': 'inverse'})
424
425     # Convert *Relative Exposure* values to *ACES* values.
426     cs.to_reference_transforms.append({
427         'type': 'matrix',
428         'matrix': [0.72286, 0.12630, 0.15084, 0,
429                    0.11923, 0.76418, 0.11659, 0,
430                    0.01427, 0.08213, 0.90359, 0,
431                    0, 0, 0, 1],
432         'direction': 'forward'})
433
434     cs.from_reference_transforms = []
435     return cs
436
437 # -------------------------------------------------------------------------
438 # *Generic Log Transform*
439 # -------------------------------------------------------------------------
440 def create_generic_log(aces_ctl_directory,
441                        lut_directory,
442                        lut_resolution_1d,
443                        cleanup,
444                        name='log',
445                        aliases=[],
446                        min_value=0,
447                        max_value=1,
448                        input_scale=1,
449                        middle_grey=0.18,
450                        min_exposure=-6,
451                        max_exposure=6.5):
452     """
453     Creates the *Generic Log* colorspace.
454
455     Parameters
456     ----------
457     parameter : type
458         Parameter description.
459
460     Returns
461     -------
462     Colorspace
463          *Generic Log* colorspace.
464     """
465
466     cs = ColorSpace(name)
467     cs.description = 'The %s color space' % name
468     cs.aliases = aliases
469     cs.equality_group = name
470     cs.family = 'Utility'
471     cs.is_data = False
472
473     ctls = [os.path.join(
474         aces_ctl_directory,
475         'utilities',
476         'ACESlib.OCIO_shaper_log2_to_lin_param.a1.0.0.ctl')]
477     lut = '%s_to_linear.spi1d' % name
478
479     lut = sanitize(lut)
480
481     generate_1d_LUT_from_CTL(
482         os.path.join(lut_directory, lut),
483         ctls,
484         lut_resolution_1d,
485         'float',
486         input_scale,
487         1,
488         {'middleGrey': middle_grey,
489          'minExposure': min_exposure,
490          'maxExposure': max_exposure},
491         cleanup,
492         aces_ctl_directory,
493         min_value,
494         max_value,
495         1)
496
497     cs.to_reference_transforms = []
498     cs.to_reference_transforms.append({
499         'type': 'lutFile',
500         'path': lut,
501         'interpolation': 'linear',
502         'direction': 'forward'})
503
504     cs.from_reference_transforms = []
505     return cs
506
507 # -------------------------------------------------------------------------
508 # *base Dolby PQ Transform*
509 # -------------------------------------------------------------------------
510 def create_dolbypq(aces_CTL_directory,
511                     lut_directory,
512                     lut_resolution_1d,
513                     cleanup,
514                     name='pq',
515                     aliases=[],
516                     min_value=0.0,
517                     max_value=1.0,
518                     input_scale=1.0):
519     cs = ColorSpace(name)
520     cs.description = 'The %s color space' % name
521     cs.aliases = aliases
522     cs.equality_group = name
523     cs.family = 'Utility'
524     cs.is_data = False
525
526     ctls = [os.path.join(
527                          aces_CTL_directory,
528                          'utilities',
529                          'ACESlib.OCIO_shaper_dolbypq_to_lin.a1.0.0.ctl')]
530     lut = '%s_to_linear.spi1d' % name
531
532     lut = sanitize(lut)
533
534     generate_1d_LUT_from_CTL(
535         os.path.join(lut_directory, lut),
536         ctls,
537         lut_resolution_1d,
538         'float',
539         input_scale,
540         1.0,
541         {},
542         cleanup,
543         aces_CTL_directory,
544         min_value,
545         max_value)
546
547     cs.to_reference_transforms = []
548     cs.to_reference_transforms.append({
549         'type': 'lutFile',
550         'path': lut,
551         'interpolation': 'linear',
552         'direction': 'forward'})
553
554     cs.from_reference_transforms = []
555     return cs
556
557 # -------------------------------------------------------------------------
558 # *Dolby PQ Transform that considers a fixed linear range*
559 # -------------------------------------------------------------------------
560 def create_dolbypq_scaled(aces_CTL_directory,
561                            lut_directory,
562                            lut_resolution_1d,
563                            cleanup,
564                            name='pq',
565                            aliases=[],
566                            min_value=0.0,
567                            max_value=1.0,
568                            input_scale=1.0,
569                            middle_grey=0.18,
570                            min_exposure=-6.0,
571                            max_exposure=6.5):
572     cs = ColorSpace(name)
573     cs.description = 'The %s color space' % name
574     cs.aliases = aliases
575     cs.equality_group = name
576     cs.family = 'Utility'
577     cs.is_data = False
578
579     ctls = [os.path.join(
580                          aces_CTL_directory,
581                          'utilities',
582                          'ACESlib.OCIO_shaper_dolbypq_to_lin_param.a1.0.0.ctl')]
583     lut = '%s_to_linear.spi1d' % name
584
585     lut = sanitize(lut)
586
587     generate_1d_LUT_from_CTL(
588         os.path.join(lut_directory, lut),
589         ctls,
590         lut_resolution_1d,
591         'float',
592         input_scale,
593         1.0,
594         {'middleGrey': middle_grey,
595          'minExposure': min_exposure,
596          'maxExposure': max_exposure},
597         cleanup,
598         aces_CTL_directory,
599         min_value,
600         max_value)
601
602     cs.to_reference_transforms = []
603     cs.to_reference_transforms.append({
604         'type': 'lutFile',
605         'path': lut,
606         'interpolation': 'linear',
607         'direction': 'forward'})
608
609     cs.from_reference_transforms = []
610     return cs
611
612 # -------------------------------------------------------------------------
613 # *Individual LMT*
614 # -------------------------------------------------------------------------
615 def create_ACES_LMT(lmt_name,
616                     lmt_values,
617                     shaper_info,
618                     aces_ctl_directory,
619                     lut_directory,
620                     lut_resolution_1d=1024,
621                     lut_resolution_3d=64,
622                     cleanup=True,
623                     aliases=None):
624     """
625     Creates the *ACES LMT* colorspace.
626
627     Parameters
628     ----------
629     parameter : type
630         Parameter description.
631
632     Returns
633     -------
634     Colorspace
635          *ACES LMT* colorspace.
636     """
637
638     if aliases is None:
639         aliases = []
640
641     cs = ColorSpace('%s' % lmt_name)
642     cs.description = 'The ACES Look Transform: %s' % lmt_name
643     cs.aliases = aliases
644     cs.equality_group = ''
645     cs.family = 'Look'
646     cs.is_data = False
647     cs.allocation_type = ocio.Constants.ALLOCATION_LG2
648     cs.allocation_vars = [-8, 5, 0.00390625]
649
650     pprint.pprint(lmt_values)
651
652     # Generating the *shaper* transform.
653     (shaper_name,
654      shaper_to_ACES_CTL,
655      shaper_from_ACES_CTL,
656      shaper_input_scale,
657      shaper_params) = shaper_info
658
659     # Add the shaper transform
660     shaper_lut = '%s_to_linear.spi1d' % shaper_name
661     shaper_lut = sanitize(shaper_lut)
662
663     shaper_OCIO_transform = {
664         'type': 'lutFile',
665         'path': shaper_lut,
666         'interpolation': 'linear',
667         'direction': 'inverse'}
668
669     # Generating the forward transform.
670     cs.from_reference_transforms = []
671
672     if 'transformCTL' in lmt_values:
673         ctls = [shaper_to_ACES_CTL % aces_ctl_directory,
674                 os.path.join(aces_ctl_directory,
675                              lmt_values['transformCTL'])]
676         lut = '%s.%s.spi3d' % (shaper_name, lmt_name)
677
678         lut = sanitize(lut)
679
680         generate_3d_LUT_from_CTL(
681             os.path.join(lut_directory, lut),
682             ctls,
683             lut_resolution_3d,
684             'float',
685             1 / shaper_input_scale,
686             1,
687             shaper_params,
688             cleanup,
689             aces_ctl_directory)
690
691         cs.from_reference_transforms.append(shaper_OCIO_transform)
692         cs.from_reference_transforms.append({
693             'type': 'lutFile',
694             'path': lut,
695             'interpolation': 'tetrahedral',
696             'direction': 'forward'})
697
698     # Generating the inverse transform.
699     cs.to_reference_transforms = []
700
701     if 'transformCTLInverse' in lmt_values:
702         ctls = [os.path.join(aces_ctl_directory,
703                              lmt_values['transformCTLInverse']),
704                 shaper_from_ACES_CTL % aces_ctl_directory]
705         lut = 'Inverse.%s.%s.spi3d' % (odt_name, shaper_name)
706
707         lut = sanitize(lut)
708
709         generate_3d_LUT_from_CTL(
710             os.path.join(lut_directory, lut),
711             ctls,
712             lut_resolution_3d,
713             'half',
714             1,
715             shaper_input_scale,
716             shaper_params,
717             cleanup,
718             aces_ctl_directory,
719             0,
720             1,
721             1)
722
723         cs.to_reference_transforms.append({
724             'type': 'lutFile',
725             'path': lut,
726             'interpolation': 'tetrahedral',
727             'direction': 'forward'})
728
729         shaper_inverse = shaper_OCIO_transform.copy()
730         shaper_inverse['direction'] = 'forward'
731         cs.to_reference_transforms.append(shaper_inverse)
732
733     return cs
734
735 # -------------------------------------------------------------------------
736 # *LMTs*
737 # -------------------------------------------------------------------------
738 def create_LMTs(aces_ctl_directory,
739                 lut_directory,
740                 lut_resolution_1d,
741                 lut_resolution_3d,
742                 lmt_info,
743                 shaper_name,
744                 cleanup):
745     """
746     Object description.
747
748     Parameters
749     ----------
750     parameter : type
751         Parameter description.
752
753     Returns
754     -------
755     type
756          Return value description.
757     """
758
759     colorspaces = []
760
761     # -------------------------------------------------------------------------
762     # *LMT Shaper*
763     # -------------------------------------------------------------------------
764     lmt_lut_resolution_1d = max(4096, lut_resolution_1d)
765     lmt_lut_resolution_3d = max(65, lut_resolution_3d)
766
767     # Defining the *Log 2* shaper.
768     lmt_shaper_name = 'LMT Shaper'
769     lmt_shaper_name_aliases = ['crv_lmtshaper']
770     lmt_params = {
771         'middleGrey': 0.18,
772         'minExposure': -10,
773         'maxExposure': 6.5}
774
775     lmt_shaper = create_generic_log(aces_ctl_directory,
776                                     lut_directory,
777                                     lmt_lut_resolution_1d,
778                                     cleanup,
779                                     name=lmt_shaper_name,
780                                     middle_grey=lmt_params['middleGrey'],
781                                     min_exposure=lmt_params['minExposure'],
782                                     max_exposure=lmt_params['maxExposure'],
783                                     aliases=lmt_shaper_name_aliases)
784     colorspaces.append(lmt_shaper)
785
786     shaper_input_scale_generic_log2 = 1
787
788     # *Log 2* shaper name and *CTL* transforms bundled up.
789     lmt_shaper_data = [
790         lmt_shaper_name,
791         os.path.join('%s',
792                      'utilities',
793                      'ACESlib.OCIO_shaper_log2_to_lin_param.a1.0.0.ctl'),
794         os.path.join('%s',
795                      'utilities',
796                      'ACESlib.OCIO_shaper_lin_to_log2_param.a1.0.0.ctl'),
797         shaper_input_scale_generic_log2,
798         lmt_params]
799
800     sorted_LMTs = sorted(lmt_info.iteritems(), key=lambda x: x[1])
801     print(sorted_LMTs)
802     for lmt in sorted_LMTs:
803         lmt_name, lmt_values = lmt
804         lmt_aliases = ["look_%s" % compact(lmt_values['transformUserName'])]
805         cs = create_ACES_LMT(
806             lmt_values['transformUserName'],
807             lmt_values,
808             lmt_shaper_data,
809             aces_ctl_directory,
810             lut_directory,
811             lmt_lut_resolution_1d,
812             lmt_lut_resolution_3d,
813             cleanup,
814             lmt_aliases)
815         colorspaces.append(cs)
816
817     return colorspaces
818
819 # -------------------------------------------------------------------------
820 # *ACES RRT* with supplied *ODT*.
821 # -------------------------------------------------------------------------
822 def create_ACES_RRT_plus_ODT(odt_name,
823                              odt_values,
824                              shaper_info,
825                              aces_ctl_directory,
826                              lut_directory,
827                              lut_resolution_1d=1024,
828                              lut_resolution_3d=64,
829                              cleanup=True,
830                              aliases=None):
831     """
832     Object description.
833
834     Parameters
835     ----------
836     parameter : type
837         Parameter description.
838
839     Returns
840     -------
841     type
842          Return value description.
843     """
844
845     if aliases is None:
846         aliases = []
847
848     cs = ColorSpace('%s' % odt_name)
849     cs.description = '%s - %s Output Transform' % (
850         odt_values['transformUserNamePrefix'], odt_name)
851     cs.aliases = aliases
852     cs.equality_group = ''
853     cs.family = 'Output'
854     cs.is_data = False
855
856     pprint.pprint(odt_values)
857
858     # Generating the *shaper* transform.
859     (shaper_name,
860      shaper_to_ACES_CTL,
861      shaper_from_ACES_CTL,
862      shaper_input_scale,
863      shaper_params) = shaper_info
864
865     if 'legalRange' in odt_values:
866         shaper_params['legalRange'] = odt_values['legalRange']
867     else:
868         shaper_params['legalRange'] = 0
869
870     # Add the shaper transform
871     shaper_lut = '%s_to_linear.spi1d' % shaper_name
872     shaper_lut = sanitize(shaper_lut)
873
874     shaper_OCIO_transform = {
875         'type': 'lutFile',
876         'path': shaper_lut,
877         'interpolation': 'linear',
878         'direction': 'inverse'}
879
880     # Generating the *forward* transform.
881     cs.from_reference_transforms = []
882
883     if 'transformLUT' in odt_values:
884         transform_LUT_file_name = os.path.basename(
885             odt_values['transformLUT'])
886         lut = os.path.join(lut_directory, transform_LUT_file_name)
887         shutil.copy(odt_values['transformLUT'], lut)
888
889         cs.from_reference_transforms.append(shaper_OCIO_transform)
890         cs.from_reference_transforms.append({
891             'type': 'lutFile',
892             'path': transform_LUT_file_name,
893             'interpolation': 'tetrahedral',
894             'direction': 'forward'})
895     elif 'transformCTL' in odt_values:
896         ctls = [
897             shaper_to_ACES_CTL % aces_ctl_directory,
898             os.path.join(aces_ctl_directory,
899                          'rrt',
900                          'RRT.a1.0.0.ctl'),
901             os.path.join(aces_ctl_directory,
902                          'odt',
903                          odt_values['transformCTL'])]
904         lut = '%s.RRT.a1.0.0.%s.spi3d' % (shaper_name, odt_name)
905
906         lut = sanitize(lut)
907
908         generate_3d_LUT_from_CTL(
909             os.path.join(lut_directory, lut),
910             # shaperLUT,
911             ctls,
912             lut_resolution_3d,
913             'float',
914             1 / shaper_input_scale,
915             1,
916             shaper_params,
917             cleanup,
918             aces_ctl_directory)
919
920         cs.from_reference_transforms.append(shaper_OCIO_transform)
921         cs.from_reference_transforms.append({
922             'type': 'lutFile',
923             'path': lut,
924             'interpolation': 'tetrahedral',
925             'direction': 'forward'})
926
927     # Generating the *inverse* transform.
928     cs.to_reference_transforms = []
929
930     if 'transformLUTInverse' in odt_values:
931         transform_LUT_inverse_file_name = os.path.basename(
932             odt_values['transformLUTInverse'])
933         lut = os.path.join(lut_directory, transform_LUT_inverse_file_name)
934         shutil.copy(odt_values['transformLUTInverse'], lut)
935
936         cs.to_reference_transforms.append({
937             'type': 'lutFile',
938             'path': transform_LUT_inverse_file_name,
939             'interpolation': 'tetrahedral',
940             'direction': 'forward'})
941
942         shaper_inverse = shaper_OCIO_transform.copy()
943         shaper_inverse['direction'] = 'forward'
944         cs.to_reference_transforms.append(shaper_inverse)
945     elif 'transformCTLInverse' in odt_values:
946         ctls = [os.path.join(aces_ctl_directory,
947                              'odt',
948                              odt_values['transformCTLInverse']),
949                 os.path.join(aces_ctl_directory,
950                              'rrt',
951                              'InvRRT.a1.0.0.ctl'),
952                 shaper_from_ACES_CTL % aces_ctl_directory]
953         lut = 'InvRRT.a1.0.0.%s.%s.spi3d' % (odt_name, shaper_name)
954
955         lut = sanitize(lut)
956
957         generate_3d_LUT_from_CTL(
958             os.path.join(lut_directory, lut),
959             # None,
960             ctls,
961             lut_resolution_3d,
962             'half',
963             1,
964             shaper_input_scale,
965             shaper_params,
966             cleanup,
967             aces_ctl_directory)
968
969         cs.to_reference_transforms.append({
970             'type': 'lutFile',
971             'path': lut,
972             'interpolation': 'tetrahedral',
973             'direction': 'forward'})
974
975         shaper_inverse = shaper_OCIO_transform.copy()
976         shaper_inverse['direction'] = 'forward'
977         cs.to_reference_transforms.append(shaper_inverse)
978
979     return cs
980
981 # -------------------------------------------------------------------------
982 # *ODTs*
983 # -------------------------------------------------------------------------
984 def create_ODTs(aces_ctl_directory,
985                 lut_directory,
986                 lut_resolution_1d,
987                 lut_resolution_3d,
988                 odt_info,
989                 shaper_name,
990                 cleanup,
991                 linear_display_space,
992                 log_display_space):
993     """
994     Object description.
995
996     Parameters
997     ----------
998     parameter : type
999         Parameter description.
1000
1001     Returns
1002     -------
1003     type
1004          Return value description.
1005     """
1006
1007     colorspaces = []
1008     displays = {}
1009
1010     # -------------------------------------------------------------------------
1011     # *RRT / ODT* Shaper Options
1012     # -------------------------------------------------------------------------
1013     shaper_data = {}
1014
1015     # Defining the *Log 2* shaper.
1016     log2_shaper_name = shaper_name
1017     log2_shaper_name_aliases = ["crv_%s" % compact(log2_shaper_name)]
1018     log2_params = {
1019         'middleGrey': 0.18,
1020         'minExposure': -6,
1021         'maxExposure': 6.5}
1022
1023     log2_shaper_colorspace = create_generic_log(
1024         aces_ctl_directory,
1025         lut_directory,
1026         lut_resolution_1d,
1027         cleanup,
1028         name=log2_shaper_name,
1029         middle_grey=log2_params['middleGrey'],
1030         min_exposure=log2_params['minExposure'],
1031         max_exposure=log2_params['maxExposure'],
1032         aliases=log2_shaper_name_aliases)
1033     colorspaces.append(log2_shaper_colorspace)
1034
1035     shaper_input_scale_generic_log2 = 1
1036
1037     # *Log 2* shaper name and *CTL* transforms bundled up.
1038     log2_shaper_data = [
1039         log2_shaper_name,
1040         os.path.join('%s',
1041                      'utilities',
1042                      'ACESlib.OCIO_shaper_log2_to_lin_param.a1.0.0.ctl'),
1043         os.path.join('%s',
1044                      'utilities',
1045                      'ACESlib.OCIO_shaper_lin_to_log2_param.a1.0.0.ctl'),
1046         shaper_input_scale_generic_log2,
1047         log2_params]
1048
1049     shaper_data[log2_shaper_name] = log2_shaper_data
1050
1051     # Space with a more user-friendly name. Direct copy otherwise.
1052     log2_shaper_copy_name = "Log2 Shaper"
1053     log2_shaper_copy_colorspace = ColorSpace(log2_shaper_copy_name)
1054     log2_shaper_copy_colorspace.description = 'The %s color space' % log2_shaper_copy_name
1055     log2_shaper_copy_colorspace.aliases = [compact(log2_shaper_copy_name)]
1056     log2_shaper_copy_colorspace.equality_group = log2_shaper_copy_name
1057     log2_shaper_copy_colorspace.family = log2_shaper_colorspace.family
1058     log2_shaper_copy_colorspace.is_data = log2_shaper_colorspace.is_data
1059     log2_shaper_copy_colorspace.to_reference_transforms = list(log2_shaper_colorspace.to_reference_transforms)
1060     log2_shaper_copy_colorspace.from_reference_transforms = list(log2_shaper_colorspace.from_reference_transforms)
1061     colorspaces.append(log2_shaper_copy_colorspace)
1062
1063     # Defining the *Log2 shaper that includes the AP1* primaries.
1064     # Needed for some LUT baking steps.
1065     log2_shaper_api1_name = "%s - AP1" % "Log2 Shaper"
1066     log2_shaper_api1_colorspace = ColorSpace(log2_shaper_api1_name)
1067     log2_shaper_api1_colorspace.description = 'The %s color space' % log2_shaper_api1_name
1068     log2_shaper_api1_colorspace.aliases = ["%s_ap1" % compact(log2_shaper_copy_name)]
1069     log2_shaper_api1_colorspace.equality_group = log2_shaper_api1_name
1070     log2_shaper_api1_colorspace.family = log2_shaper_colorspace.family
1071     log2_shaper_api1_colorspace.is_data = log2_shaper_colorspace.is_data
1072     log2_shaper_api1_colorspace.to_reference_transforms = list(log2_shaper_colorspace.to_reference_transforms)
1073     log2_shaper_api1_colorspace.from_reference_transforms = list(log2_shaper_colorspace.from_reference_transforms)
1074
1075     # *AP1* primaries to *AP0* primaries.
1076     log2_shaper_api1_colorspace.to_reference_transforms.append({
1077         'type': 'matrix',
1078         'matrix': mat44_from_mat33(ACES_AP1_TO_AP0),
1079         'direction': 'forward'
1080     })
1081     colorspaces.append(log2_shaper_api1_colorspace)
1082
1083     # Define the base *Dolby PQ Shaper*
1084     #
1085     dolbypq_shaper_name = "Dolby PQ 10000"
1086     dolbypq_shaper_name_aliases = ["crv_%s" % "dolbypq_10000"]
1087
1088     dolbypq_shaper_colorspace = create_dolbypq(
1089         aces_ctl_directory,
1090         lut_directory,
1091         lut_resolution_1d,
1092         cleanup,
1093         name=dolbypq_shaper_name,
1094         aliases=dolbypq_shaper_name_aliases)
1095     colorspaces.append(dolbypq_shaper_colorspace)
1096
1097     # *Dolby PQ* shaper name and *CTL* transforms bundled up.
1098     dolbypq_shaper_data = [
1099         dolbypq_shaper_name,
1100         os.path.join('%s',
1101                      'utilities',
1102                      'ACESlib.OCIO_shaper_dolbypq_to_lin.a1.0.0.ctl'),
1103         os.path.join('%s',
1104                      'utilities',
1105                      'ACESlib.OCIO_shaper_lin_to_dolbypq.a1.0.0.ctl'),
1106         1.0,
1107         {}]
1108
1109     shaper_data[dolbypq_shaper_name] = dolbypq_shaper_data
1110
1111     # Define the *Dolby PQ Shaper that considers a fixed linear range*
1112     #
1113     dolbypq_scaled_shaper_name = "Dolby PQ Scaled"
1114     dolbypq_scaled_shaper_name_aliases = ["crv_%s" % "dolbypq_scaled"]
1115
1116     dolbypq_scaled_shaper_colorspace = create_dolbypq_scaled(
1117         aces_ctl_directory,
1118         lut_directory,
1119         lut_resolution_1d,
1120         cleanup,
1121         name=dolbypq_scaled_shaper_name,
1122         aliases=dolbypq_scaled_shaper_name_aliases)
1123     colorspaces.append(dolbypq_scaled_shaper_colorspace)
1124
1125     # *Dolby PQ* shaper name and *CTL* transforms bundled up.
1126     dolbypq_scaled_shaper_data = [
1127         dolbypq_scaled_shaper_name,
1128         os.path.join('%s',
1129                      'utilities',
1130                      'ACESlib.OCIO_shaper_dolbypq_to_lin_param.a1.0.0.ctl'),
1131         os.path.join('%s',
1132                      'utilities',
1133                      'ACESlib.OCIO_shaper_lin_to_dolbypq_param.a1.0.0.ctl'),
1134         1.0,
1135         log2_params]
1136
1137     shaper_data[dolbypq_scaled_shaper_name] = dolbypq_scaled_shaper_data
1138
1139     #
1140     # Pick a specific shaper
1141     #
1142     rrt_shaper = log2_shaper_data
1143     #rrt_shaper = dolbypq_scaled_shaper_data
1144
1145     # *RRT + ODT* combinations.
1146     sorted_odts = sorted(odt_info.iteritems(), key=lambda x: x[1])
1147     print(sorted_odts)
1148     for odt in sorted_odts:
1149         (odt_name, odt_values) = odt
1150
1151         # Generating legal range transform for *ODTs* that can generate 
1152         # either *legal* or *full* output.
1153         if odt_values['transformHasFullLegalSwitch']:
1154             odt_name_legal = '%s - Legal' % odt_values['transformUserName']
1155         else:
1156             odt_name_legal = odt_values['transformUserName']
1157
1158         odt_legal = odt_values.copy()
1159         odt_legal['legalRange'] = 1
1160
1161         odt_aliases = ["out_%s" % compact(odt_name_legal)]
1162
1163         cs = create_ACES_RRT_plus_ODT(
1164             odt_name_legal,
1165             odt_legal,
1166             rrt_shaper,
1167             aces_ctl_directory,
1168             lut_directory,
1169             lut_resolution_1d,
1170             lut_resolution_3d,
1171             cleanup,
1172             odt_aliases)
1173         colorspaces.append(cs)
1174
1175         displays[odt_name_legal] = {
1176             'Linear': linear_display_space,
1177             'Log': log_display_space,
1178             'Output Transform': cs}
1179
1180
1181         # Generating full range transform for *ODTs* that can generate 
1182         # either *legal* or *full* output.
1183         if odt_values['transformHasFullLegalSwitch']:
1184             print('Generating full range ODT for %s' % odt_name)
1185
1186             odt_name_full = '%s - Full' % odt_values['transformUserName']
1187             odt_full = odt_values.copy()
1188             odt_full['legalRange'] = 0
1189
1190             odt_full_aliases = ["out_%s" % compact(odt_name_full)]
1191
1192             cs_full = create_ACES_RRT_plus_ODT(
1193                 odt_name_full,
1194                 odt_full,
1195                 rrt_shaper,
1196                 aces_ctl_directory,
1197                 lut_directory,
1198                 lut_resolution_1d,
1199                 lut_resolution_3d,
1200                 cleanup,
1201                 odt_full_aliases)
1202             colorspaces.append(cs_full)
1203
1204             displays[odt_name_full] = {
1205                 'Linear': linear_display_space,
1206                 'Log': log_display_space,
1207                 'Output Transform': cs_full}
1208
1209     return (colorspaces, displays)
1210
1211
1212 def get_transform_info(ctl_transform):
1213     """
1214     Object description.
1215
1216     Parameters
1217     ----------
1218     parameter : type
1219         Parameter description.
1220
1221     Returns
1222     -------
1223     type
1224          Return value description.
1225     """
1226
1227     with open(ctl_transform, 'rb') as fp:
1228         lines = fp.readlines()
1229
1230     # Retrieving the *transform ID* and *User Name*.
1231     transform_id = lines[1][3:].split('<')[1].split('>')[1].strip()
1232     transform_user_name = '-'.join(
1233         lines[2][3:].split('<')[1].split('>')[1].split('-')[1:]).strip()
1234     transform_user_name_prefix = (
1235         lines[2][3:].split('<')[1].split('>')[1].split('-')[0].strip())
1236
1237     # Figuring out if this transform has options for processing full and legal range
1238     transform_full_legal_switch = False
1239     for line in lines:
1240         if line.strip() == "input varying int legalRange = 0":
1241             # print( "%s has legal range flag" % transform_user_name)
1242             transform_full_legal_switch = True
1243             break
1244
1245     return (transform_id, transform_user_name, transform_user_name_prefix,
1246             transform_full_legal_switch)
1247
1248
1249 def get_ODTs_info(aces_ctl_directory):
1250     """
1251     Object description.
1252
1253     For versions after WGR9.
1254
1255     Parameters
1256     ----------
1257     parameter : type
1258         Parameter description.
1259
1260     Returns
1261     -------
1262     type
1263          Return value description.
1264     """
1265
1266     # TODO: Investigate usage of *files_walker* definition here.
1267     # Credit to *Alex Fry* for the original approach here.
1268     odt_dir = os.path.join(aces_ctl_directory, 'odt')
1269     all_odt = []
1270     for dir_name, subdir_list, file_list in os.walk(odt_dir):
1271         for fname in file_list:
1272             all_odt.append((os.path.join(dir_name, fname)))
1273
1274     odt_CTLs = [x for x in all_odt if
1275                 ('InvODT' not in x) and (os.path.split(x)[-1][0] != '.')]
1276
1277     odts = {}
1278
1279     for odt_CTL in odt_CTLs:
1280         odt_tokens = os.path.split(odt_CTL)
1281
1282         # Handling nested directories.
1283         odt_path_tokens = os.path.split(odt_tokens[-2])
1284         odt_dir = odt_path_tokens[-1]
1285         while odt_path_tokens[-2][-3:] != 'odt':
1286             odt_path_tokens = os.path.split(odt_path_tokens[-2])
1287             odt_dir = os.path.join(odt_path_tokens[-1], odt_dir)
1288
1289         # Building full name,
1290         transform_CTL = odt_tokens[-1]
1291         odt_name = string.join(transform_CTL.split('.')[1:-1], '.')
1292
1293         # Finding id, user name and user name prefix.
1294         (transform_ID,
1295          transform_user_name,
1296          transform_user_name_prefix,
1297          transform_full_legal_switch) = get_transform_info(
1298             os.path.join(aces_ctl_directory, 'odt', odt_dir, transform_CTL))
1299
1300         # Finding inverse.
1301         transform_CTL_inverse = 'InvODT.%s.ctl' % odt_name
1302         if not os.path.exists(
1303                 os.path.join(odt_tokens[-2], transform_CTL_inverse)):
1304             transform_CTL_inverse = None
1305
1306         # Add to list of ODTs
1307         odts[odt_name] = {}
1308         odts[odt_name]['transformCTL'] = os.path.join(odt_dir, transform_CTL)
1309         if transform_CTL_inverse is not None:
1310             odts[odt_name]['transformCTLInverse'] = os.path.join(
1311                 odt_dir, transform_CTL_inverse)
1312
1313         odts[odt_name]['transformID'] = transform_ID
1314         odts[odt_name]['transformUserNamePrefix'] = transform_user_name_prefix
1315         odts[odt_name]['transformUserName'] = transform_user_name
1316         odts[odt_name][
1317             'transformHasFullLegalSwitch'] = transform_full_legal_switch
1318
1319         forward_CTL = odts[odt_name]['transformCTL']
1320
1321         print('ODT : %s' % odt_name)
1322         print('\tTransform ID               : %s' % transform_ID)
1323         print('\tTransform User Name Prefix : %s' % transform_user_name_prefix)
1324         print('\tTransform User Name        : %s' % transform_user_name)
1325         print(
1326             '\tHas Full / Legal Switch    : %s' % transform_full_legal_switch)
1327         print('\tForward ctl                : %s' % forward_CTL)
1328         if 'transformCTLInverse' in odts[odt_name]:
1329             inverse_CTL = odts[odt_name]['transformCTLInverse']
1330             print('\tInverse ctl                : %s' % inverse_CTL)
1331         else:
1332             print('\tInverse ctl                : %s' % 'None')
1333
1334     print('\n')
1335
1336     return odts
1337
1338
1339 def get_LMTs_info(aces_ctl_directory):
1340     """
1341     Object description.
1342
1343     For versions after WGR9.
1344
1345     Parameters
1346     ----------
1347     parameter : type
1348         Parameter description.
1349
1350     Returns
1351     -------
1352     type
1353          Return value description.
1354     """
1355
1356     # TODO: Investigate refactoring with previous definition.
1357
1358     # Credit to Alex Fry for the original approach here
1359     lmt_dir = os.path.join(aces_ctl_directory, 'lmt')
1360     all_lmt = []
1361     for dir_name, subdir_list, file_list in os.walk(lmt_dir):
1362         for fname in file_list:
1363             all_lmt.append((os.path.join(dir_name, fname)))
1364
1365     lmt_CTLs = [x for x in all_lmt if
1366                 ('InvLMT' not in x) and ('README' not in x) and (
1367                     os.path.split(x)[-1][0] != '.')]
1368
1369     lmts = {}
1370
1371     for lmt_CTL in lmt_CTLs:
1372         lmt_tokens = os.path.split(lmt_CTL)
1373
1374         # Handlimg nested directories.
1375         lmt_path_tokens = os.path.split(lmt_tokens[-2])
1376         lmt_dir = lmt_path_tokens[-1]
1377         while lmt_path_tokens[-2][-3:] != 'ctl':
1378             lmt_path_tokens = os.path.split(lmt_path_tokens[-2])
1379             lmt_dir = os.path.join(lmt_path_tokens[-1], lmt_dir)
1380
1381         # Building full name.
1382         transform_CTL = lmt_tokens[-1]
1383         lmt_name = string.join(transform_CTL.split('.')[1:-1], '.')
1384
1385         # Finding id, user name and user name prefix.
1386         (transform_ID,
1387          transform_user_name,
1388          transform_user_name_prefix,
1389          transform_full_legal_switch) = get_transform_info(
1390             os.path.join(aces_ctl_directory, lmt_dir, transform_CTL))
1391
1392         # Finding inverse.
1393         transform_CTL_inverse = 'InvLMT.%s.ctl' % lmt_name
1394         if not os.path.exists(
1395                 os.path.join(lmt_tokens[-2], transform_CTL_inverse)):
1396             transform_CTL_inverse = None
1397
1398         lmts[lmt_name] = {}
1399         lmts[lmt_name]['transformCTL'] = os.path.join(lmt_dir, transform_CTL)
1400         if transform_CTL_inverse is not None:
1401             lmts[lmt_name]['transformCTLInverse'] = os.path.join(
1402                 lmt_dir, transform_CTL_inverse)
1403
1404         lmts[lmt_name]['transformID'] = transform_ID
1405         lmts[lmt_name]['transformUserNamePrefix'] = transform_user_name_prefix
1406         lmts[lmt_name]['transformUserName'] = transform_user_name
1407
1408         forward_CTL = lmts[lmt_name]['transformCTL']
1409
1410         print('LMT : %s' % lmt_name)
1411         print('\tTransform ID               : %s' % transform_ID)
1412         print('\tTransform User Name Prefix : %s' % transform_user_name_prefix)
1413         print('\tTransform User Name        : %s' % transform_user_name)
1414         print('\t Forward ctl               : %s' % forward_CTL)
1415         if 'transformCTLInverse' in lmts[lmt_name]:
1416             inverse_CTL = lmts[lmt_name]['transformCTLInverse']
1417             print('\t Inverse ctl                : %s' % inverse_CTL)
1418         else:
1419             print('\t Inverse ctl                : %s' % 'None')
1420
1421     print('\n')
1422
1423     return lmts
1424
1425
1426 def create_colorspaces(aces_ctl_directory,
1427                        lut_directory,
1428                        lut_resolution_1d,
1429                        lut_resolution_3d,
1430                        lmt_info,
1431                        odt_info,
1432                        shaper_name,
1433                        cleanup):
1434     """
1435     Generates the colorspace conversions.
1436
1437     Parameters
1438     ----------
1439     parameter : type
1440         Parameter description.
1441
1442     Returns
1443     -------
1444     type
1445          Return value description.
1446     """
1447
1448     colorspaces = []
1449
1450     ACES = create_ACES()
1451
1452     ACEScc = create_ACEScc(aces_ctl_directory, lut_directory,
1453                            lut_resolution_1d, cleanup, 
1454                            min_value=-0.35840, max_value=1.468)
1455     colorspaces.append(ACEScc)
1456
1457     ACESproxy = create_ACESproxy(aces_ctl_directory, lut_directory,
1458                                  lut_resolution_1d, cleanup)
1459     colorspaces.append(ACESproxy)
1460
1461     ACEScg = create_ACEScg(aces_ctl_directory, lut_directory,
1462                            lut_resolution_1d, cleanup)
1463     colorspaces.append(ACEScg)
1464
1465     ADX10 = create_ADX(lut_directory, lut_resolution_1d, bit_depth=10)
1466     colorspaces.append(ADX10)
1467
1468     ADX16 = create_ADX(lut_directory, lut_resolution_1d, bit_depth=16)
1469     colorspaces.append(ADX16)
1470
1471     lmts = create_LMTs(aces_ctl_directory,
1472                        lut_directory,
1473                        lut_resolution_1d,
1474                        lut_resolution_3d,
1475                        lmt_info,
1476                        shaper_name,
1477                        cleanup)
1478     colorspaces.extend(lmts)
1479
1480     odts, displays = create_ODTs(aces_ctl_directory,
1481                                  lut_directory,
1482                                  lut_resolution_1d,
1483                                  lut_resolution_3d,
1484                                  odt_info,
1485                                  shaper_name,
1486                                  cleanup,
1487                                  ACES,
1488                                  ACEScc)
1489     colorspaces.extend(odts)
1490
1491     roles = {'color_picking'   : ACEScg.name,
1492              'color_timing'    : ACEScc.name,
1493              'compositing_log' : ACEScc.name,
1494              'data'            : '',
1495              'default'         : ACES.name,
1496              'matte_paint'     : ACEScc.name,
1497              'reference'       : '',
1498              'scene_linear'    : ACEScg.name,
1499              'texture_paint'   : ''}
1500
1501
1502     return ACES, colorspaces, displays, ACEScc, roles