Python
Bits of pymel, bits of houdini, bits of general file manipulation.
General
Renaming sequence of files
Have sequence starting at 5098034.jpg, needs to be 4 digit pad starting at 1.
Yes I'm sure its faster in bash/tcsh, whatevs.
import os
def doit():
files = os.listdir(os.getcwd())
# trim list to numbered jpgs, just in case
files = [f for f in files if f[0].isdigit() and f.endswith(".jpg")]
files.sort()
fmt = '%04d.jpg'
newnames = list(enumerate(files,1))
newnames = [ (fmt % i[0], i[1]) for i in newnames]
for f in newnames:
os.rename(f[1], f[0])
print '%s -> %s' % (f[1], f[0])
'''
# from python prompt:
import renum
import os
os.chdir('/path/to/images'); renum.doit()
'''
import os
def doit():
files = os.listdir(os.getcwd())
# trim list to numbered jpgs, just in case
files = [f for f in files if f[0].isdigit() and f.endswith(".jpg")]
files.sort()
fmt = '%04d.jpg'
newnames = list(enumerate(files,1))
newnames = [ (fmt % i[0], i[1]) for i in newnames]
for f in newnames:
os.rename(f[1], f[0])
print '%s -> %s' % (f[1], f[0])
'''
# from python prompt:
import renum
import os
os.chdir('/path/to/images'); renum.doit()
'''
Fillframes, copy nearest frames in an image sequence to missing frames
Happens all the time; you have a broken render, or a long running render, tools downstream require a full image sequence to generate quicktimes or mp4s, but manually patching the missing frames is a chore. This is a largely untested, untrustworthy script that if given a directory, will find the missing exr images, and copy the nearest frame. Only works with exr, and assumes for prefix.####.exr.
#!/usr/bin/python
import os
import sys
import shutil
def fillframes():
'''
Given a directory, it will scan for a sequence of exrs, find missing images,
and copy the nearest frame to the missing ones to patch the holes.
Assumes it'll find a bunch of exrs in the specified folder, named somethingsomething.####.exr.
Error checking, saftey etc is almost non-existent. May contain traces of peanuts.
Use thusly:
fillframes.py /path/to/the/directory/of/exrs/
'''
try:
dir = sys.argv[1]
except IndexError:
print 'usage: fillframes.py /path/to/folder'
print '2nd argument not found, exiting'
sys.exit()
if not os.path.isdir(dir):
print 'usage: fillframes.py /path/to/folder'
print '2nd argument not a directory, exiting'
sys.exit()
print '\nscanning ', dir
files = [x for x in os.listdir(dir) if x.endswith('.exr')]
if not files:
print 'no exr images found, exiting'
sys.exit()
prefix = files[0].split('.')[0]
suffix = files[0].split('.')[2]
actualframes = [int(f.split('.')[1]) for f in files]
actualframes.sort()
firstframe = actualframes[0]
lastframe = actualframes[-1]
idealrange = range(firstframe,lastframe+1)
print 'found ' + str(len(actualframes)) + ' images'
print 'startframe: ', firstframe
print 'lastframe: ', lastframe
if len(idealrange) == len(actualframes):
print 'no missing frames, all good!'
else:
for idealframe in idealrange:
if idealframe not in actualframes:
print idealframe, ' missing'
nearestframe = min(actualframes, key=lambda x:abs(x-idealframe))
sourcename = [prefix, str(nearestframe), suffix]
sourcename = '.'.join(sourcename)
targetname = [prefix, str(idealframe), suffix]
targetname = '.'.join(targetname)
print 'copy ', sourcename,' -> ', targetname
sourcename = dir+sourcename
targetname = dir+targetname
shutil.copyfile(sourcename, targetname)
fillframes()
#!/usr/bin/python
import os
import sys
import shutil
def fillframes():
'''
Given a directory, it will scan for a sequence of exrs, find missing images,
and copy the nearest frame to the missing ones to patch the holes.
Assumes it'll find a bunch of exrs in the specified folder, named somethingsomething.####.exr.
Error checking, saftey etc is almost non-existent. May contain traces of peanuts.
Use thusly:
fillframes.py /path/to/the/directory/of/exrs/
'''
try:
dir = sys.argv[1]
except IndexError:
print 'usage: fillframes.py /path/to/folder'
print '2nd argument not found, exiting'
sys.exit()
if not os.path.isdir(dir):
print 'usage: fillframes.py /path/to/folder'
print '2nd argument not a directory, exiting'
sys.exit()
print '\nscanning ', dir
files = [x for x in os.listdir(dir) if x.endswith('.exr')]
if not files:
print 'no exr images found, exiting'
sys.exit()
prefix = files[0].split('.')[0]
suffix = files[0].split('.')[2]
actualframes = [int(f.split('.')[1]) for f in files]
actualframes.sort()
firstframe = actualframes[0]
lastframe = actualframes[-1]
idealrange = range(firstframe,lastframe+1)
print 'found ' + str(len(actualframes)) + ' images'
print 'startframe: ', firstframe
print 'lastframe: ', lastframe
if len(idealrange) == len(actualframes):
print 'no missing frames, all good!'
else:
for idealframe in idealrange:
if idealframe not in actualframes:
print idealframe, ' missing'
nearestframe = min(actualframes, key=lambda x:abs(x-idealframe))
sourcename = [prefix, str(nearestframe), suffix]
sourcename = '.'.join(sourcename)
targetname = [prefix, str(idealframe), suffix]
targetname = '.'.join(targetname)
print 'copy ', sourcename,' -> ', targetname
sourcename = dir+sourcename
targetname = dir+targetname
shutil.copyfile(sourcename, targetname)
fillframes()
Write to a file, read it back
#source
build = hou.node('/obj/box').asCode(brief=False, recurse=True )
f = open('/tmp/houbuild.py','w'); f.write(build); f.close()
#target
del(hou_parent) # if you've run this before
f = open('/tmp/houbuild.py','r'); build=f.read(); f.close(); exec(build)
#source
build = hou.node('/obj/box').asCode(brief=False, recurse=True )
f = open('/tmp/houbuild.py','w'); f.write(build); f.close()
#target
del(hou_parent) # if you've run this before
f = open('/tmp/houbuild.py','r'); build=f.read(); f.close(); exec(build)
Use os.walk to get all image files under the current folder
#!/usr/bin/python
suffixes = ['jpg', 'png','cr2']
suffixes += [x.upper() for x in suffixes]
suffixes = ['.'+x for x in suffixes]
other = []
matches = []
print suffixes
import os
for root, dirs, files in os.walk(os.curdir):
for name in files:
found = 0
for suf in suffixes:
if (suf in name):
matches.append(os.path.join(root, name))
found +=1
if not found:
other.append(os.path.join(root, name))
print other
print matches
#!/usr/bin/python
suffixes = ['jpg', 'png','cr2']
suffixes += [x.upper() for x in suffixes]
suffixes = ['.'+x for x in suffixes]
other = []
matches = []
print suffixes
import os
for root, dirs, files in os.walk(os.curdir):
for name in files:
found = 0
for suf in suffixes:
if (suf in name):
matches.append(os.path.join(root, name))
found +=1
if not found:
other.append(os.path.join(root, name))
print other
print matches
Maya
Clone a nurbs curve to many curves
Like cloning poly meshes with outmesh to inmesh, you can connect mycurveshape.local to othercurve.create to have many curves replicate the shape of one curve. The connection editor is sucky at the best of times, and this seemed like a good excuse to write a clean little pymel tidbit. Master curve shape is called 'master_curve', and I've selected all the other curve shapes that'll be clones.
from pymel.core import *
for c in selected():
SCENE.master_curve.local >> c.create
# same, but as a list comprehension
[ SCENE.master_curve.local >> c.create for c in selected() ]
from pymel.core import *
for c in selected():
SCENE.master_curve.local >> c.create
# same, but as a list comprehension
[ SCENE.master_curve.local >> c.create for c in selected() ]
Simple! 2 handy tricks here:
- You can refer to anything in the scene by name with the SCENE. prefix
- connecting attributes is as easy as using '>>'
clone curves with animated timeoffset
Similar to the previous example, except this time I have a soup timeoffset node which I've keyframed, I want that also duplicated and driving each curve shape I have selected. Boring repetitive work becomes very easy with pymel.
'But Matt!' you cry, 'Why don't you just duplicate with history?'. Because there's a massive history behind the original curve, and that'll remain identical for all the curves, the only thing I want different for each curve is the timeoffset, which I'll fiddle by hand. This creates me a simple setup ready for me to play with.
from pymel.core import *
driver = SCENE.hero_curve_shape
timeoffset = SCENE.timeOffset1
animcurve = SCENE.timeOffset1_time
for c in selected(): # assume this is a nurbs curve shape for now
to = duplicate(timeoffset)[0]
ac = duplicate(animcurve)[0]
driver.local >> to.inGeometry
to.outGeometry >> c.create
ac.output >> to.time
from pymel.core import *
driver = SCENE.hero_curve_shape
timeoffset = SCENE.timeOffset1
animcurve = SCENE.timeOffset1_time
for c in selected(): # assume this is a nurbs curve shape for now
to = duplicate(timeoffset)[0]
ac = duplicate(animcurve)[0]
driver.local >> to.inGeometry
to.outGeometry >> c.create
ac.output >> to.time
Random scale/rotate of lots of trees
I'd instance-duplicated out a bunch of vray proxy trees, needed a little randomising. This set of 3 list comprehensions gives a random rotation in y between 0 and 360, a random y scale between 0.8 and 1.2, and shuffles their translation 15 units in x and z.
from pymel.core import *
import random
[ x.rotate.set( 0, random.randrange(0,360),0) for x in ls(selection=True) ]
[ x.scale.set( 1, random.uniform(0.8,1.2) ,1) for x in ls(selection=True) ]
[ x.translate.set( x.translate.get() + (random.randrange(-15,15),0,random.randrange(-15,15) )) for x in ls(selection=True) ]
from pymel.core import *
import random
[ x.rotate.set( 0, random.randrange(0,360),0) for x in ls(selection=True) ]
[ x.scale.set( 1, random.uniform(0.8,1.2) ,1) for x in ls(selection=True) ]
[ x.translate.set( x.translate.get() + (random.randrange(-15,15),0,random.randrange(-15,15) )) for x in ls(selection=True) ]
Set decay region on spotlights, move each light back 200 units on its own axis
Was doing a searchlights style shot, the vray volume fog went crazy at the base of the lights. figured it was cos it was crazy high intensity at a single point, so if i could use the light decay region to offset the light intensity away from its center, then offset the translation of the light to compensate, it'd help. It did. 😃
from pymel.core import *
lgts = ls(selection=True)
for lgt in lgts:
lgt.useDecayRegions.set(1)
lgt.startDistance1.set(0)
lgt.endDistance1.set(0)
lgt.startDistance2.set(0)
lgt.endDistance2.set(0)
lgt.startDistance3.set(200)
lgt.endDistance3.set(10000)
g = group(empty=True, parent=lgt.getParent(), name='%s_offset'%lgt.name() )
g.translate.set(0,0,200)
parent(lgt, g, shape=True, relative=True)
from pymel.core import *
lgts = ls(selection=True)
for lgt in lgts:
lgt.useDecayRegions.set(1)
lgt.startDistance1.set(0)
lgt.endDistance1.set(0)
lgt.startDistance2.set(0)
lgt.endDistance2.set(0)
lgt.startDistance3.set(200)
lgt.endDistance3.set(10000)
g = group(empty=True, parent=lgt.getParent(), name='%s_offset'%lgt.name() )
g.translate.set(0,0,200)
parent(lgt, g, shape=True, relative=True)
Rename an image sequence
Good to do this in python, keep the skillz up etc.
import os
folder = '//path/to/bad/images/images/'
old = 'oldbrokenprefix'
new = 'newprefix'
os.chdir(folder)
for f in os.listdir(folder):
os.rename(f, f.replace(old,new) )
import os
folder = '//path/to/bad/images/images/'
old = 'oldbrokenprefix'
new = 'newprefix'
os.chdir(folder)
for f in os.listdir(folder):
os.rename(f, f.replace(old,new) )