#!/usr/bin/python
import os, sys, glob, operator, string, afni_base
class afni_name:
def __init__(self, name=""):
res = parse_afni_name(name)
self.path = res['path']
self.prefix = res['prefix']
self.view = res['view']
self.extension = res['extension']
self.type = res['type']
return
def p(self): #Full path
pp = "%s/" % os.path.abspath('./') #full path at this location
fn = string.find(pp,self.path) #is path at end of abspath?
if (fn > 0 and fn+len(self.path) == len(pp)): #path is at end of abs path
return pp
else:
return os.path.abspath(self.path)
def ppve(self):
s = "%s/%s%s%s" % (self.p(), self.prefix, \
self.view, self.extension)
return s
def ppv(self):
s = "%s/%s%s" % (self.p(), self.prefix, self.view)
return s
def rpv(self): # relative path, prefix, view (no leading './')
if self.path == './':
s = "%s%s" % (self.prefix, self.view)
else:
s = "%s%s%s" % (self.path, self.prefix, self.view)
return s
def pp(self):
return "%s/%s" % (self.p(), self.prefix)
def pv(self):
return "%s%s" % (self.prefix, self.view)
def pve(self):
return "%s%s%s" % (self.prefix, self.view, self.extension)
def exist(self):
if (self.type == 'NIFTI'):
if ( os.path.isfile("%s.nii" % self.ppv()) or \
os.path.isfile("%s.nii.gz" % self.ppv()) \
):
return 1
else: return 0
elif (self.type == 'BRIK'):
if ( os.path.isfile("%s.HEAD" % self.ppv()) \
and \
( os.path.isfile("%s.BRIK" % self.ppv()) or \
os.path.isfile("%s.BRIK.gz" % self.ppv()) or \
os.path.isfile("%s.BRIK.bz2" % self.ppv()) or \
os.path.isfile("%s.BRIK.Z" % self.ppv()) ) \
):
return 1
else: return 0
elif (self.type == 'NIML'):
if ( os.path.isfile("%s.niml.dset" % self.ppv()) \
):
return 1
else: return 0
else:
if ( os.path.isfile(self.ppve()) ):
return 1
else: return 0
def delete(self, oexec=""): #delete files on disk!
if (self.type == 'BRIK'):
if os.path.isfile("%s.HEAD" % self.ppv()):
shell_exec("rm %s.HEAD" % self.ppv(), oexec)
if os.path.isfile("%s.BRIK" % self.ppv()):
shell_exec("rm %s.BRIK" % self.ppv(), oexec)
if os.path.isfile("%s.BRIK.gz" % self.ppv()):
shell_exec("rm %s.BRIK.gz" % self.ppv(), oexec)
if os.path.isfile("%s.BRIK.bz2" % self.ppv()):
shell_exec("rm %s.BRIK.bz2" % self.ppv(), oexec)
if os.path.isfile("%s.BRIK.Z" % self.ppv()):
shell_exec("rm %s.BRIK.Z" % self.ppv(), oexec)
else:
if os.path.isfile(self.ppve()):
shell_exec("rm %s" % self.ppve(), oexec)
return
def move_to_dir(self, path="", oexec=""):
#self.show()
#print path
found = 0
if os.path.isdir(path):
if (self.type == 'BRIK'):
if os.path.isfile("%s.HEAD" % self.ppv()):
sv = shell_com("mv %s %s/" % (self.head(), path), oexec)
found = found + 1
if os.path.isfile("%s.BRIK" % self.ppv()):
sv = shell_com("mv %s %s/" % (self.brick(), path), oexec)
found = found + 1
if os.path.isfile("%s.BRIK.gz" % self.ppv()):
sv = shell_com("mv %s %s/" % (self.brickgz(), path), oexec)
found = found + 1
if os.path.isfile("%s.BRIK.bz2" % self.ppv()):
sv = shell_com("mv %s %s/" % (self.brickbz2(), path), oexec)
found = found + 1
if os.path.isfile("%s.BRIK.Z" % self.ppv()):
sv = shell_com("mv %s %s/" % (self.brickZ(), path), oexec)
found = found + 1
if (found > 0):
self.new_path(path)
if ( not self.exist() and oexec != "dry_run"):
print "Error: Move to %s failed" % (self.ppv())
return 0
else:
print "Error: Found no .HEAD or .BRIK or .BRIK.gz (or .bz2 or .Z) of %s" % (self.ppv())
return 0
else:
if os.path.isfile("%s" % self.ppve()):
sv = shell_com("mv %s %s/" % (self.ppve(), path), oexec)
found = found + 1
if (found > 0):
self.new_path(path)
if ( not self.exist() and oexec != "dry_run"):
print "Error: Move to %s failed" % (self.ppv())
return 0
else:
print "Error: Found no file %s to move." % self.ppve()
return 0
else:
print "Error: Path %s not found for moving %s." % (path, self.ppv())
return 0
return 1
def head(self):
return "%s.HEAD" % self.ppv()
def brick(self):
return "%s.BRIK" % self.ppv()
def brickgz(self):
return "%s.BRIK.gz" % self.ppv()
def brickbz2(self):
return "%s.BRIK.bz2" % self.ppv()
def brickZ(self):
return "%s.BRIK.Z" % self.ppv()
def new_path(self,path=""):
#give name a new path
if len(path) == 0:
self.path = "./"
else:
if path[-1] == '/':
self.path = path
else:
self.path = "%s/" % path
def new_prefix(self, prefix=""):
self.prefix = prefix
def new_view(self,view=""):
self.view = view
def show(self):
print "AFNI filename:"
print " name : %s" % self.ppve()
print " path : %s" % self.path
print " prefix : %s" % self.prefix
print " view : %s" % self.view
print " exten. : %s" % self.extension
print " type : %s" % self.type
print " On Disk : %d" % self.exist()
def new(self,new_pref='', new_view=''):
#return a copy of class member with new_prefix and new_view if needed
an = afni_name()
an.path = self.path
if len(new_pref):
an.prefix = new_pref
else:
an.prefix = self.prefix
if len(new_view):
an.view = new_view
else:
an.view = self.view
an.extension = self.extension
an.type = self.type
return an
class comopt:
def __init__(self, name, npar, defpar, acplist=[]):
self.name = name
self.i_name = -1 # index of option name in argv
self.n_exp = npar # Number of expected params, 0 if no params,
# -1 if any number > 0 is OK.
# N if exactly N numbers are expected
self.n_found = -1 # Number of parameters found after parsing
# 0 means was on command line but had no params
self.parlist = None # parameter strings list following option
self.deflist = defpar # default parameter list,if any
self.acceptlist = acplist # acceptable values if any
self.required = 0 # is the argument required?
return
def show(self, mesg = ''):
print "%sComopt: %s" % (mesg, self.name)
print " (i_name, n_exp, n_found) = (%d, %d, %d)" % \
(self.i_name, self.n_exp, self.n_found)
print " parlist = %s" % self.parlist
print " deflist = %s" % self.deflist
print " acceptlist = %s" % self.acceptlist
def test(self):
if (len(self.deflist) != 0 and self.parlist == None):
# some checks possible, parlist not set yet
if self.n_exp >= 0:
if len(self.deflist) != self.n_exp:
print "Error: Option %s needs %d parameters\n" \
"Default list has %d parameters." \
% (self.name, self.n_exp, len(self.deflist))
return None
else:
if len(self.deflist) < -self.n_exp:
print "Error: Option %s needs at least %d parameters\n" \
"Default list has %d parameters."\
% (self.name, -self.n_exp, len(self.deflist))
return None
else :
if self.n_exp >= 0:
#print "option %s n_exp = %d, len(parlist)=%d" % (self.name, self.n_exp, len(self.parlist))
#self.show()
if len(self.parlist) != self.n_exp:
print "Error: Option %s needs %d parameters\n" \
"Parameter list has %d parameters." \
% (self.name, self.n_exp, len(self.parlist))
return None
else:
if len(self.parlist) < -self.n_exp:
print "Error: Option %s needs at least %d parameters\n" \
"Parameter list has %d parameters."\
% (self.name, -self.n_exp, len(self.parlist))
return None
return 1
class shell_com:
def __init__(self, com, eo="echo"):
self.com = com #command
self.dir = os.getcwd()
self.exc = 0 #command not executed yet
self.so = ''
self.se = ''
#If command line is long, trim it, if possible
l1 = len(self.com)
if (l1 > 80):
self.trimcom = self.trim()
#if (len(self.com) < l1):
#print "Command trimmed to: %s" % (self.com)
else:
self.trimcom = self.com
if (len(self.trimcom) < len(self.com)):
ms = " (command trimmed)"
else:
ms = ""
if eo == "echo":
print "#Now running%s:\n cd %s\n %s" % (ms, self.dir, self.trimcom)
#if (len(self.trimcom)):
# print "#Command trimmed to:\n %s" % (self.trimcom)
sys.stdout.flush()
self.run()
self.out()
elif eo == "dry_run":
print "#Would be running%s:\n cd %s\n %s" % (ms, self.dir, self.trimcom)
sys.stdout.flush()
self.out()
else:
self.run()
self.out()
return
def trim(self):
#try to remove absolute path
if self.dir[-1] != '/':
tcom = string.replace(self.com, "%s/" % (self.dir), '')
else:
tcom = string.replace(self.com, self.dir, '')
return tcom
def run(self):
so, se = shell_exec(self.trimcom, "")
self.so = so
self.se = se
self.exc = 1
def stdout(self):
if (len(self.so)):
print "++++++++++ stdout:"
sys.stdout.flush()
for ln in self.so:
print " %s" % ln
sys.stdout.flush()
def stderr(self):
if (len(self.se)):
print "---------- stderr:"
sys.stdout.flush()
for ln in self.se:
print " %s" % ln
def out(self):
if self.exc:
self.stdout()
self.stderr()
else:
print "#............. not executed."
sys.stdout.flush()
def val(self, i, j=-1): #return the jth string from the ith line of output. if j=-1, return all ith line
if not self.exc:
print "Error: Command not executed"
return None
elif len(self.so) == 0:
print "Error: Empty output."
return None
elif len(self.so) <= i:
print "Error: First index i=%d >= to number of elements (%d) in output " % \
(i, len(self.so))
return None
if j>= 0:
l = string.split(self.so[i])
if len(l) <= j:
print "Error: Second index j=%d is >= to number of elements (%d) in %dth line of output" % \
(j, len(l), i)
return None
else:
return l[j]
else:
return self.so[i]
# return the attribute list for the given dataset and attribute
def read_attribute(dset, atr):
[so, se] = shell_exec('3dAttribute %s %s' % (atr, dset))
if len(so) == 0:
print '** 3dAttribute exec failure for "%s %s":' % (atr, dset)
print se
return None
list = so[0].split()
if len(list) > 0: return list
else:
print '** 3dAttribute failure for "%s %s":' % (atr, dset)
return None
#transform a list of afni names to one string for shell script usage
def anlist(vlst, sb=''):
namelst = []
if len(sb):
sbs = "'%s'" % sb
else:
sbs = ''
for an in vlst:
namelst.append("%s%s" % (an.ppv(), sbs))
return string.join(namelst,' ')
#parse options, put into dictionary
def getopts(argv):
opts = {}
while argv:
if argv[0][0] == '-':
opts[argv[0]] = argv[1]
argv = argv[2:]
else:
argv = argv[1:]
return opts
def show_opts2(opts):
if opts == None:
print "Option dictionary is None\n"
return
print opts
for key in opts.keys():
print "Option Name: %s" % key
print " Found: %d" % opts[key].n_found
print " User Parameter List: %s" % opts[key].parlist
print " Default Parameter List: %s\n" % opts[key].deflist
return
def getopts2(argv,oplist):
""" A function to parse command line arguments.
to use it, you need to set up the options list.
So, from a main you can do the following:
oplist = []
# an option that needs no params
oplist.append(afni_base.comopt('-dicom', 0, []))
# an option that needs 2 params, with 2 options, defaulting to 2 and 10.0
oplist.append(afni_base.comopt('-clust', 2, ['2', '10.0']))
# an option that needs an undetermined number of parameters
# (-1 for 1 or more, -2 for 2 or more)
oplist.append(afni_base.comopt('-dsets', -1, []))
once the list is made, you call getopts2 with argv and oplist
opts = afni_base.getopts2(sys.argv, oplist)
opts is a dictionary with the name of oplist elements as keys
to get a quick look at it use:
afni_base.show_opts2(opts) """
opts = {}
if len(argv) == 0:
return opts
#Add the program name
op = comopt('basename',0, [])
opts['basename'] = op
argv.remove( argv[0] )
#form a list of the known options
optnames = []
for op in oplist:
optnames.append(op.name)
#find those options in oplist
for op in oplist:
if op.name in argv:
op.n_found = 0 #found that argument
op.iname = argv.index(op.name) #copy index into list
argv.remove(op.name) #remove this option from list
op.parlist = []
if op.n_exp < 0 or op.n_exp > 0: #parameters expected, get them
while ((op.n_exp < 0 and op.iname < len(argv)) or \
(op.n_exp > 0 and len(op.parlist) < op.n_exp and len(argv) > 0))\
and argv[op.iname] not in optnames:
if len(op.acceptlist):
if argv[op.iname] not in op.acceptlist:
print "Error: parameter value %s for %s is not " \
"acceptable\nChoose from %s" % \
(argv[op.iname], op.name, \
string.join(op.acceptlist, ' , '))
op.parlist.append(argv[op.iname]) #string added
argv.remove(argv[op.iname]) #remove this string from list
op.n_found = len(op.parlist)
else : #No option in argv, just copy option
op.parlist = op.deflist
#Now copy results to dictionary
opts[op.name] = op #a bit of redundancy, but I don't care
if (op.test() == None):
afni_base.show_opts2(opts)
return None
#Any remaining?
for op in oplist:
if op.name == 'loose': #Expecting loose params
if op.n_exp < 0 or op.n_exp > 0: #parameters expected, get them
op.parlist.extend(argv) #stick'em all in
opts[op.name] = op
if op.n_exp > 0 and len(op.parlist) != op.n_exp:
print "Error: Expecting %d parameters\n" \
"Have %d on command line (%s).\n" % \
(op.n_exp, len(op.parlist), op.parlist)
return None
elif len(argv) > 0:
print "Error: Expecting no loose parameters.\n" \
"Have %d loose parameters (or bad option) on " \
"command line (%s).\n" % (len(argv), argv)
return None
#go west young man
return opts
#Strip the extensions from extlist out of name
#returns name without the extension and the extension
#found, if any.
#Example:
# res = strip_extension('Hello.Jim', ['.paul', '.Jim'])
# --> res[0] = 'Hello'
# --> res[1] = '.Jim'
#
# To remove anything after the last 'dot'
# res = strip_extension('Hello.Jim', [])
#
def strip_extension(name, extlist):
res = {}
nle = len(name)
if len(extlist):
while extlist:
xle = len(extlist[0])
if nle > xle:
if name[-xle:] == extlist[0]:
res[0] = name[:-xle]
res[1] = extlist[0]
return res
#else:
#nada
#print name
#Go to next element
extlist = extlist[1:]
else: #Nothing specified, work the dot
spl = string.split(name,'.')
if len(spl) > 1:
res[0] = string.join(spl[0:-1],'.')
res[1] = '.'+spl[-1]
return res
#defaults
res[0] = name
res[1] = ''
return res
#parse an afni name
def parse_afni_name(name):
res = {}
#get the path #Can also use os.path.split
rp = os.path.dirname(name) #relative path
#ap = os.path.abspath(name) #absolute path
fn = os.path.basename(name)
#is this a .nii volume?
rni = strip_extension(fn,['.nii', '.nii.gz'])
if (len(rni[1]) > 0):
vi = '' #No view
ex = rni[1]
pr = rni[0]
tp = 'NIFTI'
else:
rni = strip_extension(fn,['.HEAD','.BRIK','.BRIK.gz','.BRIK.bz2','.BRIK.Z','.1D', '.', \
'.1D.dset', '.niml.dset'])
ex = rni[1]
if (ex == '.1D' or ex == '.1D.dset'):
tp = "1D"
elif (ex == '.niml.dset'):
tp = "NIML"
else:
tp = 'BRIK'
if (ex == '.'):
ex = '' #dump the dot
rni = strip_extension(rni[0], ['+orig','+tlrc','+acpc'])
vi = rni[1]
pr = rni[0]
#Build the dictionary result
if len(rp) == 0:
rp = '.'
res['path'] = "%s/" % rp
res['prefix'] = pr
res['view'] = vi
res['extension'] = ex
res['type'] = tp
return res
#utilitiarian laziness
def afni_prefix(names):
pref = []
for run in range(0, len(names)):
res = parse_afni_name(names[run])
pref.append(res['prefix'])
return pref
def afni_view(names):
pref = []
for run in range(0, len(names)):
res = parse_afni_name(names[run])
pref.append(res['view'])
return pref
#exectute a shell command and return results in so (stdout) and se (stderr)
def shell_exec(s,opt=""):
if opt == "dry_run":
print "In %s, would execute:\n%s" % (os.getcwd(), s)
return "", ""
elif opt == "echo":
print "In %s, about to execute:\n%s" % (os.getcwd(), s)
i,o,e = os.popen3(s,'r') #captures stdout in o, stderr in e and stdin in i
so = o.readlines()
se = e.readlines()
o.close
e.close
if (len(so) and opt == "echo"):
print "++++++++++ stdout:"
for ln in so:
print " %s" % ln
if (len(se) and opt == "echo"):
print "---------- stderr:"
for ln in se:
print " %s" % ln
return so, se
#generic unique function, from:
# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52560/index_txt
def unique(s):
"""Return a list of the elements in s, but without duplicates.
For example, unique([1,2,3,1,2,3]) is some permutation of [1,2,3],
unique("abcabc") some permutation of ["a", "b", "c"], and
unique(([1, 2], [2, 3], [1, 2])) some permutation of
[[2, 3], [1, 2]].
For best speed, all sequence elements should be hashable. Then
unique() will usually work in linear time.
If not possible, the sequence elements should enjoy a total
ordering, and if list(s).sort() doesn't raise TypeError it's
assumed that they do enjoy a total ordering. Then unique() will
usually work in O(N*log2(N)) time.
If that's not possible either, the sequence elements must support
equality-testing. Then unique() will usually work in quadratic
time.
"""
n = len(s)
if n == 0:
return []
# Try using a dict first, as that's the fastest and will usually
# work. If it doesn't work, it will usually fail quickly, so it
# usually doesn't cost much to *try* it. It requires that all the
# sequence elements be hashable, and support equality comparison.
u = {}
try:
for x in s:
u[x] = 1
except TypeError:
del u # move on to the next method
else:
return u.keys()
# We can't hash all the elements. Second fastest is to sort,
# which brings the equal elements together; then duplicates are
# easy to weed out in a single pass.
# NOTE: Python's list.sort() was designed to be efficient in the
# presence of many duplicate elements. This isn't true of all
# sort functions in all languages or libraries, so this approach
# is more effective in Python than it may be elsewhere.
try:
t = list(s)
t.sort()
except TypeError:
del t # move on to the next method
else:
assert n > 0
last = t[0]
lasti = i = 1
while i < n:
if t[i] != last:
t[lasti] = last = t[i]
lasti += 1
i += 1
return t[:lasti]
# Brute force is all that's left.
u = []
for x in s:
if x not in u:
u.append(x)
return u
#Get files from a wild card list
#e.g: GetFiles(["*.HEAD", "*.1D"])
def GetFiles(wild):
#print "wild is: >>>%s<<<" % wild
an = reduce(operator.add, map(glob.glob, wild))
#print "Expanded is: %s" % an
return an
def PrintIndexedList(l):
cnt = 0
for il in l:
print "%d- %s" % (cnt, il)
cnt += 1
print ""
def match(txt, l):
lm = []
for il in l:
fnd = il.find(txt)
if fnd >= 0:
lm.append(il)
return lm
def unique_match(txt, l):
lm = match(txt,l)
if len(lm) == 1:
return lm[0]
else:
return None
def GetSelectionFromList(l, prmpt = ""):
PrintIndexedList(l)
if len(prmpt)==0:
prmpt = 'Enter Selection by number or name: '
cnt = 0
while cnt < 10:
name = raw_input(prmpt)
if not name:
return None
if name.isdigit():
if int(name) < len(l) and int(name) >= 0:
return l[int(name)]
else:
print "Input error: number must be between 0 and %d" % (len(l)-1)
else:
if name in l:
return name
nameg = unique_match(name, l)
if nameg:
return nameg
else:
print "Input error: selection %s has %d matches in list." % \
( name, len(match(name, l)))
cnt += 1
print "Vous ne comprenez pas l'anglais?"
print "Ciao"
syntax highlighted by Code2HTML, v. 0.9.1