Merge branch 'lattice-into-orientation' into 'development'
keep Orientation object clean See merge request damask/DAMASK!377
This commit is contained in:
commit
4ba4ca1337
2
PRIVATE
2
PRIVATE
|
@ -1 +1 @@
|
||||||
Subproject commit 95f7faea920dd6956884e4a55f72e5d5b1ffcdc8
|
Subproject commit 5e104e75bbfb9d0d1969658aaf10999590956e3e
|
|
@ -14,7 +14,6 @@ from . import tensor # noqa
|
||||||
from . import mechanics # noqa
|
from . import mechanics # noqa
|
||||||
from . import solver # noqa
|
from . import solver # noqa
|
||||||
from . import grid_filters # noqa
|
from . import grid_filters # noqa
|
||||||
from . import lattice # noqa
|
|
||||||
#Modules that contain only one class (of the same name), are prefixed by a '_'.
|
#Modules that contain only one class (of the same name), are prefixed by a '_'.
|
||||||
#For example, '_colormap' containsa class called 'Colormap' which is imported as 'damask.Colormap'.
|
#For example, '_colormap' containsa class called 'Colormap' which is imported as 'damask.Colormap'.
|
||||||
from ._rotation import Rotation # noqa
|
from ._rotation import Rotation # noqa
|
||||||
|
|
|
@ -110,13 +110,13 @@ class Colormap(mpl.colors.ListedColormap):
|
||||||
low_,high_ = map(Colormap._rgb2msh,low_high)
|
low_,high_ = map(Colormap._rgb2msh,low_high)
|
||||||
|
|
||||||
elif model.lower() == 'hsv':
|
elif model.lower() == 'hsv':
|
||||||
if np.any(low_high<0) or np.any(low_high[:,1:3]>1) or np.any(low_high[:,0]>360):
|
if np.any(low_high<0) or np.any(low_high>[360,1,1]):
|
||||||
raise ValueError(f'HSV color {low} | {high} are out of range.')
|
raise ValueError(f'HSV color {low} | {high} are out of range.')
|
||||||
|
|
||||||
low_,high_ = map(Colormap._hsv2msh,low_high)
|
low_,high_ = map(Colormap._hsv2msh,low_high)
|
||||||
|
|
||||||
elif model.lower() == 'hsl':
|
elif model.lower() == 'hsl':
|
||||||
if np.any(low_high<0) or np.any(low_high[:,1:3]>1) or np.any(low_high[:,0]>360):
|
if np.any(low_high<0) or np.any(low_high>[360,1,1]):
|
||||||
raise ValueError(f'HSL color {low} | {high} are out of range.')
|
raise ValueError(f'HSL color {low} | {high} are out of range.')
|
||||||
|
|
||||||
low_,high_ = map(Colormap._hsl2msh,low_high)
|
low_,high_ = map(Colormap._hsl2msh,low_high)
|
||||||
|
|
|
@ -5,6 +5,35 @@ import numpy as np
|
||||||
from . import Rotation
|
from . import Rotation
|
||||||
from . import util
|
from . import util
|
||||||
from . import tensor
|
from . import tensor
|
||||||
|
from . import _lattice
|
||||||
|
|
||||||
|
_crystal_families = ['triclinic',
|
||||||
|
'monoclinic',
|
||||||
|
'orthorhombic',
|
||||||
|
'tetragonal',
|
||||||
|
'hexagonal',
|
||||||
|
'cubic']
|
||||||
|
|
||||||
|
_lattice_symmetries = {
|
||||||
|
'aP': 'triclinic',
|
||||||
|
|
||||||
|
'mP': 'monoclinic',
|
||||||
|
'mS': 'monoclinic',
|
||||||
|
|
||||||
|
'oP': 'orthorhombic',
|
||||||
|
'oS': 'orthorhombic',
|
||||||
|
'oI': 'orthorhombic',
|
||||||
|
'oF': 'orthorhombic',
|
||||||
|
|
||||||
|
'tP': 'tetragonal',
|
||||||
|
'tI': 'tetragonal',
|
||||||
|
|
||||||
|
'hP': 'hexagonal',
|
||||||
|
|
||||||
|
'cP': 'cubic',
|
||||||
|
'cI': 'cubic',
|
||||||
|
'cF': 'cubic',
|
||||||
|
}
|
||||||
|
|
||||||
_parameter_doc = \
|
_parameter_doc = \
|
||||||
"""lattice : str
|
"""lattice : str
|
||||||
|
@ -33,7 +62,7 @@ class Orientation(Rotation):
|
||||||
"""
|
"""
|
||||||
Representation of crystallographic orientation as combination of rotation and either crystal family or Bravais lattice.
|
Representation of crystallographic orientation as combination of rotation and either crystal family or Bravais lattice.
|
||||||
|
|
||||||
The crystal family is one of Orientation.crystal_families:
|
The crystal family is one of:
|
||||||
|
|
||||||
- triclinic
|
- triclinic
|
||||||
- monoclinic
|
- monoclinic
|
||||||
|
@ -45,7 +74,7 @@ class Orientation(Rotation):
|
||||||
and enables symmetry-related operations such as
|
and enables symmetry-related operations such as
|
||||||
"equivalent", "reduced", "disorientation", "IPF_color", or "to_SST".
|
"equivalent", "reduced", "disorientation", "IPF_color", or "to_SST".
|
||||||
|
|
||||||
The Bravais lattice is one of Orientation.lattice_symmetries:
|
The Bravais lattice is given in the Pearson notation:
|
||||||
|
|
||||||
- triclinic
|
- triclinic
|
||||||
- aP : primitive
|
- aP : primitive
|
||||||
|
@ -85,35 +114,6 @@ class Orientation(Rotation):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
crystal_families = ['triclinic',
|
|
||||||
'monoclinic',
|
|
||||||
'orthorhombic',
|
|
||||||
'tetragonal',
|
|
||||||
'hexagonal',
|
|
||||||
'cubic']
|
|
||||||
|
|
||||||
lattice_symmetries = {
|
|
||||||
'aP': 'triclinic',
|
|
||||||
|
|
||||||
'mP': 'monoclinic',
|
|
||||||
'mS': 'monoclinic',
|
|
||||||
|
|
||||||
'oP': 'orthorhombic',
|
|
||||||
'oS': 'orthorhombic',
|
|
||||||
'oI': 'orthorhombic',
|
|
||||||
'oF': 'orthorhombic',
|
|
||||||
|
|
||||||
'tP': 'tetragonal',
|
|
||||||
'tI': 'tetragonal',
|
|
||||||
|
|
||||||
'hP': 'hexagonal',
|
|
||||||
|
|
||||||
'cP': 'cubic',
|
|
||||||
'cI': 'cubic',
|
|
||||||
'cF': 'cubic',
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@util.extend_docstring(_parameter_doc)
|
@util.extend_docstring(_parameter_doc)
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
rotation = None,
|
rotation = None,
|
||||||
|
@ -132,34 +132,17 @@ class Orientation(Rotation):
|
||||||
Defaults to no rotation.
|
Defaults to no rotation.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
from damask.lattice import kinematics
|
|
||||||
|
|
||||||
Rotation.__init__(self) if rotation is None else Rotation.__init__(self,rotation=rotation)
|
Rotation.__init__(self) if rotation is None else Rotation.__init__(self,rotation=rotation)
|
||||||
|
|
||||||
if ( lattice not in self.lattice_symmetries
|
|
||||||
and lattice not in self.crystal_families):
|
|
||||||
raise KeyError(f'Lattice "{lattice}" is unknown')
|
|
||||||
|
|
||||||
self.family = None
|
|
||||||
self.lattice = None
|
|
||||||
self.a = None
|
|
||||||
self.b = None
|
|
||||||
self.c = None
|
|
||||||
self.alpha = None
|
|
||||||
self.beta = None
|
|
||||||
self.gamma = None
|
|
||||||
self.kinematics = None
|
self.kinematics = None
|
||||||
|
|
||||||
if lattice in self.lattice_symmetries:
|
if lattice in _lattice_symmetries:
|
||||||
self.family = self.lattice_symmetries[lattice]
|
self.family = _lattice_symmetries[lattice]
|
||||||
self.lattice = lattice
|
self.lattice = lattice
|
||||||
|
|
||||||
self.a = 1 if a is None else a
|
self.a = 1 if a is None else a
|
||||||
self.b = b
|
self.b = b
|
||||||
self.c = c
|
self.c = c
|
||||||
self.alpha = (np.radians(alpha) if degrees else alpha) if alpha is not None else None
|
|
||||||
self.beta = (np.radians(beta) if degrees else beta) if beta is not None else None
|
|
||||||
self.gamma = (np.radians(gamma) if degrees else gamma) if gamma is not None else None
|
|
||||||
|
|
||||||
self.a = float(self.a) if self.a is not None else \
|
self.a = float(self.a) if self.a is not None else \
|
||||||
(self.b / self.ratio['b'] if self.b is not None and self.ratio['b'] is not None else
|
(self.b / self.ratio['b'] if self.b is not None and self.ratio['b'] is not None else
|
||||||
self.c / self.ratio['c'] if self.c is not None and self.ratio['c'] is not None else None)
|
self.c / self.ratio['c'] if self.c is not None and self.ratio['c'] is not None else None)
|
||||||
|
@ -171,9 +154,13 @@ class Orientation(Rotation):
|
||||||
(self.a * self.ratio['c'] if self.a is not None and self.ratio['c'] is not None else
|
(self.a * self.ratio['c'] if self.a is not None and self.ratio['c'] is not None else
|
||||||
self.b / self.ratio['b'] * self.ratio['c']
|
self.b / self.ratio['b'] * self.ratio['c']
|
||||||
if self.c is not None and self.ratio['b'] is not None and self.ratio['c'] is not None else None)
|
if self.c is not None and self.ratio['b'] is not None and self.ratio['c'] is not None else None)
|
||||||
self.alpha = self.alpha if self.alpha is not None else self.immutable['alpha'] if 'alpha' in self.immutable else None
|
|
||||||
self.beta = self.beta if self.beta is not None else self.immutable['beta'] if 'beta' in self.immutable else None
|
self.alpha = np.radians(alpha) if degrees and alpha is not None else alpha
|
||||||
self.gamma = self.gamma if self.gamma is not None else self.immutable['gamma'] if 'gamma' in self.immutable else None
|
self.beta = np.radians(beta) if degrees and beta is not None else beta
|
||||||
|
self.gamma = np.radians(gamma) if degrees and gamma is not None else gamma
|
||||||
|
if self.alpha is None and 'alpha' in self.immutable: self.alpha = self.immutable['alpha']
|
||||||
|
if self.beta is None and 'beta' in self.immutable: self.beta = self.immutable['beta']
|
||||||
|
if self.gamma is None and 'gamma' in self.immutable: self.gamma = self.immutable['gamma']
|
||||||
|
|
||||||
if \
|
if \
|
||||||
(self.a is None) \
|
(self.a is None) \
|
||||||
|
@ -190,16 +177,22 @@ class Orientation(Rotation):
|
||||||
> np.sum(np.roll([self.alpha,self.beta,self.gamma],r)[1:]) for r in range(3)]):
|
> np.sum(np.roll([self.alpha,self.beta,self.gamma],r)[1:]) for r in range(3)]):
|
||||||
raise ValueError ('Each lattice angle must be less than sum of others')
|
raise ValueError ('Each lattice angle must be less than sum of others')
|
||||||
|
|
||||||
if self.lattice in kinematics:
|
if self.lattice in _lattice.kinematics:
|
||||||
master = kinematics[self.lattice]
|
master = _lattice.kinematics[self.lattice]
|
||||||
self.kinematics = {}
|
self.kinematics = {}
|
||||||
for m in master:
|
for m in master:
|
||||||
self.kinematics[m] = {'direction':master[m][:,0:3],'plane':master[m][:,3:6]} \
|
self.kinematics[m] = {'direction':master[m][:,0:3],'plane':master[m][:,3:6]} \
|
||||||
if master[m].shape[-1] == 6 else \
|
if master[m].shape[-1] == 6 else \
|
||||||
{'direction':self.Bravais_to_Miller(uvtw=master[m][:,0:4]),
|
{'direction':self.Bravais_to_Miller(uvtw=master[m][:,0:4]),
|
||||||
'plane': self.Bravais_to_Miller(hkil=master[m][:,4:8])}
|
'plane': self.Bravais_to_Miller(hkil=master[m][:,4:8])}
|
||||||
elif lattice in self.crystal_families:
|
elif lattice in _crystal_families:
|
||||||
self.family = lattice
|
self.family = lattice
|
||||||
|
self.lattice = None
|
||||||
|
|
||||||
|
self.a = self.b = self.c = None
|
||||||
|
self.alpha = self.beta = self.gamma = None
|
||||||
|
else:
|
||||||
|
raise KeyError(f'Lattice "{lattice}" is unknown')
|
||||||
|
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
|
@ -676,11 +669,9 @@ class Orientation(Rotation):
|
||||||
https://doi.org/10.1016/j.actamat.2004.11.021
|
https://doi.org/10.1016/j.actamat.2004.11.021
|
||||||
|
|
||||||
"""
|
"""
|
||||||
from damask.lattice import relations
|
if model not in _lattice.relations:
|
||||||
|
|
||||||
if model not in relations:
|
|
||||||
raise KeyError(f'Orientation relationship "{model}" is unknown')
|
raise KeyError(f'Orientation relationship "{model}" is unknown')
|
||||||
r = relations[model]
|
r = _lattice.relations[model]
|
||||||
|
|
||||||
if self.lattice not in r:
|
if self.lattice not in r:
|
||||||
raise KeyError(f'Relationship "{model}" not supported for lattice "{self.lattice}"')
|
raise KeyError(f'Relationship "{model}" not supported for lattice "{self.lattice}"')
|
||||||
|
|
|
@ -150,9 +150,8 @@ class VTK:
|
||||||
----------
|
----------
|
||||||
fname : str or pathlib.Path
|
fname : str or pathlib.Path
|
||||||
Filename for reading. Valid extensions are .vtr, .vtu, .vtp, and .vtk.
|
Filename for reading. Valid extensions are .vtr, .vtu, .vtp, and .vtk.
|
||||||
dataset_type : str, optional
|
dataset_type : {'vtkRectilinearGrid', 'vtkUnstructuredGrid', 'vtkPolyData'}, optional
|
||||||
Name of the vtk.vtkDataSet subclass when opening a .vtk file.
|
Name of the vtk.vtkDataSet subclass when opening a .vtk file.
|
||||||
Valid types are vtkRectilinearGrid, vtkUnstructuredGrid, and vtkPolyData.
|
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
|
|
|
@ -124,9 +124,6 @@ def strain(F,t,m):
|
||||||
"""
|
"""
|
||||||
Calculate strain tensor (Seth–Hill family).
|
Calculate strain tensor (Seth–Hill family).
|
||||||
|
|
||||||
For details refer to https://en.wikipedia.org/wiki/Finite_strain_theory and
|
|
||||||
https://de.wikipedia.org/wiki/Verzerrungstensor
|
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
F : numpy.ndarray of shape (...,3,3)
|
F : numpy.ndarray of shape (...,3,3)
|
||||||
|
@ -142,6 +139,11 @@ def strain(F,t,m):
|
||||||
epsilon : numpy.ndarray of shape (...,3,3)
|
epsilon : numpy.ndarray of shape (...,3,3)
|
||||||
Strain of F.
|
Strain of F.
|
||||||
|
|
||||||
|
References
|
||||||
|
----------
|
||||||
|
https://en.wikipedia.org/wiki/Finite_strain_theory
|
||||||
|
https://de.wikipedia.org/wiki/Verzerrungstensor
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if t == 'V':
|
if t == 'V':
|
||||||
w,n = _np.linalg.eigh(deformation_Cauchy_Green_left(F))
|
w,n = _np.linalg.eigh(deformation_Cauchy_Green_left(F))
|
||||||
|
@ -150,7 +152,6 @@ def strain(F,t,m):
|
||||||
|
|
||||||
if m > 0.0:
|
if m > 0.0:
|
||||||
eps = 1.0/(2.0*abs(m)) * (+ _np.einsum('...j,...kj,...lj',w**m,n,n) - _np.eye(3))
|
eps = 1.0/(2.0*abs(m)) * (+ _np.einsum('...j,...kj,...lj',w**m,n,n) - _np.eye(3))
|
||||||
|
|
||||||
elif m < 0.0:
|
elif m < 0.0:
|
||||||
eps = 1.0/(2.0*abs(m)) * (- _np.einsum('...j,...kj,...lj',w**m,n,n) + _np.eye(3))
|
eps = 1.0/(2.0*abs(m)) * (- _np.einsum('...j,...kj,...lj',w**m,n,n) + _np.eye(3))
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
"""Miscellaneous helper functionality."""
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
import datetime
|
import datetime
|
||||||
import os
|
import os
|
||||||
|
@ -177,26 +179,36 @@ def execute(cmd,wd='./',env=None):
|
||||||
|
|
||||||
|
|
||||||
def natural_sort(key):
|
def natural_sort(key):
|
||||||
|
"""
|
||||||
|
Natural sort.
|
||||||
|
|
||||||
|
For use in python's 'sorted'.
|
||||||
|
|
||||||
|
References
|
||||||
|
----------
|
||||||
|
https://en.wikipedia.org/wiki/Natural_sort_order
|
||||||
|
|
||||||
|
"""
|
||||||
convert = lambda text: int(text) if text.isdigit() else text
|
convert = lambda text: int(text) if text.isdigit() else text
|
||||||
return [ convert(c) for c in re.split('([0-9]+)', key) ]
|
return [ convert(c) for c in re.split('([0-9]+)', key) ]
|
||||||
|
|
||||||
|
|
||||||
def show_progress(iterable,N_iter=None,prefix='',bar_length=50):
|
def show_progress(iterable,N_iter=None,prefix='',bar_length=50):
|
||||||
"""
|
"""
|
||||||
Decorate a loop with a status bar.
|
Decorate a loop with a progress bar.
|
||||||
|
|
||||||
Use similar like enumerate.
|
Use similar like enumerate.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
iterable : iterable/function with yield statement
|
iterable : iterable or function with yield statement
|
||||||
Iterable (or function with yield statement) to be decorated.
|
Iterable (or function with yield statement) to be decorated.
|
||||||
N_iter : int
|
N_iter : int, optional
|
||||||
Total # of iterations. Needed if number of iterations can not be obtained as len(iterable).
|
Total number of iterations. Required unless obtainable as len(iterable).
|
||||||
prefix : str, optional.
|
prefix : str, optional
|
||||||
Prefix string.
|
Prefix string.
|
||||||
bar_length : int, optional
|
bar_length : int, optional
|
||||||
Character length of bar. Defaults to 50.
|
Length of progress bar in characters. Defaults to 50.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if N_iter in [0,1] or (hasattr(iterable,'__len__') and len(iterable) <= 1):
|
if N_iter in [0,1] or (hasattr(iterable,'__len__') and len(iterable) <= 1):
|
||||||
|
@ -509,6 +521,7 @@ def dict_prune(d):
|
||||||
v = dict_prune(v)
|
v = dict_prune(v)
|
||||||
if not isinstance(v,dict) or v != {}:
|
if not isinstance(v,dict) or v != {}:
|
||||||
new[k] = v
|
new[k] = v
|
||||||
|
|
||||||
return new
|
return new
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ setuptools.setup(
|
||||||
author='The DAMASK team',
|
author='The DAMASK team',
|
||||||
author_email='damask@mpie.de',
|
author_email='damask@mpie.de',
|
||||||
description='DAMASK library',
|
description='DAMASK library',
|
||||||
long_description='Python library for pre and post processing of DAMASK simulations',
|
long_description='Python library for managing DAMASK simulations',
|
||||||
url='https://damask.mpie.de',
|
url='https://damask.mpie.de',
|
||||||
packages=setuptools.find_packages(),
|
packages=setuptools.find_packages(),
|
||||||
include_package_data=True,
|
include_package_data=True,
|
||||||
|
|
|
@ -5,9 +5,10 @@ from itertools import permutations
|
||||||
from damask import Rotation
|
from damask import Rotation
|
||||||
from damask import Orientation
|
from damask import Orientation
|
||||||
from damask import Table
|
from damask import Table
|
||||||
from damask import lattice
|
|
||||||
from damask import util
|
from damask import util
|
||||||
from damask import grid_filters
|
from damask import grid_filters
|
||||||
|
from damask import _lattice as lattice
|
||||||
|
from damask._orientation import _crystal_families as crystal_families
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
@ -22,7 +23,7 @@ def set_of_rodrigues(set_of_quaternions):
|
||||||
|
|
||||||
class TestOrientation:
|
class TestOrientation:
|
||||||
|
|
||||||
@pytest.mark.parametrize('lattice',Orientation.crystal_families)
|
@pytest.mark.parametrize('lattice',crystal_families)
|
||||||
@pytest.mark.parametrize('shape',[None,5,(4,6)])
|
@pytest.mark.parametrize('shape',[None,5,(4,6)])
|
||||||
def test_equal(self,lattice,shape):
|
def test_equal(self,lattice,shape):
|
||||||
R = Rotation.from_random(shape)
|
R = Rotation.from_random(shape)
|
||||||
|
@ -30,14 +31,14 @@ class TestOrientation:
|
||||||
(Orientation(R,lattice) == Orientation(R,lattice)).all()
|
(Orientation(R,lattice) == Orientation(R,lattice)).all()
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize('lattice',Orientation.crystal_families)
|
@pytest.mark.parametrize('lattice',crystal_families)
|
||||||
@pytest.mark.parametrize('shape',[None,5,(4,6)])
|
@pytest.mark.parametrize('shape',[None,5,(4,6)])
|
||||||
def test_unequal(self,lattice,shape):
|
def test_unequal(self,lattice,shape):
|
||||||
R = Rotation.from_random(shape)
|
R = Rotation.from_random(shape)
|
||||||
assert not ( Orientation(R,lattice) != Orientation(R,lattice) if shape is None else \
|
assert not ( Orientation(R,lattice) != Orientation(R,lattice) if shape is None else \
|
||||||
(Orientation(R,lattice) != Orientation(R,lattice)).any())
|
(Orientation(R,lattice) != Orientation(R,lattice)).any())
|
||||||
|
|
||||||
@pytest.mark.parametrize('lattice',Orientation.crystal_families)
|
@pytest.mark.parametrize('lattice',crystal_families)
|
||||||
@pytest.mark.parametrize('shape',[None,5,(4,6)])
|
@pytest.mark.parametrize('shape',[None,5,(4,6)])
|
||||||
def test_close(self,lattice,shape):
|
def test_close(self,lattice,shape):
|
||||||
R = Orientation.from_random(lattice=lattice,shape=shape)
|
R = Orientation.from_random(lattice=lattice,shape=shape)
|
||||||
|
@ -182,14 +183,14 @@ class TestOrientation:
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
Orientation(lattice='aP',a=1,b=2,c=3,alpha=45,beta=45,gamma=90.0001,degrees=True) # noqa
|
Orientation(lattice='aP',a=1,b=2,c=3,alpha=45,beta=45,gamma=90.0001,degrees=True) # noqa
|
||||||
|
|
||||||
@pytest.mark.parametrize('lattice',Orientation.crystal_families)
|
@pytest.mark.parametrize('lattice',crystal_families)
|
||||||
@pytest.mark.parametrize('angle',[10,20,30,40])
|
@pytest.mark.parametrize('angle',[10,20,30,40])
|
||||||
def test_average(self,angle,lattice):
|
def test_average(self,angle,lattice):
|
||||||
o = Orientation.from_axis_angle(lattice=lattice,axis_angle=[[0,0,1,10],[0,0,1,angle]],degrees=True)
|
o = Orientation.from_axis_angle(lattice=lattice,axis_angle=[[0,0,1,10],[0,0,1,angle]],degrees=True)
|
||||||
avg_angle = o.average().as_axis_angle(degrees=True,pair=True)[1]
|
avg_angle = o.average().as_axis_angle(degrees=True,pair=True)[1]
|
||||||
assert np.isclose(avg_angle,10+(angle-10)/2.)
|
assert np.isclose(avg_angle,10+(angle-10)/2.)
|
||||||
|
|
||||||
@pytest.mark.parametrize('lattice',Orientation.crystal_families)
|
@pytest.mark.parametrize('lattice',crystal_families)
|
||||||
def test_reduced_equivalent(self,lattice):
|
def test_reduced_equivalent(self,lattice):
|
||||||
i = Orientation(lattice=lattice)
|
i = Orientation(lattice=lattice)
|
||||||
o = Orientation.from_random(lattice=lattice)
|
o = Orientation.from_random(lattice=lattice)
|
||||||
|
@ -197,7 +198,7 @@ class TestOrientation:
|
||||||
FZ = np.argmin(abs(eq.misorientation(i.broadcast_to(len(eq))).as_axis_angle(pair=True)[1]))
|
FZ = np.argmin(abs(eq.misorientation(i.broadcast_to(len(eq))).as_axis_angle(pair=True)[1]))
|
||||||
assert o.reduced == eq[FZ]
|
assert o.reduced == eq[FZ]
|
||||||
|
|
||||||
@pytest.mark.parametrize('lattice',Orientation.crystal_families)
|
@pytest.mark.parametrize('lattice',crystal_families)
|
||||||
@pytest.mark.parametrize('N',[1,8,32])
|
@pytest.mark.parametrize('N',[1,8,32])
|
||||||
def test_disorientation(self,lattice,N):
|
def test_disorientation(self,lattice,N):
|
||||||
o = Orientation.from_random(lattice=lattice,shape=N)
|
o = Orientation.from_random(lattice=lattice,shape=N)
|
||||||
|
@ -215,7 +216,7 @@ class TestOrientation:
|
||||||
.misorientation(p[n].equivalent[ops[n][1]])
|
.misorientation(p[n].equivalent[ops[n][1]])
|
||||||
.as_quaternion())
|
.as_quaternion())
|
||||||
|
|
||||||
@pytest.mark.parametrize('lattice',Orientation.crystal_families)
|
@pytest.mark.parametrize('lattice',crystal_families)
|
||||||
@pytest.mark.parametrize('a,b',[
|
@pytest.mark.parametrize('a,b',[
|
||||||
((2,3,2),(2,3,2)),
|
((2,3,2),(2,3,2)),
|
||||||
((2,2),(4,4)),
|
((2,2),(4,4)),
|
||||||
|
@ -230,20 +231,20 @@ class TestOrientation:
|
||||||
assert o[tuple(loc[:len(o.shape)])].disorientation(p[tuple(loc[-len(p.shape):])]) \
|
assert o[tuple(loc[:len(o.shape)])].disorientation(p[tuple(loc[-len(p.shape):])]) \
|
||||||
.isclose(o.disorientation(p)[tuple(loc)])
|
.isclose(o.disorientation(p)[tuple(loc)])
|
||||||
|
|
||||||
@pytest.mark.parametrize('lattice',Orientation.crystal_families)
|
@pytest.mark.parametrize('lattice',crystal_families)
|
||||||
def test_disorientation360(self,lattice):
|
def test_disorientation360(self,lattice):
|
||||||
o_1 = Orientation(Rotation(),lattice)
|
o_1 = Orientation(Rotation(),lattice)
|
||||||
o_2 = Orientation.from_Euler_angles(lattice=lattice,phi=[360,0,0],degrees=True)
|
o_2 = Orientation.from_Euler_angles(lattice=lattice,phi=[360,0,0],degrees=True)
|
||||||
assert np.allclose((o_1.disorientation(o_2)).as_matrix(),np.eye(3))
|
assert np.allclose((o_1.disorientation(o_2)).as_matrix(),np.eye(3))
|
||||||
|
|
||||||
@pytest.mark.parametrize('lattice',Orientation.crystal_families)
|
@pytest.mark.parametrize('lattice',crystal_families)
|
||||||
@pytest.mark.parametrize('shape',[(1),(2,3),(4,3,2)])
|
@pytest.mark.parametrize('shape',[(1),(2,3),(4,3,2)])
|
||||||
def test_reduced_vectorization(self,lattice,shape):
|
def test_reduced_vectorization(self,lattice,shape):
|
||||||
o = Orientation.from_random(lattice=lattice,shape=shape)
|
o = Orientation.from_random(lattice=lattice,shape=shape)
|
||||||
for r, theO in zip(o.reduced.flatten(),o.flatten()):
|
for r, theO in zip(o.reduced.flatten(),o.flatten()):
|
||||||
assert r == theO.reduced
|
assert r == theO.reduced
|
||||||
|
|
||||||
@pytest.mark.parametrize('lattice',Orientation.crystal_families)
|
@pytest.mark.parametrize('lattice',crystal_families)
|
||||||
def test_reduced_corner_cases(self,lattice):
|
def test_reduced_corner_cases(self,lattice):
|
||||||
# test whether there is always a sym-eq rotation that falls into the FZ
|
# test whether there is always a sym-eq rotation that falls into the FZ
|
||||||
N = np.random.randint(10,40)
|
N = np.random.randint(10,40)
|
||||||
|
@ -253,7 +254,7 @@ class TestOrientation:
|
||||||
assert evenly_distributed.shape == evenly_distributed.reduced.shape
|
assert evenly_distributed.shape == evenly_distributed.reduced.shape
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize('lattice',Orientation.crystal_families)
|
@pytest.mark.parametrize('lattice',crystal_families)
|
||||||
@pytest.mark.parametrize('shape',[(1),(2,3),(4,3,2)])
|
@pytest.mark.parametrize('shape',[(1),(2,3),(4,3,2)])
|
||||||
@pytest.mark.parametrize('vector',np.array([[1,0,0],[1,2,3],[-1,1,-1]]))
|
@pytest.mark.parametrize('vector',np.array([[1,0,0],[1,2,3],[-1,1,-1]]))
|
||||||
@pytest.mark.parametrize('proper',[True,False])
|
@pytest.mark.parametrize('proper',[True,False])
|
||||||
|
@ -262,7 +263,7 @@ class TestOrientation:
|
||||||
for r, theO in zip(o.to_SST(vector=vector,proper=proper).reshape((-1,3)),o.flatten()):
|
for r, theO in zip(o.to_SST(vector=vector,proper=proper).reshape((-1,3)),o.flatten()):
|
||||||
assert np.allclose(r,theO.to_SST(vector=vector,proper=proper))
|
assert np.allclose(r,theO.to_SST(vector=vector,proper=proper))
|
||||||
|
|
||||||
@pytest.mark.parametrize('lattice',Orientation.crystal_families)
|
@pytest.mark.parametrize('lattice',crystal_families)
|
||||||
@pytest.mark.parametrize('shape',[(1),(2,3),(4,3,2)])
|
@pytest.mark.parametrize('shape',[(1),(2,3),(4,3,2)])
|
||||||
@pytest.mark.parametrize('vector',np.array([[1,0,0],[1,2,3],[-1,1,-1]]))
|
@pytest.mark.parametrize('vector',np.array([[1,0,0],[1,2,3],[-1,1,-1]]))
|
||||||
@pytest.mark.parametrize('proper',[True,False])
|
@pytest.mark.parametrize('proper',[True,False])
|
||||||
|
@ -272,7 +273,7 @@ class TestOrientation:
|
||||||
for r, theO in zip(o.IPF_color(vector,in_SST=in_SST,proper=proper).reshape((-1,3)),o.flatten()):
|
for r, theO in zip(o.IPF_color(vector,in_SST=in_SST,proper=proper).reshape((-1,3)),o.flatten()):
|
||||||
assert np.allclose(r,theO.IPF_color(vector,in_SST=in_SST,proper=proper))
|
assert np.allclose(r,theO.IPF_color(vector,in_SST=in_SST,proper=proper))
|
||||||
|
|
||||||
@pytest.mark.parametrize('lattice',Orientation.crystal_families)
|
@pytest.mark.parametrize('lattice',crystal_families)
|
||||||
@pytest.mark.parametrize('a,b',[
|
@pytest.mark.parametrize('a,b',[
|
||||||
((2,3,2),(2,3,2)),
|
((2,3,2),(2,3,2)),
|
||||||
((2,2),(4,4)),
|
((2,2),(4,4)),
|
||||||
|
@ -300,7 +301,7 @@ class TestOrientation:
|
||||||
assert np.allclose(np.array(color['RGB']),
|
assert np.allclose(np.array(color['RGB']),
|
||||||
cube.IPF_color(vector=np.array(direction),proper=proper))
|
cube.IPF_color(vector=np.array(direction),proper=proper))
|
||||||
|
|
||||||
@pytest.mark.parametrize('lattice',Orientation.crystal_families)
|
@pytest.mark.parametrize('lattice',crystal_families)
|
||||||
@pytest.mark.parametrize('proper',[True,False])
|
@pytest.mark.parametrize('proper',[True,False])
|
||||||
def test_IPF_equivalent(self,set_of_quaternions,lattice,proper):
|
def test_IPF_equivalent(self,set_of_quaternions,lattice,proper):
|
||||||
direction = np.random.random(3)*2.0-1.0
|
direction = np.random.random(3)*2.0-1.0
|
||||||
|
@ -308,13 +309,13 @@ class TestOrientation:
|
||||||
color = o.IPF_color(vector=direction,proper=proper)
|
color = o.IPF_color(vector=direction,proper=proper)
|
||||||
assert np.allclose(np.broadcast_to(color[0,...],color.shape),color)
|
assert np.allclose(np.broadcast_to(color[0,...],color.shape),color)
|
||||||
|
|
||||||
@pytest.mark.parametrize('lattice',Orientation.crystal_families)
|
@pytest.mark.parametrize('lattice',crystal_families)
|
||||||
def test_in_FZ_vectorization(self,set_of_rodrigues,lattice):
|
def test_in_FZ_vectorization(self,set_of_rodrigues,lattice):
|
||||||
result = Orientation.from_Rodrigues_vector(rho=set_of_rodrigues.reshape((-1,4,4)),lattice=lattice).in_FZ.reshape(-1)
|
result = Orientation.from_Rodrigues_vector(rho=set_of_rodrigues.reshape((-1,4,4)),lattice=lattice).in_FZ.reshape(-1)
|
||||||
for r,rho in zip(result,set_of_rodrigues[:len(result)]):
|
for r,rho in zip(result,set_of_rodrigues[:len(result)]):
|
||||||
assert r == Orientation.from_Rodrigues_vector(rho=rho,lattice=lattice).in_FZ
|
assert r == Orientation.from_Rodrigues_vector(rho=rho,lattice=lattice).in_FZ
|
||||||
|
|
||||||
@pytest.mark.parametrize('lattice',Orientation.crystal_families)
|
@pytest.mark.parametrize('lattice',crystal_families)
|
||||||
def test_in_disorientation_FZ_vectorization(self,set_of_rodrigues,lattice):
|
def test_in_disorientation_FZ_vectorization(self,set_of_rodrigues,lattice):
|
||||||
result = Orientation.from_Rodrigues_vector(rho=set_of_rodrigues.reshape((-1,4,4)),
|
result = Orientation.from_Rodrigues_vector(rho=set_of_rodrigues.reshape((-1,4,4)),
|
||||||
lattice=lattice).in_disorientation_FZ.reshape(-1)
|
lattice=lattice).in_disorientation_FZ.reshape(-1)
|
||||||
|
@ -322,7 +323,7 @@ class TestOrientation:
|
||||||
assert r == Orientation.from_Rodrigues_vector(rho=rho,lattice=lattice).in_disorientation_FZ
|
assert r == Orientation.from_Rodrigues_vector(rho=rho,lattice=lattice).in_disorientation_FZ
|
||||||
|
|
||||||
@pytest.mark.parametrize('proper',[True,False])
|
@pytest.mark.parametrize('proper',[True,False])
|
||||||
@pytest.mark.parametrize('lattice',Orientation.crystal_families)
|
@pytest.mark.parametrize('lattice',crystal_families)
|
||||||
def test_in_SST_vectorization(self,lattice,proper):
|
def test_in_SST_vectorization(self,lattice,proper):
|
||||||
vecs = np.random.rand(20,4,3)
|
vecs = np.random.rand(20,4,3)
|
||||||
result = Orientation(lattice=lattice).in_SST(vecs,proper).flatten()
|
result = Orientation(lattice=lattice).in_SST(vecs,proper).flatten()
|
||||||
|
@ -393,7 +394,7 @@ class TestOrientation:
|
||||||
a=a,b=b,c=c,
|
a=a,b=b,c=c,
|
||||||
alpha=alpha,beta=beta,gamma=gamma).related(relation) # noqa
|
alpha=alpha,beta=beta,gamma=gamma).related(relation) # noqa
|
||||||
|
|
||||||
@pytest.mark.parametrize('lattice',Orientation.crystal_families)
|
@pytest.mark.parametrize('lattice',crystal_families)
|
||||||
@pytest.mark.parametrize('proper',[True,False])
|
@pytest.mark.parametrize('proper',[True,False])
|
||||||
def test_in_SST(self,lattice,proper):
|
def test_in_SST(self,lattice,proper):
|
||||||
assert Orientation(lattice=lattice).in_SST(np.zeros(3),proper)
|
assert Orientation(lattice=lattice).in_SST(np.zeros(3),proper)
|
||||||
|
|
Loading…
Reference in New Issue