Merge branch 'python-improvements' into 'development'
Python improvements See merge request damask/DAMASK!335
This commit is contained in:
commit
8933dd8562
|
@ -1,3 +1,5 @@
|
||||||
|
import inspect
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
from . import Rotation
|
from . import Rotation
|
||||||
|
@ -7,7 +9,7 @@ from . import tensor
|
||||||
_parameter_doc = \
|
_parameter_doc = \
|
||||||
"""lattice : str
|
"""lattice : str
|
||||||
Either a crystal family out of [triclinic, monoclinic, orthorhombic, tetragonal, hexagonal, cubic]
|
Either a crystal family out of [triclinic, monoclinic, orthorhombic, tetragonal, hexagonal, cubic]
|
||||||
or a Bravais lattice out of [aP, mP, mS, oP, oS, oI, oF, tP, tI, hP, cP, cI, cF].
|
or a Bravais lattice out of [aP, mP, mS, oP, oS, oI, oF, tP, tI, hP, cP, cI, cF].
|
||||||
When specifying a Bravais lattice, additional lattice parameters might be required:
|
When specifying a Bravais lattice, additional lattice parameters might be required:
|
||||||
a : float, optional
|
a : float, optional
|
||||||
Length of lattice parameter "a".
|
Length of lattice parameter "a".
|
||||||
|
@ -107,8 +109,7 @@ class Orientation(Rotation):
|
||||||
lattice = None,
|
lattice = None,
|
||||||
a = None,b = None,c = None,
|
a = None,b = None,c = None,
|
||||||
alpha = None,beta = None,gamma = None,
|
alpha = None,beta = None,gamma = None,
|
||||||
degrees = False,
|
degrees = False):
|
||||||
**kwargs):
|
|
||||||
"""
|
"""
|
||||||
Initialize orientation object.
|
Initialize orientation object.
|
||||||
|
|
||||||
|
@ -263,70 +264,112 @@ class Orientation(Rotation):
|
||||||
raise TypeError('Use "O@b", i.e. matmul, to apply Orientation "O" to object "b"')
|
raise TypeError('Use "O@b", i.e. matmul, to apply Orientation "O" to object "b"')
|
||||||
|
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _split_kwargs(kwargs,target):
|
||||||
|
"""
|
||||||
|
Separate keyword arguments in 'kwargs' targeted at 'target' from general keyword arguments of Orientation objects.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
kwargs : dictionary
|
||||||
|
Contains all **kwargs.
|
||||||
|
target: method
|
||||||
|
Function to scan for kwarg signature.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
rot_kwargs: dictionary
|
||||||
|
Valid keyword arguments of 'target' function of Rotation class.
|
||||||
|
ori_kwargs: dictionary
|
||||||
|
Valid keyword arguments of Orientation object.
|
||||||
|
|
||||||
|
"""
|
||||||
|
kws = ()
|
||||||
|
for t in (target,Orientation.__init__):
|
||||||
|
kws += ({key: kwargs[key] for key in set(inspect.signature(t).parameters) & set(kwargs)},)
|
||||||
|
|
||||||
|
invalid_keys = set(kwargs)-(set(kws[0])|set(kws[1]))
|
||||||
|
if invalid_keys:
|
||||||
|
raise TypeError(f"{inspect.stack()[1][3]}() got an unexpected keyword argument '{invalid_keys.pop()}'")
|
||||||
|
|
||||||
|
return kws
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@util.extended_docstring(Rotation.from_random,_parameter_doc)
|
@util.extended_docstring(Rotation.from_random,_parameter_doc)
|
||||||
def from_random(cls,**kwargs):
|
def from_random(cls,**kwargs):
|
||||||
return cls(rotation=Rotation.from_random(**kwargs),**kwargs)
|
kwargs_rot,kwargs_ori = Orientation._split_kwargs(kwargs,Rotation.from_random)
|
||||||
|
return cls(rotation=Rotation.from_random(**kwargs_rot),**kwargs_ori)
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@util.extended_docstring(Rotation.from_quaternion,_parameter_doc)
|
@util.extended_docstring(Rotation.from_quaternion,_parameter_doc)
|
||||||
def from_quaternion(cls,**kwargs):
|
def from_quaternion(cls,**kwargs):
|
||||||
return cls(rotation=Rotation.from_quaternion(**kwargs),**kwargs)
|
kwargs_rot,kwargs_ori = Orientation._split_kwargs(kwargs,Rotation.from_quaternion)
|
||||||
|
return cls(rotation=Rotation.from_quaternion(**kwargs_rot),**kwargs_ori)
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@util.extended_docstring(Rotation.from_Euler_angles,_parameter_doc)
|
@util.extended_docstring(Rotation.from_Euler_angles,_parameter_doc)
|
||||||
def from_Euler_angles(cls,**kwargs):
|
def from_Euler_angles(cls,**kwargs):
|
||||||
return cls(rotation=Rotation.from_Euler_angles(**kwargs),**kwargs)
|
kwargs_rot,kwargs_ori = Orientation._split_kwargs(kwargs,Rotation.from_Euler_angles)
|
||||||
|
return cls(rotation=Rotation.from_Euler_angles(**kwargs_rot),**kwargs_ori)
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@util.extended_docstring(Rotation.from_axis_angle,_parameter_doc)
|
@util.extended_docstring(Rotation.from_axis_angle,_parameter_doc)
|
||||||
def from_axis_angle(cls,**kwargs):
|
def from_axis_angle(cls,**kwargs):
|
||||||
return cls(rotation=Rotation.from_axis_angle(**kwargs),**kwargs)
|
kwargs_rot,kwargs_ori = Orientation._split_kwargs(kwargs,Rotation.from_axis_angle)
|
||||||
|
return cls(rotation=Rotation.from_axis_angle(**kwargs_rot),**kwargs_ori)
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@util.extended_docstring(Rotation.from_basis,_parameter_doc)
|
@util.extended_docstring(Rotation.from_basis,_parameter_doc)
|
||||||
def from_basis(cls,**kwargs):
|
def from_basis(cls,**kwargs):
|
||||||
return cls(rotation=Rotation.from_basis(**kwargs),**kwargs)
|
kwargs_rot,kwargs_ori = Orientation._split_kwargs(kwargs,Rotation.from_basis)
|
||||||
|
return cls(rotation=Rotation.from_basis(**kwargs_rot),**kwargs_ori)
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@util.extended_docstring(Rotation.from_matrix,_parameter_doc)
|
@util.extended_docstring(Rotation.from_matrix,_parameter_doc)
|
||||||
def from_matrix(cls,**kwargs):
|
def from_matrix(cls,**kwargs):
|
||||||
return cls(rotation=Rotation.from_matrix(**kwargs),**kwargs)
|
kwargs_rot,kwargs_ori = Orientation._split_kwargs(kwargs,Rotation.from_matrix)
|
||||||
|
return cls(rotation=Rotation.from_matrix(**kwargs_rot),**kwargs_ori)
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@util.extended_docstring(Rotation.from_Rodrigues_vector,_parameter_doc)
|
@util.extended_docstring(Rotation.from_Rodrigues_vector,_parameter_doc)
|
||||||
def from_Rodrigues_vector(cls,**kwargs):
|
def from_Rodrigues_vector(cls,**kwargs):
|
||||||
return cls(rotation=Rotation.from_Rodrigues_vector(**kwargs),**kwargs)
|
kwargs_rot,kwargs_ori = Orientation._split_kwargs(kwargs,Rotation.from_Rodrigues_vector)
|
||||||
|
return cls(rotation=Rotation.from_Rodrigues_vector(**kwargs_rot),**kwargs_ori)
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@util.extended_docstring(Rotation.from_homochoric,_parameter_doc)
|
@util.extended_docstring(Rotation.from_homochoric,_parameter_doc)
|
||||||
def from_homochoric(cls,**kwargs):
|
def from_homochoric(cls,**kwargs):
|
||||||
return cls(rotation=Rotation.from_homochoric(**kwargs),**kwargs)
|
kwargs_rot,kwargs_ori = Orientation._split_kwargs(kwargs,Rotation.from_homochoric)
|
||||||
|
return cls(rotation=Rotation.from_homochoric(**kwargs_rot),**kwargs_ori)
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@util.extended_docstring(Rotation.from_cubochoric,_parameter_doc)
|
@util.extended_docstring(Rotation.from_cubochoric,_parameter_doc)
|
||||||
def from_cubochoric(cls,**kwargs):
|
def from_cubochoric(cls,**kwargs):
|
||||||
return cls(rotation=Rotation.from_cubochoric(**kwargs),**kwargs)
|
kwargs_rot,kwargs_ori = Orientation._split_kwargs(kwargs,Rotation.from_cubochoric)
|
||||||
|
return cls(rotation=Rotation.from_cubochoric(**kwargs_rot),**kwargs_ori)
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@util.extended_docstring(Rotation.from_spherical_component,_parameter_doc)
|
@util.extended_docstring(Rotation.from_spherical_component,_parameter_doc)
|
||||||
def from_spherical_component(cls,**kwargs):
|
def from_spherical_component(cls,**kwargs):
|
||||||
return cls(rotation=Rotation.from_spherical_component(**kwargs),**kwargs)
|
kwargs_rot,kwargs_ori = Orientation._split_kwargs(kwargs,Rotation.from_spherical_component)
|
||||||
|
return cls(rotation=Rotation.from_spherical_component(**kwargs_rot),**kwargs_ori)
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@util.extended_docstring(Rotation.from_fiber_component,_parameter_doc)
|
@util.extended_docstring(Rotation.from_fiber_component,_parameter_doc)
|
||||||
def from_fiber_component(cls,**kwargs):
|
def from_fiber_component(cls,**kwargs):
|
||||||
return cls(rotation=Rotation.from_fiber_component(**kwargs),**kwargs)
|
kwargs_rot,kwargs_ori = Orientation._split_kwargs(kwargs,Rotation.from_fiber_component)
|
||||||
|
return cls(rotation=Rotation.from_fiber_component(**kwargs_rot),**kwargs_ori)
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|
|
@ -502,8 +502,8 @@ class Rotation:
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
c : numpy.ndarray of shape (...,3)
|
x : numpy.ndarray of shape (...,3)
|
||||||
Cubochoric vector: (c_1, c_2, c_3), max(c_i) < 1/2*π^(2/3).
|
Cubochoric vector: (x_1, x_2, x_3), max(x_i) < 1/2*π^(2/3).
|
||||||
|
|
||||||
"""
|
"""
|
||||||
return Rotation._qu2cu(self.quaternion)
|
return Rotation._qu2cu(self.quaternion)
|
||||||
|
@ -514,8 +514,7 @@ class Rotation:
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def from_quaternion(q,
|
def from_quaternion(q,
|
||||||
accept_homomorph = False,
|
accept_homomorph = False,
|
||||||
P = -1,
|
P = -1):
|
||||||
**kwargs):
|
|
||||||
"""
|
"""
|
||||||
Initialize from quaternion.
|
Initialize from quaternion.
|
||||||
|
|
||||||
|
@ -550,8 +549,7 @@ class Rotation:
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def from_Euler_angles(phi,
|
def from_Euler_angles(phi,
|
||||||
degrees = False,
|
degrees = False):
|
||||||
**kwargs):
|
|
||||||
"""
|
"""
|
||||||
Initialize from Bunge-Euler angles.
|
Initialize from Bunge-Euler angles.
|
||||||
|
|
||||||
|
@ -578,8 +576,7 @@ class Rotation:
|
||||||
def from_axis_angle(axis_angle,
|
def from_axis_angle(axis_angle,
|
||||||
degrees = False,
|
degrees = False,
|
||||||
normalize = False,
|
normalize = False,
|
||||||
P = -1,
|
P = -1):
|
||||||
**kwargs):
|
|
||||||
"""
|
"""
|
||||||
Initialize from Axis angle pair.
|
Initialize from Axis angle pair.
|
||||||
|
|
||||||
|
@ -616,8 +613,7 @@ class Rotation:
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def from_basis(basis,
|
def from_basis(basis,
|
||||||
orthonormal = True,
|
orthonormal = True,
|
||||||
reciprocal = False,
|
reciprocal = False):
|
||||||
**kwargs):
|
|
||||||
"""
|
"""
|
||||||
Initialize from lattice basis vectors.
|
Initialize from lattice basis vectors.
|
||||||
|
|
||||||
|
@ -651,7 +647,7 @@ class Rotation:
|
||||||
return Rotation(Rotation._om2qu(om))
|
return Rotation(Rotation._om2qu(om))
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def from_matrix(R,**kwargs):
|
def from_matrix(R):
|
||||||
"""
|
"""
|
||||||
Initialize from rotation matrix.
|
Initialize from rotation matrix.
|
||||||
|
|
||||||
|
@ -695,8 +691,7 @@ class Rotation:
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def from_Rodrigues_vector(rho,
|
def from_Rodrigues_vector(rho,
|
||||||
normalize = False,
|
normalize = False,
|
||||||
P = -1,
|
P = -1):
|
||||||
**kwargs):
|
|
||||||
"""
|
"""
|
||||||
Initialize from Rodrigues-Frank vector (angle separated from axis).
|
Initialize from Rodrigues-Frank vector (angle separated from axis).
|
||||||
|
|
||||||
|
@ -727,8 +722,7 @@ class Rotation:
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def from_homochoric(h,
|
def from_homochoric(h,
|
||||||
P = -1,
|
P = -1):
|
||||||
**kwargs):
|
|
||||||
"""
|
"""
|
||||||
Initialize from homochoric vector.
|
Initialize from homochoric vector.
|
||||||
|
|
||||||
|
@ -754,21 +748,20 @@ class Rotation:
|
||||||
return Rotation(Rotation._ho2qu(ho))
|
return Rotation(Rotation._ho2qu(ho))
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def from_cubochoric(c,
|
def from_cubochoric(x,
|
||||||
P = -1,
|
P = -1):
|
||||||
**kwargs):
|
|
||||||
"""
|
"""
|
||||||
Initialize from cubochoric vector.
|
Initialize from cubochoric vector.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
c : numpy.ndarray of shape (...,3)
|
x : numpy.ndarray of shape (...,3)
|
||||||
Cubochoric vector: (c_1, c_2, c_3), max(c_i) < 1/2*π^(2/3).
|
Cubochoric vector: (x_1, x_2, x_3), max(x_i) < 1/2*π^(2/3).
|
||||||
P : int ∈ {-1,1}, optional
|
P : int ∈ {-1,1}, optional
|
||||||
Convention used. Defaults to -1.
|
Convention used. Defaults to -1.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
cu = np.array(c,dtype=float)
|
cu = np.array(x,dtype=float)
|
||||||
if cu.shape[:-2:-1] != (3,):
|
if cu.shape[:-2:-1] != (3,):
|
||||||
raise ValueError('Invalid shape.')
|
raise ValueError('Invalid shape.')
|
||||||
if abs(P) != 1:
|
if abs(P) != 1:
|
||||||
|
@ -784,8 +777,7 @@ class Rotation:
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def from_random(shape = None,
|
def from_random(shape = None,
|
||||||
rng_seed = None,
|
rng_seed = None):
|
||||||
**kwargs):
|
|
||||||
"""
|
"""
|
||||||
Draw random rotation.
|
Draw random rotation.
|
||||||
|
|
||||||
|
@ -878,8 +870,7 @@ class Rotation:
|
||||||
sigma,
|
sigma,
|
||||||
N = 500,
|
N = 500,
|
||||||
degrees = True,
|
degrees = True,
|
||||||
rng_seed = None,
|
rng_seed = None):
|
||||||
**kwargs):
|
|
||||||
"""
|
"""
|
||||||
Calculate set of rotations with Gaussian distribution around center.
|
Calculate set of rotations with Gaussian distribution around center.
|
||||||
|
|
||||||
|
@ -915,8 +906,7 @@ class Rotation:
|
||||||
sigma = 0.0,
|
sigma = 0.0,
|
||||||
N = 500,
|
N = 500,
|
||||||
degrees = True,
|
degrees = True,
|
||||||
rng_seed = None,
|
rng_seed = None):
|
||||||
**kwargs):
|
|
||||||
"""
|
"""
|
||||||
Calculate set of rotations with Gaussian distribution around direction.
|
Calculate set of rotations with Gaussian distribution around direction.
|
||||||
|
|
||||||
|
|
|
@ -118,7 +118,7 @@ class TestOrientation:
|
||||||
== np.eye(3))
|
== np.eye(3))
|
||||||
|
|
||||||
def test_from_cubochoric(self):
|
def test_from_cubochoric(self):
|
||||||
assert np.all(Orientation.from_cubochoric(c=np.zeros(3),lattice='triclinic').as_matrix()
|
assert np.all(Orientation.from_cubochoric(x=np.zeros(3),lattice='triclinic').as_matrix()
|
||||||
== np.eye(3))
|
== np.eye(3))
|
||||||
|
|
||||||
def test_from_spherical_component(self):
|
def test_from_spherical_component(self):
|
||||||
|
@ -141,7 +141,7 @@ class TestOrientation:
|
||||||
dict(lattice='hP',a=1.0 ),
|
dict(lattice='hP',a=1.0 ),
|
||||||
dict(lattice='cI',a=1.0, ),
|
dict(lattice='cI',a=1.0, ),
|
||||||
])
|
])
|
||||||
def test_from_direction(self,kwargs):
|
def test_from_directions(self,kwargs):
|
||||||
for a,b in np.random.random((10,2,3)):
|
for a,b in np.random.random((10,2,3)):
|
||||||
c = np.cross(b,a)
|
c = np.cross(b,a)
|
||||||
if np.all(np.isclose(c,0)): continue
|
if np.all(np.isclose(c,0)): continue
|
||||||
|
@ -151,6 +151,21 @@ class TestOrientation:
|
||||||
assert np.isclose(np.dot(x/np.linalg.norm(x),np.array([1,0,0])),1) \
|
assert np.isclose(np.dot(x/np.linalg.norm(x),np.array([1,0,0])),1) \
|
||||||
and np.isclose(np.dot(z/np.linalg.norm(z),np.array([0,0,1])),1)
|
and np.isclose(np.dot(z/np.linalg.norm(z),np.array([0,0,1])),1)
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('function',[Orientation.from_random,
|
||||||
|
Orientation.from_quaternion,
|
||||||
|
Orientation.from_Euler_angles,
|
||||||
|
Orientation.from_axis_angle,
|
||||||
|
Orientation.from_basis,
|
||||||
|
Orientation.from_matrix,
|
||||||
|
Orientation.from_Rodrigues_vector,
|
||||||
|
Orientation.from_homochoric,
|
||||||
|
Orientation.from_cubochoric,
|
||||||
|
Orientation.from_spherical_component,
|
||||||
|
Orientation.from_fiber_component,
|
||||||
|
Orientation.from_directions])
|
||||||
|
def test_invalid_from(self,function):
|
||||||
|
with pytest.raises(TypeError):
|
||||||
|
function(c=.1,degrees=True,invalid=66)
|
||||||
|
|
||||||
def test_negative_angle(self):
|
def test_negative_angle(self):
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
|
|
Loading…
Reference in New Issue