polishing of variable names, comments, and some of the programming structure.
This commit is contained in:
parent
fec50e424e
commit
72e9c512bd
|
@ -57,22 +57,23 @@ The final geometry is assembled by selecting at each voxel that grain index for
|
||||||
""" + string.replace(scriptID,'\n','\\n')
|
""" + string.replace(scriptID,'\n','\\n')
|
||||||
)
|
)
|
||||||
|
|
||||||
parser.add_option('-d', '--distance', dest='d', type='int', metavar='int', \
|
parser.add_option('-d', '--distance', dest='d', type='int', metavar='int',
|
||||||
help='diffusion distance in voxels [%default]')
|
help='diffusion distance in voxels [%default]')
|
||||||
parser.add_option('-N', '--smooth', dest='N', type='int', metavar='int', \
|
parser.add_option('-N', '--smooth', dest='N', type='int', metavar='int',
|
||||||
help='N for curvature flow [%default]')
|
help='N for curvature flow [%default]')
|
||||||
parser.add_option('-r', '--renumber', dest='renumber', action='store_true', \
|
parser.add_option('-r', '--renumber', dest='renumber', action='store_true',
|
||||||
help='renumber microstructure indices from 1...N [%default]')
|
help='renumber microstructure indices from 1...N [%default]')
|
||||||
parser.add_option('-i', '--immutable', action='extend', dest='immutable', type='string', \
|
parser.add_option('-i', '--immutable', action='extend', dest='immutable', type='string', metavar = '<LIST>',
|
||||||
help='immutable microstructures')
|
help='list of immutable microstructures')
|
||||||
|
|
||||||
parser.set_defaults(d = 1)
|
parser.set_defaults(d = 1)
|
||||||
parser.set_defaults(N = 1)
|
parser.set_defaults(N = 1)
|
||||||
parser.set_defaults(renumber = False)
|
parser.set_defaults(renumber = False)
|
||||||
parser.set_defaults(immutable = [0])
|
parser.set_defaults(immutable = [])
|
||||||
|
|
||||||
(options, filenames) = parser.parse_args()
|
(options, filenames) = parser.parse_args()
|
||||||
|
|
||||||
|
options.immutable = map(int,options.immutable)
|
||||||
|
|
||||||
#--- setup file handles --------------------------------------------------------------------------
|
#--- setup file handles --------------------------------------------------------------------------
|
||||||
files = []
|
files = []
|
||||||
|
@ -157,73 +158,83 @@ for file in files:
|
||||||
i += s
|
i += s
|
||||||
|
|
||||||
#--- reshape, if 2D make copy ---------------------------------------------------------------------
|
#--- reshape, if 2D make copy ---------------------------------------------------------------------
|
||||||
expandedGrid = numpy.array([2 if i == 1 else i for i in info['grid']],'i')
|
|
||||||
nMicrostuctures = numpy.prod(expandedGrid)
|
|
||||||
if nMicrostuctures > info['grid'].prod():
|
|
||||||
microstructure[info['grid'].prod():nMicrostuctures] = microstructure[0:info['grid'].prod()]
|
|
||||||
microstructure = microstructure.reshape([2 if i == 1 else i for i in info['grid']],order='F')
|
|
||||||
grid = numpy.array([2 if i == 1 else i for i in info['grid']],'i')
|
|
||||||
|
|
||||||
|
microstructure = numpy.tile(microstructure.reshape(info['grid'],order='F'),
|
||||||
|
numpy.where(info['grid'] == 1, 2,1)) # make one copy along dimensions with grid == 1
|
||||||
|
grid = numpy.array(microstructure.shape)
|
||||||
|
|
||||||
|
#--- initialize support data -----------------------------------------------------------------------
|
||||||
|
|
||||||
#--- initialize helper data -----------------------------------------------------------------------
|
periodic_microstructure = numpy.tile(microstructure,(3,3,3))[grid[0]/2:-grid[0]/2,
|
||||||
X,Y,Z = numpy.mgrid[0:expandedGrid[0],0:expandedGrid[1],0:expandedGrid[2]]
|
grid[1]/2:-grid[1]/2,
|
||||||
gauss = numpy.exp(-(X*X+Y*Y+Z*Z)/(2.0*options.d*options.d))/math.pow(2.0*numpy.pi*options.d*options.d,1.5)
|
grid[2]/2:-grid[2]/2] # periodically extend the microstructure
|
||||||
gauss[:,:,(expandedGrid[2])/2::] = gauss[:,:,(expandedGrid[2])/2-1::-1]
|
microstructure_original = numpy.copy(microstructure) # store a copy the initial microstructure to find locations of immutable indices
|
||||||
gauss[:,(expandedGrid[1])/2::,:] = gauss[:,(expandedGrid[1])/2-1::-1,:]
|
|
||||||
gauss[(expandedGrid[0])/2::,:,:] = gauss[(expandedGrid[0])/2-1::-1,:,:]
|
X,Y,Z = numpy.mgrid[0:grid[0],0:grid[1],0:grid[2]]
|
||||||
|
gauss = numpy.exp(-(X*X + Y*Y + Z*Z)/(2.0*options.d*options.d))/math.pow(2.0*numpy.pi*options.d*options.d,1.5)
|
||||||
|
gauss[:,:,grid[2]/2::] = gauss[:,:,round(grid[2]/2.)-1::-1] # trying to cope with uneven (odd) grid size
|
||||||
|
gauss[:,grid[1]/2::,:] = gauss[:,round(grid[1]/2.)-1::-1,:]
|
||||||
|
gauss[grid[0]/2::,:,:] = gauss[round(grid[0]/2.)-1::-1,:,:]
|
||||||
gauss = numpy.fft.rfftn(gauss)
|
gauss = numpy.fft.rfftn(gauss)
|
||||||
|
|
||||||
interfacialEnergy = lambda A,B: (A*B != 0)*(A != B)*1.0
|
interfacialEnergy = lambda A,B: (A*B != 0)*(A != B)*1.0
|
||||||
struc = ndimage.generate_binary_structure(3,1)
|
struc = ndimage.generate_binary_structure(3,1) # 3D von Neumann neighborhood
|
||||||
microstructure_original = numpy.copy(microstructure)
|
|
||||||
|
|
||||||
for smoothIter in xrange(options.N):
|
for smoothIter in xrange(options.N):
|
||||||
boundary = numpy.zeros(microstructure.shape)
|
boundary = numpy.zeros(microstructure.shape)
|
||||||
for i in range(3):
|
for i in (-1,0,1):
|
||||||
for j in range(3):
|
for j in (-1,0,1):
|
||||||
for k in range(3):
|
for k in (-1,0,1):
|
||||||
boundary = numpy.maximum(boundary,
|
interfaceEnergy = numpy.maximum(boundary,
|
||||||
interfacialEnergy(microstructure,numpy.roll(numpy.roll(numpy.roll(
|
interfacialEnergy(microstructure,numpy.roll(numpy.roll(numpy.roll(
|
||||||
microstructure,i-1,axis=0),j-1,axis=1),k-1,axis=2)))
|
microstructure,i,axis=0), j,axis=1), k,axis=2))) # assign interfacial energy to all voxels that have a differing neighbor (in Moore neighborhood)
|
||||||
boundaryExt = numpy.tile(boundary,(3,3,3))
|
periodic_interfaceEnergy = numpy.tile(interfaceEnergy,(3,3,3))[grid[0]/2:-grid[0]/2,
|
||||||
boundaryExt = boundaryExt[(expandedGrid[0])/2:-(expandedGrid[0])/2,
|
grid[1]/2:-grid[1]/2,
|
||||||
(expandedGrid[1])/2:-(expandedGrid[1])/2,
|
grid[2]/2:-grid[2]/2] # periodically extend interfacial energy array by half a grid size in positive and negative directions
|
||||||
(expandedGrid[2])/2:-(expandedGrid[2])/2]
|
index = ndimage.morphology.distance_transform_edt(periodic_interfaceEnergy == 0., # transform bulk volume (i.e. where interfacial energy is zero)
|
||||||
index = ndimage.morphology.distance_transform_edt(boundaryExt == 0.,return_distances = False,return_indices = True) # array index of nearest voxel on periodically extended boundary
|
return_distances = False,
|
||||||
boundaryExt = boundaryExt[index[0].flatten(),index[1].flatten(),index[2].flatten()].reshape(boundaryExt.shape) # fill bulk with energy of nearest interface
|
return_indices = True) # want array index of nearest voxel on periodically extended boundary
|
||||||
boundary = numpy.fft.irfftn(numpy.fft.rfftn(numpy.where(ndimage.morphology.binary_dilation(boundary > 0.,
|
# boundaryExt = boundaryExt[index[0].flatten(),index[1].flatten(),index[2].flatten()].reshape(boundaryExt.shape) # fill bulk with energy of nearest interface | question PE: what "flatten" for?
|
||||||
structure = struc,
|
periodic_bulkEnergy = periodic_interfaceEnergy[index[0],
|
||||||
iterations = 2*options.d-1), # fat boundary
|
index[1],
|
||||||
boundaryExt[(expandedGrid[0])/2:-(expandedGrid[0])/2, # retain filled energy on fat boundary
|
index[2]].reshape(2*grid) # fill bulk with energy of nearest interface
|
||||||
(expandedGrid[1])/2:-(expandedGrid[1])/2,
|
diffusedEnergy = numpy.fft.irfftn(numpy.fft.rfftn(numpy.where(ndimage.morphology.binary_dilation(interfaceEnergy > 0.,
|
||||||
(expandedGrid[2])/2:-(expandedGrid[2])/2],
|
structure = struc,
|
||||||
0.))*gauss) # zero everywhere else
|
iterations = options.d/2 + 1), # fat boundary | question PE: why 2d - 1? I would argue for d/2 + 1 !!
|
||||||
boundaryExt = numpy.tile(boundary,(3,3,3))
|
periodic_bulkEnergy[grid[0]/2:-grid[0]/2, # retain filled energy on fat boundary...
|
||||||
boundaryExt = boundaryExt[(expandedGrid[0])/2:-(expandedGrid[0])/2,
|
grid[1]/2:-grid[1]/2,
|
||||||
(expandedGrid[1])/2:-(expandedGrid[1])/2,
|
grid[2]/2:-grid[2]/2], # ...and zero everywhere else
|
||||||
(expandedGrid[2])/2:-(expandedGrid[2])/2]
|
0.)\
|
||||||
microstructureExt = numpy.tile(microstructure,(3,3,3))
|
)*gauss)
|
||||||
microstructureExt = microstructureExt[(expandedGrid[0])/2:-(expandedGrid[0])/2,
|
periodic_diffusedEnergy = numpy.tile(diffusedEnergy,(3,3,3))[grid[0]/2:-grid[0]/2,
|
||||||
(expandedGrid[1])/2:-(expandedGrid[1])/2,
|
grid[1]/2:-grid[1]/2,
|
||||||
(expandedGrid[2])/2:-(expandedGrid[2])/2]
|
grid[2]/2:-grid[2]/2] # periodically extend the smoothed bulk energy
|
||||||
index = ndimage.morphology.distance_transform_edt(boundaryExt >= 0.5,return_distances=False,return_indices=True)
|
index = ndimage.morphology.distance_transform_edt(periodic_diffusedEnergy >= 0.5, # transform voxels close to interface region | question PE: what motivates 1/2 (could be any small number, or)?
|
||||||
microstructureExt = microstructureExt[index[0].flatten(),index[1].flatten(),index[2].flatten()].reshape(microstructureExt.shape)
|
return_distances = False,
|
||||||
microstructure = microstructureExt[(expandedGrid[0])/2:-(expandedGrid[0])/2,
|
return_indices = True) # want index of closest bulk grain
|
||||||
(expandedGrid[1])/2:-(expandedGrid[1])/2,
|
microstructure = periodic_microstructure[index[0],
|
||||||
(expandedGrid[2])/2:-(expandedGrid[2])/2]
|
index[1],
|
||||||
|
index[2]].reshape(2*grid)[grid[0]/2:-grid[0]/2,
|
||||||
|
grid[1]/2:-grid[1]/2,
|
||||||
|
grid[2]/2:-grid[2]/2] # extent grains into interface region
|
||||||
|
|
||||||
immutable = numpy.zeros(microstructure.shape, dtype=bool)
|
immutable = numpy.zeros(microstructure.shape, dtype=bool)
|
||||||
for micro in options.immutable:
|
for micro in options.immutable:
|
||||||
immutable = numpy.logical_or(immutable, numpy.logical_or(microstructure == int(micro), microstructure_original == int(micro)))
|
immutable += numpy.logical_or(microstructure == micro, microstructure_original == micro) # find locations where immutable microstructures have been or are now
|
||||||
|
|
||||||
microstructure = numpy.where(immutable, microstructure_original,microstructure)
|
microstructure = numpy.where(immutable, microstructure_original,microstructure) # undo any changes involving immutable microstructures
|
||||||
|
|
||||||
# --- renumber to sequence 1...Ngrains if requested ------------------------------------------------
|
# --- renumber to sequence 1...Ngrains if requested ------------------------------------------------
|
||||||
# http://stackoverflow.com/questions/10741346/numpy-frequency-counts-for-unique-values-in-an-array
|
# http://stackoverflow.com/questions/10741346/numpy-frequency-counts-for-unique-values-in-an-array
|
||||||
|
|
||||||
if options.renumber:
|
if options.renumber:
|
||||||
newID=0
|
newID = 0
|
||||||
for microstructureID,count in enumerate(numpy.bincount(microstructure.reshape(info['grid'].prod()))):
|
for microstructureID,count in enumerate(numpy.bincount(microstructure.flatten())):
|
||||||
if count != 0:
|
if count != 0:
|
||||||
newID+=1
|
newID += 1
|
||||||
microstructure=numpy.where(microstructure==microstructureID,newID,microstructure).reshape(microstructure.shape)
|
microstructure = numpy.where(microstructure == microstructureID, newID, microstructure)
|
||||||
|
|
||||||
# --- assemble header -----------------------------------------------------------------------------
|
# --- assemble header -----------------------------------------------------------------------------
|
||||||
newInfo['microstructures'] = microstructure[0:info['grid'][0],0:info['grid'][1],0:info['grid'][2]].max()
|
newInfo['microstructures'] = microstructure[0:info['grid'][0],0:info['grid'][1],0:info['grid'][2]].max()
|
||||||
|
|
||||||
|
@ -246,11 +257,11 @@ for file in files:
|
||||||
|
|
||||||
# --- write microstructure information ------------------------------------------------------------
|
# --- write microstructure information ------------------------------------------------------------
|
||||||
formatwidth = int(math.floor(math.log10(microstructure.max())+1))
|
formatwidth = int(math.floor(math.log10(microstructure.max())+1))
|
||||||
theTable.data = microstructure[0:info['grid'][0],0:info['grid'][1],0:info['grid'][2]].reshape(numpy.prod(info['grid']),order='F').transpose()
|
theTable.data = microstructure[0:info['grid'][0],0:info['grid'][1],0:info['grid'][2]].reshape(numpy.prod(info['grid']),order='F').transpose() # question PE: this assumes that only the Z dimension can be 1!
|
||||||
theTable.data_writeArray('%%%ii'%(formatwidth),delimiter=' ')
|
theTable.data_writeArray('%%%ii'%(formatwidth),delimiter=' ')
|
||||||
|
|
||||||
#--- output finalization --------------------------------------------------------------------------
|
#--- output finalization --------------------------------------------------------------------------
|
||||||
if file['name'] != 'STDIN':
|
if file['name'] != 'STDIN':
|
||||||
file['input'].close()
|
theTable.input_close()
|
||||||
file['output'].close()
|
theTable.output_close()
|
||||||
os.rename(file['name']+'_tmp',file['name'])
|
os.rename(file['name']+'_tmp',file['name'])
|
||||||
|
|
Loading…
Reference in New Issue