#!/usr/bin/python import os,re,sys,math,string,numpy from optparse import OptionParser, Option # ----------------------------- class extendableOption(Option): # ----------------------------- # used for definition of new option parser action 'extend', which enables to take multiple option arguments # taken from online tutorial http://docs.python.org/library/optparse.html ACTIONS = Option.ACTIONS + ("extend",) STORE_ACTIONS = Option.STORE_ACTIONS + ("extend",) TYPED_ACTIONS = Option.TYPED_ACTIONS + ("extend",) ALWAYS_TYPED_ACTIONS = Option.ALWAYS_TYPED_ACTIONS + ("extend",) def take_action(self, action, dest, opt, value, values, parser): if action == "extend": lvalue = value.split(",") values.ensure_value(dest, []).extend(lvalue) else: Option.take_action(self, action, dest, opt, value, values, parser) def location(idx,res): return numpy.array([ idx % res[0], \ (idx // res[0]) % res[1], \ (idx // res[0] // res[1]) % res[2] ]) def index(location,res): return ( location[0] % res[0] + \ (location[1] % res[1]) * res[0] + \ (location[2] % res[2]) * res[0] * res[1] ) # -------------------------------------------------------------------- # MAIN # -------------------------------------------------------------------- parser = OptionParser(option_class=extendableOption, usage='%prog [options] [file[s]]', description = """ Average each data block of size 'packing' into single values thus reducing the former resolution to resolution/packing. (Requires numpy.) """ + string.replace('$Id$','\n','\\n') ) parser.add_option('-m','--memory', dest='memory', action='store_true', \ help='load complete file into memory [%default]') parser.add_option('-r','--resolution', dest='res', type='int', nargs=3, \ help='resolution in fast, medium, and slow dimension [%default]') parser.add_option('-p','--packing', dest='packing', type='int', nargs=3, \ help='number of data points to average down in each dimension [%default]') parser.set_defaults(memory = False) parser.set_defaults(resolution = [32,32,32]) parser.set_defaults(packing = [2,2,2]) (options,filenames) = parser.parse_args() if len(options.resolution) < 3: parser.error('resolution needs three parameters...') if len(options.packing) < 3: parser.error('packing needs three parameters...') options.packing = numpy.array(options.packing) # ------------------------------------------ setup file handles --------------------------------------- files = [] if filenames == []: files.append({'name':'STDIN', 'input':sys.stdin, 'output':sys.stdout}) else: for name in filenames: if os.path.exists(name): (head,tail) = os.path.split(name) files.append({'name':name, 'input':open(name), 'output':open(os.path.join(head,'avgDown_%s'%tail),'w')}) # ------------------------------------------ loop over input files --------------------------------------- for file in files: print file['name'] # get labels by either read the first row, or - if keyword header is present - the last line of the header firstline = file['input'].readline() m = re.search('(\d+)\s*head', firstline.lower()) if m: headerlines = int(m.group(1)) passOn = [file['input'].readline() for i in range(1,headerlines)] headers = file['input'].readline().split() else: headerlines = 1 passOn = [] headers = firstline.split() if options.memory: data = file['input'].readlines() else: data = [] # ------------------------------------------ assemble header --------------------------------------- output = '%i\theader'%(headerlines+1) + '\n' + \ ''.join(passOn) + \ string.replace('$Id$','\n','\\n')+ '\t' + \ ' '.join(sys.argv[1:]) + '\n' + \ '\t'.join(headers) + '\n' # build extended header if not options.memory: file['output'].write(output) output = '' # ------------------------------------------ read file --------------------------------------- averagedDown = numpy.zeros([options.res[2]/options.packing[2], options.res[1]/options.packing[1], options.res[0]/options.packing[0], len(headers)]) idx = 0 for line in {True : data, False : file['input']}[options.memory]: items = numpy.array(map(float,line.split()[:len(headers)])) if len(items) < len(headers): continue loc = location(idx,options.res)//options.packing averagedDown[loc[2],loc[1],loc[0],:] += items idx += 1 averagedDown /= options.packing[0]*options.packing[1]*options.packing[2] for z in range(options.res[2]/options.packing[2]): for y in range(options.res[1]/options.packing[1]): for x in range(options.res[0]/options.packing[0]): output += '\t'.join(map(str,averagedDown[z,y,x,:])) + '\n' file['input'].close() # ------------------------------------------ output result --------------------------------------- file['output'].write(output) if file['name'] != 'STDIN': file['output'].close