AWS Thinkbox Discussion Forums

Automatic VRAY Denoise Job after Render Job finishes

Hi everyone!
I was wondering if it is possible to write a script for deadline, having it automatically vray denoise frames of a previously rendered job.
It is of course possible to do this manually, but how would one go about getting the output folder and filenames of rendered frames to be input into the vray denoise job?

thanks a bunch!

Hey blenderme,

Another user is attempting a similar thing here by using an event plugin to create their own job (they’re using Nuke).

What it essentially amounts to is that if your original job has the output filenames in the job, you can access those values in an event plugin (ie. OnJobFinished) using something like this:

...
def OnJobFinished(self, job): 
    ...
    # Need to filter out non-applicable jobs
    ...
    # You'd need to submit a VDenoise job for each outputfilename
    for outputPath in job.JobOutputFileNames: # A list of the 'OutputFilename's in the job
        ...
        writer = StreamWriter( pluginInfoFilename, False, Encoding.Unicode )
        writer.Write( "InputPath=%s" % outputPath )
        # Write other applicable info needed...
        ...
        writer.Close()

Anyways, that should be enough to get you started. You can also check out the docs on event plugins or you can browse “DeadlineRepository10/scripts/Submission/VDenoiseSubmission.py” to see how we create a VDenoise job.

Let us know how it goes!

Cheers

Hi mepp!

I am completely new to phyton. I can do a couple of tricks with Maxscript but I am not a coder. My question is: Are python skills required to do an automatic post job of vray denoise? I simply can’t continue from your starting point.
I’ve tried to modify the code of this thread and all I can achieve is execute the script without errors… and without denoising xD
I would like to run VRAY Denoise after the drafting job of a tiled rendering. Is there any template, sample or tutorial which I can follow?

Thank you very much for your help :smiley:

In case it helps, here is the code (you can have a good laugh :wink: no problem)

####### START CODE ######
def main( *args ):

def __init__(self):
	self.OnJobFinishedCallback += self.OnJobFinished

def Cleanup(self):
	del self.OnJobFinishedCallback
	
def OnJobFinished( self, job ):
	# TODO: Connect to pipeline site to notify it that the job for a particular
	# shot or task is complete.

	jobInfoFilename = Path.Combine( ClientUtils.GetDeadlineTempPath(), "automVRAYDenoise_jobInfo.job" )
	writer = StreamWriter( jobInfoFilename, False, Encoding.Unicode )
	writer.WriteLine( "Plugin=VDenoise" )
	writer.WriteLine( "Name=%s - Automatic VRAY Denoise" % job.JobName )
	
	
	outputDirectory = job.OutputDirectories[0]
	outputFilename = job.OutputFileNames[0]
	outputFilename = outputFilename.replace("#","")
	outputFilename = outputFilename[:-4]
	vrayDenoisePath = "%s\%s.????.exr" % (outputDirectory,outputFilename)
	self.LogInfo( vrayDenoisePath )
	
	
	writer.WriteLine( "Frames=%s" % job.JobFrames )


	writer.Close()
	
	# Create plugin info file.
	pluginInfoFilename = Path.Combine( ClientUtils.GetDeadlineTempPath(), "automVRAYDenoise_pluginInfo.job" )
	writer = StreamWriter( pluginInfoFilename, False, Encoding.Unicode )

	writer.WriteLine( "InputPath=%s" % vrayDenoisePath )        
	writer.WriteLine( "DenoiseMode=Default" )
	writer.WriteLine( "SkipExisting=True" )
	writer.WriteLine( "DenoiseElements=False" )
	writer.WriteLine( "UseGPU=True" )

	
	writer.Close()

	ClientUtils.ExecuteCommand( (jobInfoFilename,pluginInfoFilename) )


	self.LogInfo("Event Plugin: Complete")

####### END CODE ########

Hey nomte! I think there are some tricky bits from that other thread that might need fixing up.

Specifically, I’m not sure if the tuple of commands will actually work. Namely this line:

	ClientUtils.ExecuteCommand( (jobInfoFilename,pluginInfoFilename) )

Can you change it to look like this:

	print ClientUtils.ExecuteCommand( [jobInfoFilename, pluginInfoFilename] )

The two changes here are that it will actually send a Python list (as outlined in the documentation) but also it will print out the result of running the command and will hopefully let us know if it succeeded or failed.

Hopefully that gets us a step or two closer. :slight_smile:

Hi eamsler! Thank you for your answer.

I’ve already made the change but unfortunately no improvements. I’ve check the task log but it looks as simple as before.

-###### START ######-

=======================================================

Log

=======================================================

2018-10-12 16:35:29: 0: Loading Job’s Plugin timeout is Disabled

2018-10-12 16:35:31: 0: Executing plugin command of type ‘Sync Files for Job’

2018-10-12 16:35:31: 0: Synchronization time for job files: 52.003 ms

2018-10-12 16:35:31: 0: Synchronizing Plugin DraftTileAssembler from X:/DeadlineRepository10\plugins\DraftTileAssembler took: 0 seconds

2018-10-12 16:35:31: 0: Done executing plugin command of type ‘Sync Files for Job’

2018-10-12 16:35:31: 0: Executing plugin command of type ‘Initialize Plugin’

2018-10-12 16:35:31: 0: INFO: Executing plugin script ‘C:\Users\mitarbeiter\AppData\Local\Thinkbox\Deadline10\slave\daniel\plugins\5bc0b0b52ffab829d4aaaa2c\DraftTileAssembler.py’

2018-10-12 16:35:32: 0: INFO: Found Draft python module at: ‘C:\Users\mitarbeiter\AppData\Local\Thinkbox\Deadline10\slave\daniel\Draft\Draft.pyd’

2018-10-12 16:35:32: 0: INFO: About: Draft Tile Assembler Plugin for Deadline

2018-10-12 16:35:32: 0: INFO: Render Job As User disabled, running as current user ‘mitarbeiter’

2018-10-12 16:35:32: 0: INFO: The job’s environment will be merged with the current environment before rendering

2018-10-12 16:35:32: 0: Done executing plugin command of type ‘Initialize Plugin’

2018-10-12 16:35:32: 0: Start Job timeout is disabled.

2018-10-12 16:35:32: 0: Task timeout is being ignored because this is a Post Job Script Task

2018-10-12 16:35:32: 0: Loaded job: TEAPOT 2018 - Draft Tile Assembly (5bc0b0b52ffab829d4aaaa2c)

2018-10-12 16:35:32: 0: Plugin executing post job script

2018-10-12 16:35:32: 0: Executing Post Job Script: "Z:/11 Links Internet/Temp/Alo_Denoiser_Python004.py"

2018-10-12 16:35:32: 0: Executing plugin command of type ‘Execute Script’

2018-10-12 16:35:32: 0: INFO: Executing post job script ‘Z:/11 Links Internet/Temp/Alo_Denoiser_Python004.py’

2018-10-12 16:35:32: 0: Done executing plugin command of type ‘Execute Script’

=======================================================

Details …
-###### END ########-

Is this the LOG where the Print command dumps the results of execution?

Thanks again

Ah, this looks like the actual render log. The event gets its own job report that’s separate from this.

Can you check to see that your event is enabled? You’ll find it in “Tools” then “Configure Events” in the Monitor while in super user mode.

Hi eamsler,

Thanks for your reply. This weekend I’ve been trying to get to the basics of scripting for Deadline and certainly I need to get some skills before getting into this. Any other thing than an Out-of-the-box solution needs more coding than expected so I better get ready myself.

Thank you very much for your time and your support. I’ll be back with smarter questions :slight_smile:

I don’t mind pointing you to more information if you need it, so don’t feel bad for asking. You never know who might benefit from it.

In case anyone hits this thread, this is the working solution. Better late than never. Probably, it is highly optimizable, any C&C is welcom :slight_smile:

###### START OF THE CODE ####### 

from Deadline.Events import *

import os
import re

from System import *
from System.Collections.Specialized import *
from System.IO import *
from System.Text import *

from Deadline.Scripting import *

######################################################################
# This is the function that Deadline calls to get an instance of the
# main DeadlineEventListener class.
######################################################################
def GetDeadlineEventListener():
    return automaticVRAYDenoise()

######################################################################
# This is the function that Deadline calls when the event plugin is
# no longer in use so that it can get cleaned up.
######################################################################
def CleanupDeadlineEventListener( deadlinePlugin ):
    deadlinePlugin.Cleanup()

######################################################################
# This is the main DeadlineEventListener class for MyEvent.
######################################################################
class automaticVRAYDenoise (DeadlineEventListener):

    def __init__(self):
        self.OnJobFinishedCallback += self.OnJobFinished
        self.OnJobSubmittedCallback += self.OnJobSubmitted

    def Cleanup(self):
        del self.OnJobFinishedCallback
        del self.OnJobSubmittedCallback
        
    def OnJobSubmitted ( self, job ):
        
        ##### Discriminators to run the script
        if job.JobPlugin != "DraftTileAssembler":   #It triggers when a drafttileJob is sent
            return
        
        if job.JobGroup != "vraynext5":     #It triggers only of jobs of a certain Dealine group
            return
            
        mainString = job.JobBatchName       #It triggers if the job name contains the string "FastLane"
        subString = "FastLane"
        if (subString in mainString) == False:
            return
            
        #Comment this next line for production
        # if job.JobSubmitMachine != "alo":     #For debugging it only triggers for jobs sent from the testing machine
            # return
            
        ##### END Discriminators
        
        # jobMaestroLista = job.JobDependencyIDs
        # jobMaestroID = jobMaestroLista[0]
        # self.LogInfo("La ID del job maestro es = %s" % jobMaestroID )
        
        outputDirectoryList = job.JobOutputDirectories
        outputDirectoryToDenoise = outputDirectoryList[0]
        outputFilenameList = job.JobOutputFileNames
        outputFilenameToDenoise = outputFilenameList[0]
        archivoExrSalida = "%s\%s" % (outputDirectoryToDenoise, outputFilenameToDenoise)
        self.LogInfo("The EXR output path is = %s" % archivoExrSalida )
        
        jobInfoFilename = Path.Combine( ClientUtils.GetDeadlineTempPath(), "automVRAYDenoise_jobInfo.job" )
        writer = StreamWriter( jobInfoFilename, False, Encoding.Unicode )
        
        # CREATE JOB INFO FILE
        writer.WriteLine( "Plugin=VDenoise" )
        nombreJob = job.JobName
        nombreJob = nombreJob.replace(" (Render)", "")
        nombreJob = nombreJob.replace(" [Frame 0 - 36 Tiles]", "")
        nombreJob = nombreJob.replace(" - Draft Tile Assembly", "")
        nombreBatch = job.JobBatchName
        self.LogInfo("Name of the JOB = %s" % nombreJob)
        writer.WriteLine( "Name=%s - Automatic VRAY Denoise" % nombreJob )
        # Descomentar la siguiente linea para incluir el denoise en el Batch.
        writer.WriteLine( "BatchName=%s" % nombreBatch )
        writer.WriteLine( "MachineName=%s" % job.JobSubmitMachine)
        writer.WriteLine( "JobDependencies=%s" % job.JobId )
        #writer.WriteLine( "Frames=%s" % job.JobFrames )
        #writer.WriteLine( "Comment=%s" % scriptDialog.GetValue( "CommentBox" ) )
        #writer.WriteLine( "Department=%s" % scriptDialog.GetValue( "DepartmentBox" ) )
        writer.WriteLine( "Pool=%s" % "critical" )
        #writer.WriteLine( "SecondaryPool=%s" % scriptDialog.GetValue( "SecondaryPoolBox" ) )
        writer.WriteLine( "Group=%s" % job.JobGroup )
        #writer.WriteLine( "Priority=%s" % scriptDialog.GetValue( "PriorityBox" ) )
        #writer.WriteLine( "TaskTimeoutMinutes=%s" % scriptDialog.GetValue( "TaskTimeoutBox" ) )
        #writer.WriteLine( "EnableAutoTimeout=%s" % scriptDialog.GetValue( "AutoTimeoutBox" ) )
        #writer.WriteLine( "ConcurrentTasks=%s" % scriptDialog.GetValue( "ConcurrentTasksBox" ) )
        #writer.WriteLine( "LimitConcurrentTasksToNumberOfCpus=%s" % scriptDialog.GetValue( "LimitConcurrentTasksBox" ) )
        #writer.WriteLine( "MachineLimit=%s" % scriptDialog.GetValue( "MachineLimitBox" ) )
        #if( bool(scriptDialog.GetValue( "IsBlacklistBox" ) ) ):
        #    writer.WriteLine( "Blacklist=%s" % scriptDialog.GetValue( "MachineListBox" ) )
        #else:
        #    writer.WriteLine( "Whitelist=%s" % scriptDialog.GetValue( "MachineListBox" ) )
        
        #writer.WriteLine( "LimitGroups=%s" % scriptDialog.GetValue( "LimitGroupBox" ) )
        #writer.WriteLine( "OnJobComplete=%s" % scriptDialog.GetValue( "OnJobCompleteBox" ) )
        


        writer.Close()
        
        # CREATE PLUGIN INFO FILE
        pluginInfoFilename = Path.Combine( ClientUtils.GetDeadlineTempPath(), "automVRAYDenoise_pluginInfo.job" )
        writer = StreamWriter( pluginInfoFilename, False, Encoding.Unicode )

        writer.WriteLine( "InputPath=%s" % archivoExrSalida )        
        writer.WriteLine( "DenoiseMode=Default" )
        #writer.WriteLine( "Boost=%s" % scriptDialog.GetValue("BoostBox" ) )
        writer.WriteLine( "SkipExisting=True" )
        writer.WriteLine( "DenoiseElements=False" )
        writer.WriteLine( "UseGPU=True" )
        #writer.WriteLine( "OverrideThreshold=%s" % scriptDialog.GetValue("OverrideThresholdCheck" )) 
        #writer.WriteLine( "Threshold=%s" % scriptDialog.GetValue("ThresholdBox" ) )
        #writer.WriteLine( "OverrideStrength=%s" % scriptDialog.GetValue("OverrideStrengthCheck" ) )
        #writer.WriteLine( "Strength=%s" % scriptDialog.GetValue("StrengthBox" ) )
        #writer.WriteLine( "OverrideRadius=%s" % scriptDialog.GetValue("OverrideRadiusCheck" ) )
        #writer.WriteLine( "PixelRadius=%s" % scriptDialog.GetValue("RadiusBox" ) )
        #writer.WriteLine( "AdjustRadius=%s" % scriptDialog.GetValue("AutoRadiusCheck" ) )
        #writer.WriteLine( "FrameBlend=%s" % scriptDialog.GetValue("BlendBox" ) )
        #writer.WriteLine( "RenderStrips=%s" % scriptDialog.GetValue("StripsBox" ) )
        #writer.WriteLine( "UsingFrames=%s" % scriptDialog.GetValue( "UseFramesCheck" ) )
        
        writer.Close()

        ClientUtils.ExecuteCommand( (jobInfoFilename,pluginInfoFilename) )


        self.LogInfo("Event Plugin: Complete")
        
    
###### END OF THE CODE ####### 

Cheers, and thanks for the support!

1 Like
Privacy | Site terms | Cookie preferences