From e48fd338bcce4eb02e25ea398b45a34ee1515af8 Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Wed, 5 Dec 2018 08:55:26 -0500 Subject: [PATCH 1/3] fixed shallow copy problem of quaternion.p object --- lib/damask/orientation.py | 45 +++++++++++++++++---------------------- 1 file changed, 20 insertions(+), 25 deletions(-) diff --git a/lib/damask/orientation.py b/lib/damask/orientation.py index 9910b7a25..d3cd4f94a 100644 --- a/lib/damask/orientation.py +++ b/lib/damask/orientation.py @@ -62,8 +62,7 @@ class Quaternion: def __copy__(self): """Copy""" - Q = Quaternion(q=self.q,p=self.p) - return Q + return self.__class__(q=self.q,p=self.p.copy()) copy = __copy__ @@ -91,10 +90,8 @@ class Quaternion: # Rowenhorst_etal2015 MSMSE: value of P is selected as -1 P = -1.0 try: # quaternion - Q = Quaternion() - Q.q = self.q*other.q - np.dot(self.p,other.p) - Q.p = self.q*other.p + other.q*self.p + P * np.cross(self.p,other.p) - return Q + return self.__class__(q=self.q*other.q - np.dot(self.p,other.p), + p=self.q*other.p + other.q*self.p + P * np.cross(self.p,other.p)) except: pass try: # vector (perform passive rotation) return (self.q*self.q - np.dot(self.p,self.p)) * np.array(other[:3]) \ @@ -102,10 +99,8 @@ class Quaternion: + 2.0*P*self.q * np.cross(self.p,other[:3]) except: pass try: # scalar - Q = self.copy() - Q.q *= other - Q.p *= other - return Q + return self.__class__(q=self.q*other, + p=self.p*other) except: return self.copy() @@ -122,9 +117,8 @@ class Quaternion: def __div__(self, other): """Division""" if isinstance(other, (int,float)): - q = self.q / other - p = self.p / other - return self.__class__(q=q,p=p) + return self.__class__(q=self.q / other, + p=self.p / other) else: return NotImplemented @@ -138,9 +132,8 @@ class Quaternion: def __add__(self, other): """Addition""" if isinstance(other, Quaternion): - q = self.q + other.q - p = self.p + other.p - return self.__class__(q=q,p=p) + return self.__class__(q=self.q + other.q, + p=self.p + other.p) else: return NotImplemented @@ -154,12 +147,10 @@ class Quaternion: def __sub__(self, other): """Subtraction""" if isinstance(other, Quaternion): - Q = self.copy() - Q.q -= other.q - Q.p -= other.p - return Q + return self.__class__(q=self.q - other.q, + p=self.p - other.p) else: - return self.copy() + return NotImplemented def __isub__(self, other): """In-place subtraction""" @@ -190,7 +181,8 @@ class Quaternion: def __cmp__(self,other): """Linear ordering""" - return (self.Rodrigues()>other.Rodrigues()) - (self.Rodrigues() np.linalg.norm(other.asRodrigues()) else 0) \ + - (1 if np.linalg.norm(self.asRodrigues()) < np.linalg.norm(other.asRodrigues()) else 0) def magnitude_squared(self): return self.q ** 2 + np.dot(self.p,self.p) @@ -203,7 +195,8 @@ class Quaternion: def normalize(self): d = self.magnitude() if d > 0.0: - self /= d + self.q /= d + self.p /= d return self def conjugate(self): @@ -322,9 +315,11 @@ class Quaternion: @classmethod def fromRodrigues(cls, rodrigues): if not isinstance(rodrigues, np.ndarray): rodrigues = np.array(rodrigues) - halfangle = math.atan(np.linalg.norm(rodrigues)) + norm = np.linalg.norm(rodrigues) + halfangle = math.atan(norm) + s = math.sin(halfangle) c = math.cos(halfangle) - return cls(q=c,p=rodrigues/c) + return cls(q=c,p=s*rodrigues/norm) @classmethod From c0f7ae27983ed6c75e68234113e9857fce77f9e4 Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Wed, 5 Dec 2018 09:07:29 -0500 Subject: [PATCH 2/3] updated scripts that still used formerly valid object properties of quaternions --- lib/damask/orientation.py | 2 +- processing/post/addGrainID.py | 4 ++-- processing/pre/geom_fromTable.py | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/damask/orientation.py b/lib/damask/orientation.py index d3cd4f94a..63fb124a6 100644 --- a/lib/damask/orientation.py +++ b/lib/damask/orientation.py @@ -855,7 +855,7 @@ class Orientation: M = closest.quaternion.asM() * n if i == 0 else M + closest.quaternion.asM() * n # noqa add (multiples) of this orientation to average noqa eig, vec = np.linalg.eig(M/N) - return Orientation(quaternion = Quaternion(quatArray = np.real(vec.T[eig.argmax()])), + return Orientation(quaternion = Quaternion(quat = np.real(vec.T[eig.argmax()])), symmetry = reference.symmetry.lattice) diff --git a/processing/post/addGrainID.py b/processing/post/addGrainID.py index 45034034b..c3b98f4e6 100755 --- a/processing/post/addGrainID.py +++ b/processing/post/addGrainID.py @@ -200,9 +200,9 @@ for name in filenames: if gID != -1 and gID not in alreadyChecked: # indexed point belonging to a grain not yet tested? alreadyChecked[gID] = True # remember not to check again disorientation = o.disorientation(orientations[gID],SST = False)[0] # compare against other orientation - if disorientation.quaternion.w > cos_disorientation: # within threshold ... + if disorientation.quaternion.q > cos_disorientation: # within threshold ... candidates.append(gID) # remember as potential candidate - if disorientation.quaternion.w >= bestDisorientation.w: # ... and better than current best? + if disorientation.quaternion.q >= bestDisorientation.q: # ... and better than current best? matched = True matchedID = gID # remember that grain bestDisorientation = disorientation.quaternion diff --git a/processing/pre/geom_fromTable.py b/processing/pre/geom_fromTable.py index 3cdd1b2e6..e1157d325 100755 --- a/processing/pre/geom_fromTable.py +++ b/processing/pre/geom_fromTable.py @@ -258,7 +258,7 @@ for name in filenames: if len(grains) > 0: # check immediate neighborhood first cos_disorientations = np.array([o.disorientation(orientations[grainID], - SST = False)[0].quaternion.w \ + SST = False)[0].quaternion.q \ for grainID in grains]) # store disorientation per grainID closest_grain = np.argmax(cos_disorientations) # grain among grains with closest orientation to myself match = 'local' @@ -269,7 +269,7 @@ for name in filenames: if len(grains) > 0: cos_disorientations = np.array([o.disorientation(orientations[grainID], - SST = False)[0].quaternion.w \ + SST = False)[0].quaternion.q \ for grainID in grains]) # store disorientation per grainID closest_grain = np.argmax(cos_disorientations) # grain among grains with closest orientation to myself match = 'global' From a6d4c73de0e559f1484930f29e52777c15111b06 Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Wed, 5 Dec 2018 10:20:05 -0500 Subject: [PATCH 3/3] added list of map and introduced "quat" keyword in quaternion init --- lib/damask/orientation.py | 22 ++++++++++++++-------- processing/pre/geom_addPrimitive.py | 8 ++++---- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/lib/damask/orientation.py b/lib/damask/orientation.py index 63fb124a6..c1862e13c 100644 --- a/lib/damask/orientation.py +++ b/lib/damask/orientation.py @@ -72,15 +72,13 @@ class Quaternion: def __pow__(self, exponent): """Power""" - Q = Quaternion() omega = math.acos(self.q) - Q.q = math.cos(exponent*omega) - Q.p = self.p * math.sin(exponent*omega)/math.sin(omega) - return Q + return self.__class__(q= math.cos(exponent*omega), + p=self.p * math.sin(exponent*omega)/math.sin(omega)) def __ipow__(self, exponent): """In-place power""" - omega = math.acos(self.q[0]) + omega = math.acos(self.q) self.q = math.cos(exponent*omega) self.p *= math.sin(exponent*omega)/math.sin(omega) return self @@ -94,9 +92,17 @@ class Quaternion: p=self.q*other.p + other.q*self.p + P * np.cross(self.p,other.p)) except: pass try: # vector (perform passive rotation) - return (self.q*self.q - np.dot(self.p,self.p)) * np.array(other[:3]) \ - + 2.0*np.dot(self.p,other[:3]) * self.p \ - + 2.0*P*self.q * np.cross(self.p,other[:3]) + ( x, y, z) = self.p + (Vx,Vy,Vz) = other[0:3] + A = self.q*self.q - np.dot(self.p,self.p) + B = 2.0 * (x*Vx + y*Vy + z*Vz) + C = 2.0 * P*self.q + + return np.array([ + A*Vx + B*x + C*(y*Vz - z*Vy), + A*Vy + B*y + C*(z*Vx - x*Vz), + A*Vz + B*z + C*(x*Vy - y*Vx), + ]) except: pass try: # scalar return self.__class__(q=self.q*other, diff --git a/processing/pre/geom_addPrimitive.py b/processing/pre/geom_addPrimitive.py index 35000d8bf..54de558f7 100755 --- a/processing/pre/geom_addPrimitive.py +++ b/processing/pre/geom_addPrimitive.py @@ -64,11 +64,11 @@ if options.dimension is None: parser.error('no dimension specified.') if options.angleaxis is not None: options.angleaxis = list(map(float,options.angleaxis)) - rotation = damask.Quaternion().fromAngleAxis(np.radians(options.angleaxis[0]) if options.degrees else options.angleaxis[0], - options.angleaxis[1:4]) + rotation = damask.Quaternion.fromAngleAxis(np.radians(options.angleaxis[0]) if options.degrees else options.angleaxis[0], + options.angleaxis[1:4]) elif options.quaternion is not None: - options.quaternion = map(float,options.quaternion) - rotation = damask.Quaternion(options.quaternion) + options.quaternion = list(map(float,options.quaternion)) + rotation = damask.Quaternion(quat=options.quaternion) else: rotation = damask.Quaternion()