Geom.load_ASCII now auto-shifts material indices

This commit is contained in:
Philip Eisenlohr 2020-11-18 16:45:54 +01:00
commit cb22c34db2
6 changed files with 26 additions and 19 deletions

View File

@ -247,7 +247,7 @@ class Geom:
raise TypeError(f'Invalid file: expected {grid.prod()} entries, found {i}') raise TypeError(f'Invalid file: expected {grid.prod()} entries, found {i}')
if not np.any(np.mod(material,1) != 0.0): # no float present if not np.any(np.mod(material,1) != 0.0): # no float present
material = material.astype('int') material = material.astype('int') - (1 if material.min() > 0 else 0)
return Geom(material.reshape(grid,order='F'),size,origin,comments) return Geom(material.reshape(grid,order='F'),size,origin,comments)

View File

@ -802,7 +802,7 @@ class Orientation(Rotation):
return np.all(components >= 0.0,axis=-1) 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. 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 : numpy.ndarray of shape (...,3)
Vector to colorize. Vector to colorize.
in_SST : bool, optional
Consider symmetrically equivalent orientations such that poles are located in SST.
Defaults to True.
proper : bool, optional proper : bool, optional
Consider only vectors with z >= 0, hence combine two neighboring SSTs (with mirrored colors). Consider only vectors with z >= 0, hence combine two neighboring SSTs (with mirrored colors).
Defaults to False. 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: Inverse pole figure color of the e_3 direction for a crystal in "Cube" orientation with cubic symmetry:
>>> o = damask.Orientation(lattice='cubic') >>> o = damask.Orientation(lattice='cubic')
>>> o.IPF_color(o.to_SST([0,0,1])) >>> o.IPF_color([0,0,1])
array([1., 0., 0.]) array([1., 0., 0.])
References References
@ -847,10 +850,13 @@ class Orientation(Rotation):
... } ... }
""" """
vector_ = np.array(vector) if np.array(vector).shape[-1] != 3:
if vector_.shape[-1] != 3:
raise ValueError('Input is not a field of three-dimensional vectors.') 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': if self.family == 'cubic':
basis = {'improper':np.array([ [-1. , 0. , 1. ], basis = {'improper':np.array([ [-1. , 0. , 1. ],
[ np.sqrt(2.) , -np.sqrt(2.) , 0. ], [ np.sqrt(2.) , -np.sqrt(2.) , 0. ],
@ -1076,7 +1082,7 @@ class Orientation(Rotation):
@classmethod @classmethod
def Bravais_to_Miller(cls,uvtw=None,hkil=None): def Bravais_to_Miller(cls,*,uvtw=None,hkil=None):
""" """
Transform 4 MillerBravais indices to 3 Miller indices of crystal direction [uvw] or plane normal (hkl). Transform 4 MillerBravais indices to 3 Miller indices of crystal direction [uvw] or plane normal (hkl).
@ -1104,7 +1110,7 @@ class Orientation(Rotation):
@classmethod @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 MillerBravais indices of crystal direction [uvtw] or plane normal (hkil). Transform 3 Miller indices to 4 MillerBravais indices of crystal direction [uvtw] or plane normal (hkil).
@ -1133,7 +1139,7 @@ class Orientation(Rotation):
return np.einsum('il,...l->...i',basis,axis) 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. 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) 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). 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)) 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). Calculate lab frame vector along lattice direction [uvw] or plane normal (hkl).

View File

@ -746,7 +746,7 @@ class Result:
'hex':'hP'}[q['meta']['Lattice']]) 'hex':'hP'}[q['meta']['Lattice']])
return { return {
'data': np.uint8(o.IPF_color(o.to_SST(l))*255), 'data': np.uint8(o.IPF_color(l)*255),
'label': 'IPFcolor_[{} {} {}]'.format(*m), 'label': 'IPFcolor_[{} {} {}]'.format(*m),
'meta' : { 'meta' : {
'Unit': '8-bit RGB', 'Unit': '8-bit RGB',

View File

@ -74,6 +74,7 @@ class TestGeom:
def test_save_load_ASCII(self,default,tmp_path): def test_save_load_ASCII(self,default,tmp_path):
default.save_ASCII(tmp_path/'ASCII') default.save_ASCII(tmp_path/'ASCII')
default.material -= 1
assert geom_equal(Geom.load_ASCII(tmp_path/'ASCII'),default) assert geom_equal(Geom.load_ASCII(tmp_path/'ASCII'),default)
def test_invalid_origin(self,default): def test_invalid_origin(self,default):

View File

@ -231,11 +231,11 @@ class TestOrientation:
@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])
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) o = Orientation.from_random(lattice=lattice,shape=shape)
poles = o.to_SST(vector=vector,proper=proper) 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(poles,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(theO.to_SST(vector=vector,proper=proper),proper=proper))
@pytest.mark.parametrize('lattice',Orientation.crystal_families) @pytest.mark.parametrize('lattice',Orientation.crystal_families)
@pytest.mark.parametrize('a,b',[ @pytest.mark.parametrize('a,b',[
@ -263,14 +263,14 @@ class TestOrientation:
cube = Orientation(lattice='cubic') cube = Orientation(lattice='cubic')
for direction in set(permutations(np.array(color['direction']))): for direction in set(permutations(np.array(color['direction']))):
assert np.allclose(np.array(color['RGB']), 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('lattice',Orientation.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
o = Orientation(rotation=set_of_quaternions,lattice=lattice).equivalent 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) assert np.allclose(np.broadcast_to(color[0,...],color.shape),color)
@pytest.mark.parametrize('lattice',Orientation.crystal_families) @pytest.mark.parametrize('lattice',Orientation.crystal_families)

View File

@ -177,7 +177,7 @@ class TestResult:
lattice={'fcc':'cF', lattice={'fcc':'cF',
'bcc':'cI', 'bcc':'cI',
'hex':'hP'}[crystal_structure]) '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']) in_file = default.read_dataset(loc['color'])
assert np.allclose(in_memory,in_file) 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_memory = mechanics.Mises_stress(default.read_dataset(loc['sigma'],0)).reshape(-1,1)
in_file = default.read_dataset(loc['sigma_vM'],0) in_file = default.read_dataset(loc['sigma_vM'],0)
assert np.allclose(in_memory,in_file) assert np.allclose(in_memory,in_file)
def test_add_Mises_invalid(self,default): def test_add_Mises_invalid(self,default):
default.add_Cauchy('P','F') default.add_Cauchy('P','F')
default.add_calculation('sigma_y','#sigma#',unit='y') default.add_calculation('sigma_y','#sigma#',unit='y')