Pre & Post Render Scripts

Pre and Post Render Python Scripts in Mantra

I’ve been working with Python lately in Houdini and creating some pre and post processing render scripts for Mantra. There are a bunch of things I want to try and one of them is recreating my Cinema 4D Hangover plugin for Houdini. Not sure if and when that will happen though. Considering Houdini has nice Python integration, I figured access to Mantra would be a breeze. Well, Sort of. First order of business is how to actually run pre and post render Python scripts in Mantra. That’s our focus today.

Mantra Render Scripts

Houdini has a Scripts folder within the Mantra node that lets you specify Pre render and frame scripts as well as Post render and frame scripts. Wait! What? Yeah, may catch you off guard if you’re not paying attention. The Pre and Post render scripts run only once before and after an IFD and the Pre and Post frame scripts get called after each frame IFD is generated.

Mantra Scripts Folder
Mantra Scripts Folder

Notice I said IFD. Put simply, Houdini will first write out the contents of the scene to a file or better known as description file. This is the IFD file or Instantaneous Frame Description file. Mantra will then consume this file like Pac-Man and render out your image. If you are not familiar with the IFD workflow, please refer to the docs.

The consequence of this is that although the IFD might have been generated, it does not mean Mantra has actually finished rendering the image. This is where things start to get a little hairy. The RopNode module is a bit scarce. This is something I need to keep digging into some more because I could not find any properties or methods that would spit out some info regarding the renders. There is one other place Mantra can call Python methods but I’ll leave this for another post.

Running the Scripts

You can use Hscript or Python for your Pre and Post render scripts. I will stick to Python for now. First thing you want to do is change the dropdown option from Hscript to Python. Now here is the million dollar question. What goes in the text field? Your first instinct might be to click on the file browser and navigate to your Python script and be done. However, this will not work. If you hunt the docs for the answer, you won’t find it. At least I didn’t come across it.

Path to Python script file.
Path to Python script file.

In order to run external Python script files in this particular section, you need to need to use the Python Built-In function execfile(fn) . This function takes in a file and optional locals and globals arguments. For our purposes, we will just pass in the path to the Python file. The function will parse the file and execute the contents of the file, which is what we want. Whether there is another way of doing it is beyond me. This is a little strange since using execfile(fn) is frowned upon in Python circles due to being able to run malicious arbitrary code. Just keep this in mind.

So as an example, let’s say you want to log some info about your render before it starts such as a timestamp or adding additional notes about the render for other artists or the compositors. Here is my Python script that opens up a file handle and writes out a timestamp using the Python date module. I’m also importing the os module to wrangle the file path.

import datetime
import os

home = os.path.expandvars("$HOME")
fh = "{0}/Desktop/Mantra-Render-Scripts/log-tester.txt".format(home)

with open(fh, 'w') as log_file:
  log_file.write('Render started: {0}'.format(datetime.datetime.now().strftime('%H:%M: %d/%m/%Y')))

 

Mantra Python Pre render script
Mantra Python Pre render script

 

Pre Render Result.
Pre Render Result.

Just before the IFD is generated, our Python script will run and continue on its merry way. As you can see, it worked nicely. Obviously, you would take care of date formatting and any additional information you would want to add in a production script. One last thing I want to point out. As of Python 3.x, execfile(fn) has been removed. Instead of execfile(fn) use exec(open(fn).read()). Houdini version 15.5.480 is using Python 2.7.10 so we are good using the former. Happy rendering!

 

Share:
990adjustments

990adjustments

I am a motion designer & developer based out of South Florida. When not designing or animating pixels, I wrangle some code. If all else fails, I watch Twilight Zone, I Love Lucy, or Three's Company reruns.