Bits of pymel, bits of houdini, bits of general file manipulation.
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.isdigit() and f.endswith(".jpg")] files.sort() fmt = '%04d.jpg' newnames = list(enumerate(files,1)) newnames = [ (fmt % i, i) for i in newnames] for f in newnames: os.rename(f, f) print '%s -> %s' % (f, f) ''' # 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 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.split('.') suffix = files.split('.') actualframes = [int(f.split('.')) for f in files] actualframes.sort() firstframe = actualframes 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)
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() ]
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) ac = duplicate(animcurve) 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) ]
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)
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) )
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