Documente Academic
Documente Profesional
Documente Cultură
Katana
for beginner's
M.Kedarnath
Structure of the book
Overview
The following documentation will give basic understanding of the below topics. After
going through this one can be able to script small programs using python. Which also gives a
basic understanding how Katana works inside and will be able to automate Katana as per
requirement.
Understanding scripting
Python-programming
Understanding Katana
Katana Scripting
Prerequisite
Scripting languages are languages that don't require an explicit compilation step. For
example, you have to compile a C program before you can run it. But in the normal case, you
don't have to compile a JavaScript program before you run it. So JavaScript is sometimes
called a "scripting" language.
Some examples of "scripting" languages (languages that are traditionally used without
an explicit compilation step):
Python
JavaScript
VBScript
Python can do almost all types of things except creating OS. For python we can use
words - scripting and programming interchangeably. Python runs through interpreter and also
can be compiled and used. Python supports multiple programming paradigms, including
object-oriented, imperative and functional programming or procedural styles. It features a
dynamic type system and automatic memory management and has a large and
comprehensive standard library
About python
Most current Linux distributions and Macs are still using 2.x as default. Also most of
the VFX Houses use 2.x, so we are going to concentrate in 2.x. There is a syntax differences
in 2.x and 3.x.
Why Python
Download and install python. By default python is installed in linux distributions. Get
into shell and type python to start python directly in shell.
[abc@localhost]# python
Here we can find which version of python we are using on which version GCC. To get
out of python use command exit()
>>>exit()
Syntax of python
Identifier is the name given to entities like class, functions, variables etc. in Python. It
helps differentiating one entity from another. Python is a case sensitive programming
language. Thus, name and Name are two different identifiers in Python.
Here are following naming convention for Python:
Class names start with an uppercase letter and all other identifiers with a lowercase
letter.
Starting an identifier with a single leading underscore indicates by convention that the
identifier is private.
Reserved words
The following list shows the reserved words in Python. These reserved words may not
be used as constant or variable or any other identifier names. All the Python keywords
contain lowercase letters only.
and exec not
assert finally or
break for pass
class from print
continue global raise
def if return
del import try
elif in while
else is with
except lambda yield
Multi-Line Statements:
Statements in python are usually one liners. Python allows the use of the line
continuation character (\) to denote that the line should continue. For example:
>>> total = 5+ \
6 + \
8
Quotation in Python:
Python accepts single ('), double (") and triple (''' or """) quotes to denote strings , as
long as the same type of quotes ends the string. In the below example all are correct.
>>> a = 'hi'
>>> a= hi
>>> a= ''' hi'''
Comments in Python:
A hash sign (#) begins a comment. All characters after the # and up to the physical line
end are part of the comment and the Python interpreter ignores them.
Along with the command line statements we can save .py file and run it through
command line. Different commands / statements can be combined in a python file and which
can be executed using 'python' command in shell.
Mathematical operators
+ Addition
- Subtraction
* Multiplication
/ Division
% Reminder
** exponent 10**20 is 10 to the power 20
// floor division 9//2 is equal to 4
Comparison operators
== equal
!= not equal
<> not equal
> greater than
< less than
>= greater than or equal
<= less than or equal
Assignment operators
= equal
+= c +=a is equivalent to c = c+a
-= c-=a is equivalent to c=c-a
*= c =a is equivalent to c= c*a
/= c/=a is equivalent to c =c/a
%= c%=a is equivalent to c=c%a
**= c**=a is equivalent to c=c**a
//= c//=a is equivalent to c=c//a
Logical operators
Membership operators
in x in y, result is 1 if x is a member of y
not in x not in y, results 1 if x is not a member of y
Decision Making
if x < 0:
x = 0
print 'Negative changed to zero'
elif x == 0:
print 'Zero'
elif x == 1:
print 'Single'
else:
print 'More'
Loops
while loop: Repeats a statement or group of statements while a given condition is true. It
tests the condition before executing the loop body.
for loop: Executes a sequence of statements multiple times and abbreviates the code
that manages the loop variable.
Nested loops:You can use one or more loop inside any another while, for or do..while loop.
Continue: Causes the loop to skip the remainder of its body and immediately retest its
condition before to reiterating.
Functions:
You can define functions to create the required functionality. Here are few
rules to define a function in Python.
Function blocks begin with the keyword def followed by the function name and
parentheses ( ( ) ).
Any input parameters or arguments should be placed within these parentheses. we
can also define parameters inside these parentheses.
The code in every function starts with a colon (:) and is indented.
IT returns value [expression] .
#syntax of a function
def functionname( parameters ):
"function_docstring"
function_suite
return [expression]
Syntax of module
### EXAMPLE
# Define variables:
one = 1
pi = 3.14
# defining functions
def printhello():
print "hello"
def circumf(input):
print input * 2*pi
# define a class
class mytest:
def __init__(self):
self.name = input("Name class? ")
self.num = input("number of students")
self.section = input("section of class")
def printdetails(self):
print "name of class is " + self.name
print self.section, "has, " + self.num +of students
once we have run the above module it created .pyc file. Now in the folder we can see
firstmodule.py and firstmodule.pyc.
.pyc contain the compiled bytecode of Python source files. The Python interpreter
loads .pyc files before .py files, so if they're present, it can save some time by not having to
re-compile the Python source code
Locating Modules:
When we import a module, the Python interpreter searches for the module in the
following sequences. One can write own python modules and keep at PYTHONPATH
location and use import to use the functions and classes
The current directory.
If the module isn't found, Python then searches each directory in the shell variable
called PYTHONPATH.
Both fails, Python checks the default path which is /usr/local/lib/python/. In linux
Using python we can create and edit the text data in any file. For example we can
store the any specific connections data of a maya scene file to a text file and it can be reused
in another file.
Opening A File
To open a file, we use the open() function to create a file object. Open takes two
arguments: the name of the file and the mode for which we'd like to open the file.
A file can be opened for reading ("r") or writing ("w"), just as with most other languages.
filename = myfile.txt
file = open(filename,'r')
content = file.read()
print content
lines = file.readlines()
for line in lines:
print line
file.close()
filename = 'myfile.txt'
file = open(filename, 'w')
file.write(hi this is my file)
file.close()
Class are blueprint of the programme. It describes how to make something. You can
create lots of objects in class. And there can be lots of classes in a programme. We can
create classes using 'class' . Below is the syntax of a class
# Defining a class
class myclass:
[statement 1]
[statement 2]
[statement 3]
def area(self):
return self.x * self.y
def perimeter(self):
return 2 * self.x + 2 * self.y
def scaleSize(self,scale):
self.x = self.x * scale
The first method __init__() is a special method, which is called class constructor or
initialization method that Python calls when you create a new instance of this class.
We can use inheritance to inherit one class from another.
We can write several programs using python. Below are the few examples which we
can try to write using different modules available online, which we can download and use.
By now we understood the basics of python and its uses. Lets understand Katana
Katana
Katana is a 3D appliction designed for lookdev and lighting. Katana mainly consists of
SceneGraph: A data tree containing all the information needed to render a scene.All data of
the scene graph is stored in Attributes. Scenegraphs heirarchical structure is made up of
locations that can be referenced by their path.
Group : Group nodes are nodes that can contain a number of child nodes. They are used to
simplify the nodegraph by collecting nodes.
Group node can be created by selecting on or more nodes and pressing Ctrl+G
Macros: Macros are nodes that can contain a number of child nodes, and publish them so
that they can be saved and recalled in other projects.
SuperTools: Super tools are compound nodes where the internal structure of nodes is
dynamically created using python scripting. Internal nodes can be created and deleted using
user actions.
Creating a Macro:
Lets create a sample macro step by step, which prunes object based on location in
scenegraph. This macro will prune lights having name ML0 and ML1 internally, and shows
the parameter which are exposed to user.
Create prune node and a switch which will prune *ML0* location from scene graph.
Similarly create another prune node and a switch which will prune *ML1* location from
scene graph
We can create as many as prune nodes and switches based on our requirement
Now we need to create a group out of these 4 nodes
Use ctrl+ Middle click to go inside the group node and using python scripting we
create input and output port for the node Group.
test = NodegraphAPI.GetNode('Group')
test.addOutputPort('Out')
test.addInputPort('In')
We can see if the switch value is 1 then the location is not pruned and if it is 0 then
location is pruned
Copy parameter from 'ML0', and paste expression to 'ML0Switch' parameter of Group
node
Copy parameter from 'ML1', and paste expression to 'ML1Switch' parameter of Group
node
This will set link between the two values and if we edit the parameter from Group node
then the value of the merge node will change automatically.
To change group node appearance we can use
Editnode -> Toggle Group node Appearance
Now go to Group node and click ' Finish editing user parameters' to finish the editing
Now you can set the parameters to yes / no to prune the location
Once everything is done we can publish the 'Group' node using editNode-> save as
Macro and give the name prune.macro
Now we can use prune_User macro in any project/ scene
We can re-edit the macro if required and republish it with the same name prune.macro
and can be used again
Once the macro is published it can be used in different scenes and recipes as per our
requirement.
Now lets jump into scripting in Katana
Katana Scripting
Now we can work with python to create and edit nodes in katana. Use python tab in
katana to write scripts.
We have noticed that while we can manually edit parameters on nodes in Nodegraph,
we cont edit attributes on scene graph location, this is because the flow of information from
Nodegraph to Scenegraph is strictly one way. This an important concept to keep mind when
writing attribute script nodes.
The following code shows how to get the full list of all the available node types using
the GetNodeTypes method in the NodegraphAPI module:
nodetypes = NodegraphAPI.GetNodeTypes()
nodetypes.sort()
for nodetype in nodetypes:
print nodetype
NodegraphAPI : The Nodegraph API is a Python interface for creating Katana recipes by
adding and connecting nodes, and setting Parameters. The Nodegraph API
cannot access the Scene Graph . The Node Graph API can be accessed by Python scripts in
the Python tab, Super Tools, plug-ins, shelves and other custom UI.
help(NodegraphAPI)
help(Nodes3DAPI)
help(UI4)
Similarly help can be used for other node types aswell. In UI4 we have other
classes/packages called Util.
help(UI4.Util)
Try out help on other nodes as well. Also print can be used to print to know about the
nodes
help(GeoAPI)
print(NodegraphAPI)
print(NodegraphaAPI.GetAllFlavors())
NodegraphAPI.GroupStack
help(NodegraphAPI.GroupStack.GroupStackNode)
As we know we need to create a node at root, we need to get the root and then create
any node. The below script will create GroupStack node and Rename the node.
root=NodegraphAPI.GetRootNode()
mynode = NodegraphAPI.CreateNode('GroupStack',root)
Now lets create a prman object settings node, rename it and stack it in mystack node
#create node
myprman = NodegraphAPI.CreateNode('PrmanObjectSettings', root)
#rename node
mprman.setName('myprmanobj1')
We can adjust the attributes of any node through script. We need to enable the local
assignment and we can set the value of any attribute. The below script will create a
prmanGlobalSettings node and set the pixelVariance value.
root = NodegraphAPI.GetRootNode()
myprman = NodegraphAPI.CreateNode('PrmanGlobalSettings', root)
en = myprman.getParameter
('args.prmanGlobalStatements.pixelVariance.enable')
If we already have the node PrmanGlobalSettings then we can use the below script to
select the node (using GetNode) and the other script remains same
#get the node wiht name 'PrmanGlobalSettings' and store it in
myprman to edit its values
myprman = NodegrapAPI.GetNode('PrmanGlobalSettings')
Selecting nodes:
Select nodes and run the below script to get selected nodes.
sel = NodegraphAPI.GetAllSelectedNodes()
print sel
Create a prman global settings node and use the below script to get child parameters
of the node
sel = NodegraphAPI.GetNode('PrmanGlobalSettings')
for p in sel.getParameters().getChildren():
print p
Delete nodes
sel = NodegraphAPI.GetNode('PrmanGlobalSettings')
sel.delete()
Delete selected nodes through script, select the nodes and save in list, to get the
items from list and delete use for loop
sel = NodegraphAPI.GetAllSelectedNodes()
for i in sel:
i.delete()
Producers
In any scene we can getnode which is in the end of a nodegraph and use producer to
get the accurate scene graph at that node. Below is the script to select objects through CEL
statement using python. Create a collection named bone to get the CEL command working
for the below script.
mynode = NodegraphAPI.GetNode('PrmanGlobalSettings')
prodcuer = Nodes3DAPI.GetGeometryProducer(mynode, 0)
cel = GeoAPI.Util.CollectPathsFromCELStatement(producer,
'(FLATTEN(//$bone))')
sg = ScenegraphManager.getActiveScenegraph()
sg.selectAndCreateLocations(cel)
Example Script
Lets create a script which creates an prmanObjectSettings node and add the selected
objects from the scene graph. In UI we can define the name of the node . Along with this we
can set the attributes of the PrmanObjectSettings. For now if the node exists then it replaces
the selected objects
class Example(QtGui.QDialog):
#########UI Design###########
self.setWindowTitle('ObjSettings')
layout = QtGui.QGridLayout()
label = QtGui.QLabel("name",self)
self._labelInput = QtGui.QLineEdit(self)
self._labelInput.setText(QtGui.QApplication.translate("MainW
indow","",None, QtGui.QApplication.UnicodeUTF8))
self._labelInput.move(100,150)
label.move(20,150)
createButton = QtGui.QPushButton("create",self)
layout.addWidget(createButton , 3, 0, 1, 2)
createButton.setDefault(1)
createButton.clicked.connect(self.prmanobj)
createButton.move(30, 200)
name = str(self._labelInput.text())
selected =
ScenegraphManager.getActiveScenegraph().getSelectedLocations()
root = NodegraphAPI.GetRootNode()
if NodegraphAPI.GetNode(name):
print('Exists')
else:
groupnode =
NodegraphAPI.CreateNode('PrmanObjectSettings', root)
groupnode.setName(name)
sel = NodegraphAPI.GetNode(name)
selection = sel.getParameter('CEL')
selection.setValue('('+' '.join(selected)+')', 0)
window = Example()
window.show()
Attribute Scripts:
Attribute scripts are similar to attribute modifiers, where we can modify the attributes
through python scripts. Through attribute script we can modify attribute at any given location.
We can create attribute scripts which run only on certain type of locations. AttributeSet will be
much faster than AttributeScript if all you're doing is setting attributes. AttributeScript can do a
lot more than set attributes.
Lets create an attributescript which changes the maxTimeSamples using python script.
MaxTimeSamples is an option which is not an object based setting, which is scene based or
layer based. So we need to apply the script at '/root' location. It wont work on any other
location or on object.
setAttr(renderSettings.maxTimeSamples,[4])
Similarly we can write different types of attribute scripts which can do lot of
manipulation in the scene/Nodegraph. We can set visibility setting using script which wont be
rendering.
Lets write a small script which checks the shutterclose, if it is 1 then make
maxtimeSamples to 4, and if shutterclose isn't 1 then it sets maxTimeSamples to 1
motionblur = GetAttr('renderSettings.shutterClose')
if motionblur == [1]:
SetAttr('renderSettings.maxTimeSamples',[4])
else:
SetAttr('renderSettings.maxTimeSamples',[3])
We can set anything based on conditions, Get the value of any attribute and based on
the value we can set any attributes value on the fly. Below examples can be created using
AttributeScripts
Disabling Deep AOVs using Attribute Script
Disable indirect specular
Disable material
SuperTools:
Super tools are compound nodes where the internal structure of nodes is dynamically
created using python scripting. Internal nodes can be created and deleted using user actions.
Many of Katana's common user level nodes (such as Importomatic, Gaffer and
lookfileManager) are actually super tools.
We can Ctrl+middle click to see the internal structure of SuperTool
AttributeAPI
RanderfarmAPI
ImportometiAPI
Viewer manipulaterAPI
RendererAPI
There are several enhancements and changes are being made in Katana2.x
compared to Katana 1.x. Lets have a look of few major changes.
Gaffer3 : New gaffer node is introduced in Katana2.x, has been created to provide improved
performance when dealing with large number of lights in the scene.
Lua OpScripts: Katana 2.x introduces a Lua based Opscript node which can be used
instead of python based AttributeScript nodes. It is recommended to use OpScript where
ever possible.
Keyboard Shortcut manager: A new module has been added to assign keyboard shortcuts
in Katana which was not available in the earlier versions.
Geolib3 : It is Katana's new scene graph processing library. It works at Katana's core to
support large data sets. In the earlier versions Geolib2 reconstructed the whole scene graph
on every edit, Where as Geolib3 allows inter-cook scene data re-use.
Python Tab: Tab has been enhanced for user friendly usage.
###################
Katana references
There are very few resources available on katana and its scripting.
Katana documentation
http://tomcowland.com/katana
http://community.thefoundry.co.uk/discussion/katana/
Python Reference:
There is a huge list of resources available online for Python. Advanced python-
programming can be learned through internet.
www.python.org