2012-11-08 21:14:51 +05:30
#!/usr/bin/env python
2013-05-13 18:40:31 +05:30
# -*- coding: UTF-8 no BOM -*-
2012-11-08 21:14:51 +05:30
2014-10-09 22:33:06 +05:30
import os , sys , math , string
import numpy as np
from optparse import OptionParser
import damask
2013-07-18 18:58:54 +05:30
2014-11-17 03:14:46 +05:30
scriptID = string . replace ( ' $Id$ ' , ' \n ' , ' \\ n ' )
2014-11-18 21:01:39 +05:30
scriptName = os . path . splitext ( scriptID . split ( ) [ 1 ] ) [ 0 ]
2012-11-08 21:14:51 +05:30
2013-05-13 18:40:31 +05:30
#--------------------------------------------------------------------------------------------------
2012-11-08 21:14:51 +05:30
# MAIN
2013-05-13 18:40:31 +05:30
#--------------------------------------------------------------------------------------------------
2014-10-09 22:33:06 +05:30
parser = OptionParser ( option_class = damask . extendableOption , usage = ' % prog options [file[s]] ' , description = """
2012-11-08 21:14:51 +05:30
Generate geometry description and material configuration from EBSD data in given square - gridded ' ang ' file .
2013-04-12 16:45:17 +05:30
Two phases can be discriminated based on threshold value in a given data column .
2012-11-08 21:14:51 +05:30
2014-10-09 22:33:06 +05:30
""" , version = scriptID)
2012-11-08 21:14:51 +05:30
2015-04-10 18:27:25 +05:30
parser . add_option ( ' --column ' , dest = ' column ' , type = ' int ' , metavar = ' int ' ,
2014-11-14 20:23:48 +05:30
help = ' data column to discriminate between both phases [ %d efault] ' )
2015-04-10 18:27:25 +05:30
parser . add_option ( ' -t ' , ' --threshold ' , dest = ' threshold ' , type = ' float ' , metavar = ' float ' ,
2014-11-14 20:23:48 +05:30
help = ' threshold value for phase discrimination [ %d efault] ' )
2015-04-10 18:27:25 +05:30
parser . add_option ( ' --homogenization ' , dest = ' homogenization ' , type = ' int ' , metavar = ' int ' ,
2014-11-14 20:23:48 +05:30
help = ' homogenization index for <microstructure> configuration [ %d efault] ' )
2015-04-10 18:27:25 +05:30
parser . add_option ( ' --phase ' , dest = ' phase ' , type = ' int ' , nargs = 2 , metavar = ' int int ' ,
2014-11-14 20:23:48 +05:30
help = ' phase indices for <microstructure> configuration %d efault ' )
2015-04-10 18:27:25 +05:30
parser . add_option ( ' --crystallite ' , dest = ' crystallite ' , type = ' int ' , metavar = ' int ' ,
2014-11-14 20:23:48 +05:30
help = ' crystallite index for <microstructure> configuration [ %d efault] ' )
2015-04-10 18:27:25 +05:30
parser . add_option ( ' -c ' , ' --configuration ' , dest = ' config ' , action = ' store_true ' ,
2013-04-12 16:45:17 +05:30
help = ' output material configuration [ %d efault] ' )
2015-04-10 18:27:25 +05:30
parser . add_option ( ' --compress ' , dest = ' compress ' , action = ' store_true ' ,
2014-11-14 20:23:48 +05:30
help = ' lump identical microstructure and texture information [ %d efault] ' )
2015-04-10 18:27:25 +05:30
parser . add_option ( ' -a ' , ' --axes ' , dest = ' axes ' , nargs = 3 , metavar = ' string string string ' ,
2014-11-14 20:23:48 +05:30
help = ' Euler angle coordinate system for <texture> configuration x,y,z = %d efault ' )
2015-04-10 18:27:25 +05:30
parser . add_option ( ' -p ' , ' --precision ' , dest = ' precision ' , choices = [ ' 0 ' , ' 1 ' , ' 2 ' , ' 3 ' ] , metavar = ' int ' ,
help = ' euler angles decimal places for output format and compressing (0,1,2,3) [2] ' )
2013-04-12 16:45:17 +05:30
2014-11-14 20:23:48 +05:30
parser . set_defaults ( column = 11 )
parser . set_defaults ( threshold = 0.5 )
2012-11-08 21:14:51 +05:30
parser . set_defaults ( homogenization = 1 )
parser . set_defaults ( phase = [ 1 , 2 ] )
parser . set_defaults ( crystallite = 1 )
2014-11-14 20:23:48 +05:30
parser . set_defaults ( config = False )
parser . set_defaults ( compress = False )
2013-07-24 16:39:39 +05:30
parser . set_defaults ( axes = [ ' y ' , ' x ' , ' -z ' ] )
2015-04-10 18:27:25 +05:30
parser . set_defaults ( precision = ' 2 ' )
2012-11-08 21:14:51 +05:30
( options , filenames ) = parser . parse_args ( )
2015-04-10 18:27:25 +05:30
2013-07-24 16:39:39 +05:30
for i in options . axes :
2013-07-18 18:58:54 +05:30
if i . lower ( ) not in [ ' x ' , ' +x ' , ' -x ' , ' y ' , ' +y ' , ' -y ' , ' z ' , ' +z ' , ' -z ' ] :
2014-11-14 20:23:48 +05:30
parser . error ( ' invalid axes %s %s %s ' % ( options . axes [ 0 ] , options . axes [ 1 ] , options . axes [ 2 ] ) )
2013-07-18 18:58:54 +05:30
2013-05-13 18:40:31 +05:30
#--- setup file handles ---------------------------------------------------------------------------
2012-11-08 21:14:51 +05:30
files = [ ]
if filenames == [ ] :
files . append ( { ' name ' : ' STDIN ' ,
' input ' : sys . stdin ,
' output ' : sys . stdout ,
' croak ' : sys . stderr ,
} )
else :
for name in filenames :
if os . path . exists ( name ) :
files . append ( { ' name ' : name ,
' input ' : open ( name ) ,
' output ' : open ( name + ' _tmp ' , ' w ' ) ,
' croak ' : sys . stdout ,
} )
2013-05-13 18:40:31 +05:30
#--- loop over input files ------------------------------------------------------------------------
2012-11-08 21:14:51 +05:30
for file in files :
2014-11-14 20:23:48 +05:30
file [ ' croak ' ] . write ( ' \033 [1m ' + scriptName + ' \033 [0m: ' + ( file [ ' name ' ] if file [ ' name ' ] != ' STDIN ' else ' ' ) + ' \n ' )
2012-11-08 21:14:51 +05:30
2013-05-13 18:40:31 +05:30
info = {
2015-06-14 11:21:53 +05:30
' grid ' : np . ones ( 3 , ' i ' ) ,
2014-01-30 17:30:20 +05:30
' size ' : np . zeros ( 3 , ' d ' ) ,
' origin ' : np . zeros ( 3 , ' d ' ) ,
2013-05-13 18:40:31 +05:30
' microstructures ' : 0 ,
2015-06-11 15:36:53 +05:30
' homogenization ' : options . homogenization
2013-05-13 18:40:31 +05:30
}
2015-06-11 15:36:53 +05:30
coords = [ { } , { } , { 1 : True } ]
pos = { ' min ' : [ float ( " inf " ) , float ( " inf " ) ] ,
' max ' : [ - float ( " inf " ) , - float ( " inf " ) ] }
phase = [ ]
eulerangles = [ ]
# --------------- read data -----------------------------------------------------------------------
2012-11-08 21:14:51 +05:30
for line in file [ ' input ' ] :
2015-06-11 15:36:53 +05:30
if line . strip ( ) :
words = line . split ( )
if words [ 0 ] == ' # ' : # process initial comments/header block
if len ( words ) > 2 :
if words [ 2 ] . lower ( ) == ' hexgrid ' :
file [ ' croak ' ] . write ( ' The file has HexGrid format. Please first convert to SquareGrid... \n ' )
break
else :
currPos = words [ 3 : 5 ]
for i in xrange ( 2 ) :
coords [ i ] [ currPos [ i ] ] = True
currPos = map ( float , currPos )
for i in xrange ( 2 ) :
pos [ ' min ' ] [ i ] = min ( pos [ ' min ' ] [ i ] , currPos [ i ] )
pos [ ' max ' ] [ i ] = max ( pos [ ' max ' ] [ i ] , currPos [ i ] )
eulerangles . append ( map ( math . degrees , map ( float , words [ : 3 ] ) ) )
phase . append ( options . phase [ int ( float ( words [ options . column - 1 ] ) > options . threshold ) ] )
# --------------- determine size and grid ---------------------------------------------------------
info [ ' grid ' ] = np . array ( map ( len , coords ) , ' i ' )
info [ ' size ' ] [ 0 : 2 ] = info [ ' grid ' ] [ 0 : 2 ] / ( info [ ' grid ' ] [ 0 : 2 ] - 1.0 ) * \
np . array ( [ pos [ ' max ' ] [ 0 ] - pos [ ' min ' ] [ 0 ] ,
pos [ ' max ' ] [ 1 ] - pos [ ' min ' ] [ 1 ] ] , ' d ' )
info [ ' size ' ] [ 2 ] = info [ ' size ' ] [ 0 ] / info [ ' grid ' ] [ 0 ]
eulerangles = np . array ( eulerangles , dtype = ' f ' ) . reshape ( info [ ' grid ' ] . prod ( ) , 3 )
phase = np . array ( phase , dtype = ' i ' ) . reshape ( info [ ' grid ' ] . prod ( ) )
2015-04-10 20:20:23 +05:30
limits = [ 360 , 180 , 360 ]
if any ( [ np . any ( eulerangles [ : , i ] > = limits [ i ] ) for i in [ 0 , 1 , 2 ] ] ) :
2015-04-10 18:27:25 +05:30
file [ ' croak ' ] . write ( ' Error: euler angles out of bound. Ang file might contain unidexed poins. \n ' )
2015-04-10 20:20:23 +05:30
for i , angle in enumerate ( [ ' phi1 ' , ' PHI ' , ' phi2 ' ] ) :
for n in np . nditer ( np . where ( eulerangles [ : , i ] > = limits [ i ] ) , [ ' zerosize_ok ' ] ) :
file [ ' croak ' ] . write ( ' %s in line %i ( %4.2f %4.2f %4.2f ) \n '
% ( angle , n , eulerangles [ n , 0 ] , eulerangles [ n , 1 ] , eulerangles [ n , 2 ] ) )
continue
eulerangles = np . around ( eulerangles , int ( options . precision ) ) # round to desired precision
for i , angle in enumerate ( [ ' phi1 ' , ' PHI ' , ' phi2 ' ] ) :
eulerangles [ : , i ] % = limits [ i ] # ensure, that rounded euler angles are not out of bounds (modulo by limits)
2014-01-30 17:30:20 +05:30
if options . compress :
2015-04-10 18:27:25 +05:30
formatString = ' { 0:0> ' + str ( int ( options . precision ) + 3 ) + ' } '
euleranglesRadInt = ( eulerangles * 10 * * int ( options . precision ) ) . astype ( ' int ' ) # scale by desired precision and convert to int
eulerKeys = np . array ( [ int ( ' ' . join ( map ( formatString . format , euleranglesRadInt [ i , : ] ) ) ) \
for i in xrange ( info [ ' grid ' ] . prod ( ) ) ] ) # create unique integer key from three euler angles by concatenating the string representation with leading zeros and store as integer
2015-06-11 15:36:53 +05:30
devNull , texture , eulerKeys_idx = np . unique ( eulerKeys , return_index = True , return_inverse = True ) # search unique euler angle keys. Texture IDs are the indices of the first occurrence, the inverse is used to construct the microstructure
2015-04-10 18:27:25 +05:30
msFull = np . array ( [ [ eulerKeys_idx [ i ] , phase [ i ] ] for i in xrange ( info [ ' grid ' ] . prod ( ) ) ] , ' i8 ' ) # create a microstructure (texture/phase pair) for each point using unique texture IDs. Use longInt (64bit, i8) because the keys might be long
devNull , msUnique , matPoints = np . unique ( msFull . view ( ' c16 ' ) , True , True )
matPoints + = 1
microstructure = np . array ( [ msFull [ i ] for i in msUnique ] ) # pick only unique microstructures
2014-01-30 17:30:20 +05:30
else :
2015-04-10 18:27:25 +05:30
texture = np . arange ( info [ ' grid ' ] . prod ( ) )
microstructure = np . hstack ( zip ( texture , phase ) ) . reshape ( info [ ' grid ' ] . prod ( ) , 2 ) # create texture/phase pairs
2014-01-30 17:30:20 +05:30
formatOut = 1 + int ( math . log10 ( len ( texture ) ) )
textureOut = [ ' \n \n <texture> ' ]
2015-04-10 18:27:25 +05:30
eulerFormatOut = ' %% %i . %i f ' % ( int ( options . precision ) + 4 , int ( options . precision ) )
outStringAngles = ' (gauss) phi1 ' + eulerFormatOut + ' Phi ' + eulerFormatOut + ' phi2 ' + eulerFormatOut + ' scatter 0.0 fraction 1.0 \n '
2014-01-30 17:30:20 +05:30
for i in xrange ( len ( texture ) ) :
2015-04-10 18:27:25 +05:30
textureOut + = [ ' [Texture %s ] \n ' % str ( i + 1 ) . zfill ( formatOut ) +
' axes %s %s %s \n ' % ( options . axes [ 0 ] , options . axes [ 1 ] , options . axes [ 2 ] ) +
outStringAngles % tuple ( eulerangles [ texture [ i ] , . . . ] )
2014-01-30 17:30:20 +05:30
]
formatOut = 1 + int ( math . log10 ( len ( microstructure ) ) )
microstructureOut = [ ' <microstructure> ' ]
for i in xrange ( len ( microstructure ) ) :
2015-04-10 18:27:25 +05:30
microstructureOut + = [ ' [Grain %s ] \n ' % str ( i + 1 ) . zfill ( formatOut ) +
' crystallite \t %i \n ' % options . crystallite +
' (constituent) \t phase %i \t texture %i \t fraction 1.0 \n ' % ( microstructure [ i , 1 ] , microstructure [ i , 0 ] + 1 )
2014-01-30 17:30:20 +05:30
]
info [ ' microstructures ' ] = len ( microstructure )
2013-05-13 18:40:31 +05:30
#--- report ---------------------------------------------------------------------------------------
2015-04-10 18:27:25 +05:30
file [ ' croak ' ] . write ( ' grid a b c: %s \n ' % ( ' x ' . join ( map ( str , info [ ' grid ' ] ) ) ) +
' size x y z: %s \n ' % ( ' x ' . join ( map ( str , info [ ' size ' ] ) ) ) +
' origin x y z: %s \n ' % ( ' : ' . join ( map ( str , info [ ' origin ' ] ) ) ) +
' homogenization: %i \n ' % info [ ' homogenization ' ] +
2013-05-13 18:40:31 +05:30
' microstructures: %i \n \n ' % info [ ' microstructures ' ] )
2014-01-30 17:30:20 +05:30
if np . any ( info [ ' grid ' ] < 1 ) :
2013-05-17 22:14:03 +05:30
file [ ' croak ' ] . write ( ' invalid grid a b c. \n ' )
2014-11-14 20:23:48 +05:30
continue
2014-01-30 17:30:20 +05:30
if np . any ( info [ ' size ' ] < = 0.0 ) :
2013-05-17 22:14:03 +05:30
file [ ' croak ' ] . write ( ' invalid size x y z. \n ' )
2014-11-14 20:23:48 +05:30
continue
2014-01-30 17:30:20 +05:30
2013-05-15 02:39:37 +05:30
2013-05-13 18:40:31 +05:30
#--- write data -----------------------------------------------------------------------------------
2012-11-08 21:14:51 +05:30
if options . config :
2014-11-14 20:23:48 +05:30
file [ ' output ' ] . write ( ' \n ' . join ( microstructureOut + textureOut ) + ' \n ' )
2013-05-13 18:40:31 +05:30
else :
2014-11-14 20:23:48 +05:30
header = [ ' ' . join ( [ scriptID ] + sys . argv [ 1 : ] ) ,
" grid \t a %i \t b %i \t c %i " % ( info [ ' grid ' ] [ 0 ] , info [ ' grid ' ] [ 1 ] , info [ ' grid ' ] [ 2 ] , ) ,
" size \t x %f \t y %f \t z %f " % ( info [ ' size ' ] [ 0 ] , info [ ' size ' ] [ 1 ] , info [ ' size ' ] [ 2 ] , ) ,
" origin \t x %f \t y %f \t z %f " % ( info [ ' origin ' ] [ 0 ] , info [ ' origin ' ] [ 1 ] , info [ ' origin ' ] [ 2 ] , ) ,
" microstructures \t %i " % info [ ' microstructures ' ] ,
" homogenization \t %i " % info [ ' homogenization ' ] ,
]
file [ ' output ' ] . write ( ' \n ' . join ( [ ' %i \t header ' % ( len ( header ) ) ] + header ) + ' \n ' )
2014-01-30 17:30:20 +05:30
if options . compress :
matPoints = matPoints . reshape ( ( info [ ' grid ' ] [ 1 ] , info [ ' grid ' ] [ 0 ] ) )
np . savetxt ( file [ ' output ' ] , matPoints , fmt = ' % 0 ' + str ( 1 + int ( math . log10 ( np . amax ( matPoints ) ) ) ) + ' d ' )
else :
file [ ' output ' ] . write ( " 1 to %i \n " % ( info [ ' microstructures ' ] ) )
2012-11-08 21:14:51 +05:30
2013-05-13 18:40:31 +05:30
#--- output finalization --------------------------------------------------------------------------
2012-11-08 21:14:51 +05:30
if file [ ' name ' ] != ' STDIN ' :
2014-11-14 20:23:48 +05:30
file [ ' output ' ] . close ( )
os . rename ( file [ ' name ' ] + ' _tmp ' ,
2014-11-17 03:14:46 +05:30
os . path . splitext ( file [ ' name ' ] ) [ 0 ] + ' %s ' % ( ' _material.config ' if options . config else ' .geom ' ) )