symQuats-related functions can take optional argument to downselect return values.

“getAverageOrientations” —> “average” and takes optional multiplicities of orientations in list.
This commit is contained in:
Philip Eisenlohr 2015-11-14 01:46:44 +00:00
parent 1395714c87
commit 6211a9faad
1 changed files with 31 additions and 22 deletions

View File

@ -555,7 +555,7 @@ class Symmetry:
def __cmp__(self,other): def __cmp__(self,other):
return cmp(Symmetry.lattices.index(self.lattice),Symmetry.lattices.index(other.lattice)) return cmp(Symmetry.lattices.index(self.lattice),Symmetry.lattices.index(other.lattice))
def symmetryQuats(self): def symmetryQuats(self,who = []):
''' '''
List of symmetry operations as quaternions. List of symmetry operations as quaternions.
''' '''
@ -623,15 +623,18 @@ class Symmetry:
symQuats = [ symQuats = [
[ 1.0,0.0,0.0,0.0 ], [ 1.0,0.0,0.0,0.0 ],
] ]
return map(Quaternion,symQuats) return map(Quaternion,
np.array(symQuats)[np.atleast_1d(np.array(who)) if who != [] else xrange(len(symQuats))])
def equivalentQuaternions(self,quaternion): def equivalentQuaternions(self,
quaternion,
who = []):
''' '''
List of symmetrically equivalent quaternions based on own symmetry. List of symmetrically equivalent quaternions based on own symmetry.
''' '''
return [quaternion*Quaternion(q) for q in self.symmetryQuats()] return [quaternion*q for q in self.symmetryQuats(who)]
def inFZ(self,R): def inFZ(self,R):
@ -852,14 +855,14 @@ class Orientation:
return self.symmetry.inFZ(self.quaternion.asRodrigues()) return self.symmetry.inFZ(self.quaternion.asRodrigues())
infz = property(inFZ) infz = property(inFZ)
def equivalentQuaternions(self): def equivalentQuaternions(self,
return self.symmetry.equivalentQuaternions(self.quaternion) who = []):
equiQuaternions = property(equivalentQuaternions) return self.symmetry.equivalentQuaternions(self.quaternion,who)
def equivalentOrientations(self): def equivalentOrientations(self,
who = []):
return map(lambda q: Orientation(quaternion = q, symmetry = self.symmetry.lattice), return map(lambda q: Orientation(quaternion = q, symmetry = self.symmetry.lattice),
self.equivalentQuaternions()) self.equivalentQuaternions(who))
equiOrientations = property(equivalentQuaternions)
def reduced(self): def reduced(self):
''' '''
@ -893,9 +896,8 @@ class Orientation:
theQ = sA.conjugated()*misQ*sB theQ = sA.conjugated()*misQ*sB
for k in xrange(2): for k in xrange(2):
theQ.conjugate() theQ.conjugate()
hitFZ = self.symmetry.inFZ(theQ) breaker = self.symmetry.inFZ(theQ) \
hitSST = other.symmetry.inDisorientationSST(theQ) and (not SST or other.symmetry.inDisorientationSST(theQ))
breaker = hitFZ and (hitSST or not SST)
if breaker: break if breaker: break
if breaker: break if breaker: break
if breaker: break if breaker: break
@ -936,7 +938,9 @@ class Orientation:
return color return color
@classmethod @classmethod
def getAverageOrientation(cls, orientationList): def average(cls,
orientations,
multiplicity = []):
"""RETURN THE AVERAGE ORIENTATION """RETURN THE AVERAGE ORIENTATION
ref: F. Landis Markley, Yang Cheng, John Lucas Crassidis, and Yaakov Oshman. ref: F. Landis Markley, Yang Cheng, John Lucas Crassidis, and Yaakov Oshman.
Averaging Quaternions, Averaging Quaternions,
@ -945,19 +949,24 @@ class Orientation:
usage: usage:
a = Orientation(Eulers=np.radians([10, 10, 0]), symmetry='hexagonal') a = Orientation(Eulers=np.radians([10, 10, 0]), symmetry='hexagonal')
b = Orientation(Eulers=np.radians([20, 0, 0]), symmetry='hexagonal') b = Orientation(Eulers=np.radians([20, 0, 0]), symmetry='hexagonal')
avg = Orientation.getAverageOrientation([a,b]) avg = Orientation.average([a,b])
""" """
if not all(isinstance(item, Orientation) for item in orientationList): if not all(isinstance(item, Orientation) for item in orientations):
raise TypeError("Only instances of Orientation can be averaged.") raise TypeError("Only instances of Orientation can be averaged.")
N = len(orientationList) N = len(orientations)
M = orientationList.pop(0).quaternion.asM() if multiplicity == [] or not multiplicity:
for o in orientationList: multiplicity = np.ones(N,dtype='i')
M += o.quaternion.asM()
reference = orientations[0] # take first as reference
for i,(o,n) in enumerate(zip(orientations,multiplicity)):
closest = o.equivalentOrientations(reference.disorientation(o,SST = False)[2])[0] # select sym orientation with lowest misorientation
M = closest.quaternion.asM() * n if i == 0 else M + closest.quaternion.asM() * n # add (multiples) of this orientation to average
eig, vec = np.linalg.eig(M/N) eig, vec = np.linalg.eig(M/N)
return Orientation(quaternion = Quaternion(quatArray = vec.T[eig.argmax()])) return Orientation(quaternion = Quaternion(quatArray = np.real(vec.T[eig.argmax()])))
def related(self, def related(self,