polished langauge of help messages

This commit is contained in:
Philip Eisenlohr 2021-09-08 13:10:49 -04:00
parent 0c2956e0e1
commit b337575963
1 changed files with 88 additions and 93 deletions

View File

@ -481,7 +481,7 @@ class Rotation:
Returns Returns
------- -------
q : numpy.ndarray of shape (...,4) q : numpy.ndarray of shape (...,4)
Unit quaternion in positive real hemisphere: (q_0, q_1, q_2, q_3), ǀqǀ=1, q_0 0. Unit quaternion (q_0, q_1, q_2, q_3) in positive real hemisphere, i.e. ǀqǀ = 1, q_0 0.
""" """
return self.quaternion.copy() return self.quaternion.copy()
@ -489,7 +489,7 @@ class Rotation:
def as_Euler_angles(self, def as_Euler_angles(self,
degrees = False): degrees = False):
""" """
Represent as Bunge-Euler angles. Represent as BungeEuler angles.
Parameters Parameters
---------- ----------
@ -499,12 +499,12 @@ class Rotation:
Returns Returns
------- -------
phi : numpy.ndarray of shape (...,3) phi : numpy.ndarray of shape (...,3)
Bunge-Euler angles: (φ_1, ϕ, φ_2), φ_1 [0,2π], ϕ [0,π], φ_2 [0,2π] BungeEuler angles (φ_1 [0,2π], ϕ [0,π], φ_2 [0,2π])
unless degrees == True: φ_1 [0,360], ϕ [0,180], φ_2 [0,360] or (φ_1 [0,360], ϕ [0,180], φ_2 [0,360]) if degrees == True.
Examples Examples
-------- --------
Cube orientation as Bunge-Euler angles. Cube orientation as BungeEuler angles.
>>> import damask >>> import damask
>>> import numpy as np >>> import numpy as np
@ -520,7 +520,7 @@ class Rotation:
degrees = False, degrees = False,
pair = False): pair = False):
""" """
Represent as axis angle pair. Represent as axisangle pair.
Parameters Parameters
---------- ----------
@ -531,19 +531,18 @@ class Rotation:
Returns Returns
------- -------
axis_angle : numpy.ndarray of shape (...,4) unless pair == True: axis_angle : numpy.ndarray of shape (...,4) or tuple ((...,3), (...)) if pair == True
tuple containing numpy.ndarray of shapes (...,3) and (...) Axis and angle (n_1, n_2, n_3, ω) with ǀnǀ = 1 and ω [0,π]
Axis angle pair: (n_1, n_2, n_3, ω), ǀnǀ = 1 and ω [0,π] or ω [0,180] if degrees == True.
unless degrees = True: ω [0,180].
Examples Examples
-------- --------
Cube orientation as axis angle pair. Cube orientation as axisangle pair.
>>> import damask >>> import damask
>>> import numpy as np >>> import numpy as np
>>> damask.Rotation(np.array([1,0,0,0])).as_axis_angle() >>> damask.Rotation(np.array([1,0,0,0])).as_axis_angle(pair=True)
array([0., 0., 1., 0.]) (array([0., 0., 1.]), array(0.))
""" """
ax = Rotation._qu2ax(self.quaternion) ax = Rotation._qu2ax(self.quaternion)
@ -557,7 +556,7 @@ class Rotation:
Returns Returns
------- -------
R : numpy.ndarray of shape (...,3,3) R : numpy.ndarray of shape (...,3,3)
Rotation matrix R, det(R) = 1, R.TR=I. Rotation matrix R with det(R) = 1, R.T R = I.
Examples Examples
-------- --------
@ -576,25 +575,23 @@ class Rotation:
def as_Rodrigues_vector(self, def as_Rodrigues_vector(self,
compact = False): compact = False):
""" """
Represent as Rodrigues-Frank vector with separated axis and angle argument. Represent as RodriguesFrank vector with separated axis and angle argument.
Parameters Parameters
---------- ----------
compact : bool, optional compact : bool, optional
Return as actual Rodrigues-Frank vector, Return three-component Rodrigues-Frank vector,
i.e. axis and angle argument are not separated. i.e. axis and angle argument are not separated.
Returns Returns
------- -------
rho : numpy.ndarray of shape (...,4) containing rho : numpy.ndarray of shape (...,4) or (...,3) if compact == True
[n_1, n_2, n_3, tan(ω/2)], ǀnǀ = 1 and ω [0,π] RodriguesFrank vector [n_1, n_2, n_3, tan(ω/2)] with ǀnǀ = 1 and ω [0,π]
unless compact == True: or tan(ω/2) [n_1, n_2, n_3] with ω [0,π] if compact == True.
numpy.ndarray of shape (...,3) containing
tan(ω/2) [n_1, n_2, n_3], ω [0,π].
Examples Examples
-------- --------
Cube orientation as 'real' Rodrigues-Frank vector. Cube orientation as three-component RodriguesFrank vector.
>>> import damask >>> import damask
>>> import numpy as np >>> import numpy as np
@ -616,7 +613,7 @@ class Rotation:
Returns Returns
------- -------
h : numpy.ndarray of shape (...,3) h : numpy.ndarray of shape (...,3)
Homochoric vector: (h_1, h_2, h_3), ǀhǀ < (3/4*π)^(1/3). Homochoric vector (h_1, h_2, h_3) with ǀhǀ < (3/4*π)^(1/3).
Examples Examples
-------- --------
@ -637,7 +634,7 @@ class Rotation:
Returns Returns
------- -------
x : numpy.ndarray of shape (...,3) x : numpy.ndarray of shape (...,3)
Cubochoric vector: (x_1, x_2, x_3), max(x_i) < 1/2*π^(2/3). Cubochoric vector (x_1, x_2, x_3) with max(x_i) < 1/2*π^(2/3).
Examples Examples
-------- --------
@ -664,13 +661,12 @@ class Rotation:
Parameters Parameters
---------- ----------
q : numpy.ndarray of shape (...,4) q : numpy.ndarray of shape (...,4)
Unit quaternion in positive real hemisphere: (q_0, q_1, q_2, q_3), Unit quaternion (q_0, q_1, q_2, q_3) in positive real hemisphere, i.e. ǀqǀ = 1, q_0 0.
ǀqǀ=1, q_0 0.
accept_homomorph : boolean, optional accept_homomorph : boolean, optional
Allow homomorphic variants, i.e. q_0 < 0 (negative real hemisphere). Allow homomorphic variants, i.e. q_0 < 0 (negative real hemisphere).
Defaults to False. Defaults to False.
P : int {-1,1}, optional P : int {-1,1}, optional
Convention used. Defaults to -1. Sign convention. Defaults to -1.
""" """
qu = np.array(q,dtype=float) qu = np.array(q,dtype=float)
@ -694,15 +690,15 @@ class Rotation:
def from_Euler_angles(phi, def from_Euler_angles(phi,
degrees = False): degrees = False):
""" """
Initialize from Bunge-Euler angles. Initialize from BungeEuler angles.
Parameters Parameters
---------- ----------
phi : numpy.ndarray of shape (...,3) phi : numpy.ndarray of shape (...,3)
Bunge-Euler angles: (φ_1, ϕ, φ_2), φ_1 [0,2π], ϕ [0,π], φ_2 [0,2π] BungeEuler angles ()φ_1 [0,2π], ϕ [0,π], φ_2 [0,2π])
unless degrees == True: φ_1 [0,360], ϕ [0,180], φ_2 [0,360]. or ()φ_1 [0,360], ϕ [0,180], φ_2 [0,360]) if degrees == True.
degrees : boolean, optional degrees : boolean, optional
Bunge-Euler angles are given in degrees. Defaults to False. BungeEuler angles are given in degrees. Defaults to False.
""" """
eu = np.array(phi,dtype=float) eu = np.array(phi,dtype=float)
@ -726,14 +722,14 @@ class Rotation:
Parameters Parameters
---------- ----------
axis_angle : numpy.ndarray of shape (...,4) axis_angle : numpy.ndarray of shape (...,4)
Axis angle pair: [n_1, n_2, n_3, ω], ǀnǀ = 1 and ω [0,π] Axis and angle (n_1, n_2, n_3, ω) with ǀnǀ = 1 and ω [0,π]
unless degrees = True: ω [0,180]. or ω [0,180] if degrees == True.
degrees : boolean, optional degrees : boolean, optional
Angle ω is given in degrees. Defaults to False. Angle ω is given in degrees. Defaults to False.
normalize: boolean, optional normalize: boolean, optional
Allow ǀnǀ 1. Defaults to False. Allow ǀnǀ 1. Defaults to False.
P : int {-1,1}, optional P : int {-1,1}, optional
Convention used. Defaults to -1. Sign convention. Defaults to -1.
""" """
ax = np.array(axis_angle,dtype=float) ax = np.array(axis_angle,dtype=float)
@ -746,10 +742,10 @@ class Rotation:
if degrees: ax[..., 3] = np.radians(ax[...,3]) if degrees: ax[..., 3] = np.radians(ax[...,3])
if normalize: ax[...,0:3] /= np.linalg.norm(ax[...,0:3],axis=-1,keepdims=True) if normalize: ax[...,0:3] /= np.linalg.norm(ax[...,0:3],axis=-1,keepdims=True)
if np.any(ax[...,3] < 0.0) or np.any(ax[...,3] > np.pi): if np.any(ax[...,3] < 0.0) or np.any(ax[...,3] > np.pi):
raise ValueError('Axis angle rotation angle outside of [0..π].') raise ValueError('Axisangle rotation angle outside of [0..π].')
if not np.all(np.isclose(np.linalg.norm(ax[...,0:3],axis=-1), 1.0)): if not np.all(np.isclose(np.linalg.norm(ax[...,0:3],axis=-1), 1.0)):
print(np.linalg.norm(ax[...,0:3],axis=-1)) print(np.linalg.norm(ax[...,0:3],axis=-1))
raise ValueError('Axis angle rotation axis is not of unit length.') raise ValueError('Axisangle rotation axis is not of unit length.')
return Rotation(Rotation._ax2qu(ax)) return Rotation(Rotation._ax2qu(ax))
@ -797,7 +793,7 @@ class Rotation:
Parameters Parameters
---------- ----------
R : numpy.ndarray of shape (...,3,3) R : numpy.ndarray of shape (...,3,3)
Rotation matrix: det(R) = 1, R.TR=I. Rotation matrix with det(R) = 1, R.T R = I.
""" """
return Rotation.from_basis(R) return Rotation.from_basis(R)
@ -836,16 +832,16 @@ class Rotation:
normalize = False, normalize = False,
P = -1): P = -1):
""" """
Initialize from Rodrigues-Frank vector (angle separated from axis). Initialize from RodriguesFrank vector (angle separated from axis).
Parameters Parameters
---------- ----------
rho : numpy.ndarray of shape (...,4) rho : numpy.ndarray of shape (...,4)
Rodrigues-Frank vector. (n_1, n_2, n_3, tan(ω/2)), ǀnǀ = 1 and ω [0,π]. RodriguesFrank vector (n_1, n_2, n_3, tan(ω/2)) with ǀnǀ = 1 and ω [0,π].
normalize : boolean, optional normalize : boolean, optional
Allow ǀnǀ 1. Defaults to False. Allow ǀnǀ 1. Defaults to False.
P : int {-1,1}, optional P : int {-1,1}, optional
Convention used. Defaults to -1. Sign convention. Defaults to -1.
""" """
ro = np.array(rho,dtype=float) ro = np.array(rho,dtype=float)
@ -857,7 +853,7 @@ class Rotation:
ro[...,0:3] *= -P ro[...,0:3] *= -P
if normalize: ro[...,0:3] /= np.linalg.norm(ro[...,0:3],axis=-1,keepdims=True) if normalize: ro[...,0:3] /= np.linalg.norm(ro[...,0:3],axis=-1,keepdims=True)
if np.any(ro[...,3] < 0.0): if np.any(ro[...,3] < 0.0):
raise ValueError('Rodrigues vector rotation angle not positive.') raise ValueError('Rodrigues vector rotation angle is negative.')
if not np.all(np.isclose(np.linalg.norm(ro[...,0:3],axis=-1), 1.0)): if not np.all(np.isclose(np.linalg.norm(ro[...,0:3],axis=-1), 1.0)):
raise ValueError('Rodrigues vector rotation axis is not of unit length.') raise ValueError('Rodrigues vector rotation axis is not of unit length.')
@ -872,9 +868,9 @@ class Rotation:
Parameters Parameters
---------- ----------
h : numpy.ndarray of shape (...,3) h : numpy.ndarray of shape (...,3)
Homochoric vector: (h_1, h_2, h_3), ǀhǀ < (3/4*π)^(1/3). Homochoric vector (h_1, h_2, h_3) with ǀhǀ < (3/4*π)^(1/3).
P : int {-1,1}, optional P : int {-1,1}, optional
Convention used. Defaults to -1. Sign convention. Defaults to -1.
""" """
ho = np.array(h,dtype=float) ho = np.array(h,dtype=float)
@ -899,9 +895,9 @@ class Rotation:
Parameters Parameters
---------- ----------
x : numpy.ndarray of shape (...,3) x : numpy.ndarray of shape (...,3)
Cubochoric vector: (x_1, x_2, x_3), max(x_i) < 1/2*π^(2/3). Cubochoric vector (x_1, x_2, x_3) with max(x_i) < 1/2*π^(2/3).
P : int {-1,1}, optional P : int {-1,1}, optional
Convention used. Defaults to -1. Sign convention. Defaults to -1.
""" """
cu = np.array(x,dtype=float) cu = np.array(x,dtype=float)
@ -922,18 +918,17 @@ class Rotation:
def from_random(shape = None, def from_random(shape = None,
rng_seed = None): rng_seed = None):
""" """
Draw random rotation. Initialize with random rotation.
Rotations are uniformly distributed. Rotations are uniformly distributed.
Parameters Parameters
---------- ----------
shape : tuple of ints, optional shape : tuple of ints, optional
Shape of the sample. Defaults to None which gives a Shape of the sample. Defaults to None, which gives a single rotation.
single rotation
rng_seed : {None, int, array_like[ints], SeedSequence, BitGenerator, Generator}, optional rng_seed : {None, int, array_like[ints], SeedSequence, BitGenerator, Generator}, optional
A seed to initialize the BitGenerator. Defaults to None. A seed to initialize the BitGenerator.
If None, then fresh, unpredictable entropy will be pulled from the OS. Defaults to None, i.e. unpredictable entropy will be pulled from the OS.
""" """
rng = np.random.default_rng(rng_seed) rng = np.random.default_rng(rng_seed)
@ -958,25 +953,25 @@ class Rotation:
rng_seed = None, rng_seed = None,
**kwargs): **kwargs):
""" """
Sample discrete values from a binned ODF. Sample discrete values from a binned orientation distribution function (ODF).
Parameters Parameters
---------- ----------
weights : numpy.ndarray of shape (n) weights : numpy.ndarray of shape (n)
Texture intensity values (probability density or volume fraction) at Euler grid points. Texture intensity values (probability density or volume fraction) at Euler space grid points.
phi : numpy.ndarray of shape (n,3) phi : numpy.ndarray of shape (n,3)
Grid coordinates in Euler space at which weights are defined. Grid coordinates in Euler space at which weights are defined.
N : integer, optional N : integer, optional
Number of discrete orientations to be sampled from the given ODF. Number of discrete orientations to be sampled from the given ODF.
Defaults to 500. Defaults to 500.
degrees : boolean, optional degrees : boolean, optional
Euler grid values are in degrees. Defaults to True. Euler space grid coordinates are in degrees. Defaults to True.
fractions : boolean, optional fractions : boolean, optional
ODF values correspond to volume fractions, not probability density. ODF values correspond to volume fractions, not probability densities.
Defaults to True. Defaults to True.
rng_seed: {None, int, array_like[ints], SeedSequence, BitGenerator, Generator}, optional rng_seed: {None, int, array_like[ints], SeedSequence, BitGenerator, Generator}, optional
A seed to initialize the BitGenerator. Defaults to None, i.e. unpredictable entropy A seed to initialize the BitGenerator.
will be pulled from the OS. Defaults to None, i.e. unpredictable entropy will be pulled from the OS.
Returns Returns
------- -------
@ -1024,12 +1019,12 @@ class Rotation:
sigma : float sigma : float
Standard deviation of (Gaussian) misorientation distribution. Standard deviation of (Gaussian) misorientation distribution.
N : int, optional N : int, optional
Number of samples, defaults to 500. Number of samples. Defaults to 500.
degrees : boolean, optional degrees : boolean, optional
sigma is given in degrees. Defaults to True. sigma is given in degrees. Defaults to True.
rng_seed : {None, int, array_like[ints], SeedSequence, BitGenerator, Generator}, optional rng_seed : {None, int, array_like[ints], SeedSequence, BitGenerator, Generator}, optional
A seed to initialize the BitGenerator. Defaults to None, i.e. unpredictable entropy A seed to initialize the BitGenerator.
will be pulled from the OS. Defaults to None, i.e. unpredictable entropy will be pulled from the OS.
""" """
rng = np.random.default_rng(rng_seed) rng = np.random.default_rng(rng_seed)
@ -1063,12 +1058,12 @@ class Rotation:
Standard deviation of (Gaussian) misorientation distribution. Standard deviation of (Gaussian) misorientation distribution.
Defaults to 0. Defaults to 0.
N : int, optional N : int, optional
Number of samples, defaults to 500. Number of samples. Defaults to 500.
degrees : boolean, optional degrees : boolean, optional
sigma, alpha, and beta are given in degrees. sigma, alpha, and beta are given in degrees.
rng_seed : {None, int, array_like[ints], SeedSequence, BitGenerator, Generator}, optional rng_seed : {None, int, array_like[ints], SeedSequence, BitGenerator, Generator}, optional
A seed to initialize the BitGenerator. Defaults to None, i.e. unpredictable entropy A seed to initialize the BitGenerator.
will be pulled from the OS. Defaults to None, i.e. unpredictable entropy will be pulled from the OS.
""" """
rng = np.random.default_rng(rng_seed) rng = np.random.default_rng(rng_seed)
@ -1171,9 +1166,9 @@ class Rotation:
@staticmethod @staticmethod
def _qu2ax(qu): def _qu2ax(qu):
""" """
Quaternion to axis angle pair. Quaternion to axisangle pair.
Modified version of the original formulation, should be numerically more stable Modified version of the original formulation, should be numerically more stable.
""" """
with np.errstate(invalid='ignore',divide='ignore'): with np.errstate(invalid='ignore',divide='ignore'):
s = np.sign(qu[...,0:1])/np.sqrt(qu[...,1:2]**2+qu[...,2:3]**2+qu[...,3:4]**2) s = np.sign(qu[...,0:1])/np.sqrt(qu[...,1:2]**2+qu[...,2:3]**2+qu[...,3:4]**2)
@ -1186,7 +1181,7 @@ class Rotation:
@staticmethod @staticmethod
def _qu2ro(qu): def _qu2ro(qu):
"""Quaternion to Rodrigues-Frank vector.""" """Quaternion to RodriguesFrank vector."""
with np.errstate(invalid='ignore',divide='ignore'): with np.errstate(invalid='ignore',divide='ignore'):
s = np.linalg.norm(qu[...,1:4],axis=-1,keepdims=True) s = np.linalg.norm(qu[...,1:4],axis=-1,keepdims=True)
ro = np.where(np.broadcast_to(np.abs(qu[...,0:1]) < 1.0e-12,qu.shape), ro = np.where(np.broadcast_to(np.abs(qu[...,0:1]) < 1.0e-12,qu.shape),
@ -1260,7 +1255,7 @@ class Rotation:
@staticmethod @staticmethod
def _om2eu(om): def _om2eu(om):
"""Rotation matrix to Bunge-Euler angles.""" """Rotation matrix to BungeEuler angles."""
with np.errstate(invalid='ignore',divide='ignore'): with np.errstate(invalid='ignore',divide='ignore'):
zeta = 1.0/np.sqrt(1.0-om[...,2,2:3]**2) zeta = 1.0/np.sqrt(1.0-om[...,2,2:3]**2)
eu = np.where(np.isclose(np.abs(om[...,2,2:3]),1.0,0.0), eu = np.where(np.isclose(np.abs(om[...,2,2:3]),1.0,0.0),
@ -1279,7 +1274,7 @@ class Rotation:
@staticmethod @staticmethod
def _om2ax(om): def _om2ax(om):
"""Rotation matrix to axis angle pair.""" """Rotation matrix to axisangle pair."""
diag_delta = -_P*np.block([om[...,1,2:3]-om[...,2,1:2], diag_delta = -_P*np.block([om[...,1,2:3]-om[...,2,1:2],
om[...,2,0:1]-om[...,0,2:3], om[...,2,0:1]-om[...,0,2:3],
om[...,0,1:2]-om[...,1,0:1] om[...,0,1:2]-om[...,1,0:1]
@ -1300,7 +1295,7 @@ class Rotation:
@staticmethod @staticmethod
def _om2ro(om): def _om2ro(om):
"""Rotation matrix to Rodrigues-Frank vector.""" """Rotation matrix to RodriguesFrank vector."""
return Rotation._eu2ro(Rotation._om2eu(om)) return Rotation._eu2ro(Rotation._om2eu(om))
@staticmethod @staticmethod
@ -1317,7 +1312,7 @@ class Rotation:
#---------- Bunge-Euler angles ---------- #---------- Bunge-Euler angles ----------
@staticmethod @staticmethod
def _eu2qu(eu): def _eu2qu(eu):
"""Bunge-Euler angles to quaternion.""" """BungeEuler angles to quaternion."""
ee = 0.5*eu ee = 0.5*eu
cPhi = np.cos(ee[...,1:2]) cPhi = np.cos(ee[...,1:2])
sPhi = np.sin(ee[...,1:2]) sPhi = np.sin(ee[...,1:2])
@ -1330,7 +1325,7 @@ class Rotation:
@staticmethod @staticmethod
def _eu2om(eu): def _eu2om(eu):
"""Bunge-Euler angles to rotation matrix.""" """BungeEuler angles to rotation matrix."""
c = np.cos(eu) c = np.cos(eu)
s = np.sin(eu) s = np.sin(eu)
om = np.block([+c[...,0:1]*c[...,2:3]-s[...,0:1]*s[...,2:3]*c[...,1:2], om = np.block([+c[...,0:1]*c[...,2:3]-s[...,0:1]*s[...,2:3]*c[...,1:2],
@ -1348,7 +1343,7 @@ class Rotation:
@staticmethod @staticmethod
def _eu2ax(eu): def _eu2ax(eu):
"""Bunge-Euler angles to axis angle pair.""" """BungeEuler angles to axisangle pair."""
t = np.tan(eu[...,1:2]*0.5) t = np.tan(eu[...,1:2]*0.5)
sigma = 0.5*(eu[...,0:1]+eu[...,2:3]) sigma = 0.5*(eu[...,0:1]+eu[...,2:3])
delta = 0.5*(eu[...,0:1]-eu[...,2:3]) delta = 0.5*(eu[...,0:1]-eu[...,2:3])
@ -1367,7 +1362,7 @@ class Rotation:
@staticmethod @staticmethod
def _eu2ro(eu): def _eu2ro(eu):
"""Bunge-Euler angles to Rodrigues-Frank vector.""" """BungeEuler angles to RodriguesFrank vector."""
ax = Rotation._eu2ax(eu) ax = Rotation._eu2ax(eu)
ro = np.block([ax[...,:3],np.tan(ax[...,3:4]*.5)]) ro = np.block([ax[...,:3],np.tan(ax[...,3:4]*.5)])
ro[ax[...,3]>=np.pi,3] = np.inf ro[ax[...,3]>=np.pi,3] = np.inf
@ -1376,19 +1371,19 @@ class Rotation:
@staticmethod @staticmethod
def _eu2ho(eu): def _eu2ho(eu):
"""Bunge-Euler angles to homochoric vector.""" """BungeEuler angles to homochoric vector."""
return Rotation._ax2ho(Rotation._eu2ax(eu)) return Rotation._ax2ho(Rotation._eu2ax(eu))
@staticmethod @staticmethod
def _eu2cu(eu): def _eu2cu(eu):
"""Bunge-Euler angles to cubochoric vector.""" """BungeEuler angles to cubochoric vector."""
return Rotation._ho2cu(Rotation._eu2ho(eu)) return Rotation._ho2cu(Rotation._eu2ho(eu))
#---------- Axis angle pair ---------- #---------- Axis angle pair ----------
@staticmethod @staticmethod
def _ax2qu(ax): def _ax2qu(ax):
"""Axis angle pair to quaternion.""" """Axisangle pair to quaternion."""
c = np.cos(ax[...,3:4]*.5) c = np.cos(ax[...,3:4]*.5)
s = np.sin(ax[...,3:4]*.5) s = np.sin(ax[...,3:4]*.5)
qu = np.where(np.abs(ax[...,3:4])<1.e-6,[1.0, 0.0, 0.0, 0.0],np.block([c, ax[...,:3]*s])) qu = np.where(np.abs(ax[...,3:4])<1.e-6,[1.0, 0.0, 0.0, 0.0],np.block([c, ax[...,:3]*s]))
@ -1396,7 +1391,7 @@ class Rotation:
@staticmethod @staticmethod
def _ax2om(ax): def _ax2om(ax):
"""Axis angle pair to rotation matrix.""" """Axis-angle pair to rotation matrix."""
c = np.cos(ax[...,3:4]) c = np.cos(ax[...,3:4])
s = np.sin(ax[...,3:4]) s = np.sin(ax[...,3:4])
omc = 1. -c omc = 1. -c
@ -1413,12 +1408,12 @@ class Rotation:
@staticmethod @staticmethod
def _ax2eu(ax): def _ax2eu(ax):
"""Rotation matrix to Bunge Euler angles.""" """Rotation matrix to BungeEuler angles."""
return Rotation._om2eu(Rotation._ax2om(ax)) return Rotation._om2eu(Rotation._ax2om(ax))
@staticmethod @staticmethod
def _ax2ro(ax): def _ax2ro(ax):
"""Axis angle pair to Rodrigues-Frank vector.""" """Axisangle pair to RodriguesFrank vector."""
ro = np.block([ax[...,:3], ro = np.block([ax[...,:3],
np.where(np.isclose(ax[...,3:4],np.pi,atol=1.e-15,rtol=.0), np.where(np.isclose(ax[...,3:4],np.pi,atol=1.e-15,rtol=.0),
np.inf, np.inf,
@ -1429,36 +1424,36 @@ class Rotation:
@staticmethod @staticmethod
def _ax2ho(ax): def _ax2ho(ax):
"""Axis angle pair to homochoric vector.""" """Axisangle pair to homochoric vector."""
f = (0.75 * ( ax[...,3:4] - np.sin(ax[...,3:4]) ))**(1.0/3.0) f = (0.75 * ( ax[...,3:4] - np.sin(ax[...,3:4]) ))**(1.0/3.0)
ho = ax[...,:3] * f ho = ax[...,:3] * f
return ho return ho
@staticmethod @staticmethod
def _ax2cu(ax): def _ax2cu(ax):
"""Axis angle pair to cubochoric vector.""" """Axisangle pair to cubochoric vector."""
return Rotation._ho2cu(Rotation._ax2ho(ax)) return Rotation._ho2cu(Rotation._ax2ho(ax))
#---------- Rodrigues-Frank vector ---------- #---------- Rodrigues-Frank vector ----------
@staticmethod @staticmethod
def _ro2qu(ro): def _ro2qu(ro):
"""Rodrigues-Frank vector to quaternion.""" """RodriguesFrank vector to quaternion."""
return Rotation._ax2qu(Rotation._ro2ax(ro)) return Rotation._ax2qu(Rotation._ro2ax(ro))
@staticmethod @staticmethod
def _ro2om(ro): def _ro2om(ro):
"""Rodgrigues-Frank vector to rotation matrix.""" """RodgriguesFrank vector to rotation matrix."""
return Rotation._ax2om(Rotation._ro2ax(ro)) return Rotation._ax2om(Rotation._ro2ax(ro))
@staticmethod @staticmethod
def _ro2eu(ro): def _ro2eu(ro):
"""Rodrigues-Frank vector to Bunge-Euler angles.""" """RodriguesFrank vector to BungeEuler angles."""
return Rotation._om2eu(Rotation._ro2om(ro)) return Rotation._om2eu(Rotation._ro2om(ro))
@staticmethod @staticmethod
def _ro2ax(ro): def _ro2ax(ro):
"""Rodrigues-Frank vector to axis angle pair.""" """RodriguesFrank vector to axisangle pair."""
with np.errstate(invalid='ignore',divide='ignore'): with np.errstate(invalid='ignore',divide='ignore'):
ax = np.where(np.isfinite(ro[...,3:4]), ax = np.where(np.isfinite(ro[...,3:4]),
np.block([ro[...,0:3]*np.linalg.norm(ro[...,0:3],axis=-1,keepdims=True),2.*np.arctan(ro[...,3:4])]), np.block([ro[...,0:3]*np.linalg.norm(ro[...,0:3],axis=-1,keepdims=True),2.*np.arctan(ro[...,3:4])]),
@ -1468,7 +1463,7 @@ class Rotation:
@staticmethod @staticmethod
def _ro2ho(ro): def _ro2ho(ro):
"""Rodrigues-Frank vector to homochoric vector.""" """RodriguesFrank vector to homochoric vector."""
f = np.where(np.isfinite(ro[...,3:4]),2.0*np.arctan(ro[...,3:4]) -np.sin(2.0*np.arctan(ro[...,3:4])),np.pi) f = np.where(np.isfinite(ro[...,3:4]),2.0*np.arctan(ro[...,3:4]) -np.sin(2.0*np.arctan(ro[...,3:4])),np.pi)
ho = np.where(np.broadcast_to(np.sum(ro[...,0:3]**2.0,axis=-1,keepdims=True) < 1.e-8,ro[...,0:3].shape), ho = np.where(np.broadcast_to(np.sum(ro[...,0:3]**2.0,axis=-1,keepdims=True) < 1.e-8,ro[...,0:3].shape),
np.zeros(3), ro[...,0:3]* (0.75*f)**(1.0/3.0)) np.zeros(3), ro[...,0:3]* (0.75*f)**(1.0/3.0))
@ -1476,7 +1471,7 @@ class Rotation:
@staticmethod @staticmethod
def _ro2cu(ro): def _ro2cu(ro):
"""Rodrigues-Frank vector to cubochoric vector.""" """RodriguesFrank vector to cubochoric vector."""
return Rotation._ho2cu(Rotation._ro2ho(ro)) return Rotation._ho2cu(Rotation._ro2ho(ro))
@ -1493,12 +1488,12 @@ class Rotation:
@staticmethod @staticmethod
def _ho2eu(ho): def _ho2eu(ho):
"""Homochoric vector to Bunge-Euler angles.""" """Homochoric vector to BungeEuler angles."""
return Rotation._ax2eu(Rotation._ho2ax(ho)) return Rotation._ax2eu(Rotation._ho2ax(ho))
@staticmethod @staticmethod
def _ho2ax(ho): def _ho2ax(ho):
"""Homochoric vector to axis angle pair.""" """Homochoric vector to axisangle pair."""
tfit = np.array([+1.0000000000018852, -0.5000000002194847, tfit = np.array([+1.0000000000018852, -0.5000000002194847,
-0.024999992127593126, -0.003928701544781374, -0.024999992127593126, -0.003928701544781374,
-0.0008152701535450438, -0.0002009500426119712, -0.0008152701535450438, -0.0002009500426119712,
@ -1521,7 +1516,7 @@ class Rotation:
@staticmethod @staticmethod
def _ho2ro(ho): def _ho2ro(ho):
"""Axis angle pair to Rodrigues-Frank vector.""" """Axisangle pair to RodriguesFrank vector."""
return Rotation._ax2ro(Rotation._ho2ax(ho)) return Rotation._ax2ro(Rotation._ho2ax(ho))
@staticmethod @staticmethod
@ -1576,17 +1571,17 @@ class Rotation:
@staticmethod @staticmethod
def _cu2eu(cu): def _cu2eu(cu):
"""Cubochoric vector to Bunge-Euler angles.""" """Cubochoric vector to BungeEuler angles."""
return Rotation._ho2eu(Rotation._cu2ho(cu)) return Rotation._ho2eu(Rotation._cu2ho(cu))
@staticmethod @staticmethod
def _cu2ax(cu): def _cu2ax(cu):
"""Cubochoric vector to axis angle pair.""" """Cubochoric vector to axisangle pair."""
return Rotation._ho2ax(Rotation._cu2ho(cu)) return Rotation._ho2ax(Rotation._cu2ho(cu))
@staticmethod @staticmethod
def _cu2ro(cu): def _cu2ro(cu):
"""Cubochoric vector to Rodrigues-Frank vector.""" """Cubochoric vector to RodriguesFrank vector."""
return Rotation._ho2ro(Rotation._cu2ho(cu)) return Rotation._ho2ro(Rotation._cu2ho(cu))
@staticmethod @staticmethod
@ -1642,7 +1637,7 @@ class Rotation:
Parameters Parameters
---------- ----------
xyz : numpy.ndarray xyz : numpy.ndarray
coordinates of a point on a uniform refinable grid on a ball or Coordinates of a point on a uniform refinable grid on a ball or
in a uniform refinable cubical grid. in a uniform refinable cubical grid.
References References