ASCIItable -> Table

This commit is contained in:
Martin Diehl 2020-03-18 13:47:09 +01:00
parent 1c75198af5
commit b5a1295cb9
4 changed files with 87 additions and 144 deletions

View File

@ -2,6 +2,7 @@
import os import os
import sys import sys
from io import StringIO
from optparse import OptionParser from optparse import OptionParser
import numpy as np import numpy as np
@ -71,60 +72,30 @@ parser.set_defaults(bins = (10,10),
) )
(options,filenames) = parser.parse_args() (options,filenames) = parser.parse_args()
if filenames == []: filenames = [None]
minmax = np.array([np.array(options.xrange), minmax = np.array([options.xrange,options.yrange,options.zrange])
np.array(options.yrange), result = np.empty((options.bins[0],options.bins[1],3),'f')
np.array(options.zrange)])
grid = np.zeros(options.bins,'f')
result = np.zeros((options.bins[0],options.bins[1],3),'f')
if options.data is None: parser.error('no data columns specified.') if options.data is None: parser.error('no data columns specified.')
labels = list(options.data)
if options.weight is not None: labels += [options.weight] # prevent character splitting of single string value
# --- loop over input files -------------------------------------------------------------------------
if filenames == []: filenames = [None]
for name in filenames: for name in filenames:
try:
table = damask.ASCIItable(name = name,
outname = os.path.join(os.path.dirname(name),
'binned-{}-{}_'.format(*options.data) +
('weighted-{}_'.format(options.weight) if options.weight else '') +
os.path.basename(name)) if name else name)
except IOError:
continue
damask.util.report(scriptName,name) damask.util.report(scriptName,name)
# ------------------------------------------ read header ------------------------------------------ table = damask.Table.from_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name)
data = np.hstack((table.get(options.data[0]),table.get(options.data[1])))
table.head_read()
# ------------------------------------------ sanity checks ----------------------------------------
missing_labels = table.data_readArray(labels)
if len(missing_labels) > 0:
damask.util.croak('column{} {} not found.'.format('s' if len(missing_labels) > 1 else '',', '.join(missing_labels)))
table.close(dismiss = True)
continue
for c in (0,1): # check data minmax for x and y (i = 0 and 1) for c in (0,1): # check data minmax for x and y (i = 0 and 1)
if (minmax[c] == 0.0).all(): minmax[c] = [table.data[:,c].min(),table.data[:,c].max()] if (minmax[c] == 0.0).all(): minmax[c] = [data[:,c].min(),data[:,c].max()]
if options.type[c].lower() == 'log': # if log scale if options.type[c].lower() == 'log': # if log scale
table.data[:,c] = np.log(table.data[:,c]) # change x,y coordinates to log data[:,c] = np.log(data[:,c]) # change x,y coordinates to log
minmax[c] = np.log(minmax[c]) # change minmax to log, too minmax[c] = np.log(minmax[c]) # change minmax to log, too
delta = minmax[:,1]-minmax[:,0] delta = minmax[:,1]-minmax[:,0]
(grid,xedges,yedges) = np.histogram2d(table.data[:,0],table.data[:,1], (grid,xedges,yedges) = np.histogram2d(data[:,0],data[:,1],
bins=options.bins, bins=options.bins,
range=minmax[:2], range=minmax[:2],
weights=None if options.weight is None else table.data[:,2]) weights=table.get(options.weight) if options.weight else None)
if options.normCol: if options.normCol:
for x in range(options.bins[0]): for x in range(options.bins[0]):
sum = np.sum(grid[x,:]) sum = np.sum(grid[x,:])
@ -153,24 +124,20 @@ for name in filenames:
for y in range(options.bins[1]): for y in range(options.bins[1]):
result[x,y,:] = [minmax[0,0]+delta[0]/options.bins[0]*(x+0.5), result[x,y,:] = [minmax[0,0]+delta[0]/options.bins[0]*(x+0.5),
minmax[1,0]+delta[1]/options.bins[1]*(y+0.5), minmax[1,0]+delta[1]/options.bins[1]*(y+0.5),
min(1.0,max(0.0,(grid[x,y]-minmax[2,0])/delta[2]))] np.clip((grid[x,y]-minmax[2,0])/delta[2],0.0,1.0)]
for c in (0,1): for c in (0,1):
if options.type[c].lower() == 'log': result[:,:,c] = np.exp(result[:,:,c]) if options.type[c].lower() == 'log': result[:,:,c] = np.exp(result[:,:,c])
if options.invert: result[:,:,2] = 1.0 - result[:,:,2] if options.invert: result[:,:,2] = 1.0 - result[:,:,2]
# --- assemble header ------------------------------------------------------------------------------- comments = scriptID + '\t' + ' '.join(sys.argv[1:])
shapes = {'bin_%s'%options.data[0]:(1,),'bin_%s'%options.data[1]:(1,),'z':(1,)}
table.info_clear() table = damask.Table(result.reshape(options.bins[0]*options.bins[1],3),shapes,[comments])
table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:])) if name:
table.labels_clear() outname = os.path.join(os.path.dirname(name),'binned-{}-{}_'.format(*options.data) +
table.labels_append(['bin_%s'%options.data[0],'bin_%s'%options.data[1],'z']) ('weighted-{}_'.format(options.weight) if options.weight else '') +
table.head_write() os.path.basename(name))
table.to_ASCII(outname)
# --- output result --------------------------------------------------------------------------------- else:
table.to_ASCII(sys.stdout)
table.data = result.reshape(options.bins[0]*options.bins[1],3)
table.data_writeArray()
table.close()

View File

@ -255,8 +255,8 @@ for name in filenames:
table.data_readArray(labels) table.data_readArray(labels)
coords = table.data[:,table.label_indexrange(options.pos)] * info['size'] if options.normalized \ coords = table.data[:,table.label_indexrange(options.pos)] * info['size'] if options.normalized \
else table.data[:,table.label_indexrange(options.pos)] - info['origin'] else table.data[:,table.label_indexrange(options.pos)] - info['origin']
eulers = table.data[:,table.label_indexrange(options.eulers)] if hasEulers \ if hasEulers:
else np.zeros(3*len(coords)) eulers = table.data[:,table.label_indexrange(options.eulers)]
grains = table.data[:,table.label_indexrange(options.microstructure)].astype(int) if hasGrains \ grains = table.data[:,table.label_indexrange(options.microstructure)].astype(int) if hasGrains \
else np.arange(len(coords))+1 else np.arange(len(coords))+1

View File

@ -1,11 +1,16 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: UTF-8 no BOM -*-
import os
import sys
import math
import random
from optparse import OptionParser from optparse import OptionParser
import damask
import os,sys,math,random
import numpy as np import numpy as np
import damask
scriptName = os.path.splitext(os.path.basename(__file__))[0] scriptName = os.path.splitext(os.path.basename(__file__))[0]
scriptID = ' '.join([scriptName,damask.version]) scriptID = ' '.join([scriptName,damask.version])
@ -223,54 +228,29 @@ parser.set_defaults(randomSeed = None,
) )
(options,filenames) = parser.parse_args() (options,filenames) = parser.parse_args()
nSamples = options.number
methods = [options.algorithm]
# --- loop over input files -------------------------------------------------------------------------
if filenames == []: filenames = [None] if filenames == []: filenames = [None]
for name in filenames: for name in filenames:
try:
table = damask.ASCIItable(name = name, readonly=True)
except IOError:
continue
damask.util.report(scriptName,name) damask.util.report(scriptName,name)
randomSeed = int(os.urandom(4).hex(), 16) if options.randomSeed is None else options.randomSeed # random seed per file for second phase table = damask.Table.from_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name)
randomSeed = int(os.urandom(4).hex(),16) if options.randomSeed is None else options.randomSeed # random seed per file
random.seed(randomSeed) random.seed(randomSeed)
# ------------------------------------------ read header and data ---------------------------------
table.head_read()
errors = []
labels = ['1_euler','2_euler','3_euler','intensity']
for i,index in enumerate(table.label_index(labels)):
if index < 0: errors.append('label {} not present.'.format(labels[i]))
if errors != []:
damask.util.croak(errors)
table.close(dismiss = True)
continue
table.data_readArray(labels)
# --------------- figure out limits (left/right), delta, and interval ----------------------------- # --------------- figure out limits (left/right), delta, and interval -----------------------------
ODF = {} ODF = {}
limits = np.array([np.min(table.data[:,0:3],axis=0), eulers = table.get('euler')
np.max(table.data[:,0:3],axis=0)]) # min/max euler angles in degrees limits = np.array([np.min(eulers,axis=0),np.max(eulers,axis=0)]) # min/max euler angles in degrees
ODF['limit'] = np.radians(limits[1,:]) # right hand limits in radians ODF['limit'] = np.radians(limits[1,:]) # right hand limits in radians
ODF['center'] = 0.0 if all(limits[0,:]<1e-8) else 0.5 # vertex or cell centered ODF['center'] = 0.0 if all(limits[0,:]<1e-8) else 0.5 # vertex or cell centered
ODF['interval'] = np.array(list(map(len,[np.unique(table.data[:,i]) for i in range(3)])),'i') # steps are number of distict values ODF['interval'] = np.array(list(map(len,[np.unique(eulers[:,i]) for i in range(3)])),'i') # steps are number of distict values
ODF['nBins'] = ODF['interval'].prod() ODF['nBins'] = ODF['interval'].prod()
ODF['delta'] = np.radians(np.array(limits[1,0:3]-limits[0,0:3])/(ODF['interval']-1)) # step size ODF['delta'] = np.radians(np.array(limits[1,0:3]-limits[0,0:3])/(ODF['interval']-1)) # step size
if table.data.shape[0] != ODF['nBins']: if eulers.shape[0] != ODF['nBins']:
damask.util.croak('expecting %i values but got %i'%(ODF['nBins'],table.data.shape[0])) damask.util.croak('expecting %i values but got %i'%(ODF['nBins'],eulers.shape[0]))
continue continue
# ----- build binnedODF array and normalize ------------------------------------------------------ # ----- build binnedODF array and normalize ------------------------------------------------------
@ -278,9 +258,10 @@ for name in filenames:
ODF['dV_V'] = [None]*ODF['nBins'] ODF['dV_V'] = [None]*ODF['nBins']
ODF['nNonZero'] = 0 ODF['nNonZero'] = 0
dg = ODF['delta'][0]*2.0*math.sin(ODF['delta'][1]/2.0)*ODF['delta'][2] dg = ODF['delta'][0]*2.0*math.sin(ODF['delta'][1]/2.0)*ODF['delta'][2]
intensity = table.get('intensity')
for b in range(ODF['nBins']): for b in range(ODF['nBins']):
ODF['dV_V'][b] = \ ODF['dV_V'][b] = \
max(0.0,table.data[b,table.label_index('intensity')]) * dg * \ max(0.0,intensity[b,0]) * dg * \
math.sin(((b//ODF['interval'][2])%ODF['interval'][1]+ODF['center'])*ODF['delta'][1]) math.sin(((b//ODF['interval'][2])%ODF['interval'][1]+ODF['center'])*ODF['delta'][1])
if ODF['dV_V'][b] > 0.0: if ODF['dV_V'][b] > 0.0:
sumdV_V += ODF['dV_V'][b] sumdV_V += ODF['dV_V'][b]
@ -296,11 +277,10 @@ for name in filenames:
'Reference Integral: %12.11f\n'%(ODF['limit'][0]*ODF['limit'][2]*(1-math.cos(ODF['limit'][1]))), 'Reference Integral: %12.11f\n'%(ODF['limit'][0]*ODF['limit'][2]*(1-math.cos(ODF['limit'][1]))),
]) ])
# call methods
Functions = {'IA': 'directInversion', 'STAT': 'TothVanHoutteSTAT', 'MC': 'MonteCarloBins'} Functions = {'IA': 'directInversion', 'STAT': 'TothVanHoutteSTAT', 'MC': 'MonteCarloBins'}
method = Functions[options.algorithm] method = Functions[options.algorithm]
Orientations, ReconstructedODF = (globals()[method])(ODF,nSamples) Orientations, ReconstructedODF = (globals()[method])(ODF,options.number)
# calculate accuracy of sample # calculate accuracy of sample
squaredDiff = {'orig':0.0,method:0.0} squaredDiff = {'orig':0.0,method:0.0}
@ -319,7 +299,7 @@ for name in filenames:
indivSum['orig'] += ODF['dV_V'][bin] indivSum['orig'] += ODF['dV_V'][bin]
indivSquaredSum['orig'] += ODF['dV_V'][bin]**2 indivSquaredSum['orig'] += ODF['dV_V'][bin]**2
damask.util.croak(['sqrt(N*)RMSD of ODFs:\t %12.11f'% math.sqrt(nSamples*squaredDiff[method]), damask.util.croak(['sqrt(N*)RMSD of ODFs:\t %12.11f'% math.sqrt(options.number*squaredDiff[method]),
'RMSrD of ODFs:\t %12.11f'%math.sqrt(squaredRelDiff[method]), 'RMSrD of ODFs:\t %12.11f'%math.sqrt(squaredRelDiff[method]),
'rMSD of ODFs:\t %12.11f'%(squaredDiff[method]/indivSquaredSum['orig']), 'rMSD of ODFs:\t %12.11f'%(squaredDiff[method]/indivSquaredSum['orig']),
'nNonZero correlation slope:\t %12.11f'\ 'nNonZero correlation slope:\t %12.11f'\
@ -331,10 +311,10 @@ for name in filenames:
(indivSquaredSum[method]/ODF['nNonZero']-(indivSum[method]/ODF['nNonZero'])**2)))), (indivSquaredSum[method]/ODF['nNonZero']-(indivSum[method]/ODF['nNonZero'])**2)))),
]) ])
if method == 'IA' and nSamples < ODF['nNonZero']: if method == 'IA' and options.number < ODF['nNonZero']:
strOpt = '(%i)'%ODF['nNonZero'] strOpt = '(%i)'%ODF['nNonZero']
formatwidth = 1+int(math.log10(nSamples)) formatwidth = 1+int(math.log10(options.number))
materialConfig = [ materialConfig = [
'#' + scriptID + ' ' + ' '.join(sys.argv[1:]), '#' + scriptID + ' ' + ' '.join(sys.argv[1:]),
@ -344,7 +324,7 @@ for name in filenames:
'#-------------------#', '#-------------------#',
] ]
for i,ID in enumerate(range(nSamples)): for i,ID in enumerate(range(options.number)):
materialConfig += ['[Grain%s]'%(str(ID+1).zfill(formatwidth)), materialConfig += ['[Grain%s]'%(str(ID+1).zfill(formatwidth)),
'(constituent) phase %i texture %s fraction 1.0'%(options.phase,str(ID+1).rjust(formatwidth)), '(constituent) phase %i texture %s fraction 1.0'%(options.phase,str(ID+1).rjust(formatwidth)),
] ]
@ -355,7 +335,7 @@ for name in filenames:
'#-------------------#', '#-------------------#',
] ]
for ID in range(nSamples): for ID in range(options.number):
eulers = Orientations[ID] eulers = Orientations[ID]
materialConfig += ['[Grain%s]'%(str(ID+1).zfill(formatwidth)), materialConfig += ['[Grain%s]'%(str(ID+1).zfill(formatwidth)),
@ -364,7 +344,5 @@ for name in filenames:
#--- output finalization -------------------------------------------------------------------------- #--- output finalization --------------------------------------------------------------------------
with (open(os.path.splitext(name)[0]+'_'+method+'_'+str(nSamples)+'_material.config','w')) as outfile: with (open(os.path.splitext(name)[0]+'_'+method+'_'+str(options.number)+'_material.config','w')) as outfile:
outfile.write('\n'.join(materialConfig)+'\n') outfile.write('\n'.join(materialConfig)+'\n')
table.close()

View File

@ -1,9 +1,15 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import threading,time,os,sys,random import threading
import numpy as np import time
import os
import sys
import random
from optparse import OptionParser from optparse import OptionParser
from io import StringIO from io import StringIO
import numpy as np
import damask import damask
scriptName = os.path.splitext(os.path.basename(__file__))[0] scriptName = os.path.splitext(os.path.basename(__file__))[0]
@ -49,7 +55,7 @@ class myThread (threading.Thread):
s.acquire() # ensure only one thread acces global data s.acquire() # ensure only one thread acces global data
if bestSeedsUpdate > knownSeedsUpdate: # write best fit to virtual file if bestSeedsUpdate > knownSeedsUpdate: # write best fit to virtual file
knownSeedsUpdate = bestSeedsUpdate knownSeedsUpdate = bestSeedsUpdate
bestSeedsVFile.reset() bestSeedsVFile.seek(0)
myBestSeedsVFile.close() myBestSeedsVFile.close()
myBestSeedsVFile = StringIO() myBestSeedsVFile = StringIO()
i=0 i=0
@ -67,46 +73,38 @@ class myThread (threading.Thread):
for i in range(NmoveGrains): for i in range(NmoveGrains):
selectedMs.append(random.randrange(1,nMicrostructures)) selectedMs.append(random.randrange(1,nMicrostructures))
direction.append(np.array(((random.random()-0.5)*delta[0], direction.append((np.random.random()-0.5)*delta)
(random.random()-0.5)*delta[1],
(random.random()-0.5)*delta[2])))
perturbedSeedsVFile.close() # reset virtual file perturbedSeedsVFile.close() # reset virtual file
perturbedSeedsVFile = StringIO() perturbedSeedsVFile = StringIO()
myBestSeedsVFile.reset() myBestSeedsVFile.seek(0)
perturbedSeedsTable = damask.ASCIItable(myBestSeedsVFile,perturbedSeedsVFile,labeled=True) # write best fit to perturbed seed file perturbedSeedsTable = damask.Table.from_ASCII(myBestSeedsVFile)
perturbedSeedsTable.head_read() coords = perturbedSeedsTable.get('pos')
perturbedSeedsTable.head_write()
outputAlive=True
ms = 1
i = 0 i = 0
while outputAlive and perturbedSeedsTable.data_read(): # perturbe selected microstructure for ms,coord in enumerate(coords):
if ms in selectedMs: if ms in selectedMs:
newCoords=np.array(tuple(map(float,perturbedSeedsTable.data[0:3]))+direction[i]) newCoords=coord+direction[i]
newCoords=np.where(newCoords>=1.0,newCoords-1.0,newCoords) # ensure that the seeds remain in the box newCoords=np.where(newCoords>=1.0,newCoords-1.0,newCoords) # ensure that the seeds remain in the box
newCoords=np.where(newCoords <0.0,newCoords+1.0,newCoords) newCoords=np.where(newCoords <0.0,newCoords+1.0,newCoords)
perturbedSeedsTable.data[0:3]=[format(f, '8.6f') for f in newCoords] coords[i]=newCoords
direction[i]*=2. direction[i]*=2.
i+= 1 i+= 1
ms+=1 perturbedSeedsTable.set('pos',coords)
perturbedSeedsTable.data_write() perturbedSeedsTable.to_ASCII(perturbedSeedsVFile)
#--- do tesselation with perturbed seed file ----------------------------------------------------------
#--- do tesselation with perturbed seed file ------------------------------------------------------
perturbedGeomVFile.close() perturbedGeomVFile.close()
perturbedGeomVFile = StringIO() perturbedGeomVFile = StringIO()
perturbedSeedsVFile.reset() perturbedSeedsVFile.seek(0)
perturbedGeomVFile.write(damask.util.execute('geom_fromVoronoiTessellation '+ perturbedGeomVFile.write(damask.util.execute('geom_fromVoronoiTessellation '+
' -g '+' '.join(list(map(str, options.grid))),streamIn=perturbedSeedsVFile)[0]) ' -g '+' '.join(list(map(str, options.grid))),streamIn=perturbedSeedsVFile)[0])
perturbedGeomVFile.reset() perturbedGeomVFile.seek(0)
#--- evaluate current seeds file ---------------------------------------------------------------------- #--- evaluate current seeds file ------------------------------------------------------------------
perturbedGeomTable = damask.ASCIItable(perturbedGeomVFile,None,labeled=False,readonly=True) perturbedGeom = damask.Geom.from_file(perturbedGeomVFile)
perturbedGeomTable.head_read() myNmicrostructures = len(np.unique(perturbedGeom.microstructure))
for i in perturbedGeomTable.info: currentData=np.bincount(perturbedGeom.microstructure.ravel())[1:]/points
if i.startswith('microstructures'): myNmicrostructures = int(i.split('\t')[1])
perturbedGeomTable.data_readArray()
perturbedGeomTable.output_flush()
currentData=np.bincount(perturbedGeomTable.data.astype(int).ravel())[1:]/points
currentError=[] currentError=[]
currentHist=[] currentHist=[]
for i in range(nMicrostructures): # calculate the deviation in all bins per histogram for i in range(nMicrostructures): # calculate the deviation in all bins per histogram
@ -137,7 +135,7 @@ class myThread (threading.Thread):
damask.util.croak(' target: '+np.array_str(target[i]['histogram'])) damask.util.croak(' target: '+np.array_str(target[i]['histogram']))
damask.util.croak(' best: '+np.array_str(currentHist[i])) damask.util.croak(' best: '+np.array_str(currentHist[i]))
currentSeedsName = baseFile+'_'+str(bestSeedsUpdate).replace('.','-') # name of new seed file (use time as unique identifier) currentSeedsName = baseFile+'_'+str(bestSeedsUpdate).replace('.','-') # name of new seed file (use time as unique identifier)
perturbedSeedsVFile.reset() perturbedSeedsVFile.seek(0)
bestSeedsVFile.close() bestSeedsVFile.close()
bestSeedsVFile = StringIO() bestSeedsVFile = StringIO()
sys.stdout.flush() sys.stdout.flush()
@ -154,7 +152,7 @@ class myThread (threading.Thread):
break break
if i == min(nMicrostructures,myMatch+options.bins)-1: # same quality as before: take it to keep on moving if i == min(nMicrostructures,myMatch+options.bins)-1: # same quality as before: take it to keep on moving
bestSeedsUpdate = time.time() bestSeedsUpdate = time.time()
perturbedSeedsVFile.reset() perturbedSeedsVFile.seek(0)
bestSeedsVFile.close() bestSeedsVFile.close()
bestSeedsVFile = StringIO() bestSeedsVFile = StringIO()
for line in perturbedSeedsVFile: for line in perturbedSeedsVFile:
@ -216,7 +214,7 @@ damask.util.report(scriptName,options.seedFile)
if options.randomSeed is None: if options.randomSeed is None:
options.randomSeed = int(os.urandom(4).hex(),16) options.randomSeed = int(os.urandom(4).hex(),16)
damask.util.croak(options.randomSeed) damask.util.croak(options.randomSeed)
delta = (options.scale/options.grid[0],options.scale/options.grid[1],options.scale/options.grid[2]) delta = options.scale/np.array(options.grid)
baseFile=os.path.splitext(os.path.basename(options.seedFile))[0] baseFile=os.path.splitext(os.path.basename(options.seedFile))[0]
points = np.array(options.grid).prod().astype('float') points = np.array(options.grid).prod().astype('float')