diff --git a/VERSION b/VERSION index fe2e304cb..d50ee7c7e 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v3.0.0-alpha-777-g523a0979e +v3.0.0-alpha-782-ga0b6c2690 diff --git a/python/damask/_orientation.py b/python/damask/_orientation.py index e60459489..f91cc9850 100644 --- a/python/damask/_orientation.py +++ b/python/damask/_orientation.py @@ -802,7 +802,7 @@ class Orientation(Rotation): return np.all(components >= 0.0,axis=-1) - def IPF_color(self,vector,proper=False): + def IPF_color(self,vector,in_SST=True,proper=False): """ Map vector to RGB color within standard stereographic triangle of own symmetry. @@ -810,6 +810,9 @@ class Orientation(Rotation): ---------- vector : numpy.ndarray of shape (...,3) Vector to colorize. + in_SST : bool, optional + Consider symmetrically equivalent orientations such that poles are located in SST. + Defaults to True. proper : bool, optional Consider only vectors with z >= 0, hence combine two neighboring SSTs (with mirrored colors). Defaults to False. @@ -824,7 +827,7 @@ class Orientation(Rotation): Inverse pole figure color of the e_3 direction for a crystal in "Cube" orientation with cubic symmetry: >>> o = damask.Orientation(lattice='cubic') - >>> o.IPF_color(o.to_SST([0,0,1])) + >>> o.IPF_color([0,0,1]) array([1., 0., 0.]) References @@ -847,10 +850,13 @@ class Orientation(Rotation): ... } """ - vector_ = np.array(vector) - if vector_.shape[-1] != 3: + if np.array(vector).shape[-1] != 3: raise ValueError('Input is not a field of three-dimensional vectors.') + 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. ], @@ -1076,7 +1082,7 @@ class Orientation(Rotation): @classmethod - def Bravais_to_Miller(cls,uvtw=None,hkil=None): + def Bravais_to_Miller(cls,*,uvtw=None,hkil=None): """ Transform 4 Miller–Bravais indices to 3 Miller indices of crystal direction [uvw] or plane normal (hkl). @@ -1104,7 +1110,7 @@ class Orientation(Rotation): @classmethod - def Miller_to_Bravais(cls,uvw=None,hkl=None): + def Miller_to_Bravais(cls,*,uvw=None,hkl=None): """ Transform 3 Miller indices to 4 Miller–Bravais indices of crystal direction [uvtw] or plane normal (hkil). @@ -1133,7 +1139,7 @@ class Orientation(Rotation): return np.einsum('il,...l->...i',basis,axis) - def to_lattice(self,direction=None,plane=None): + def to_lattice(self,*,direction=None,plane=None): """ Calculate lattice vector corresponding to crystal frame direction or plane normal. @@ -1157,7 +1163,7 @@ class Orientation(Rotation): return np.einsum('il,...l->...i',basis,axis) - def to_frame(self,uvw=None,hkl=None,with_symmetry=False): + def to_frame(self,*,uvw=None,hkl=None,with_symmetry=False): """ Calculate crystal frame vector along lattice direction [uvw] or plane normal (hkl). @@ -1185,7 +1191,7 @@ class Orientation(Rotation): np.einsum('il,...l->...i',basis,axis)) - def to_pole(self,uvw=None,hkl=None,with_symmetry=False): + def to_pole(self,*,uvw=None,hkl=None,with_symmetry=False): """ Calculate lab frame vector along lattice direction [uvw] or plane normal (hkl). diff --git a/python/damask/_result.py b/python/damask/_result.py index cb69c0dbb..2813c92f4 100644 --- a/python/damask/_result.py +++ b/python/damask/_result.py @@ -740,7 +740,7 @@ class Result: 'hex':'hP'}[q['meta']['Lattice']]) return { - 'data': np.uint8(o.IPF_color(o.to_SST(l))*255), + 'data': np.uint8(o.IPF_color(l)*255), 'label': 'IPFcolor_[{} {} {}]'.format(*m), 'meta' : { 'Unit': '8-bit RGB', diff --git a/python/tests/test_Orientation.py b/python/tests/test_Orientation.py index 3e6aad134..ccd757e06 100644 --- a/python/tests/test_Orientation.py +++ b/python/tests/test_Orientation.py @@ -231,11 +231,11 @@ class TestOrientation: @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('proper',[True,False]) - def test_IPF_color_vectorization(self,lattice,shape,vector,proper): + @pytest.mark.parametrize('in_SST',[True,False]) + def test_IPF_color_vectorization(self,lattice,shape,vector,proper,in_SST): o = Orientation.from_random(lattice=lattice,shape=shape) - poles = o.to_SST(vector=vector,proper=proper) - for r, theO in zip(o.IPF_color(poles,proper=proper).reshape((-1,3)),o.flatten()): - assert np.allclose(r,theO.IPF_color(theO.to_SST(vector=vector,proper=proper),proper=proper)) + 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)) @pytest.mark.parametrize('lattice',Orientation.crystal_families) @pytest.mark.parametrize('a,b',[ @@ -263,14 +263,14 @@ class TestOrientation: cube = Orientation(lattice='cubic') for direction in set(permutations(np.array(color['direction']))): assert np.allclose(np.array(color['RGB']), - cube.IPF_color(cube.to_SST(vector=np.array(direction),proper=proper),proper=proper)) + cube.IPF_color(vector=np.array(direction),proper=proper)) @pytest.mark.parametrize('lattice',Orientation.crystal_families) @pytest.mark.parametrize('proper',[True,False]) def test_IPF_equivalent(self,set_of_quaternions,lattice,proper): direction = np.random.random(3)*2.0-1.0 o = Orientation(rotation=set_of_quaternions,lattice=lattice).equivalent - color = o.IPF_color(o.to_SST(vector=direction,proper=proper),proper=proper) + color = o.IPF_color(vector=direction,proper=proper) assert np.allclose(np.broadcast_to(color[0,...],color.shape),color) @pytest.mark.parametrize('lattice',Orientation.crystal_families) diff --git a/python/tests/test_Result.py b/python/tests/test_Result.py index 312cdbf4b..c48f5acb8 100644 --- a/python/tests/test_Result.py +++ b/python/tests/test_Result.py @@ -177,7 +177,7 @@ class TestResult: lattice={'fcc':'cF', 'bcc':'cI', 'hex':'hP'}[crystal_structure]) - in_memory = np.uint8(c.IPF_color(c.to_SST(np.array(d)))*255) + in_memory = np.uint8(c.IPF_color(np.array(d))*255) in_file = default.read_dataset(loc['color']) assert np.allclose(in_memory,in_file) @@ -210,7 +210,7 @@ class TestResult: in_memory = mechanics.Mises_stress(default.read_dataset(loc['sigma'],0)).reshape(-1,1) in_file = default.read_dataset(loc['sigma_vM'],0) assert np.allclose(in_memory,in_file) - + def test_add_Mises_invalid(self,default): default.add_Cauchy('P','F') default.add_calculation('sigma_y','#sigma#',unit='y')