more user friendly constructors
This commit is contained in:
parent
ef3fc0b58a
commit
97ac437686
2
PRIVATE
2
PRIVATE
|
@ -1 +1 @@
|
||||||
Subproject commit 25006bc974b752faf3464b082511590d50093c37
|
Subproject commit 406d482f8059b4459634af729ce85491a9a3245c
|
|
@ -79,8 +79,8 @@ parser.add_option('-z',
|
||||||
help = 'label of lab z vector (expressed in crystal coords)')
|
help = 'label of lab z vector (expressed in crystal coords)')
|
||||||
|
|
||||||
parser.set_defaults(output = [],
|
parser.set_defaults(output = [],
|
||||||
labrotation = (0.,1.,1.,1.), # no rotation about 1,1,1
|
labrotation = (0.,1.,0.,0.), # no rotation about 1,0,0
|
||||||
crystalrotation = (0.,1.,1.,1.), # no rotation about 1,1,1
|
crystalrotation = (0.,1.,0.,0.), # no rotation about 1,0,0
|
||||||
degrees = False,
|
degrees = False,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -108,8 +108,8 @@ if np.sum(input) != 1: parser.error('needs exactly one input format.')
|
||||||
(options.quaternion,4,'quaternion'),
|
(options.quaternion,4,'quaternion'),
|
||||||
][np.where(input)[0][0]] # select input label that was requested
|
][np.where(input)[0][0]] # select input label that was requested
|
||||||
|
|
||||||
r = damask.Rotation.fromAngleAxis(np.array(options.crystalrotation),options.degrees) # crystal frame rotation
|
r = damask.Rotation.fromAngleAxis(options.crystalrotation,options.degrees) # crystal frame rotation
|
||||||
R = damask.Rotation.fromAngleAxis(np.array(options.labrotation),options.degrees) # lab frame rotation
|
R = damask.Rotation.fromAngleAxis(options.labrotation,options.degrees) # lab frame rotation
|
||||||
|
|
||||||
# --- loop over input files ------------------------------------------------------------------------
|
# --- loop over input files ------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -153,13 +153,13 @@ for name in filenames:
|
||||||
outputAlive = True
|
outputAlive = True
|
||||||
while outputAlive and table.data_read(): # read next data line of ASCII table
|
while outputAlive and table.data_read(): # read next data line of ASCII table
|
||||||
if inputtype == 'eulers':
|
if inputtype == 'eulers':
|
||||||
o = damask.Rotation.fromEulers(np.array(list(map(float,table.data[column:column+3]))),options.degrees)
|
o = damask.Rotation.fromEulers(list(map(float,table.data[column:column+3])),options.degrees)
|
||||||
|
|
||||||
elif inputtype == 'rodrigues':
|
elif inputtype == 'rodrigues':
|
||||||
o = damask.Rotation.fromRodrigues(np.array(list(map(float,table.data[column:column+3]))))
|
o = damask.Rotation.fromRodrigues(list(map(float,table.data[column:column+3])))
|
||||||
|
|
||||||
elif inputtype == 'matrix':
|
elif inputtype == 'matrix':
|
||||||
o = damask.Rotation.fromMatrix(np.array(list(map(float,table.data[column:column+9]))).reshape(3,3))
|
o = damask.Rotation.fromMatrix(list(map(float,table.data[column:column+9])).reshape(3,3))
|
||||||
|
|
||||||
elif inputtype == 'frame':
|
elif inputtype == 'frame':
|
||||||
M = np.array(list(map(float,table.data[column[0]:column[0]+3] + \
|
M = np.array(list(map(float,table.data[column[0]:column[0]+3] + \
|
||||||
|
@ -168,7 +168,7 @@ for name in filenames:
|
||||||
o = damask.Rotation.fromMatrix(M/np.linalg.norm(M,axis=0))
|
o = damask.Rotation.fromMatrix(M/np.linalg.norm(M,axis=0))
|
||||||
|
|
||||||
elif inputtype == 'quaternion':
|
elif inputtype == 'quaternion':
|
||||||
o = damask.Rotation.fromQuaternion(np.array(list(map(float,table.data[column:column+4]))))
|
o = damask.Rotation.fromQuaternion(list(map(float,table.data[column:column+4])))
|
||||||
|
|
||||||
o= r*o*R # apply additional lab and crystal frame rotations
|
o= r*o*R # apply additional lab and crystal frame rotations
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# -*- coding: UTF-8 no BOM -*-
|
# -*- coding: UTF-8 no BOM -*-
|
||||||
|
|
||||||
import os,sys,math
|
import os,sys
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from optparse import OptionParser
|
from optparse import OptionParser
|
||||||
import damask
|
import damask
|
||||||
|
@ -29,9 +29,9 @@ parser.add_option('-r', '--rotation',
|
||||||
parser.add_option('--degrees',
|
parser.add_option('--degrees',
|
||||||
dest = 'degrees',
|
dest = 'degrees',
|
||||||
action = 'store_true',
|
action = 'store_true',
|
||||||
help = 'angles are given in degrees [%default]')
|
help = 'angle is given in degrees [%default]')
|
||||||
|
|
||||||
parser.set_defaults(rotation = (0.,1.,1.,1.), # no rotation about 1,1,1
|
parser.set_defaults(rotation = (0.,1.,0.,0.), # no rotation about 1,0,0
|
||||||
degrees = False,
|
degrees = False,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ parser.set_defaults(rotation = (0.,1.,1.,1.),
|
||||||
if options.data is None:
|
if options.data is None:
|
||||||
parser.error('no data column specified.')
|
parser.error('no data column specified.')
|
||||||
|
|
||||||
r = damask.Rotation.fromAngleAxis(options.rotation,degrees)
|
r = damask.Rotation.fromAngleAxis(options.rotation,options.degrees,normalise=True)
|
||||||
|
|
||||||
# --- loop over input files -------------------------------------------------------------------------
|
# --- loop over input files -------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
|
@ -63,9 +63,9 @@ parser.set_defaults(center = (.0,.0,.0),
|
||||||
if options.dimension is None:
|
if options.dimension is None:
|
||||||
parser.error('no dimension specified.')
|
parser.error('no dimension specified.')
|
||||||
if options.angleaxis is not None:
|
if options.angleaxis is not None:
|
||||||
rotation = damask.Rotation.fromAngleAxis(np.array(options.angleaxis),options.degrees,normalise=True)
|
rotation = damask.Rotation.fromAngleAxis(options.angleaxis,options.degrees,normalise=True)
|
||||||
elif options.quaternion is not None:
|
elif options.quaternion is not None:
|
||||||
rotation = damask.Rotation.fromQuaternion(np.array(options.quaternion))
|
rotation = damask.Rotation.fromQuaternion(options.quaternion)
|
||||||
else:
|
else:
|
||||||
rotation = damask.Rotation()
|
rotation = damask.Rotation()
|
||||||
|
|
||||||
|
|
|
@ -236,7 +236,12 @@ class Rotation:
|
||||||
__slots__ = ['quaternion']
|
__slots__ = ['quaternion']
|
||||||
|
|
||||||
def __init__(self,quaternion = np.array([1.0,0.0,0.0,0.0])):
|
def __init__(self,quaternion = np.array([1.0,0.0,0.0,0.0])):
|
||||||
"""Initializes to identity unless specified"""
|
"""
|
||||||
|
Initializes to identity unless specified
|
||||||
|
|
||||||
|
If a quaternion is given, it needs to comply with the convection. Use .fromQuaternion
|
||||||
|
to check the input.
|
||||||
|
"""
|
||||||
self.quaternion = Quaternion2(q=quaternion[0],p=quaternion[1:4])
|
self.quaternion = Quaternion2(q=quaternion[0],p=quaternion[1:4])
|
||||||
self.quaternion.homomorph() # ToDo: Needed?
|
self.quaternion.homomorph() # ToDo: Needed?
|
||||||
|
|
||||||
|
@ -247,7 +252,9 @@ class Rotation:
|
||||||
'Matrix:\n{}'.format( '\n'.join(['\t'.join(list(map(str,self.asMatrix()[i,:]))) for i in range(3)]) ),
|
'Matrix:\n{}'.format( '\n'.join(['\t'.join(list(map(str,self.asMatrix()[i,:]))) for i in range(3)]) ),
|
||||||
'Bunge Eulers / deg: {}'.format('\t'.join(list(map(str,self.asEulers(degrees=True)))) ),
|
'Bunge Eulers / deg: {}'.format('\t'.join(list(map(str,self.asEulers(degrees=True)))) ),
|
||||||
])
|
])
|
||||||
|
|
||||||
|
################################################################################################
|
||||||
|
# convert to different orientation representations (numpy arrays)
|
||||||
|
|
||||||
def asQuaternion(self):
|
def asQuaternion(self):
|
||||||
return self.quaternion.asArray()
|
return self.quaternion.asArray()
|
||||||
|
@ -276,14 +283,16 @@ class Rotation:
|
||||||
def asCubochoric(self):
|
def asCubochoric(self):
|
||||||
return qu2cu(self.quaternion.asArray())
|
return qu2cu(self.quaternion.asArray())
|
||||||
|
|
||||||
|
|
||||||
|
################################################################################################
|
||||||
|
# static constructors. The input data needs to follow the convention, options allow to
|
||||||
|
# relax these convections
|
||||||
@classmethod
|
@classmethod
|
||||||
def fromQuaternion(cls,
|
def fromQuaternion(cls,
|
||||||
quaternion,
|
quaternion,
|
||||||
P = -1):
|
P = -1):
|
||||||
|
|
||||||
qu = quaternion
|
qu = quaternion if isinstance(quaternion, np.ndarray) else np.array(quaternion)
|
||||||
if P > 0: qu[1:4] *= -1 # convert from P=1 to P=-1
|
if P > 0: qu[1:4] *= -1 # convert from P=1 to P=-1
|
||||||
if qu[0] < 0.0:
|
if qu[0] < 0.0:
|
||||||
raise ValueError('Quaternion has negative first component.\n{}'.format(qu[0]))
|
raise ValueError('Quaternion has negative first component.\n{}'.format(qu[0]))
|
||||||
|
@ -296,8 +305,9 @@ class Rotation:
|
||||||
def fromEulers(cls,
|
def fromEulers(cls,
|
||||||
eulers,
|
eulers,
|
||||||
degrees = False):
|
degrees = False):
|
||||||
|
|
||||||
eu = np.radians(eulers) if degrees else eulers
|
eu = eulers if isinstance(eulers, np.ndarray) else np.array(eulers)
|
||||||
|
eu = np.radians(eu) if degrees else eu
|
||||||
if np.any(eu < 0.0) or np.any(eu > 2.0*np.pi) or eu[1] > np.pi:
|
if np.any(eu < 0.0) or np.any(eu > 2.0*np.pi) or eu[1] > np.pi:
|
||||||
raise ValueError('Euler angles outside of [0..2π],[0..π],[0..2π].\n{} {} {}.'.format(*eu))
|
raise ValueError('Euler angles outside of [0..2π],[0..π],[0..2π].\n{} {} {}.'.format(*eu))
|
||||||
|
|
||||||
|
@ -309,8 +319,8 @@ class Rotation:
|
||||||
degrees = False,
|
degrees = False,
|
||||||
normalise = False,
|
normalise = False,
|
||||||
P = -1):
|
P = -1):
|
||||||
|
|
||||||
ax = angleAxis
|
ax = angleAxis if isinstance(angleAxis, np.ndarray) else np.array(angleAxis)
|
||||||
if P > 0: ax[1:4] *= -1 # convert from P=1 to P=-1
|
if P > 0: ax[1:4] *= -1 # convert from P=1 to P=-1
|
||||||
if degrees: ax[0] = np.degrees(ax[0])
|
if degrees: ax[0] = np.degrees(ax[0])
|
||||||
if normalise: ax[1:4] /=np.linalg.norm(ax[1:4])
|
if normalise: ax[1:4] /=np.linalg.norm(ax[1:4])
|
||||||
|
@ -323,9 +333,13 @@ class Rotation:
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def fromMatrix(cls,
|
def fromMatrix(cls,
|
||||||
matrix):
|
matrix,
|
||||||
|
containsStretch = False): #ToDo: better name?
|
||||||
|
|
||||||
om = matrix
|
om = matrix if isinstance(matrix, np.ndarray) else np.array(matrix)
|
||||||
|
if containsStretch:
|
||||||
|
(U,S,Vh) = np.linalg.svd(om) # singular value decomposition
|
||||||
|
om = np.dot(U,Vh)
|
||||||
if not np.isclose(np.linalg.det(om),1.0):
|
if not np.isclose(np.linalg.det(om),1.0):
|
||||||
raise ValueError('matrix is not a proper rotation.\n{}'.format(om))
|
raise ValueError('matrix is not a proper rotation.\n{}'.format(om))
|
||||||
if not np.isclose(np.dot(om[0],om[1]), 0.0) \
|
if not np.isclose(np.dot(om[0],om[1]), 0.0) \
|
||||||
|
@ -341,7 +355,7 @@ class Rotation:
|
||||||
normalise = False,
|
normalise = False,
|
||||||
P = -1):
|
P = -1):
|
||||||
|
|
||||||
ro = rodrigues
|
ro = rodrigues if isinstance(rodrigues, np.ndarray) else np.array(rodrigues)
|
||||||
if P > 0: ro[1:4] *= -1 # convert from P=1 to P=-1
|
if P > 0: ro[1:4] *= -1 # convert from P=1 to P=-1
|
||||||
if normalise: ro[1:4] /=np.linalg.norm(ro[1:4])
|
if normalise: ro[1:4] /=np.linalg.norm(ro[1:4])
|
||||||
if not np.isclose(np.linalg.norm(ro[1:4]), 1.0):
|
if not np.isclose(np.linalg.norm(ro[1:4]), 1.0):
|
||||||
|
@ -356,7 +370,7 @@ class Rotation:
|
||||||
"""
|
"""
|
||||||
Multiplication
|
Multiplication
|
||||||
|
|
||||||
Rotation: Details needed (active/passive), more cases (3,3), (3,3,3,3) need to be considered
|
Rotation: Details needed (active/passive), more rotation of (3,3,3,3) should be considered
|
||||||
"""
|
"""
|
||||||
if isinstance(other, Rotation): # rotate a rotation
|
if isinstance(other, Rotation): # rotate a rotation
|
||||||
return self.__class__((self.quaternion * other.quaternion).asArray())
|
return self.__class__((self.quaternion * other.quaternion).asArray())
|
||||||
|
|
Loading…
Reference in New Issue