From b55d51491df055747ca5deb2b520029ad926bc2d Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Tue, 1 Jun 2021 23:23:04 +0200 Subject: [PATCH] separating functionality --- python/damask/__init__.py | 1 + python/damask/_lattice_family.py | 192 +++++++++++++++++++++++ python/damask/_orientation.py | 258 +++---------------------------- python/damask/lattice.py | 57 ------- python/tests/test_Orientation.py | 11 +- 5 files changed, 220 insertions(+), 299 deletions(-) create mode 100644 python/damask/_lattice_family.py diff --git a/python/damask/__init__.py b/python/damask/__init__.py index ad46d454f..5cdfbe899 100644 --- a/python/damask/__init__.py +++ b/python/damask/__init__.py @@ -18,6 +18,7 @@ from . import lattice # noqa #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'. from ._rotation import Rotation # noqa +from ._lattice_family import LatticeFamily # noqa from ._orientation import Orientation # noqa from ._table import Table # noqa from ._vtk import VTK # noqa diff --git a/python/damask/_lattice_family.py b/python/damask/_lattice_family.py new file mode 100644 index 000000000..8f352e8df --- /dev/null +++ b/python/damask/_lattice_family.py @@ -0,0 +1,192 @@ +import numpy as np + +from . import Rotation + +class LatticeFamily(): + + def __init__(self,family): + """Symmetry-related operations for crystal families.""" + if family not in self._immutable.keys(): + raise KeyError(f'invalid lattice family "{family}"') + self.family = family + + + @property + def symmetry_operations(self): + """Symmetry operations as Rotations.""" + return Rotation.from_quaternion(self._symmetry_operations[self.family],accept_homomorph=True) + + + @property + def immutable(self): + """Return immutable parameters lattice parameters.""" + return self._immutable[self.family] + + + @property + def basis(self): + """ + Corners of the standard triangle. + + Not yet defined for monoclinic. + + + References + ---------- + Bases are computed from + + >>> basis = { + ... 'cubic' : np.linalg.inv(np.array([[0.,0.,1.], # direction of red + ... [1.,0.,1.]/np.sqrt(2.), # green + ... [1.,1.,1.]/np.sqrt(3.)]).T), # blue + ... 'hexagonal' : np.linalg.inv(np.array([[0.,0.,1.], # direction of red + ... [1.,0.,0.], # green + ... [np.sqrt(3.),1.,0.]/np.sqrt(4.)]).T), # blue + ... 'tetragonal' : np.linalg.inv(np.array([[0.,0.,1.], # direction of red + ... [1.,0.,0.], # green + ... [1.,1.,0.]/np.sqrt(2.)]).T), # blue + ... 'orthorhombic': np.linalg.inv(np.array([[0.,0.,1.], # direction of red + ... [1.,0.,0.], # green + ... [0.,1.,0.]]).T), # blue + ... } + + """ + return self._basis.get(self.family,None) + + + _symmetry_operations = { + 'cubic': [ + [ 1.0, 0.0, 0.0, 0.0 ], + [ 0.0, 1.0, 0.0, 0.0 ], + [ 0.0, 0.0, 1.0, 0.0 ], + [ 0.0, 0.0, 0.0, 1.0 ], + [ 0.0, 0.0, 0.5*np.sqrt(2), 0.5*np.sqrt(2) ], + [ 0.0, 0.0, 0.5*np.sqrt(2),-0.5*np.sqrt(2) ], + [ 0.0, 0.5*np.sqrt(2), 0.0, 0.5*np.sqrt(2) ], + [ 0.0, 0.5*np.sqrt(2), 0.0, -0.5*np.sqrt(2) ], + [ 0.0, 0.5*np.sqrt(2),-0.5*np.sqrt(2), 0.0 ], + [ 0.0, -0.5*np.sqrt(2),-0.5*np.sqrt(2), 0.0 ], + [ 0.5, 0.5, 0.5, 0.5 ], + [-0.5, 0.5, 0.5, 0.5 ], + [-0.5, 0.5, 0.5, -0.5 ], + [-0.5, 0.5, -0.5, 0.5 ], + [-0.5, -0.5, 0.5, 0.5 ], + [-0.5, -0.5, 0.5, -0.5 ], + [-0.5, -0.5, -0.5, 0.5 ], + [-0.5, 0.5, -0.5, -0.5 ], + [-0.5*np.sqrt(2), 0.0, 0.0, 0.5*np.sqrt(2) ], + [ 0.5*np.sqrt(2), 0.0, 0.0, 0.5*np.sqrt(2) ], + [-0.5*np.sqrt(2), 0.0, 0.5*np.sqrt(2), 0.0 ], + [-0.5*np.sqrt(2), 0.0, -0.5*np.sqrt(2), 0.0 ], + [-0.5*np.sqrt(2), 0.5*np.sqrt(2), 0.0, 0.0 ], + [-0.5*np.sqrt(2),-0.5*np.sqrt(2), 0.0, 0.0 ], + ], + 'hexagonal': [ + [ 1.0, 0.0, 0.0, 0.0 ], + [-0.5*np.sqrt(3), 0.0, 0.0, -0.5 ], + [ 0.5, 0.0, 0.0, 0.5*np.sqrt(3) ], + [ 0.0, 0.0, 0.0, 1.0 ], + [-0.5, 0.0, 0.0, 0.5*np.sqrt(3) ], + [-0.5*np.sqrt(3), 0.0, 0.0, 0.5 ], + [ 0.0, 1.0, 0.0, 0.0 ], + [ 0.0, -0.5*np.sqrt(3), 0.5, 0.0 ], + [ 0.0, 0.5, -0.5*np.sqrt(3), 0.0 ], + [ 0.0, 0.0, 1.0, 0.0 ], + [ 0.0, -0.5, -0.5*np.sqrt(3), 0.0 ], + [ 0.0, 0.5*np.sqrt(3), 0.5, 0.0 ], + ], + 'tetragonal': [ + [ 1.0, 0.0, 0.0, 0.0 ], + [ 0.0, 1.0, 0.0, 0.0 ], + [ 0.0, 0.0, 1.0, 0.0 ], + [ 0.0, 0.0, 0.0, 1.0 ], + [ 0.0, 0.5*np.sqrt(2), 0.5*np.sqrt(2), 0.0 ], + [ 0.0, -0.5*np.sqrt(2), 0.5*np.sqrt(2), 0.0 ], + [ 0.5*np.sqrt(2), 0.0, 0.0, 0.5*np.sqrt(2) ], + [-0.5*np.sqrt(2), 0.0, 0.0, 0.5*np.sqrt(2) ], + ], + 'orthorhombic': [ + [ 1.0,0.0,0.0,0.0 ], + [ 0.0,1.0,0.0,0.0 ], + [ 0.0,0.0,1.0,0.0 ], + [ 0.0,0.0,0.0,1.0 ], + ], + 'monoclinic': [ + [ 1.0,0.0,0.0,0.0 ], + [ 0.0,0.0,1.0,0.0 ], + ], + 'triclinic': [ + [ 1.0,0.0,0.0,0.0 ], + ]} + + + _immutable = { + 'cubic': + { + 'b': 1.0, + 'c': 1.0, + 'alpha': np.pi/2., + 'beta': np.pi/2., + 'gamma': np.pi/2., + }, + 'hexagonal': + { + 'b': 1.0, + 'alpha': np.pi/2., + 'beta': np.pi/2., + 'gamma': 2.*np.pi/3., + }, + 'tetragonal': + { + 'b': 1.0, + 'alpha': np.pi/2., + 'beta': np.pi/2., + 'gamma': np.pi/2., + }, + 'orthorhombic': + { + 'alpha': np.pi/2., + 'beta': np.pi/2., + 'gamma': np.pi/2., + }, + 'monoclinic': + { + 'alpha': np.pi/2., + 'gamma': np.pi/2., + }, + 'triclinic': {} + } + + + _basis = { + 'cubic': {'improper':np.array([ [-1. , 0. , 1. ], + [ np.sqrt(2.) , -np.sqrt(2.) , 0. ], + [ 0. , np.sqrt(3.) , 0. ] ]), + 'proper':np.array([ [ 0. , -1. , 1. ], + [-np.sqrt(2.) , np.sqrt(2.) , 0. ], + [ np.sqrt(3.) , 0. , 0. ] ]), + }, + 'hexagonal': + {'improper':np.array([ [ 0. , 0. , 1. ], + [ 1. , -np.sqrt(3.) , 0. ], + [ 0. , 2. , 0. ] ]), + 'proper':np.array([ [ 0. , 0. , 1. ], + [-1. , np.sqrt(3.) , 0. ], + [ np.sqrt(3.) , -1. , 0. ] ]), + }, + 'tetragonal': + {'improper':np.array([ [ 0. , 0. , 1. ], + [ 1. , -1. , 0. ], + [ 0. , np.sqrt(2.) , 0. ] ]), + 'proper':np.array([ [ 0. , 0. , 1. ], + [-1. , 1. , 0. ], + [ np.sqrt(2.) , 0. , 0. ] ]), + }, + 'orthorhombic': + {'improper':np.array([ [ 0., 0., 1.], + [ 1., 0., 0.], + [ 0., 1., 0.] ]), + 'proper':np.array([ [ 0., 0., 1.], + [-1., 0., 0.], + [ 0., 1., 0.] ]), + }} diff --git a/python/damask/_orientation.py b/python/damask/_orientation.py index f3919d1ff..8a3f9fe24 100644 --- a/python/damask/_orientation.py +++ b/python/damask/_orientation.py @@ -3,6 +3,7 @@ import inspect import numpy as np from . import Rotation +from . import LatticeFamily from . import util from . import tensor from . import lattice as lattice_ @@ -132,16 +133,27 @@ class Orientation(Rotation): Rotation.__init__(self,rotation=rotation) if family in set(lattice_symmetries.values()) and lattice is None: - self.family = family + self.family = family self.lattice = None + l = LatticeFamily(self.family) + self.immutable = l.immutable + self.basis = l.basis + self.symmetry_operations = l.symmetry_operations + self.a = self.b = self.c = None self.alpha = self.beta = self.gamma = None elif lattice in lattice_symmetries: + self.family = lattice_symmetries[lattice] self.lattice = lattice + l = LatticeFamily(self.family) + self.immutable = l.immutable + self.basis = l.basis + self.symmetry_operations = l.symmetry_operations + self.a = 1 if a is None else a self.b = b self.c = c @@ -201,7 +213,6 @@ class Orientation(Rotation): alpha = kwargs['alpha'] if 'alpha' in kwargs else self.alpha, beta = kwargs['beta'] if 'beta' in kwargs else self.beta, gamma = kwargs['gamma'] if 'gamma' in kwargs else self.gamma, - degrees = kwargs['degrees'] if 'degrees' in kwargs else None, ) copy = __copy__ @@ -435,84 +446,6 @@ class Orientation(Rotation): return o.copy(rotation=Rotation.from_matrix(tensor.transpose(om/np.linalg.norm(om,axis=-1,keepdims=True)))) - @property - def symmetry_operations(self): - """Symmetry operations as Rotations.""" - if self.family == 'cubic': - sym_quats = [ - [ 1.0, 0.0, 0.0, 0.0 ], - [ 0.0, 1.0, 0.0, 0.0 ], - [ 0.0, 0.0, 1.0, 0.0 ], - [ 0.0, 0.0, 0.0, 1.0 ], - [ 0.0, 0.0, 0.5*np.sqrt(2), 0.5*np.sqrt(2) ], - [ 0.0, 0.0, 0.5*np.sqrt(2),-0.5*np.sqrt(2) ], - [ 0.0, 0.5*np.sqrt(2), 0.0, 0.5*np.sqrt(2) ], - [ 0.0, 0.5*np.sqrt(2), 0.0, -0.5*np.sqrt(2) ], - [ 0.0, 0.5*np.sqrt(2),-0.5*np.sqrt(2), 0.0 ], - [ 0.0, -0.5*np.sqrt(2),-0.5*np.sqrt(2), 0.0 ], - [ 0.5, 0.5, 0.5, 0.5 ], - [-0.5, 0.5, 0.5, 0.5 ], - [-0.5, 0.5, 0.5, -0.5 ], - [-0.5, 0.5, -0.5, 0.5 ], - [-0.5, -0.5, 0.5, 0.5 ], - [-0.5, -0.5, 0.5, -0.5 ], - [-0.5, -0.5, -0.5, 0.5 ], - [-0.5, 0.5, -0.5, -0.5 ], - [-0.5*np.sqrt(2), 0.0, 0.0, 0.5*np.sqrt(2) ], - [ 0.5*np.sqrt(2), 0.0, 0.0, 0.5*np.sqrt(2) ], - [-0.5*np.sqrt(2), 0.0, 0.5*np.sqrt(2), 0.0 ], - [-0.5*np.sqrt(2), 0.0, -0.5*np.sqrt(2), 0.0 ], - [-0.5*np.sqrt(2), 0.5*np.sqrt(2), 0.0, 0.0 ], - [-0.5*np.sqrt(2),-0.5*np.sqrt(2), 0.0, 0.0 ], - ] - elif self.family == 'hexagonal': - sym_quats = [ - [ 1.0, 0.0, 0.0, 0.0 ], - [-0.5*np.sqrt(3), 0.0, 0.0, -0.5 ], - [ 0.5, 0.0, 0.0, 0.5*np.sqrt(3) ], - [ 0.0, 0.0, 0.0, 1.0 ], - [-0.5, 0.0, 0.0, 0.5*np.sqrt(3) ], - [-0.5*np.sqrt(3), 0.0, 0.0, 0.5 ], - [ 0.0, 1.0, 0.0, 0.0 ], - [ 0.0, -0.5*np.sqrt(3), 0.5, 0.0 ], - [ 0.0, 0.5, -0.5*np.sqrt(3), 0.0 ], - [ 0.0, 0.0, 1.0, 0.0 ], - [ 0.0, -0.5, -0.5*np.sqrt(3), 0.0 ], - [ 0.0, 0.5*np.sqrt(3), 0.5, 0.0 ], - ] - elif self.family == 'tetragonal': - sym_quats = [ - [ 1.0, 0.0, 0.0, 0.0 ], - [ 0.0, 1.0, 0.0, 0.0 ], - [ 0.0, 0.0, 1.0, 0.0 ], - [ 0.0, 0.0, 0.0, 1.0 ], - [ 0.0, 0.5*np.sqrt(2), 0.5*np.sqrt(2), 0.0 ], - [ 0.0, -0.5*np.sqrt(2), 0.5*np.sqrt(2), 0.0 ], - [ 0.5*np.sqrt(2), 0.0, 0.0, 0.5*np.sqrt(2) ], - [-0.5*np.sqrt(2), 0.0, 0.0, 0.5*np.sqrt(2) ], - ] - elif self.family == 'orthorhombic': - sym_quats = [ - [ 1.0,0.0,0.0,0.0 ], - [ 0.0,1.0,0.0,0.0 ], - [ 0.0,0.0,1.0,0.0 ], - [ 0.0,0.0,0.0,1.0 ], - ] - elif self.family == 'monoclinic': - sym_quats = [ - [ 1.0,0.0,0.0,0.0 ], - [ 0.0,0.0,1.0,0.0 ], - ] - elif self.family == 'triclinic': - sym_quats = [ - [ 1.0,0.0,0.0,0.0 ], - ] - else: - raise KeyError(f'unknown crystal family "{self.family}"') - - return Rotation.from_quaternion(sym_quats,accept_homomorph=True) - - @property def equivalent(self): """ @@ -707,46 +640,6 @@ class Orientation(Rotation): return (self.a,self.b,self.c,self.alpha,self.beta,self.gamma) - @property - def immutable(self): - """Return immutable parameters of own lattice.""" - if self.family == 'triclinic': - return {} - if self.family == 'monoclinic': - return { - 'alpha': np.pi/2., - 'gamma': np.pi/2., - } - if self.family == 'orthorhombic': - return { - 'alpha': np.pi/2., - 'beta': np.pi/2., - 'gamma': np.pi/2., - } - if self.family == 'tetragonal': - return { - 'b': 1.0, - 'alpha': np.pi/2., - 'beta': np.pi/2., - 'gamma': np.pi/2., - } - if self.family == 'hexagonal': - return { - 'b': 1.0, - 'alpha': np.pi/2., - 'beta': np.pi/2., - 'gamma': 2.*np.pi/3., - } - if self.family == 'cubic': - return { - 'b': 1.0, - 'c': 1.0, - 'alpha': np.pi/2., - 'beta': np.pi/2., - 'gamma': np.pi/2., - } - - @property def ratio(self): """Return axes ratios of own lattice.""" @@ -808,76 +701,25 @@ class Orientation(Rotation): in : numpy.ndarray of shape (...) Boolean array indicating whether vector falls into SST. - References - ---------- - Bases are computed from - - >>> basis = { - ... 'cubic' : np.linalg.inv(np.array([[0.,0.,1.], # direction of red - ... [1.,0.,1.]/np.sqrt(2.), # green - ... [1.,1.,1.]/np.sqrt(3.)]).T), # blue - ... 'hexagonal' : np.linalg.inv(np.array([[0.,0.,1.], # direction of red - ... [1.,0.,0.], # green - ... [np.sqrt(3.),1.,0.]/np.sqrt(4.)]).T), # blue - ... 'tetragonal' : np.linalg.inv(np.array([[0.,0.,1.], # direction of red - ... [1.,0.,0.], # green - ... [1.,1.,0.]/np.sqrt(2.)]).T), # blue - ... 'orthorhombic': np.linalg.inv(np.array([[0.,0.,1.], # direction of red - ... [1.,0.,0.], # green - ... [0.,1.,0.]]).T), # blue - ... } - """ if not isinstance(vector,np.ndarray) or vector.shape[-1] != 3: raise ValueError('input is not a field of three-dimensional vectors') - if self.family == 'cubic': - basis = {'improper':np.array([ [-1. , 0. , 1. ], - [ np.sqrt(2.) , -np.sqrt(2.) , 0. ], - [ 0. , np.sqrt(3.) , 0. ] ]), - 'proper':np.array([ [ 0. , -1. , 1. ], - [-np.sqrt(2.) , np.sqrt(2.) , 0. ], - [ np.sqrt(3.) , 0. , 0. ] ]), - } - elif self.family == 'hexagonal': - basis = {'improper':np.array([ [ 0. , 0. , 1. ], - [ 1. , -np.sqrt(3.) , 0. ], - [ 0. , 2. , 0. ] ]), - 'proper':np.array([ [ 0. , 0. , 1. ], - [-1. , np.sqrt(3.) , 0. ], - [ np.sqrt(3.) , -1. , 0. ] ]), - } - elif self.family == 'tetragonal': - basis = {'improper':np.array([ [ 0. , 0. , 1. ], - [ 1. , -1. , 0. ], - [ 0. , np.sqrt(2.) , 0. ] ]), - 'proper':np.array([ [ 0. , 0. , 1. ], - [-1. , 1. , 0. ], - [ np.sqrt(2.) , 0. , 0. ] ]), - } - elif self.family == 'orthorhombic': - basis = {'improper':np.array([ [ 0., 0., 1.], - [ 1., 0., 0.], - [ 0., 1., 0.] ]), - 'proper':np.array([ [ 0., 0., 1.], - [-1., 0., 0.], - [ 0., 1., 0.] ]), - } - else: # direct exit for unspecified symmetry + if self.basis is None: # direct exit for no symmetry return np.ones_like(vector[...,0],bool) if proper: components_proper = np.around(np.einsum('...ji,...i', - np.broadcast_to(basis['proper'], vector.shape+(3,)), + np.broadcast_to(self.basis['proper'], vector.shape+(3,)), vector), 12) components_improper = np.around(np.einsum('...ji,...i', - np.broadcast_to(basis['improper'], vector.shape+(3,)), + np.broadcast_to(self.basis['improper'], vector.shape+(3,)), vector), 12) return np.all(components_proper >= 0.0,axis=-1) \ | np.all(components_improper >= 0.0,axis=-1) else: components = np.around(np.einsum('...ji,...i', - np.broadcast_to(basis['improper'], vector.shape+(3,)), + np.broadcast_to(self.basis['improper'], vector.shape+(3,)), np.block([vector[...,:2],np.abs(vector[...,2:3])])), 12) return np.all(components >= 0.0,axis=-1) @@ -911,25 +753,6 @@ class Orientation(Rotation): >>> o.IPF_color([0,0,1]) array([1., 0., 0.]) - References - ---------- - Bases are computed from - - >>> basis = { - ... 'cubic' : np.linalg.inv(np.array([[0.,0.,1.], # direction of red - ... [1.,0.,1.]/np.sqrt(2.), # green - ... [1.,1.,1.]/np.sqrt(3.)]).T), # blue - ... 'hexagonal' : np.linalg.inv(np.array([[0.,0.,1.], # direction of red - ... [1.,0.,0.], # green - ... [np.sqrt(3.),1.,0.]/np.sqrt(4.)]).T), # blue - ... 'tetragonal' : np.linalg.inv(np.array([[0.,0.,1.], # direction of red - ... [1.,0.,0.], # green - ... [1.,1.,0.]/np.sqrt(2.)]).T), # blue - ... 'orthorhombic': np.linalg.inv(np.array([[0.,0.,1.], # direction of red - ... [1.,0.,0.], # green - ... [0.,1.,0.]]).T), # blue - ... } - """ if np.array(vector).shape[-1] != 3: raise ValueError('input is not a field of three-dimensional vectors') @@ -937,47 +760,15 @@ class Orientation(Rotation): vector_ = self.to_SST(vector,proper) if in_SST else \ self @ np.broadcast_to(vector,self.shape+(3,)) - if self.family == 'cubic': - basis = {'improper':np.array([ [-1. , 0. , 1. ], - [ np.sqrt(2.) , -np.sqrt(2.) , 0. ], - [ 0. , np.sqrt(3.) , 0. ] ]), - 'proper':np.array([ [ 0. , -1. , 1. ], - [-np.sqrt(2.) , np.sqrt(2.) , 0. ], - [ np.sqrt(3.) , 0. , 0. ] ]), - } - elif self.family == 'hexagonal': - basis = {'improper':np.array([ [ 0. , 0. , 1. ], - [ 1. , -np.sqrt(3.) , 0. ], - [ 0. , 2. , 0. ] ]), - 'proper':np.array([ [ 0. , 0. , 1. ], - [-1. , np.sqrt(3.) , 0. ], - [ np.sqrt(3.) , -1. , 0. ] ]), - } - elif self.family == 'tetragonal': - basis = {'improper':np.array([ [ 0. , 0. , 1. ], - [ 1. , -1. , 0. ], - [ 0. , np.sqrt(2.) , 0. ] ]), - 'proper':np.array([ [ 0. , 0. , 1. ], - [-1. , 1. , 0. ], - [ np.sqrt(2.) , 0. , 0. ] ]), - } - elif self.family == 'orthorhombic': - basis = {'improper':np.array([ [ 0., 0., 1.], - [ 1., 0., 0.], - [ 0., 1., 0.] ]), - 'proper':np.array([ [ 0., 0., 1.], - [-1., 0., 0.], - [ 0., 1., 0.] ]), - } - else: # direct exit for unspecified symmetry + if self.basis is None: # direct exit for no symmetry return np.zeros_like(vector_) if proper: components_proper = np.around(np.einsum('...ji,...i', - np.broadcast_to(basis['proper'], vector_.shape+(3,)), + np.broadcast_to(self.basis['proper'], vector_.shape+(3,)), vector_), 12) components_improper = np.around(np.einsum('...ji,...i', - np.broadcast_to(basis['improper'], vector_.shape+(3,)), + np.broadcast_to(self.basis['improper'], vector_.shape+(3,)), vector_), 12) in_SST = np.all(components_proper >= 0.0,axis=-1) \ | np.all(components_improper >= 0.0,axis=-1) @@ -985,16 +776,17 @@ class Orientation(Rotation): components_proper,components_improper) else: components = np.around(np.einsum('...ji,...i', - np.broadcast_to(basis['improper'], vector_.shape+(3,)), + np.broadcast_to(self.basis['improper'], vector_.shape+(3,)), np.block([vector_[...,:2],np.abs(vector_[...,2:3])])), 12) in_SST = np.all(components >= 0.0,axis=-1) with np.errstate(invalid='ignore',divide='ignore'): - rgb = (components/np.linalg.norm(components,axis=-1,keepdims=True))**0.5 # smoothen color ramps - rgb = np.clip(rgb,0.,1.) # clip intensity - rgb /= np.max(rgb,axis=-1,keepdims=True) # normalize to (HS)V = 1 + rgb = (components/np.linalg.norm(components,axis=-1,keepdims=True))**0.5 # smoothen color ramps + rgb = np.clip(rgb,0.,1.) # clip intensity + rgb /= np.max(rgb,axis=-1,keepdims=True) # normalize to (HS)V = 1 rgb[np.broadcast_to(~in_SST[...,np.newaxis],rgb.shape)] = 0.0 + return rgb diff --git a/python/damask/lattice.py b/python/damask/lattice.py index e335fc85b..5b4621f3d 100644 --- a/python/damask/lattice.py +++ b/python/damask/lattice.py @@ -1,62 +1,5 @@ import numpy as _np - -def Bravais_to_Miller(*,uvtw=None,hkil=None): - """ - Transform 4 Miller–Bravais indices to 3 Miller indices of crystal direction [uvw] or plane normal (hkl). - - Parameters - ---------- - uvtw|hkil : numpy.ndarray of shape (...,4) - Miller–Bravais indices of crystallographic direction [uvtw] or plane normal (hkil). - - Returns - ------- - uvw|hkl : numpy.ndarray of shape (...,3) - Miller indices of [uvw] direction or (hkl) plane normal. - - """ - if (uvtw is not None) ^ (hkil is None): - raise KeyError('Specify either "uvtw" or "hkil"') - axis,basis = (_np.array(uvtw),_np.array([[1,0,-1,0], - [0,1,-1,0], - [0,0, 0,1]])) \ - if hkil is None else \ - (_np.array(hkil),_np.array([[1,0,0,0], - [0,1,0,0], - [0,0,0,1]])) - return _np.einsum('il,...l',basis,axis) - - -def Miller_to_Bravais(*,uvw=None,hkl=None): - """ - Transform 3 Miller indices to 4 Miller–Bravais indices of crystal direction [uvtw] or plane normal (hkil). - - Parameters - ---------- - uvw|hkl : numpy.ndarray of shape (...,3) - Miller indices of crystallographic direction [uvw] or plane normal (hkl). - - Returns - ------- - uvtw|hkil : numpy.ndarray of shape (...,4) - Miller–Bravais indices of [uvtw] direction or (hkil) plane normal. - - """ - if (uvw is not None) ^ (hkl is None): - raise KeyError('Specify either "uvw" or "hkl"') - axis,basis = (_np.array(uvw),_np.array([[ 2,-1, 0], - [-1, 2, 0], - [-1,-1, 0], - [ 0, 0, 3]])/3) \ - if hkl is None else \ - (_np.array(hkl),_np.array([[ 1, 0, 0], - [ 0, 1, 0], - [-1,-1, 0], - [ 0, 0, 1]])) - return _np.einsum('il,...l',basis,axis) - - kinematics = { 'cF': { 'slip' : _np.array([ diff --git a/python/tests/test_Orientation.py b/python/tests/test_Orientation.py index 7fc20a3e6..471dada58 100644 --- a/python/tests/test_Orientation.py +++ b/python/tests/test_Orientation.py @@ -336,17 +336,10 @@ class TestOrientation: for r,v in zip(result,vecs.reshape((-1,3))): assert np.all(r == Orientation(family=family).in_SST(v,proper)) - @pytest.mark.parametrize('invalid_family',['fcc','bcc','hello']) + @pytest.mark.parametrize('invalid_family',[None,'fcc','bcc','hello']) def test_invalid_lattice_init(self,invalid_family): with pytest.raises(KeyError): - Orientation(family=invalid_family) # noqa - - @pytest.mark.parametrize('invalid_family',[None,'fcc','bcc','hello']) - def test_invalid_symmetry_family(self,invalid_family): - with pytest.raises(KeyError): - o = Orientation(family='cubic') - o.family = invalid_family - o.symmetry_operations # noqa + Orientation(family=invalid_family) def test_invalid_rot(self): with pytest.raises(TypeError):