Storing and retrieving LUTs per shot with custom field

I’m working on a LUT management tool that I’ve got working in Nuke, but I want to take it one step further and have references to the LUTs saved in Shotgun on a per-shot basis.

Right now my code does this via environment variables, so that I can save and retrieve them easily from one part in my script to another (setting via the Plugin I wrote, and then retrieving in the Quick Review node).

So what I’m looking to do is start saving this in a custom field on each shot in Shotgun, and I’m thinking that the way to do this is by taking over the tk-nuke configuration and modifying it there. However, I would love some guidance on where exactly I should be de-serializing the context coming from Shotgun when a shot is loaded, in order to grab that field in the right place and then add it to my ENV.

2 Likes hooks are your friend for this use-case.
Beware, syntax errors in this hook can cause strange behaviour with no error messages and/or crash the DCC.


Thanks for the tip Patrick, any chance you’ve got a rough example for this?

Both for the syntax on taking over this hook in the pipeline configuration, and what the file might look like, to make sure that I end up with the right stuff in there.


Hi Jeff,

Are you writing a custom toolkit app to handle this? If so, you can set the context_change_allowed to True and use the pre/post_context_change methods to update stuff.

def context_change_allowed(self):
    Specifies that context changes are allowed.
    return True

def post_context_change(self, old_context, new_context):
    Run OCIO Setup after context change

    # update environment variables here

We have something very similar to what you are describing, and we’ve wrapped it all up in a toolkit app. Since our app is using OCIO, we can use it in more DCCs then just Nuke as well which is nice.

Good luck!


Ok the context_change hook is a core hook, so it needs to be placed in the core/hooks folder.
You can see all core hooks on the tk-core github site. Here’s the context_change hook :

To query SG, you can do the following to get an SG object:

sg = self.parent.shotgun

Then you can get your lut data in the usual way…

sg.find(your query here)

Only thing to watch out for… the context change hooks get called ALOT so you want to have if statements so the query only gets called if you have a valid context and if that context has changed.

This is all with the core hook. Jonas’s suggestion of a dedicated app is interesting and may well be a nicer approach.

1 Like

I wasn’t going to write a custom toolkit app, but it does sound like a pretty good idea for something that could work across apps.

The deeper I dig into OCIO, the more it looks like the right way to handle this.

Since you mentioned it though, I am curious - did you guys make your own tool for managing and creating the OCIO configs themselves? Writing those by hand really doesn’t seem like the best approach, and that’s what I’ve been doing so far - and it has yet to feel efficient.

This is very helpful Patrick! Thanks a TON for going into more detail.

I think with what you just shared, I just should have everything I need to pull this off!

No problem.

My approach with the configs is just to work with ocio env vars that we set in Nuke or RV from the SG ocio fields.
We tend to populate the look and lut fields during ingest (hiero_export hooks) using Nuke Studio. I’ve also gone so far as to publish any cdl, cubes used on the NS timeline.
The config.ocio becomes almost generic enough for most projects. The only major headache at the moment is the fact you can’t define colorspaceTransform in and out profiles via environment variables, so these still need hard-coded on a per-project basis. That being said, I think Nuke 12 is using a more up-to-date compile of OCIO which is supposed to support env vars for those values… I just haven’t had a chance to test it yet.

Our approach sounds very similar to Patricks.

We have a generic OCIO config (based on the default-nuke one, haven’t made the switch to ACES yet) which works in most cases. Looks are setup in the config that are driven by environment variables to handle per shot luts (cdl) etc.

The toolkit app that we use for handling all this sets the env vars to match the current context. Since we have multiple offices often working on the same project, we actually upload our luts/cdls to Shotgun and the ocio-toolkit app takes care of downloading any missing luts that are needed for the current shot.

I did not now that OCIO in Nuke 12 can handle env vars for colorspace transforms, that’s awesome! Our work around has been to store the name of the expected .spi1d lut in shotgun on our LUT entity, and then use a file transform with an env var to have some flexibility. But I don’t think this would work if we were working in ACES for example.

An example of how we have a look setup in the most basic of cases. Lets say our plate is pre-linearized with AlexaV3LogC to Linear, and we want to use the regular Alexa-Rec709 lut. We just need to add the inverse of AlexaV3LogC and then add the Alexa-Rec709 lut after that.

name: project_lut
process_space: linear
transform: !<GroupTransform>
    - !<FileTransform> {src: '${PROJECT_LUT_PROCESS_SPACE}.spi1d', interpolation: linear, direction: inverse}
    - !<FileTransform> {src: '${PROJECT_LUT}', interpolation: linear}

All best,

Thanks for sharing Jonas,
Does your app hook in to RV or have you gone down the ocio_source_setup route ?
Are you using SG Review or Screeningroom in RV?

No problem!

No unfortunately it does not hook in to RV, as far as I know RV is using a baked version of Toolkit and wouldn’t work with our setup using distributed configs. It would be ideal for us if RV was more integrated into the whole toolkit infrastructure, where we could port an app like this to RV as well. Maybe it is possible already but it’s not something that we are using.

Yeah we’re using the ocio_source_setup stuff with just some minor configuration, it works great when launching RV from Nuke where all envs are already setup, then it works out of the box. But for reviewing playlists we just stick to the project lut and smile… For now. In other words no fancy context based luts for sequences. We’re using Screeningrom in RV.