diff --git a/python/damask/_orientation.py b/python/damask/_orientation.py index b3395acfd..0bb0e1bc8 100644 --- a/python/damask/_orientation.py +++ b/python/damask/_orientation.py @@ -61,7 +61,7 @@ class Orientation: # ToDo: make subclass of lattice and Rotation? if self.lattice.symmetry != other.lattice.symmetry: raise NotImplementedError('disorientation between different symmetry classes not supported yet.') - mySymEqs = self.equivalent if SST else self.equivalent[0] #ToDo: This is just me! # take all or only first sym operation + mySymEqs = self.equivalent if SST else self.equivalent[0] #ToDo: This is just me! # take all or only first sym operation otherSymEqs = other.equivalent for i,sA in enumerate(mySymEqs): @@ -177,7 +177,7 @@ class Orientation: # ToDo: make subclass of lattice and Rotation? # ToDo: Discuss vectorization/calling signature @staticmethod - def fromAverage(orientations, + def from_average(orientations, weights = []): """Create orientation from average of list of orientations.""" # further read: Orientation distribution analysis in deformed grains @@ -193,10 +193,10 @@ class Orientation: # ToDo: make subclass of lattice and Rotation? SST = False, # select (o[ther]'s) sym orientation symmetries = True)[2]].rotation) # with lowest misorientation - return Orientation(Rotation.fromAverage(closest,weights),ref.lattice) + return Orientation(Rotation.from_average(closest,weights),ref.lattice) # ToDo: Discuss vectorization/calling signature def average(self,other): """Calculate the average rotation.""" - return Orientation.fromAverage([self,other]) + return Orientation.from_average([self,other]) diff --git a/python/damask/_rotation.py b/python/damask/_rotation.py index 28e2b428f..674656d4b 100644 --- a/python/damask/_rotation.py +++ b/python/damask/_rotation.py @@ -199,7 +199,7 @@ class Rotation: """ if self.quaternion.shape != (4,) or other.quaternion.shape != (4,): raise NotImplementedError('Support for multiple rotations missing') - return Rotation.fromAverage([self,other]) + return Rotation.from_average([self,other]) ################################################################################################ @@ -294,7 +294,11 @@ class Rotation: """ ro = Rotation._qu2ro(self.quaternion) - return ro[...,:3]*ro[...,3:4] if vector else ro + if vector: + with np.errstate(invalid='ignore'): + return ro[...,:3]*ro[...,3:4] + else: + return ro def as_homochoric(self): """ @@ -577,7 +581,7 @@ class Rotation: @staticmethod - def fromAverage(rotations,weights = None): + def from_average(rotations,weights = None): """ Average rotation. diff --git a/python/tests/test_Orientation.py b/python/tests/test_Orientation.py index 4a7c3e54d..84414a343 100644 --- a/python/tests/test_Orientation.py +++ b/python/tests/test_Orientation.py @@ -20,6 +20,16 @@ def IPF_color(orientation,direction): return color +def inverse_pole(orientation,axis,proper=False,SST=True): + if SST: + for eq in orientation.equivalent: + pole = eq.rotation @ axis/np.linalg.norm(axis) + if orientation.lattice.in_SST(pole,proper=proper): + return pole + else: + return orientation.rotation @ axis/np.linalg.norm(axis) + + @pytest.fixture def reference_dir(reference_dir_base): """Directory containing reference results.""" @@ -44,6 +54,15 @@ class TestOrientation: for i,color in enumerate(oris.IPF_color(direction)): assert np.allclose(color,IPF_color(oris[i],direction)) + @pytest.mark.parametrize('SST',[False,True]) + @pytest.mark.parametrize('proper',[True,False]) + @pytest.mark.parametrize('lattice',Lattice.lattices) + def test_inverse_pole_vectorize(self,set_of_quaternions,lattice,SST,proper): + axis = np.random.random(3)*2.0-1 + oris = Orientation(Rotation(set_of_quaternions),lattice)[:200] + for i,pole in enumerate(oris.inverse_pole(axis,SST=SST)): + assert np.allclose(pole,inverse_pole(oris[i],axis,SST=SST)) + @pytest.mark.parametrize('color',[{'label':'red', 'RGB':[1,0,0],'direction':[0,0,1]}, {'label':'green','RGB':[0,1,0],'direction':[0,1,1]}, {'label':'blue', 'RGB':[0,0,1],'direction':[1,1,1]}]) @@ -95,3 +114,19 @@ class TestOrientation: R_1 = Orientation(Rotation(),lattice) R_2 = Orientation(damask.Rotation.from_Eulers([360,0,0],degrees=True),lattice) assert np.allclose(R_1.disorientation(R_2).as_matrix(),np.eye(3)) + + @pytest.mark.parametrize('lattice',Lattice.lattices) + @pytest.mark.parametrize('angle',[10,20,30,40]) + def test_average(self,angle,lattice): + R_1 = Orientation(Rotation.from_axis_angle([0,0,1,10],degrees=True),lattice) + R_2 = Orientation(Rotation.from_axis_angle([0,0,1,angle],degrees=True),lattice) + avg_angle = R_1.average(R_2).rotation.as_axis_angle(degrees=True,pair=True)[1] + assert np.isclose(avg_angle,10+(angle-10)/2.) + + @pytest.mark.parametrize('lattice',Lattice.lattices) + def test_from_average(self,lattice): + R_1 = Orientation(Rotation.from_random(),lattice) + eqs = [r for r in R_1.equivalent] + R_2 = damask.Orientation.from_average(eqs) + assert np.allclose(R_1.rotation.quaternion,R_2.rotation.quaternion) +